WIP quiet and ban

This commit is contained in:
Pratyush Desai 2021-08-20 14:05:26 +05:30
parent 076a74e601
commit ab75d45867
Signed by: pratyush
GPG Key ID: DBA5BB7505946FAD
2 changed files with 186 additions and 49 deletions

View File

@ -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| | |
+-----------+-------------+------------+-------------+----------+

213
plugin.py
View File

@ -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
# 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>]
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
# 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
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)
# # Seconds needs to be human readable i.e. 5w 3d 2h
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')])
# # 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
"""