]> jfr.im git - erebus.git/commitdiff
add admin_channel
authorJohn Runyon <redacted>
Sun, 12 Nov 2023 12:57:26 +0000 (05:57 -0700)
committerJohn Runyon <redacted>
Sun, 12 Nov 2023 12:57:26 +0000 (05:57 -0700)
TODO
bot.py
erebus.py
modlib.py
modules/admin_channel.py [new file with mode: 0644]
modules/admin_user.py

diff --git a/TODO b/TODO
index 31fcacf7184d99e3a60c703fb2193dc05cac576c..9df83229d4f315165ea2d38ac786176ce5587f8c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -54,3 +54,7 @@ vim: expandtab sw=2 ts=2
 - fix softdeps, if they're used through lib.mod() or parent.module() they break, need a `'mod' in modules` check somewhere
 
 - ctlmod.unload: track what modules are unloaded and return that info to caller
+
+- lookup User object by auth
+  modules should be able to (attempt to) look up a User object by auth, that way if the user is online
+  !clevel and !glevel can look up their existing object and adjust the permissions there
diff --git a/bot.py b/bot.py
index 51b7a0a33414decb30f7dcf8ceb9a23da4ee42d8..813151b68650a837cb63c14ecd606273ac59d821 100644 (file)
--- a/bot.py
+++ b/bot.py
@@ -239,15 +239,20 @@ class Bot(object):
                if nick == self.nick:
                        self.conn.send("WHO %s c%%cant,3" % (chan))
                else:
-                       user = self.parent.user(nick, justjoined=True)
+                       user = self.parent.user(nick, send_who=True)
                        chan.userjoin(user)
                        user.join(chan)
        def _clientLeft(self, nick, chan):
-               if nick != self.nick:
-                       gone = self.parent.user(nick).part(chan)
-                       chan.userpart(self.parent.user(nick))
+               if nick == self.nick:
+                       for u in chan.users:
+                               if u.nick != self.nick:
+                                       self._clientLeft(u.nick, chan)
+               else:
+                       user = self.parent.user(nick)
+                       gone = user.part(chan)
+                       chan.userpart(user)
                        if gone:
-                               self.parent.user(nick).quit()
+                               user.quit()
                                del self.parent.users[nick.lower()]
        def _gotpart(self, pieces):
                nick = pieces[0].split('!')[0][1:]
index 47f9a59d6a4633263166f82eb4664ead4e625f10..c161a42c3b612b655d4749f695096f4afd365f2d 100644 (file)
--- a/erebus.py
+++ b/erebus.py
@@ -228,17 +228,17 @@ class Erebus(object): #singleton to pass around
        def randbot(self): #get Bot() randomly
                return self.bots[random.choice(list(self.bots.keys()))]
 
-       def user(self, _nick, justjoined=False, create=True):
+       def user(self, _nick, send_who=False, create=True):
                nick = _nick.lower()
+
+               if send_who and (nick not in self.users or not self.users[nick].isauthed()):
+                       self.randbot().conn.send("WHO %s n%%ant,1" % (nick))
+
                if nick in self.users:
                        return self.users[nick]
                elif create:
                        user = self.User(_nick)
                        self.users[nick] = user
-
-                       if justjoined:
-                               self.randbot().conn.send("WHO %s n%%ant,1" % (nick))
-
                        return user
                else:
                        return None
index a04dd7878e22898f222cb06318ddcf6569b7e502..eeb7c4ea2acd353d9e6f94abdfe7e1c9baabedfa 100644 (file)
--- a/modlib.py
+++ b/modlib.py
@@ -50,11 +50,11 @@ class modlib(object):
        MASTER  =   4
        OP      =   3
        VOICE   =   2
-       #KNOWN  =   1 is set above by glevels
+       FRIEND  =   1
        PUBLIC  =   0 # Anyone (use glevel to control whether auth is needed)
        BANNED  =  -1 # The default reqclevel is PUBLIC, so any commands which needchan will be ignored from BANNED users unless the command reqclevel=-1
        #         [   0         1        2     3         4        5    -1]
-       clevs   = [None, 'Friend', 'Voice', 'Op', 'Master', 'Owner', None]
+       clevs   = [None, 'Friend', 'Voice', 'Op', 'Master', 'Owner', 'Banned']
 
        # messages
        WRONGARGS = "Wrong number of arguments."
diff --git a/modules/admin_channel.py b/modules/admin_channel.py
new file mode 100644 (file)
index 0000000..0f9f7fe
--- /dev/null
@@ -0,0 +1,89 @@
+# Erebus IRC bot - Author: Erebus Team
+# vim: fileencoding=utf-8
+# simple module example
+# This file is released into the public domain; see http://unlicense.org/
+
+# module info
+modinfo = {
+       'author': 'Erebus Team',
+       'license': 'public domain',
+       'compatible': [0], # compatible module API versions
+       'depends': [], # other modules required to work properly?
+       'softdeps': ['help'], # modules which are preferred but not required
+}
+# note: softdeps will be loaded before this module, IF not disabled in the configuration (autoload.module = 0) (and if it exists)
+# however, if it is disabled it will be silently ignored, and if it is unloaded at runtime it won't cause this one to unload.
+#
+# basically, softdeps are things this module will use if available, but does not require (no errors will occur if it's not loaded)
+# for example, @lib.help() will attempt to use the help module, but swallow errors if it is not loaded
+
+# preamble
+import modlib
+lib = modlib.modlib(__name__)
+modstart = lib.modstart
+modstop = lib.modstop
+
+# module code
+
+@lib.hook(clevel=lib.FRIEND)
+@lib.help(None, "rejoin a channel (if the bot has been kicked)")
+def rejoin(bot, user, chan, realtarget, *args):
+       bot.join(str(chan))
+       bot.msg(user, "Rejoined.")
+
+
+def _resolve_user(s):
+       if s.startswith("#"):
+               return lib.parent.User(s, s[1:])
+       else:
+               return lib.parent.user(s, create=False)
+
+
+def _resolve_level(s):
+       s = s.lower()
+       levels = ['unknown'] + [x.lower() for x in lib.clevs if x is not None]
+       if s in levels:
+               return levels.index(s)
+       try:
+               return int(s)
+       except:
+               pass
+
+
+@lib.hook(('clevel','setlevel','chanlev'), clevel=lib.FRIEND)
+@lib.help('<nick|#auth> <level>', "adds or sets a user's channel access level", "Levels: Unknown, " + ', '.join([x for x in lib.clevs if x]))
+@lib.argsEQ(2)
+def clevel(bot, user, chan, realtarget, *args):
+       target = _resolve_user(args[0])
+       level = _resolve_level(args[1])
+       user_clevel = chan.levelof(user.auth)
+
+       if target is None:
+               return "User not found (try #auth)"
+       if target.auth is None:
+               return "User is not authed"
+       if level is None or level < 0 or level > lib.COWNER:
+               return "Level is unknown"
+
+       target_clevel = chan.levelof(target.auth)
+
+       if not (target == user and level == 0) and user_clevel != lib.COWNER:
+               if user_clevel < lib.MASTER:
+                       return "I'm afraid I can't let you do that. You can only reset your own level to 0."
+               if user_clevel <= target_clevel:
+                       return "I'm afraid I can't let you do that. Your current access level is not higher than theirs."
+               if user_clevel <= level:
+                       return "I'm afraid I can't let you do that. Your current access level is not higher than you are trying to set."
+
+       chan.setlevel(target.auth, level)
+       return "Set #%s channel level to %s" % (target.auth, args[1])
+
+
+@lib.hook(glevel=lib.OWNER)
+@lib.help('<level>', "sets your own clevel on a channel")
+@lib.argsEQ(1)
+def forceclevel(bot, user, chan, realtarget, *args):
+       target = user.auth
+       level = _resolve_level(args[0])
+       chan.setlevel(target, level)
+       return 'Your level on %s has been set to %d' % (chan, level)
index cc069a6dd4a7fef6ef3655c6dd0d77717f75336a..3e4a02c3c0b2601d304f5239c40cbd208415f0f2 100644 (file)
@@ -65,8 +65,11 @@ def glevel(bot, user, chan, realtarget, *args):
                user.msg("Level must -2, 0, or a positive integer")
                return
 
-
+       # Skip checks if the user is setting their own level to 0, or if the user is OWNER
        if not (target == user and level == 0) and user.glevel != lib.OWNER:
+               if user.glevel <= lib.ADMIN:
+                       user.msg("I'm afraid I can't let you do that. You can only reset your own level to 0.")
+                       return
                if user.glevel <= target.glevel:
                        user.msg("I'm afraid I can't let you do that. Your current access level is not higher than theirs.")
                        return