]> jfr.im git - erebus.git/commitdiff
admin_user module to set users' glevel
authorJohn Runyon <redacted>
Mon, 4 Sep 2023 02:23:29 +0000 (20:23 -0600)
committerJohn Runyon <redacted>
Mon, 4 Sep 2023 02:23:43 +0000 (20:23 -0600)
TODO
erebus.py
modlib.py
modules/admin_user.py [new file with mode: 0644]

diff --git a/TODO b/TODO
index 3fc9933051f7322ea2f3d45a1422b8d51de32d76..a915322f3e92d6eda3db77c529b922dff262b952 100644 (file)
--- a/TODO
+++ b/TODO
@@ -29,3 +29,5 @@ vim: expandtab sw=2 ts=2
 - better config... or better yet just move non-DB-related config into the database
   - needs a better format if its used for generic module data; particularly because /\s#/ starts a comment instead of naming a channel
   - needs to retain comments when config file is saved
+
+- a module for administering channel users (copy from admin_user) and adding/removing channels
index 0377d92ded68ae4014a3546e917048ec4303bb2d..42a2f416cefef07c20fdcfc3935431a63934ec9a 100644 (file)
--- a/erebus.py
+++ b/erebus.py
@@ -24,7 +24,10 @@ class Erebus(object): #singleton to pass around
        class User(object):
                def __init__(self, nick, auth=None):
                        self.nick = nick
-                       self.auth = auth
+                       if auth is None:
+                               self.auth = None
+                       else:
+                               self.auth = auth.lower()
                        self.checklevel()
 
                        self.chans = []
@@ -59,6 +62,23 @@ class Erebus(object): #singleton to pass around
                                        self.glevel = 0
                        return self.glevel
 
+               def setlevel(self, level, savetodb=True):
+                       if savetodb:
+                               if level != 0:
+                                       c = main.query("REPLACE INTO users (auth, level) VALUES (%s, %s)", (self.auth, level))
+                               else:
+                                       c = main.query("DELETE FROM users WHERE auth = %s", (self.auth,))
+                                       if c == 0: # no rows affected
+                                               c = True # is fine
+                               if c:
+                                       self.glevel = level
+                                       return True
+                               else:
+                                       return False
+                       else:
+                               self.glevel = level
+                               return True
+
                def join(self, chan):
                        if chan not in self.chans: self.chans.append(chan)
                def part(self, chan):
@@ -117,6 +137,9 @@ class Erebus(object): #singleton to pass around
                                        return True
                                else:
                                        return False
+                       else:
+                               self.levels[auth] = level
+                               return True
 
                def userjoin(self, user, level=None):
                        if user not in self.users: self.users.append(user)
index ee94e9ee38679a7dd928a89a9b69c1c40677645c..ae19fb5e0f77e3311000886b22073db3f91e1d2c 100644 (file)
--- a/modlib.py
+++ b/modlib.py
@@ -29,16 +29,27 @@ class modlib(object):
        MANAGER =  99
        ADMIN   =  75
        STAFF   =  50
+       KNOWN   =   1
        AUTHED  =   0 # Users which have are known to be authed
        ANYONE  =  -1 # non-authed users have glevel set to -1
        IGNORED =  -2 # The default reqglevel is ANYONE, so any commands will be ignored from IGNORED users unless the command reglevel=-2
+       glevs   = {
+               'OWNER': OWNER,
+               'MANAGER': MANAGER,
+               'ADMIN': ADMIN,
+               'STAFF': STAFF,
+               'KNOWN': KNOWN,
+               'AUTHED': AUTHED,
+               'ANYONE': ANYONE,
+               'IGNORED': IGNORED,
+       }
 
        # (channel) access levels
        COWNER  =   5
        MASTER  =   4
        OP      =   3
        VOICE   =   2
-       KNOWN   =   1
+       #KNOWN  =   1 is set above by glevels
        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]
diff --git a/modules/admin_user.py b/modules/admin_user.py
new file mode 100644 (file)
index 0000000..cc069a6
--- /dev/null
@@ -0,0 +1,80 @@
+# 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
+
+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):
+       try:
+               i = int(s)
+               return i
+       except ValueError:
+               su = s.upper()
+               if su == "ANYONE":
+                       su = "AUTHED" # resolve to 0 instead of -1
+               if su in lib.glevs:
+                       return lib.glevs[su]
+       return None
+
+@lib.hook(('glevel','glev','adduser','setuser'), needchan=False, glevel=1)
+@lib.help('<nick|#auth> <level>', "adds or sets a user's global level", "global level is any positive integer, 0 to delete a user, or -2 to ignore a user", "-2: ignored; 0: no special access (anyone); 1: known; 50: staff; 75: admin; 100: owner", "alternately you may use one of those keywords", "non-admins may only change their own level, and only to 0", "admins may only set lower access levels and may not set the access level of a user with higher access")
+@lib.argsEQ(2)
+def glevel(bot, user, chan, realtarget, *args):
+       target_s = args[0]
+       level_s = args[1]
+       target = _resolve_user(target_s)
+       level = _resolve_level(level_s)
+
+       if target is None:
+               user.msg('User not found (try #auth)')
+               return
+       if target.auth is None:
+               user.msg('User is not authed')
+               return
+       if level is None:
+               user.msg("Level is unknown, must be an integer or one of %s" % (', '.join(lib.glevs.keys())))
+               return
+       if level != -2 and level < 0:
+               user.msg("Level must -2, 0, or a positive integer")
+               return
+
+
+       if not (target == user and level == 0) and user.glevel != lib.OWNER:
+               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
+               if user.glevel <= level:
+                       user.msg("I'm afraid I can't let you do that. Your current access level is not higher than you are trying to set.")
+                       return
+
+       if target.setlevel(level):
+               user.msg("The glevel of #%s has been updated successfully" % (target.auth))
+       else:
+               user.msg("Failed to update the level")