Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

267
LINES

< > BotCompany Repo | #1025128 // OLD DynTalkBot2 - DynServerAwareDiscordBot + input simplification, onUserJoin, name, authorizedUsers

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (15409L) is out of date.

1  
ifdef JDA40
2  
import net.dv8tion.jda.api.events.Event;
3  
import net.dv8tion.jda.api.events.user.update.*;
4  
endifdef
5  
ifndef JDA40
6  
import net.dv8tion.jda.core.events.Event;
7  
import net.dv8tion.jda.core.events.user.update.*;
8  
endifndef
9  
10  
asclass DynTalkBot2<A extends DynTalkBot2.ByServer> extends DynServerAwareDiscordBot<A> {
11  
  switchable S myName = "Anonymous bot";
12  
  transient bool useAGIBlueForDropPunctuation = true;
13  
  transient bool preprocessAtSelfToMyName = true;
14  
  transient bool dropPunctuation = true;
15  
  transient bool ngbCommands = true;
16  
  L<Long> authorizedUsers = ll(547706854680297473); // stefan
17  
  
18  
  srecord ISaid(long channelID, long date, S text) {}
19  
  
20  
  void init {
21  
    super.init();
22  
    
23  
    onPostedInChannel.add((channel, msg) -> {
24  
      if (channel cast Channel) {
25  
        Guild guild = channel.getGuild();
26  
        if (guild == null) ret;
27  
        ByServer bs = getByServer(guild);
28  
        long channelID = channel.getIdLong();
29  
        mapPut(bs.lastSaidInChannel, channelID, nu ISaid(+channelID, text := msg));
30  
        change();
31  
      }
32  
    });
33  
    
34  
    // We leave it as null to force subclasses to set this
35  
    // (avoids serializing bad instances)
36  
    // makeByServer = () -> (A) new ByServer;
37  
    
38  
    dm_vmBus_onMessage_q discordGuildJoin(voidfunc(Map map) {
39  
      ret unless map.get('module) == module();
40  
      print("Got join");
41  
      getByServer(getLong guildID(map), true)
42  
        .onUserJoin(getLong userID(map), map);
43  
    });
44  
    
45  
    onDiscordEvent(e -> {
46  
      //print("Generic Discord event: " + e);
47  
      if (e cast UserUpdateOnlineStatusEvent)
48  
        getByServer(e.getGuild()).onOnlineStatusChange(e);
49  
    });
50  
  }
51  
  
52  
  class ByServer extends DynServerAwareDiscordBot<DynTalkBot2.ByServer>.ByServer {
53  
    transient Lock lock;
54  
    L<Long> guildAuthorizedUsers = synchroList();
55  
    Map<Long, ISaid> lastSaidInChannel = synchroMap();
56  
    long preferredChannelInGuild;
57  
58  
    DynTalkBot2 m2() { ret DynTalkBot2.this; } // for debugging
59  
    
60  
    // overridable
61  
    void onUserJoin(long userID, O... _) {}
62  
    void onOnlineStatusChange(UserUpdateOnlineStatusEvent e) {}
63  
  
64  
    @Override S answer(S input, Map map) {
65  
      if (preferredChannelInGuild == 0) {
66  
        long channelID = longPar channelID(map);
67  
        if (channelID != 0) {
68  
          preferredChannelInGuild = channelID;
69  
          change();
70  
        }
71  
      }
72  
        
73  
      S answer = processLine(input, map);
74  
      try answer super.answer(input, map); // server-aware stuff
75  
      
76  
      ret answer;
77  
    }
78  
    
79  
    S dropMyPrefixOpt(S s) {
80  
      ret or(dropMyPrefixOrNull(s), s);
81  
    }
82  
    
83  
    S dropMyPrefixOrNull(S s) {
84  
      S sOld = s;
85  
      s = dropPrefixICTrim_orNull(myPrefix(), s);
86  
      if (s == null)
87  
        print("no got prefix: " + quote(myPrefix()) + " / " + quote(sOld));
88  
      ret s;
89  
    }
90  
  
91  
    S processLine(S s, O... _) {
92  
      s = preprocess(s, _);
93  
      ret processSimplifiedLine(s, _);
94  
    }
95  
    
96  
    S preprocess(S s, O... _) {
97  
      print("Preprocessing: " + s);
98  
      //pcall { print("mother: " + DynTalkBot2.this); }
99  
      if (preprocessAtSelfToMyName && discordBotID != 0)
100  
        s = replace(s, atSelf(), " " + myName + " ");
101  
      if (dropPunctuation)
102  
        s = dropPunctuation3_withAGIBlue(useAGIBlueForDropPunctuation, s);
103  
      s = trim(simpleSpaces_noTok(s));
104  
      print("simplified >> " + quote(s));
105  
      ret s;
106  
    }
107  
    
108  
    S myPrefix() {
109  
      ret preprocessAtSelfToMyName ?
110  
        (endsWithLetterOrDigit(myName) ? myName + " " : myName) :
111  
        (dropPunctuation ? replace(atSelf(), "@", "") /* @ is killed by preprocessing */ : atSelf()) + " ";
112  
    }
113  
    
114  
    synchronized Lock myLock() {
115  
      if (lock == null) lock = lock();
116  
      ret lock;
117  
    }
118  
  
119  
    // extend me
120  
    S processSimplifiedLine(S input, O... _) {
121  
      lock myLock();
122  
      new Matches m;
123  
      
124  
      input = dropMyPrefixOrNull(input);
125  
      if (input == null) null;
126  
      
127  
      if (ngbCommands) {
128  
        if (eqicOneOf(input, "support channel", "support server", "support"))
129  
          ret "Get support for me here: " + nextGenBotsDiscordInvite();
130  
          
131  
        if (eqicOneOf(input, "source", "sources", "source code"))
132  
          ret snippetLink(programID());
133  
      }
134  
  
135  
      if (swic_trim(input, "add master ", m)) {
136  
        try answer checkAuth(_);
137  
  
138  
        setAdd(authorizedUsers, parseFirstLong(m.rest()));
139  
        change();
140  
        
141  
        ret "Okidoki. Have " + n2(l(authorizedUsers), "master");
142  
      }
143  
      
144  
      if (eqic(input, "masters"))
145  
        ret renderMasters();
146  
      
147  
      if (swic_trim(input, "delete master ", m)) {
148  
        try answer checkAuth(_);
149  
  
150  
        remove(authorizedUsers, parseFirstLong(m.rest()));
151  
        change();
152  
        
153  
        ret "Okidoki. Have " + n2(l(authorizedUsers), "master");
154  
      }
155  
      
156  
      if (swic_trim(input, "add guild master ", m)) {
157  
        try answer checkPerGuildAuth(_);
158  
  
159  
        setAdd(guildAuthorizedUsers, parseFirstLong(m.rest()));
160  
        change();
161  
        
162  
        ret "Okidoki. " + renderGuildMasters();
163  
      }
164  
      
165  
      if (eqic(input, "guild masters"))
166  
        ret renderGuildMasters();
167  
      
168  
      if (swic_trim(input, "delete guild master ", m)) {
169  
        try answer checkPerGuildAuth(_);
170  
  
171  
        remove(guildAuthorizedUsers, parseFirstLong(m.rest()));
172  
        change();
173  
        
174  
        ret "Okidoki. " + renderGuildMasters();
175  
      }
176  
      
177  
      if (eqic(input, "guild count")) {
178  
        try answer checkAuth(_);
179  
        ret renderGuildCount();
180  
      }
181  
      
182  
      if (eqic(input, "guild names")) {
183  
        try answer checkAuth(_);
184  
        ret renderGuildNames();
185  
      }
186  
      
187  
      null;
188  
    }
189  
    
190  
    S renderGuildMasters() {
191  
      ret empty(guildAuthorizedUsers) ? "Only this guild's owner can control me."
192  
          : "I am controlled by this guild's owner and these people: " + joinWithComma(map discordAtPlusID(guildAuthorizedUsers));
193  
    }
194  
    
195  
    S renderGuildCount() {
196  
      ret "Total guilds joined: " + guildCount + ". Live guilds: " + liveGuildCount();
197  
    }
198  
    
199  
    S renderGuildNames() {
200  
      ret lines(map(discord.getGuilds(), g -> g.getName()));
201  
    }
202  
    
203  
    bool authed(O... _) {
204  
      ret contains(authorizedUsers, optPar userID(_));
205  
    }
206  
  
207  
    bool perGuildAuthed(O... _) {
208  
      long userID = longPar userID(_);
209  
      ret contains(guildAuthorizedUsers, userID)
210  
        || guildID != 0 && userID == getGuild().getOwnerIdLong();
211  
    }
212  
    
213  
    Guild getGuild() {
214  
      ret guildID == 0 ? null : discord.getGuildById(guildID);
215  
    }
216  
  
217  
    S checkAuth(O... _) {  
218  
      long userID = longPar userID(_);
219  
      bool result = authed(_);
220  
      print("Auth-checking user ID: " + userID + " => " + result);
221  
      if (!result) ret "You are not authorized";
222  
      null;
223  
    }
224  
    
225  
    S checkPerGuildAuth(O... _) {  
226  
      long userID = longPar userID(_);
227  
      bool result = perGuildAuthed(_);
228  
      print("Guild-auth-checking user ID: " + userID + " => " + result);
229  
      if (!result) ret "You are not authorized";
230  
      null;
231  
    }
232  
    
233  
    S guildStructure() {
234  
      ret structure_nullingInstancesOfClass(_getClass(module()), this);
235  
    }
236  
  } // end of class ByServer
237  
  
238  
  S serveGuildBackup(MessageChannel channel, Guild guild, S data) {
239  
    if (guild == null) ret "Do this in a guild";
240  
    if (containsDiscordToken(data)) ret "DISCORD TOKEN EXPOSED ALARM!! NOTIFY ADMINISTRATOR";
241  
    S baseName = urlencode(jda_selfUserName(discord))
242  
      + "-" + guild.getIdLong() + "-" + ymd_minus_hms();
243  
    S zipName = baseName + ".zip";
244  
    File zip = programFile("backups/" + zipName);
245  
    createZipFileWithSingleTextFile(zip, baseName + ".txt", data);
246  
    channel.sendMessage("Here's my latest brain contents for this guild.").addFile(zip).queue();
247  
    null;
248  
  }
249  
  
250  
  // use structure() on ByServer
251  
  S serveGuildBackup(MessageChannel channel, Guild guild, ByServer bs) {
252  
    ret serveGuildBackup(channel, guild, bs.guildStructure());
253  
  }
254  
  
255  
  // e.g. for help texts
256  
  S atSelfOrMyName() {
257  
    ret preprocessAtSelfToMyName ? myName : atSelf();
258  
  }
259  
  
260  
  S atSelfOrMyName_space() {
261  
    ret preprocessAtSelfToMyName ? appendSpaceIfEndsWithLetter(myName) : atSelf();
262  
  }
263  
  
264  
  S renderMasters() {
265  
    ret empty(authorizedUsers) ? "I have no masters." : "My masters are: " + joinWithComma(map discordAtPlusID(authorizedUsers));
266  
  }
267  
}

Author comment

Began life as a copy of #1024519

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: #1025128
Snippet name: OLD DynTalkBot2 - DynServerAwareDiscordBot + input simplification, onUserJoin, name, authorizedUsers
Eternal ID of this version: #1025128/74
Text MD5: 0e737c53da4586304954912f58b22eb8
Author: stefan
Category: javax / agi.blue
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-01-23 23:47:35
Source code size: 8512 bytes / 267 lines
Pitched / IR pitched: No / No
Views / Downloads: 539 / 1328
Version history: 73 change(s)
Referenced in: [show references]