diff options
| author | Pratyush Desai | 2021-08-20 14:05:26 +0530 |
|---|---|---|
| committer | Pratyush Desai | 2021-08-20 14:05:26 +0530 |
| commit | ab75d45867ce62aa2ab71e2dc8077cabd0010e45 (patch) | |
| tree | 0b5231228279069d2941db01d868ec576559db8b | |
| parent | 076a74e6014c627b8e5728afa7bbf992ad06da90 (diff) | |
| download | egoserv-ab75d45867ce62aa2ab71e2dc8077cabd0010e45.tar.gz egoserv-ab75d45867ce62aa2ab71e2dc8077cabd0010e45.tar.bz2 egoserv-ab75d45867ce62aa2ab71e2dc8077cabd0010e45.zip | |
WIP quiet and bantripsit
| -rw-r--r-- | outline.rst | 22 | ||||
| -rw-r--r-- | plugin.py | 215 |
2 files changed, 187 insertions, 50 deletions
diff --git a/outline.rst b/outline.rst index 0506ec2..db4c8cb 100644 --- a/outline.rst +++ b/outline.rst @@ -7,27 +7,27 @@ The permissions are inherited in descending order. Tier 1 inherits Tier 2 ... |Commands |Description | Tier | Channel | Status | | | | | Restrictions| | +===========+=============+============+=============+==========+ -| DEFCON | | Admins/Ops | column 3 | DONE | +| DEFCON | | Admins/Ops | public | DONE | +-----------+-------------+------------+-------------+----------+ -| SAJOIN | | Admins/Ops | | DONE | +| SAJOIN | | Admins/Ops | public | DONE | +-----------+-------------+------------+-------------+----------+ -| SANICK | | Admins/Ops | column 3 | column 4 | +| SANICK | | Admins/Ops | column 3 | DONE | +-----------+-------------+------------+-------------+----------+ -| KILL | | Admins/Ops | | | +| KILL | | Admins/Ops | public | DONE | +-----------+-------------+------------+-------------+----------+ -| UBAN | | Moderators | column 3 | column 4 | +| UBAN | | Moderators | public | WIP | +-----------+-------------+------------+-------------+----------+ -| NBAN | | Moderators | | | +| NBAN | | Moderators | public | WIP | +-----------+-------------+------------+-------------+----------+ -| KBAN | | Moderators | column 3 | column 4 | +| KBAN | | Moderators | public | EXISTS | +-----------+-------------+------------+-------------+----------+ -| SUSTATUS | | Moderators | | | +| SUSTATUS | | Moderators | staff, pm | TBD | +-----------+-------------+------------+-------------+----------+ -| WARN | | Tripsitters| column 3 | column 4 | +| WARN | | Tripsitters| public | TBD | +-----------+-------------+------------+-------------+----------+ -| ADDNOTE | | Tripsitters| | | +| ADDNOTE | | Tripsitters| staff, pm | TBD | +-----------+-------------+------------+-------------+----------+ -| STATUS | | Tripsitters| column 3 | column 4 | +| STATUS | | Tripsitters| staff, pm | TBD | +-----------+-------------+------------+-------------+----------+ | QUIET | | Tripsitters| | | +-----------+-------------+------------+-------------+----------+ @@ -28,7 +28,12 @@ ### -from supybot import utils, plugins, ircutils, callbacks, irclib, ircmsgs, conf, world, log +# My Imports + + + +from supybot import utils, plugins, ircutils, callbacks, irclib, ircmsgs, +from supybot import conf, world, log, ircdb, registry, schedule from supybot.commands import * try: from supybot.i18n import PluginInternationalization @@ -44,6 +49,69 @@ except ImportError: # filename = conf.supybot.directories.data.dirize("EgoServ.db") +# Perms Decorator +def ensure_permissions(min_permission_group): + "Ensures user belongs to a least permission group" + def decorator(function): + def wrapper(*args,**kwargs): + print(args) + print(kwargs) + return function(*args, **kwargs) + return wrapper + return decorator + +# Taken from plugins.Time.seconds +def getTs(irc, msg, args, state): + """[<years>y] [<weeks>w] [<days>d] [<hours>h] [<minutes>m] [<seconds>s] + Returns the number of seconds in the number of <years>, <weeks>, + <days>, <hours>, <minutes>, and <seconds> given. An example usage is + "seconds 2h 30m", which would return 9000, which is '3600*2 + 30*60'. + Useful for scheduling events at a given number of seconds in the + future. + """ + # here there is some glitch / ugly hack to allow any('getTs'), with rest('test') after... + # TODO: check that bot can't kill itself with loop + seconds = -1 + items = list(args) + for arg in items: + if not (arg and arg[-1] in 'ywdhms'): + try: + n = int(arg) + state.args.append(n) + except: + state.args.append(float(seconds)) + raise callbacks.ArgumentError + (s, kind) = arg[:-1], arg[-1] + try: + i = int(s) + except ValueError: + state.args.append(float(seconds)) + raise callbacks.ArgumentError + if kind == 'y': + seconds += i*31536000 + elif kind == 'w': + seconds += i*604800 + elif kind == 'd': + seconds += i*86400 + elif kind == 'h': + seconds += i*3600 + elif kind == 'm': + seconds += i*60 + elif kind == 's': + if i == 0: + i = 1 + seconds += i + elif kind == '-': + state.args.append(float(seconds)) + raise callbacks.ArgumentError + args.pop(0) + state.args.append(float(seconds)) + + +addConverter('getTs', getTs) + + + class EgoServ(callbacks.Plugin): """Suite of tools to help Network Operators run their ErgoIRCd nets""" threaded = True @@ -100,6 +168,7 @@ class EgoServ(callbacks.Plugin): # KILL + @ensure_permissions(5) @wrap(['nick', optional('something')]) def kill(self, irc, msg, args, nick, reason): """<nick> [<reason>] @@ -162,48 +231,115 @@ class EgoServ(callbacks.Plugin): # Channel Administration ###### - # Only Talking to CS isn't enough because - # CS doesn't handle expiring bans mutes + def _ban(self, irc, msg, args, + channel, optlist, target, getTs, reason, kick): + # Check that they're not trying to make us kickban ourself. + if irc.isNick(target): + bannedNick = target + try: + bannedHostmask = irc.state.nickToHostmask(target) + banmaskstyle = conf.supybot.protocols.irc.banmask + banmask = banmaskstyle.makeBanmask(bannedHostmask, [o[0] for o in optlist]) + except KeyError: + ## WTF IS THIS + if not conf.supybot.protocols.irc.strictRfc() and \ + target.startswith('$'): + # Select the last part, or the whole target: + bannedNick = target.split(':')[-1] + banmask = bannedHostmask = target + else: + irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True) + else: + bannedNick = ircutils.nickFromHostmask(target) + banmask = bannedHostmask = target + if not irc.isNick(bannedNick): + self.log.warning('%q tried to kban a non nick: %q', + msg.prefix, bannedNick) + raise callbacks.ArgumentError + elif bannedNick == irc.nick: + self.log.warning('%q tried to make me kban myself.', msg.prefix) + irc.error(_('I cowardly refuse to kickban myself.')) + return + if not reason: + reason = msg.nick + + capability = ircdb.makeChannelCapability(channel, 'op') + # Check (again) that they're not trying to make us kickban ourself. + if ircutils.hostmaskPatternEqual(banmask, irc.prefix): + if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix): + self.log.warning('%q tried to make me kban myself.',msg.prefix) + irc.error(_('I cowardly refuse to ban myself.')) + return + else: + self.log.warning('Using exact hostmask since banmask would ' + 'ban myself.') + banmask = bannedHostmask + # Now, let's actually get to it. Check to make sure they have + # #channel,op and the bannee doesn't have #channel,op; or that the + # bannee and the banner are both the same person. + def doBan(): + if irc.state.channels[channel].isOp(bannedNick): + irc.queueMsg(ircmsgs.deop(channel, bannedNick)) + irc.queueMsg(ircmsgs.ban(channel, banmask)) + if kick: + irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason)) + if getTs > 0: + def f(): + if channel in irc.state.channels and \ + banmask in irc.state.channels[channel].bans: + irc.queueMsg(ircmsgs.unban(channel, banmask)) + schedule.addEvent(f, ) + if bannedNick == msg.nick: + doBan() + elif ircdb.checkCapability(msg.prefix, capability): + if ircdb.checkCapability(bannedHostmask, capability) and \ + not ircdb.checkCapability(msg.prefix, 'owner'): + self.log.warning('%s tried to ban %q, but both have %s', + msg.prefix, bannedHostmask, capability) + irc.error(format(_('%s has %s too, you can\'t ban ' + 'them.'), bannedNick, capability)) + else: + doBan() + else: + self.log.warning('%q attempted kban without %s', + msg.prefix, capability) + irc.errorNoCapability(capability) + + def nban(self, irc, msg, args, + bannedNick, getTs, reason): + """ <nick> [<seconds>] [<reason>] + If you have the #channel,op capability, this will kickban <nick>'s banmask from + for + the time period specified. Not specifying the time period it will ban the user + indefinitely. <reason> is optional but recommended. + """ + self._ban(irc, msg, args, bannedNick, reason, True) + nban = wrap(nban, + ['haveOp', + + ('haveHalfop+', _('kick or ban someone')), + 'nickInChannel', + optional('', 0), + additional('text')]) - # Use mute Extban - # @wrap(['nick', 'channel', optional('expiry', 0), 'something']) - # def mute(self, irc, msg, args, nick, channel, duration, reason): - # @wrap(['nick', 'channel']) - # def mute(self, irc, msg, args, nick, channel): - # """<nick> [<channel>] - - # Issues an extban which mutes the hostmask associated with the - # <nick> - # """ - # # add --all flag for muting the hostmask/account in all channels - # # on the current network - - # # Seconds needs to be human readable i.e. 5w 3d 2h - - # # Do we care about adding quiets/mutes for accounts not online - # # via --host specification or even an --account - # # Fuck 'duration' and 'reason' for now - - # # What I'm doing is very filthy - # # Refer to how the core channel plugin deals with this. - # # https://github.com/ProgVal/Limnoria/blob/master/plugins/Channel/plugin.py#L358 - - # try: - # (nick, ident, host) = ircutils.splitHostmask(irc.state.nickToHostmask(nick)) - # except KeyError: - # irc.error( - # "No such nick", - # Raise=True, - # ) - # if nick == irc.nick: - # self.log.warning(f'{msg.prefix} tried to make me mute myself.', ) - # irc.error(_('No, I would like to preserve my right to speech!')) - # return - - # irc.queueMsg() + @wrap(['nick', 'channel', optional('getTs'), 'something']) + def quiet(self, irc, msg, args, nick, channel, duration, reason="Fuck Knows!"): + """<nick> [<channel>] [<seconds>] [<reason>] + + Quiets the banmask associated with <nick> for the time period specified + <seconds>. If not specified, it will quiet the user indefinitely. + <reason> is optional but recommended! <channel> is only necessary if + the command is not sent in the channel itself. + """ + try: + (nick, ident, host) = \ + ircutils.splitHostmask(irc.state.nickToHostmask(nick)) + except KeyError: + irc.error(format("No such nick"), Raise=True) + @wrap(['channel', 'something', many('nick')]) def amode(self, irc, msg, args, channel, mode, nicks): @@ -245,6 +381,7 @@ class EgoServ(callbacks.Plugin): @wrap([many('channel')]) def chanreg(self, irc, msg, args, channels): """[<channel>].. [<channel>..] + Registered the given channel/s by the bot """ |
