600 lines
20 KiB
Dart
Raw Normal View History

2024-02-18 16:23:10 +01:00
import 'dart:convert';
2024-02-11 01:08:51 +01:00
import 'package:http/http.dart' as http;
2024-06-02 17:09:57 +02:00
import 'package:simplecloudnotifier/api/api_exception.dart';
2024-05-25 18:09:39 +02:00
import 'package:simplecloudnotifier/models/api_error.dart';
2024-05-27 17:21:29 +02:00
import 'package:simplecloudnotifier/models/client.dart';
import 'package:simplecloudnotifier/models/keytoken.dart';
2025-04-13 00:17:06 +02:00
import 'package:simplecloudnotifier/models/send_message_response.dart';
2024-10-19 19:42:05 +02:00
import 'package:simplecloudnotifier/models/sender_name_statistics.dart';
2024-05-27 17:21:29 +02:00
import 'package:simplecloudnotifier/models/subscription.dart';
2024-02-18 16:23:10 +01:00
import 'package:simplecloudnotifier/models/user.dart';
import 'package:simplecloudnotifier/state/app_auth.dart';
2024-05-26 00:20:25 +02:00
import 'package:simplecloudnotifier/state/application_log.dart';
2024-05-25 18:09:39 +02:00
import 'package:simplecloudnotifier/state/globals.dart';
import 'package:simplecloudnotifier/state/request_log.dart';
2024-05-25 22:06:43 +02:00
import 'package:simplecloudnotifier/models/channel.dart';
2024-06-15 21:29:51 +02:00
import 'package:simplecloudnotifier/models/scn_message.dart';
2024-06-02 17:09:57 +02:00
import 'package:simplecloudnotifier/state/token_source.dart';
2024-05-31 23:21:24 +02:00
import 'package:simplecloudnotifier/utils/toaster.dart';
2024-02-18 17:36:58 +01:00
enum ChannelSelector {
owned(apiKey: 'owned'), // Return all channels of the user
2024-05-27 17:21:29 +02:00
subscribedAny(apiKey: 'subscribed_any'), // Return all channels that the user is subscribing to (even unconfirmed)
allAny(apiKey: 'all_any'), // Return channels that the user owns or is subscribing (even unconfirmed)
subscribed(apiKey: 'subscribed'), // Return all channels that the user is subscribing to
all(apiKey: 'all'); // Return channels that the user owns or is subscribing
2024-02-18 17:36:58 +01:00
const ChannelSelector({required this.apiKey});
final String apiKey;
}
class MessageFilter {
List<String>? channelIDs;
List<String>? searchFilter;
List<String>? plainSearchFilter;
List<String>? senderNames;
List<String>? usedKeys;
List<int>? priority;
DateTime? timeBefore;
DateTime? timeAfter;
bool? hasSenderName;
List<String>? senderUserID;
MessageFilter({
this.channelIDs,
this.searchFilter,
this.plainSearchFilter,
this.senderNames,
this.usedKeys,
this.priority,
this.timeBefore,
this.timeAfter,
this.senderUserID,
});
}
2024-02-11 01:08:51 +01:00
class APIClient {
2025-04-13 00:17:06 +02:00
static const String _base = 'https://simplecloudnotifier.de';
static const String _prefix = '/api/v2';
2024-02-11 01:08:51 +01:00
2024-05-25 18:09:39 +02:00
static Future<T> _request<T>({
required String name,
required String method,
required String relURL,
Map<String, Iterable<String>>? query,
2024-05-25 18:09:39 +02:00
required T Function(Map<String, dynamic> json)? fn,
dynamic jsonBody,
2024-06-01 14:00:16 +02:00
String? authToken,
2024-05-25 18:09:39 +02:00
Map<String, String>? header,
2025-04-13 00:17:06 +02:00
bool? nonAPI,
2024-05-25 18:09:39 +02:00
}) async {
final t0 = DateTime.now();
2025-04-13 00:17:06 +02:00
final uri = Uri.parse('$_base${(nonAPI ?? false) ? '' : _prefix}/$relURL').replace(queryParameters: query ?? {});
2024-05-25 18:09:39 +02:00
final req = http.Request(method, uri);
print('[REQUEST|RUN] [${method}] ${name} | ${uri.toString()}');
2024-05-25 18:09:39 +02:00
if (jsonBody != null) {
req.body = jsonEncode(jsonBody);
req.headers['Content-Type'] = 'application/json';
}
2024-02-11 01:08:51 +01:00
2024-06-01 14:00:16 +02:00
if (authToken != null) {
req.headers['Authorization'] = 'SCN ${authToken}';
2024-05-25 18:09:39 +02:00
}
2024-02-18 16:23:10 +01:00
2024-05-25 18:09:39 +02:00
req.headers['User-Agent'] = 'simplecloudnotifier/flutter/${Globals().platform.replaceAll(' ', '_')} ${Globals().version}+${Globals().buildNumber}';
2024-02-18 16:23:10 +01:00
2024-05-25 18:09:39 +02:00
if (header != null && !header.isEmpty) {
req.headers.addAll(header);
2024-02-18 16:23:10 +01:00
}
2024-05-25 18:09:39 +02:00
int responseStatusCode = 0;
String responseBody = '';
Map<String, String> responseHeaders = {};
try {
final response = await req.send();
responseBody = await response.stream.bytesToString();
responseStatusCode = response.statusCode;
responseHeaders = response.headers;
} catch (exc, trace) {
RequestLog.addRequestException(name, t0, method, uri, req.body, req.headers, exc, trace);
2024-05-31 23:21:24 +02:00
Toaster.error("Error", 'Request "${name}" failed');
2024-05-26 00:20:25 +02:00
ApplicationLog.error('Request "${name}" failed: ' + exc.toString(), trace: trace);
2024-05-25 18:09:39 +02:00
rethrow;
}
2024-02-18 17:36:58 +01:00
2024-05-25 18:09:39 +02:00
if (responseStatusCode != 200) {
2024-10-19 19:42:05 +02:00
APIError apierr;
2024-02-18 17:36:58 +01:00
2024-10-19 19:42:05 +02:00
try {
apierr = APIError.fromJson(jsonDecode(responseBody) as Map<String, dynamic>);
2024-05-26 00:20:25 +02:00
} catch (exc, trace) {
ApplicationLog.warn('Failed to decode api response as error-object', additional: exc.toString() + "\nBody:\n" + responseBody, trace: trace);
2024-10-19 19:42:05 +02:00
RequestLog.addRequestErrorStatuscode(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
Toaster.error("Error", 'Request "${name}" failed');
throw Exception('API request failed with status code ${responseStatusCode}');
2024-05-26 00:20:25 +02:00
}
2024-02-18 17:36:58 +01:00
2024-10-19 19:42:05 +02:00
RequestLog.addRequestAPIError(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders, apierr);
Toaster.error("Error", apierr.message);
throw APIException(responseStatusCode, apierr.error, apierr.errhighlight, apierr.message);
2024-02-18 17:36:58 +01:00
}
2024-05-25 18:09:39 +02:00
try {
final data = jsonDecode(responseBody);
if (fn != null) {
2024-05-25 21:36:05 +02:00
final result = fn(data as Map<String, dynamic>);
2024-05-25 18:09:39 +02:00
RequestLog.addRequestSuccess(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
print('[REQUEST|FIN] [${method}] ${name}');
2024-05-25 18:09:39 +02:00
return result;
} else {
RequestLog.addRequestSuccess(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders);
print('[REQUEST|FIN] [${method}] ${name}');
2024-05-25 18:09:39 +02:00
return null as T;
}
} catch (exc, trace) {
RequestLog.addRequestDecodeError(name, t0, method, uri, req.body, req.headers, responseStatusCode, responseBody, responseHeaders, exc, trace);
2024-05-31 23:21:24 +02:00
Toaster.error("Error", 'Request "${name}" failed');
2024-05-26 00:20:25 +02:00
ApplicationLog.error('Failed to decode response: ' + exc.toString(), additional: "\nBody:\n" + responseBody, trace: trace);
2024-05-25 18:09:39 +02:00
rethrow;
2024-02-18 17:36:58 +01:00
}
2024-05-25 18:09:39 +02:00
}
2024-02-18 17:36:58 +01:00
2024-05-25 18:09:39 +02:00
// ==========================================================================================================================================================
2024-02-18 17:36:58 +01:00
2024-06-02 17:09:57 +02:00
static Future<User> getUser(TokenSource auth, String uid) async {
2024-05-25 18:09:39 +02:00
return await _request(
name: 'getUser',
method: 'GET',
relURL: 'users/$uid',
fn: User.fromJson,
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-25 18:09:39 +02:00
);
}
2024-02-18 17:36:58 +01:00
2024-06-12 01:17:00 +02:00
static Future<UserPreview> getUserPreview(TokenSource auth, String uid) async {
return await _request(
name: 'getUserPreview',
method: 'GET',
relURL: 'preview/users/$uid',
fn: UserPreview.fromJson,
authToken: auth.getToken(),
);
}
2025-04-12 14:35:08 +02:00
static Future<User> updateUser(TokenSource auth, String uid, {String? username, String? proToken}) async {
return await _request(
name: 'updateUser',
method: 'PATCH',
relURL: 'users/$uid',
jsonBody: {
if (username != null) 'username': username,
if (proToken != null) 'pro_token': proToken,
},
fn: User.fromJson,
authToken: auth.getToken(),
);
}
2025-04-13 16:32:59 +02:00
static Future<User> deleteUser(TokenSource auth, String uid) async {
return await _request(
name: 'deleteUser',
method: 'DELETE',
relURL: 'users/$uid',
fn: User.fromJson,
authToken: auth.getToken(),
);
}
2024-06-02 17:09:57 +02:00
static Future<Client> addClient(TokenSource auth, String fcmToken, String agentModel, String agentVersion, String? name, String clientType) async {
2024-05-31 15:22:27 +02:00
return await _request(
name: 'addClient',
method: 'POST',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/clients',
2024-05-31 15:22:27 +02:00
jsonBody: {
'fcm_token': fcmToken,
'agent_model': agentModel,
'agent_version': agentVersion,
'client_type': clientType,
2024-06-01 14:00:16 +02:00
'name': name,
2024-05-31 15:22:27 +02:00
},
fn: Client.fromJson,
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-31 15:22:27 +02:00
);
}
2024-06-02 17:09:57 +02:00
static Future<Client> updateClient(TokenSource auth, String clientID, String fcmToken, String agentModel, String? name, String agentVersion) async {
2024-05-31 15:22:27 +02:00
return await _request(
name: 'updateClient',
method: 'PUT',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/clients/$clientID',
2024-05-31 15:22:27 +02:00
jsonBody: {
'fcm_token': fcmToken,
'agent_model': agentModel,
'agent_version': agentVersion,
2024-06-01 14:00:16 +02:00
'name': name,
2024-05-31 15:22:27 +02:00
},
fn: Client.fromJson,
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-31 15:22:27 +02:00
);
}
2024-06-02 17:09:57 +02:00
static Future<Client> getClient(TokenSource auth, String cid) async {
return await _request(
name: 'getClient',
method: 'GET',
relURL: 'users/${auth.getUserID()}/clients/$cid',
fn: Client.fromJson,
authToken: auth.getToken(),
);
}
static Future<List<ChannelWithSubscription>> getChannelList(TokenSource auth, ChannelSelector sel) async {
2024-05-25 18:09:39 +02:00
return await _request(
name: 'getChannelList',
method: 'GET',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/channels',
query: {
'selector': [sel.apiKey]
},
2024-05-25 21:36:05 +02:00
fn: (json) => ChannelWithSubscription.fromJsonArray(json['channels'] as List<dynamic>),
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-06-07 23:44:32 +02:00
);
}
static Future<ChannelWithSubscription> getChannel(TokenSource auth, String cid) async {
return await _request(
name: 'getChannel',
method: 'GET',
relURL: 'users/${auth.getUserID()}/channels/${cid}',
fn: ChannelWithSubscription.fromJson,
authToken: auth.getToken(),
2024-05-25 18:09:39 +02:00
);
}
2024-02-18 17:36:58 +01:00
2024-06-12 01:17:00 +02:00
static Future<ChannelPreview> getChannelPreview(TokenSource auth, String cid) async {
return await _request(
name: 'getChannelPreview',
method: 'GET',
relURL: 'preview/channels/${cid}',
fn: ChannelPreview.fromJson,
authToken: auth.getToken(),
);
}
static Future<ChannelWithSubscription> updateChannel(AppAuth auth, String cid, {String? displayName, String? descriptionName}) async {
return await _request(
name: 'updateChannel',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/channels/${cid}',
jsonBody: {
if (displayName != null) 'display_name': displayName,
if (descriptionName != null) 'description_name': descriptionName,
},
fn: ChannelWithSubscription.fromJson,
authToken: auth.getToken(),
);
}
static Future<(String, List<SCNMessage>)> getMessageList(TokenSource auth, String pageToken, {int? pageSize, MessageFilter? filter, bool? includeNonSuscribed}) async {
2024-05-25 18:09:39 +02:00
return await _request(
name: 'getMessageList',
method: 'GET',
relURL: 'messages',
2024-05-26 19:24:19 +02:00
query: {
'next_page_token': [pageToken],
if (pageSize != null) 'page_size': [pageSize.toString()],
if (filter?.searchFilter != null) 'search': filter!.searchFilter!,
if (filter?.plainSearchFilter != null) 'string_search': filter!.plainSearchFilter!,
if (filter?.channelIDs != null) 'channel_id': filter!.channelIDs!,
if (filter?.senderNames != null) 'sender': filter!.senderNames!,
if (filter?.hasSenderName != null) 'has_sender': [filter!.hasSenderName!.toString()],
if (filter?.timeBefore != null) 'before': [filter!.timeBefore!.toIso8601String()],
if (filter?.timeAfter != null) 'after': [filter!.timeAfter!.toIso8601String()],
if (filter?.priority != null) 'priority': filter!.priority!.map((p) => p.toString()).toList(),
if (filter?.usedKeys != null) 'used_key': filter!.usedKeys!,
if (filter?.senderUserID != null) 'sender_user_id': filter!.senderUserID!,
if (includeNonSuscribed ?? false) 'subscription_status': ['all'],
2024-05-26 19:24:19 +02:00
},
2024-06-15 21:29:51 +02:00
fn: (json) => SCNMessage.fromPaginatedJsonArray(json, 'messages', 'next_page_token'),
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-25 18:09:39 +02:00
);
2024-05-21 23:20:34 +02:00
}
2024-06-15 21:29:51 +02:00
static Future<SCNMessage> getMessage(TokenSource auth, String msgid) async {
2024-05-25 18:09:39 +02:00
return await _request(
name: 'getMessage',
method: 'GET',
relURL: 'messages/$msgid',
2024-06-15 21:29:51 +02:00
fn: SCNMessage.fromJson,
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-25 18:09:39 +02:00
);
2024-02-18 17:36:58 +01:00
}
2024-05-27 17:21:29 +02:00
2024-10-19 19:42:05 +02:00
static Future<(String, List<SCNMessage>)> getChannelMessageList(TokenSource auth, String cid, String pageToken, {int? pageSize}) async {
return await _request(
name: 'getChannelMessageList',
method: 'GET',
relURL: 'users/${auth.getUserID()}/channels/${cid}/messages',
query: {
'next_page_token': [pageToken],
if (pageSize != null) 'page_size': [pageSize.toString()],
},
fn: (json) => SCNMessage.fromPaginatedJsonArray(json, 'messages', 'next_page_token'),
authToken: auth.getToken(),
);
}
2025-04-18 01:45:56 +02:00
static Future<Subscription> getSubscription(TokenSource auth, String subscriptionID) async {
return await _request(
name: 'getSubscription',
method: 'GET',
relURL: 'users/${auth.getUserID()}/subscriptions/${subscriptionID}',
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
2024-06-02 17:09:57 +02:00
static Future<List<Subscription>> getSubscriptionList(TokenSource auth) async {
2024-05-27 17:21:29 +02:00
return await _request(
name: 'getSubscriptionList',
method: 'GET',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/subscriptions',
2025-04-18 01:45:56 +02:00
query: {
'direction': ['both'],
'confirmation': ['all'],
'external': ['all'],
},
2024-05-27 17:21:29 +02:00
fn: (json) => Subscription.fromJsonArray(json['subscriptions'] as List<dynamic>),
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-27 17:21:29 +02:00
);
}
2024-06-25 20:49:40 +02:00
static Future<List<Subscription>> getChannelSubscriptions(TokenSource auth, String cid) async {
return await _request(
name: 'getChannelSubscriptions',
method: 'GET',
relURL: 'users/${auth.getUserID()}/channels/${cid}/subscriptions',
fn: (json) => Subscription.fromJsonArray(json['subscriptions'] as List<dynamic>),
authToken: auth.getToken(),
);
}
2024-06-02 17:09:57 +02:00
static Future<List<Client>> getClientList(TokenSource auth) async {
2024-05-27 17:21:29 +02:00
return await _request(
name: 'getClientList',
method: 'GET',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/clients',
2024-05-27 17:21:29 +02:00
fn: (json) => Client.fromJsonArray(json['clients'] as List<dynamic>),
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-27 17:21:29 +02:00
);
}
2024-06-02 17:09:57 +02:00
static Future<List<KeyToken>> getKeyTokenList(TokenSource auth) async {
2024-05-27 17:21:29 +02:00
return await _request(
name: 'getKeyTokenList',
method: 'GET',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/keys',
2024-05-27 17:21:29 +02:00
fn: (json) => KeyToken.fromJsonArray(json['keys'] as List<dynamic>),
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-05-27 17:21:29 +02:00
);
}
2024-06-01 14:00:16 +02:00
static Future<UserWithClientsAndKeys> createUserWithClient(String? username, String clientFcmToken, String clientAgentModel, String clientAgentVersion, String? clientName, String clientType) async {
return await _request(
name: 'createUserWithClient',
method: 'POST',
relURL: 'users',
jsonBody: {
'username': username,
'fcm_token': clientFcmToken,
'agent_model': clientAgentModel,
'agent_version': clientAgentVersion,
2024-06-01 14:00:16 +02:00
'client_name': clientName,
'client_type': clientType,
'no_client': false,
},
fn: UserWithClientsAndKeys.fromJson,
);
}
2024-06-01 14:00:16 +02:00
2024-06-02 17:09:57 +02:00
static Future<KeyToken> getKeyToken(TokenSource auth, String kid) async {
2024-06-01 14:00:16 +02:00
return await _request(
name: 'getKeyToken',
method: 'GET',
2024-06-02 17:09:57 +02:00
relURL: 'users/${auth.getUserID()}/keys/$kid',
2024-06-01 14:00:16 +02:00
fn: KeyToken.fromJson,
2024-06-02 17:09:57 +02:00
authToken: auth.getToken(),
2024-06-01 14:00:16 +02:00
);
}
2025-04-13 00:17:06 +02:00
static Future<KeyTokenPreview> getKeyTokenPreviewByID(TokenSource auth, String kid) async {
2024-06-12 01:17:00 +02:00
return await _request(
2025-04-13 00:17:06 +02:00
name: 'getKeyTokenPreviewByID',
2024-06-12 01:17:00 +02:00
method: 'GET',
relURL: 'preview/keys/$kid',
fn: KeyTokenPreview.fromJson,
authToken: auth.getToken(),
);
}
2025-04-13 00:17:06 +02:00
static Future<KeyTokenPreview> getKeyTokenPreviewByToken(TokenSource auth, String tok) async {
return await _request(
name: 'getKeyTokenPreviewByToken',
method: 'GET',
relURL: 'preview/keys/$tok',
fn: KeyTokenPreview.fromJson,
authToken: auth.getToken(),
);
}
2024-06-01 14:00:16 +02:00
static Future<KeyToken> getKeyTokenByToken(String userid, String token) async {
return await _request(
name: 'getCurrentKeyToken',
method: 'GET',
relURL: 'users/${userid}/keys/current',
fn: KeyToken.fromJson,
authToken: token,
);
}
2025-04-18 18:56:17 +02:00
static Future<void> deleteKeyToken(AppAuth acc, String keytokenID) {
return _request(
name: 'deleteKeyToken',
method: 'DELETE',
relURL: 'users/${acc.getUserID()}/keys/${keytokenID}',
fn: (_) => null,
authToken: acc.getToken(),
);
}
static Future<KeyToken> updateKeyToken(TokenSource auth, String kid, {String? name, bool? allChannels, List<String>? channels, String? permissions}) async {
return await _request(
name: 'updateKeyToken',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/keys/${kid}',
jsonBody: {
if (name != null) 'name': name,
if (allChannels != null) 'all_channels': allChannels,
if (channels != null) 'channels': channels,
if (permissions != null) 'permissions': permissions,
},
fn: KeyToken.fromJson,
authToken: auth.getToken(),
);
}
2025-04-13 02:16:24 +02:00
static Future<KeyTokenWithToken> createKeyToken(TokenSource auth, String name, String perm, bool allChannels, {List<String>? channels}) async {
return await _request(
name: 'createKeyToken',
method: 'POST',
relURL: 'users/${auth.getUserID()}/keys',
jsonBody: {
'name': name,
2025-04-18 18:56:17 +02:00
'permissions': perm,
2025-04-13 02:16:24 +02:00
'all_channels': allChannels,
if (channels != null) 'channels': channels,
},
fn: KeyTokenWithToken.fromJson,
authToken: auth.getToken(),
);
}
2024-10-19 19:42:05 +02:00
static Future<List<SenderNameStatistics>> getSenderNameList(TokenSource auth) async {
return await _request(
name: 'getSenderNameList',
method: 'GET',
relURL: 'users/${auth.getUserID()}/sender-names',
fn: (json) => SenderNameStatistics.fromJsonArray(json['sender_names'] as List<dynamic>),
authToken: auth.getToken(),
);
}
2025-04-13 00:17:06 +02:00
static Future<Subscription> subscribeToChannelbyID(TokenSource auth, String channelID, {String? subscribeKey}) async {
2024-10-19 19:42:05 +02:00
return await _request(
name: 'subscribeToChannelbyID',
method: 'POST',
relURL: 'users/${auth.getUserID()}/subscriptions',
2025-04-13 00:17:06 +02:00
query: {
if (subscribeKey != null) 'chan_subscribe_key': [subscribeKey],
},
2024-10-19 19:42:05 +02:00
jsonBody: {
'channel_id': channelID,
},
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
static Future<Subscription> deleteSubscription(TokenSource auth, String channelID, String subID) async {
return await _request(
name: 'deleteSubscription',
method: 'DELETE',
relURL: 'users/${auth.getUserID()}/subscriptions/${subID}',
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
static Future<Subscription> confirmSubscription(TokenSource auth, String channelID, String subID) async {
return await _request(
name: 'confirmSubscription',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/subscriptions/${subID}',
jsonBody: {
'confirmed': true,
},
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
static Future<Subscription> unconfirmSubscription(TokenSource auth, String channelID, String subID) async {
return await _request(
name: 'unconfirmSubscription',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/subscriptions/${subID}',
jsonBody: {
'confirmed': false,
},
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
2025-04-13 00:17:06 +02:00
static Future<Subscription> activateSubscription(TokenSource auth, String channelID, String subID) async {
return await _request(
name: 'activateSubscription',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/subscriptions/${subID}',
jsonBody: {
'active': true,
},
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
static Future<Subscription> deactivateSubscription(TokenSource auth, String channelID, String subID) async {
return await _request(
name: 'deactivateSubscription',
method: 'PATCH',
relURL: 'users/${auth.getUserID()}/subscriptions/${subID}',
jsonBody: {
'active': false,
},
fn: Subscription.fromJson,
authToken: auth.getToken(),
);
}
2025-04-13 00:17:06 +02:00
static Future<SendMessageResponse> sendMessage(String userid, String keytoken, String text, {String? channel, String? content, String? messageID, int? priority, String? senderName, DateTime? timestamp}) async {
return await _request(
name: 'sendMessage',
method: 'POST',
relURL: '/send',
nonAPI: true,
jsonBody: {
'user_id': userid,
'key': keytoken,
'title': text,
if (channel != null) 'channel': channel,
if (content != null) 'content': content,
if (priority != null) 'priority': priority,
if (messageID != null) 'msg_id': messageID,
if (timestamp != null) 'timestamp': (timestamp.microsecondsSinceEpoch / 1000).toInt(),
if (senderName != null) 'sender_name': senderName,
},
fn: SendMessageResponse.fromJson,
authToken: null,
);
}
2024-02-11 01:08:51 +01:00
}