# -*- Encoding: utf-8 -*- ### # Copyright (c) 2008-2010 Terence Simpson # Copyright (c) 2017- Krytarik Raido # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ### from supybot.commands import * import supybot.utils as utils import supybot.ircutils as ircutils import supybot.ircmsgs as ircmsgs import supybot.ircdb as ircdb import supybot.callbacks as callbacks import supybot.conf as conf import re, time from . import packages _stripNickChars = """!"#$%&'()*+,./:;<=>?@~""" def stripNick(nick): while nick and nick[-1] in _stripNickChars: nick = nick[:-1] return nick def defaultIgnored(hostmask): if not conf.supybot.defaultIgnore(): return False try: user = ircdb.users.getUser(hostmask) except KeyError: return True return False def checkIgnored(hostmask, channel): try: user = ircdb.users.getUser(hostmask) try: if user._checkCapability('trusted'): return False except KeyError: pass if user.ignore: return True except KeyError: pass if ircdb.ignores.checkIgnored(hostmask): return True if channel: c = ircdb.channels.getChannel(channel) if c.checkIgnored(hostmask): return True return False ## Taken from Encyclopedia ## # Repeat filtering message queue msgcache = {} def queue(irc, target, msg): now = time.time() for m in list(msgcache.keys()): if msgcache[m] < now - 30: msgcache.pop(m) for m in msgcache: if m[0] == irc and m[1] == target: oldmsg = m[2] if oldmsg.endswith(msg): break if msg.endswith(oldmsg) and msg[:-len(oldmsg)].endswith(': '): msg = msg[:-len(oldmsg)] + 'Please see above' else: msgcache[(irc, target, msg)] = now irc.reply(msg, to=target, private=True) class PackageInfo(callbacks.Plugin): """Look up package information via apt-cache/apt-file""" threaded = True def __init__(self, irc): self.__parent = super(PackageInfo, self) self.__parent.__init__(irc) self.Apt = packages.Apt(self) def __getRelease(self, irc, release, channel, doError=True): if release: release = release.strip() defaultRelease = self.registryValue("defaultRelease", channel, irc.network) if not defaultRelease: if doError: irc.error("'supybot.plugins.PackageInfo.defaultRelease' is not set") return (None, None) if not release: return (defaultRelease, None) (release, rest) = (release.split(None, 1) + [None])[:2] if release[0] in '|>': return (defaultRelease, "%s %s" % (release, rest)) return (release, rest) def __getPackage(self, package): if package.startswith('src:'): package = package[4:] return (package, True) return (package, False) def __handleRest(self, irc, msg, target, reply, rest): targeto = target prefix = '' if rest[0] == '|': rest = rest.lstrip('|').strip() if rest: if rest.lower() == "me": rest = msg.nick prefix = "%s: " % rest elif rest[0] == '>': rest = rest.lstrip('>').strip() if rest: # Take the first "nick" and strip off bad chars target = stripNick(rest.split()[0]) if target.lower() == "me": target = msg.nick prefix = "<%s> wants you to know: " % msg.nick if target.lower() != targeto.lower() and irc.isChannel(target): target = targeto prefix = "(Forwarding to channels is not permitted) " elif msg.nick.lower() in (target.lower(), prefix[:-2].lower()) \ and msg.nick.lower() != targeto.lower(): target = msg.nick prefix = "(In the future, please use a private message to investigate) " return (target, prefix + reply) def info(self, irc, msg, args, package, release=None): """<[src:]package> [] Look up information for , optionally in """ channel = msg.channel if not self.registryValue("enabled", channel, irc.network): return (release, rest) = self.__getRelease(irc, release, channel) if not release: return if release not in self.Apt.distros: irc.reply("%r is not a valid release" % release) if self.registryValue("listReleasesOnError", channel, irc.network): irc.reply("Valid releases are: %s" % ', '.join(self.Apt.distros), private=True) return (package, isSource) = self.__getPackage(package) target = ircutils.replyTo(msg) reply = self.Apt.info(package, release, isSource) if rest: (target, reply) = self.__handleRest(irc, msg, target, reply, rest) queue(irc, target, reply) info = wrap(info, ['anything', optional('text')]) def depends(self, irc, msg, args, package, release=None): """<[src:]package> [] Look up dependencies for , optionally in """ channel = msg.channel if not self.registryValue("enabled", channel, irc.network): return (release, rest) = self.__getRelease(irc, release, channel) if not release: return if release not in self.Apt.distros: irc.reply("%r is not a valid release" % release) if self.registryValue("listReleasesOnError", channel, irc.network): irc.reply("Valid releases are: %s" % ', '.join(self.Apt.distros), private=True) return (package, isSource) = self.__getPackage(package) target = ircutils.replyTo(msg) reply = self.Apt.depends(package, release, isSource) if rest: (target, reply) = self.__handleRest(irc, msg, target, reply, rest) queue(irc, target, reply) depends = wrap(depends, ['anything', optional('text')]) def find(self, irc, msg, args, package, release=None): """ [] Search for or, if that fails, in packages, optionally in """ channel = msg.channel if not self.registryValue("enabled", channel, irc.network): return (release, rest) = self.__getRelease(irc, release, channel) if not release: return if release not in self.Apt.distros: irc.reply("%r is not a valid release" % release) if self.registryValue("listReleasesOnError", channel, irc.network): irc.reply("Valid releases are: %s" % ', '.join(self.Apt.distros), private=True) return target = ircutils.replyTo(msg) reply = self.Apt.find(package, release) if rest: (target, reply) = self.__handleRest(irc, msg, target, reply, rest) queue(irc, target, reply) find = wrap(find, ['anything', optional('text')]) def releases(self, irc, msg, args): """takes no arguments List all valid releases. """ irc.reply("Valid releases are: %s" % ', '.join(self.Apt.distros)) releases = wrap(releases) def doPrivmsg(self, irc, msg): if chr(1) in msg.args[1]: # CTCP return text = msg.args[1].strip() if not text: return channel = msg.channel if text[0] == self.registryValue("prefixchar", channel, irc.network): text = text[1:].strip() elif channel or text[0] in conf.supybot.reply.whenAddressedBy.chars(): return if not text: return (cmd, rest) = (text.split(None, 1) + [None])[:2] if not cmd: return cmd = cmd.lower() if not (cmd in ("info", "depends", "find") and rest): return (package, release) = (rest.split(None, 1) + [''])[:2] callbacks.NestedCommandsIrcProxy(irc, msg, [cmd, package, release]) def inFilter(self, irc, msg): if not (msg.prefix and msg.args): return msg if not ircutils.isUserHostmask(msg.prefix): return msg if not defaultIgnored(msg.prefix): return msg if checkIgnored(msg.prefix, msg.channel): return msg if msg.command == "PRIVMSG": self.doPrivmsg(irc, msg) return msg Class = PackageInfo