212 lines
5.4 KiB
Dart
212 lines
5.4 KiB
Dart
import 'dart:async';
|
|
import 'package:get_it/get_it.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:moxxmpp/moxxmpp.dart';
|
|
import 'package:moxxyv2/service/database/constants.dart';
|
|
import 'package:moxxyv2/service/database/database.dart';
|
|
import 'package:moxxyv2/service/service.dart';
|
|
import 'package:moxxyv2/shared/events.dart';
|
|
|
|
enum BlockPushType { block, unblock }
|
|
|
|
class BlocklistService {
|
|
BlocklistService();
|
|
List<String>? _blocklist;
|
|
bool _requested = false;
|
|
bool? _supported;
|
|
final Logger _log = Logger('BlocklistService');
|
|
|
|
Future<void> _removeBlocklistEntry(String jid) async {
|
|
await GetIt.I.get<DatabaseService>().database.delete(
|
|
blocklistTable,
|
|
where: 'jid = ?',
|
|
whereArgs: [jid],
|
|
);
|
|
}
|
|
|
|
Future<void> _addBlocklistEntry(String jid) async {
|
|
await GetIt.I.get<DatabaseService>().database.insert(
|
|
blocklistTable,
|
|
{
|
|
'jid': jid,
|
|
},
|
|
);
|
|
}
|
|
|
|
void onNewConnection() {
|
|
// Invalidate the caches
|
|
_blocklist = null;
|
|
_requested = false;
|
|
_supported = null;
|
|
}
|
|
|
|
Future<bool> _checkSupport() async {
|
|
return _supported ??= await GetIt.I
|
|
.get<XmppConnection>()
|
|
.getManagerById<BlockingManager>(blockingManager)!
|
|
.isSupported();
|
|
}
|
|
|
|
Future<void> _requestBlocklist() async {
|
|
assert(
|
|
_blocklist != null,
|
|
'The blocklist must be loaded from the database before requesting',
|
|
);
|
|
|
|
// Check if blocking is supported
|
|
if (!(await _checkSupport())) {
|
|
_log.warning('Blocklist requested but server does not support it.');
|
|
return;
|
|
}
|
|
|
|
final blocklist = await GetIt.I
|
|
.get<XmppConnection>()
|
|
.getManagerById<BlockingManager>(blockingManager)!
|
|
.getBlocklist();
|
|
|
|
// Diff the received blocklist with the cache
|
|
final newItems = List<String>.empty(growable: true);
|
|
final removedItems = List<String>.empty(growable: true);
|
|
for (final item in blocklist) {
|
|
if (!_blocklist!.contains(item)) {
|
|
await _addBlocklistEntry(item);
|
|
_blocklist!.add(item);
|
|
newItems.add(item);
|
|
}
|
|
}
|
|
|
|
// Diff the cache with the received blocklist
|
|
for (final item in _blocklist!) {
|
|
if (!blocklist.contains(item)) {
|
|
await _removeBlocklistEntry(item);
|
|
_blocklist!.remove(item);
|
|
removedItems.add(item);
|
|
}
|
|
}
|
|
|
|
_requested = true;
|
|
|
|
// Trigger an UI event if we have anything to tell the UI
|
|
if (newItems.isNotEmpty || removedItems.isNotEmpty) {
|
|
sendEvent(
|
|
BlocklistPushEvent(
|
|
added: newItems,
|
|
removed: removedItems,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Returns the blocklist from the database
|
|
Future<List<String>> getBlocklist() async {
|
|
if (_blocklist == null) {
|
|
final blocklistRaw =
|
|
await GetIt.I.get<DatabaseService>().database.query(blocklistTable);
|
|
_blocklist = blocklistRaw.map((m) => m['jid']! as String).toList();
|
|
|
|
if (!_requested) {
|
|
unawaited(_requestBlocklist());
|
|
}
|
|
|
|
return _blocklist!;
|
|
}
|
|
|
|
if (!_requested) {
|
|
unawaited(_requestBlocklist());
|
|
}
|
|
|
|
return _blocklist!;
|
|
}
|
|
|
|
void onUnblockAllPush() {
|
|
_blocklist = List<String>.empty(growable: true);
|
|
sendEvent(
|
|
BlocklistUnblockAllEvent(),
|
|
);
|
|
}
|
|
|
|
Future<void> onBlocklistPush(BlockPushType type, List<String> items) async {
|
|
// We will fetch it later when getBlocklist is called
|
|
if (!_requested) return;
|
|
|
|
final newBlocks = List<String>.empty(growable: true);
|
|
final removedBlocks = List<String>.empty(growable: true);
|
|
for (final item in items) {
|
|
switch (type) {
|
|
case BlockPushType.block:
|
|
{
|
|
if (_blocklist!.contains(item)) continue;
|
|
_blocklist!.add(item);
|
|
newBlocks.add(item);
|
|
|
|
await _addBlocklistEntry(item);
|
|
}
|
|
break;
|
|
case BlockPushType.unblock:
|
|
{
|
|
_blocklist!.removeWhere((i) => i == item);
|
|
removedBlocks.add(item);
|
|
|
|
await _removeBlocklistEntry(item);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
sendEvent(
|
|
BlocklistPushEvent(
|
|
added: newBlocks,
|
|
removed: removedBlocks,
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<bool> blockJid(String jid) async {
|
|
// Check if blocking is supported
|
|
if (!(await _checkSupport())) {
|
|
_log.warning('Blocking $jid requested but server does not support it.');
|
|
return false;
|
|
}
|
|
|
|
_blocklist!.add(jid);
|
|
await _addBlocklistEntry(jid);
|
|
return GetIt.I
|
|
.get<XmppConnection>()
|
|
.getManagerById<BlockingManager>(blockingManager)!
|
|
.block([jid]);
|
|
}
|
|
|
|
Future<bool> unblockJid(String jid) async {
|
|
// Check if blocking is supported
|
|
if (!(await _checkSupport())) {
|
|
_log.warning('Unblocking $jid requested but server does not support it.');
|
|
return false;
|
|
}
|
|
|
|
_blocklist!.remove(jid);
|
|
await _removeBlocklistEntry(jid);
|
|
return GetIt.I
|
|
.get<XmppConnection>()
|
|
.getManagerById<BlockingManager>(blockingManager)!
|
|
.unblock([jid]);
|
|
}
|
|
|
|
Future<bool> unblockAll() async {
|
|
// Check if blocking is supported
|
|
if (!(await _checkSupport())) {
|
|
_log.warning(
|
|
'Unblocking all JIDs requested but server does not support it.',
|
|
);
|
|
return false;
|
|
}
|
|
|
|
_blocklist!.clear();
|
|
await GetIt.I.get<DatabaseService>().database.delete(blocklistTable);
|
|
|
|
return GetIt.I
|
|
.get<XmppConnection>()
|
|
.getManagerById<BlockingManager>(blockingManager)!
|
|
.unblockAll();
|
|
}
|
|
}
|