| 1 | import net.dv8tion.jda.core.events.Event; | 
| 2 | import net.dv8tion.jda.core.events.user.update.*; | 
| 3 | |
| 4 | asclass DynTalkBot2<A extends DynTalkBot2.ByServer> extends DynServerAwareDiscordBot<A> {
 | 
| 5 | switchable S myName = "Anonymous bot"; | 
| 6 | transient bool useAGIBlueForDropPunctuation = true; | 
| 7 | transient bool preprocessAtSelfToMyName = true; | 
| 8 | transient bool dropPunctuation = true; | 
| 9 | transient bool ngbCommands = true; | 
| 10 | //transient bool perGuildAuth; // implementing | 
| 11 | L<Long> authorizedUsers = ll(547706854680297473); // stefan | 
| 12 | |
| 13 |   srecord ISaid(long channelID, long date, S text) {}
 | 
| 14 | |
| 15 |   void init {
 | 
| 16 | super.init(); | 
| 17 | |
| 18 |     onPostedInChannel.add((channel, msg) -> {
 | 
| 19 |       if (channel cast Channel) {
 | 
| 20 | Guild guild = channel.getGuild(); | 
| 21 | if (guild == null) ret; | 
| 22 | ByServer bs = getByServer(guild); | 
| 23 | long channelID = channel.getIdLong(); | 
| 24 | mapPut(bs.lastSaidInChannel, channelID, nu ISaid(+channelID, text := msg)); | 
| 25 | change(); | 
| 26 | } | 
| 27 | }); | 
| 28 | |
| 29 | // We leave it as null to force subclasses to set this | 
| 30 | // (avoids serializing bad instances) | 
| 31 | // makeByServer = () -> (A) new ByServer; | 
| 32 | |
| 33 |     dm_vmBus_onMessage_q discordGuildJoin(voidfunc(Map map) {
 | 
| 34 |       ret unless map.get('module) == module();
 | 
| 35 |       print("Got join");
 | 
| 36 | getByServer(getLong guildID(map), true) | 
| 37 | .onUserJoin(getLong userID(map), map); | 
| 38 | }); | 
| 39 | |
| 40 |     onDiscordEvent(e -> {
 | 
| 41 |       //print("Generic Discord event: " + e);
 | 
| 42 | if (e cast UserUpdateOnlineStatusEvent) | 
| 43 | getByServer(e.getGuild()).onOnlineStatusChange(e); | 
| 44 | }); | 
| 45 | } | 
| 46 | |
| 47 |   class ByServer extends DynServerAwareDiscordBot.ByServer {
 | 
| 48 | L<Long> guildAuthorizedUsers; | 
| 49 | Map<Long, ISaid> lastSaidInChannel = synchroMap(); | 
| 50 | |
| 51 |     DynTalkBot2 m2() { ret DynTalkBot2.this; } // for debugging
 | 
| 52 | |
| 53 | // overridable | 
| 54 |     void onUserJoin(long userID, O... _) {}
 | 
| 55 |     void onOnlineStatusChange(UserUpdateOnlineStatusEvent e) {}
 | 
| 56 | |
| 57 |     @Override S answer(S input, Map map) {
 | 
| 58 | try answer super.answer(input, map); // server-aware stuff | 
| 59 | S answer = processLine(input, map); | 
| 60 | ret answer; | 
| 61 | } | 
| 62 | |
| 63 |     S dropMyPrefixOrNull(S s) {
 | 
| 64 | S sOld = s; | 
| 65 | s = dropPrefixICTrim_orNull(myPrefix(), s); | 
| 66 | if (s == null) | 
| 67 |         print("no got prefix: " + quote(myPrefix()) + " / " + quote(sOld));
 | 
| 68 | ret s; | 
| 69 | } | 
| 70 | |
| 71 |     S processLine(S s, O... _) {
 | 
| 72 | s = preprocess(s, _); | 
| 73 | ret processSimplifiedLine(s, _); | 
| 74 | } | 
| 75 | |
| 76 |     S preprocess(S s, O... _) {
 | 
| 77 |       print("Preprocessing: " + s);
 | 
| 78 |       //pcall { print("mother: " + DynTalkBot2.this); }
 | 
| 79 | if (preprocessAtSelfToMyName && discordBotID != 0) | 
| 80 | s = replace(s, atSelf(), " " + myName + " "); | 
| 81 | if (dropPunctuation) | 
| 82 | s = dropPunctuation3_withAGIBlue(useAGIBlueForDropPunctuation, s); | 
| 83 | s = trim(simpleSpaces_noTok(s)); | 
| 84 |       print("simplified >> " + quote(s));
 | 
| 85 | ret s; | 
| 86 | } | 
| 87 | |
| 88 |     S myPrefix() {
 | 
| 89 | ret preprocessAtSelfToMyName ? | 
| 90 | (endsWithLetterOrDigit(myName) ? myName + " " : myName) : | 
| 91 | (dropPunctuation ? replace(atSelf(), "@", "") /* @ is killed by preprocessing */ : atSelf()) + " "; | 
| 92 | } | 
| 93 | |
| 94 | // extend me | 
| 95 |     S processSimplifiedLine(S input, O... _) {
 | 
| 96 | new Matches m; | 
| 97 | |
| 98 | input = dropMyPrefixOrNull(input); | 
| 99 | if (input == null) null; | 
| 100 | |
| 101 |       if (ngbCommands) {
 | 
| 102 | if (eqicOneOf(input, "support channel", "support server", "support")) | 
| 103 | ret "Get support for me here: " + nextGenBotsDiscordInvite(); | 
| 104 | |
| 105 | if (eqicOneOf(input, "source", "sources", "source code")) | 
| 106 | ret snippetLink(programID()); | 
| 107 | } | 
| 108 | |
| 109 |       if (swic_trim(input, "add master ", m)) {
 | 
| 110 | try answer checkAuth(_); | 
| 111 | |
| 112 | setAdd(authorizedUsers, parseFirstLong(m.rest())); | 
| 113 | change(); | 
| 114 | |
| 115 | ret "Okidoki. Have " + n2(l(authorizedUsers), "master"); | 
| 116 | } | 
| 117 | |
| 118 | if (eqic(input, "masters")) | 
| 119 | ret empty(authorizedUsers) ? "I have no masters." : "My masters are: " + joinWithComma(map discordAtPlusID(authorizedUsers)); | 
| 120 | |
| 121 |       if (swic_trim(input, "delete master ", m)) {
 | 
| 122 | try answer checkAuth(_); | 
| 123 | |
| 124 | remove(authorizedUsers, parseFirstLong(m.rest())); | 
| 125 | change(); | 
| 126 | |
| 127 | ret "Okidoki. Have " + n2(l(authorizedUsers), "master"); | 
| 128 | } | 
| 129 | |
| 130 |       if (eqic(input, "guild count")) {
 | 
| 131 | try answer checkAuth(_); | 
| 132 | ret renderGuildCount(); | 
| 133 | } | 
| 134 | |
| 135 |       if (eqic(input, "guild names")) {
 | 
| 136 | try answer checkAuth(_); | 
| 137 | ret renderGuildNames(); | 
| 138 | } | 
| 139 | |
| 140 | null; | 
| 141 | } | 
| 142 | |
| 143 |     S renderGuildCount() {
 | 
| 144 | ret "Total guilds joined: " + guildCount + ". Live guilds: " + liveGuildCount(); | 
| 145 | } | 
| 146 | |
| 147 |     S renderGuildNames() {
 | 
| 148 | ret lines(map(discord.getGuilds(), g -> g.getName())); | 
| 149 | } | 
| 150 | |
| 151 |     bool authed(O... _) {
 | 
| 152 | ret contains(authorizedUsers, optPar userID(_)); | 
| 153 | } | 
| 154 | |
| 155 |     S checkAuth(O... _) {  
 | 
| 156 | long userID = longPar userID(_); | 
| 157 | bool result = authed(_); | 
| 158 |       print("Auth-checking user ID: " + userID + " => " + result);
 | 
| 159 | if (!result) ret "You are not authorized"; | 
| 160 | null; | 
| 161 | } | 
| 162 | |
| 163 |     S guildStructure() {
 | 
| 164 | ret structure_nullingInstancesOfClass(_getClass(module()), this); | 
| 165 | } | 
| 166 | } // end of class ByServer | 
| 167 | |
| 168 |   S serveGuildBackup(MessageChannel channel, Guild guild, S data) {
 | 
| 169 | if (guild == null) ret "Do this in a guild"; | 
| 170 | if (containsDiscordToken(data)) ret "DISCORD TOKEN EXPOSED ALARM!! NOTIFY ADMINISTRATOR"; | 
| 171 | S baseName = urlencode(jda_selfUserName(discord)) | 
| 172 | + "-" + guild.getIdLong() + "-" + ymd_minus_hms(); | 
| 173 | S zipName = baseName + ".zip"; | 
| 174 |     File zip = programFile("backups/" + zipName);
 | 
| 175 | createZipFileWithSingleTextFile(zip, baseName + ".txt", data); | 
| 176 |     channel.sendMessage("Here's my latest brain contents for this guild.").addFile(zip).queue();
 | 
| 177 | null; | 
| 178 | } | 
| 179 | |
| 180 | // use structure() on ByServer | 
| 181 |   S serveGuildBackup(MessageChannel channel, Guild guild, ByServer bs) {
 | 
| 182 | ret serveGuildBackup(channel, guild, bs.guildStructure()); | 
| 183 | } | 
| 184 | |
| 185 | // e.g. for help texts | 
| 186 |   S atSelfOrMyName() {
 | 
| 187 | ret preprocessAtSelfToMyName ? myName : atSelf(); | 
| 188 | } | 
| 189 | } | 
Began life as a copy of #1025128
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1025820 | 
| Snippet name: | DynTalkBot2 backup before guild masters | 
| Eternal ID of this version: | #1025820/1 | 
| Text MD5: | 97b0ce68ef93a6e417c6de5ea58db1e2 | 
| Author: | stefan | 
| Category: | javax / agi.blue | 
| Type: | JavaX fragment (include) | 
| Public (visible to everyone): | Yes | 
| Archived (hidden from active list): | No | 
| Created/modified: | 2019-10-23 14:01:33 | 
| Source code size: | 6263 bytes / 189 lines | 
| Pitched / IR pitched: | No / No | 
| Views / Downloads: | 379 / 401 | 
| Referenced in: | [show references] |