|
| 1 | +import 'package:collection/collection.dart'; |
| 2 | +import 'package:injector/injector.dart'; |
| 3 | +import 'package:nyxx/nyxx.dart'; |
| 4 | +import 'package:running_on_dart/src/models/feature_settings.dart'; |
| 5 | +import 'package:running_on_dart/src/repository/feature_settings.dart'; |
| 6 | +import 'package:running_on_dart/src/settings.dart'; |
| 7 | +import 'package:running_on_dart/src/util/util.dart'; |
| 8 | + |
| 9 | +import 'package:nyxx/src/models/emoji.dart'; // TODO: This should be imported |
| 10 | + |
| 11 | +enum Mode { |
| 12 | + react('react'), |
| 13 | + message('message'); |
| 14 | + |
| 15 | + final String name; |
| 16 | + |
| 17 | + const Mode(this.name); |
| 18 | +} |
| 19 | + |
| 20 | +class EmojiFeatureSetting { |
| 21 | + final bool useBuiltin; |
| 22 | + final Mode mode; |
| 23 | + final bool processOtherBots; |
| 24 | + |
| 25 | + EmojiFeatureSetting({required this.useBuiltin, required this.mode, required this.processOtherBots}); |
| 26 | + |
| 27 | + factory EmojiFeatureSetting.fromJson(Map<String, dynamic> raw) { |
| 28 | + return EmojiFeatureSetting( |
| 29 | + useBuiltin: raw['use_builtin'] ?? true, |
| 30 | + mode: Mode.values.singleWhereOrNull((e) => e.name == raw['mode']) ?? Mode.message, |
| 31 | + processOtherBots: raw['process_other_bots'] ?? true, |
| 32 | + ); |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +class EmojiReactModule implements RequiresInitialization { |
| 37 | + final NyxxGateway _client = Injector.appInstance.get(); |
| 38 | + final FeatureSettingsRepository _featureSettingsRepository = Injector.appInstance.get(); |
| 39 | + |
| 40 | + late Set<ApplicationEmoji> _emojis; |
| 41 | + late Map<Snowflake, EmojiFeatureSetting> _emojiFeatureSettingsCache; |
| 42 | + |
| 43 | + @override |
| 44 | + Future<void> init() async { |
| 45 | + if (!intentFeaturesEnabled) { |
| 46 | + return; |
| 47 | + } |
| 48 | + |
| 49 | + _emojiFeatureSettingsCache = (await _featureSettingsRepository.fetchSettingsForType(Setting.emojiReact)) |
| 50 | + .map((setting) => MapEntry(setting.guildId, EmojiFeatureSetting.fromJson(setting.dataAsJson!))) |
| 51 | + .toMap(); |
| 52 | + _emojis = (await _client.application.emojis.list()) |
| 53 | + .toSet(); // TODO: Add ability to reload module (download new emojis in this case) |
| 54 | + |
| 55 | + _client.onMessageCreate.listen(_handleMessage); |
| 56 | + } |
| 57 | + |
| 58 | + Future<void> _handleMessage(MessageCreateEvent event) async { |
| 59 | + if (event.message.author.id == _client.user.id) { |
| 60 | + return; |
| 61 | + } |
| 62 | + |
| 63 | + if (event.guildId == null) { |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + final (enabled, data) = _fetchSettingForGuild(event.guildId!); |
| 68 | + if (!enabled) { |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + if (!data!.processOtherBots && event.message.author is User && (event.message.author as User).isBot) { |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + final matchingEmojis = [ |
| 77 | + if (data.useBuiltin) ..._findBuiltinEmojis(event.message.content.toLowerCase()), |
| 78 | + ]; |
| 79 | + |
| 80 | + if (matchingEmojis.isEmpty) { |
| 81 | + return; |
| 82 | + } |
| 83 | + |
| 84 | + switch (data.mode) { |
| 85 | + case Mode.react: |
| 86 | + for (final emoji in matchingEmojis) { |
| 87 | + event.message.react(ReactionBuilder(name: emoji.name, id: emoji.id)); |
| 88 | + } |
| 89 | + break; |
| 90 | + case Mode.message: |
| 91 | + final content = matchingEmojis.map((emoji) => emoji.mention).join(' '); |
| 92 | + |
| 93 | + event.message.channel.sendMessage(MessageBuilder(content: content)); |
| 94 | + break; |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + Iterable<ApplicationEmoji> _findBuiltinEmojis(String messageContent) => |
| 99 | + _emojis.where((emoji) => messageContent.contains(emoji.name)); |
| 100 | + (bool, EmojiFeatureSetting?) _fetchSettingForGuild(Snowflake guildId) { |
| 101 | + final result = _emojiFeatureSettingsCache[guildId]; |
| 102 | + |
| 103 | + return (result != null, result); |
| 104 | + } |
| 105 | +} |
0 commit comments