summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--outline.rst22
-rw-r--r--plugin.py215
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| | |
+-----------+-------------+------------+-------------+----------+
diff --git a/plugin.py b/plugin.py
index a40a029..ea537df 100644
--- a/plugin.py
+++ b/plugin.py
@@ -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
"""