def testNickFromHostmask(self): self.assertEqual( ircutils.nickFromHostmask('[email protected]'), 'nick') # Hostmasks with user prefixes are sent via userhost-in-names. We need to # properly handle the case where ! is a prefix and not grab '' as the nick # instead. self.assertEqual( ircutils.nickFromHostmask('@[email protected]'), '@nick') self.assertEqual( ircutils.nickFromHostmask('!@[email protected]'), '!@nick')
def testNickFromHostmask(self): self.assertEqual(ircutils.nickFromHostmask('[email protected]'), 'nick') # Hostmasks with user prefixes are sent via userhost-in-names. We need to # properly handle the case where ! is a prefix and not grab '' as the nick # instead. self.assertEqual(ircutils.nickFromHostmask('@[email protected]'), '@nick') self.assertEqual(ircutils.nickFromHostmask('!@[email protected]'), '!@nick')
def quiet(self, irc, msg, args, channel, nick, expiry): """[<channel>] <nick> [<expiry>] Quietens <nick> from <channel> for <expiry>. If <expiry> isn't given, the duration is permanent. <channel> is only necessary if the message isn't sent in the channel itself. """ if irc.isNick(nick): bannedNick = nick try: bannedHostmask = irc.state.nickToHostmask(nick) except KeyError: irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True) else: bannedNick = ircutils.nickFromHostmask(nick) bannedHostmask = nick if not irc.isNick(bannedNick): self.log.warning('%q tried to quiet a non nick: %q', msg.prefix, bannedNick) raise callbacks.ArgumentError banmaskstyle = conf.supybot.protocols.irc.banmask banmask = banmaskstyle.makeBanmask(bannedHostmask) if ircutils.strEqual(nick, irc.nick): irc.error('I cowardly refuse to quiet myself.', Raise=True) thismsg=self.registryValue('message') self._sendMsg(irc, ircmsgs.mode(channel, ("+q", banmask))) if self.registryValue('SendMsgPvt'): self._sendMsg(irc, ircmsgs.privmsg(nick,nick+", "+thismsg )) else: self._sendMsg(irc, ircmsgs.privmsg(channel,nick+", "+thismsg )) def f(): irc.queueMsg(ircmsgs.mode(channel, ("-q", banmask))) if expiry: schedule.addEvent(f, expiry)
def requestComment(self, irc, channel, ban): if not ban or not self.registryValue('request', channel): return # check the type of the action taken mask = ban.mask type = guessBanType(mask) if type == 'quiet': mask = mask[1:] # check if type is enabled if type not in self.registryValue('request.type', channel): return prefix = conf.supybot.reply.whenAddressedBy.chars()[0] # prefix char for commands # check to who send the request try: nick = ircutils.nickFromHostmask(ban.who) except: nick = ban.who if nickMatch(nick, self.registryValue('request.ignore', channel)): return if nickMatch(nick, self.registryValue('request.forward', channel)): s = "Please somebody comment on the %s of %s in %s done by %s, use:"\ " %scomment %s <comment>" %(type, mask, channel, nick, prefix, ban.id) self._sendForward(irc, s, channel) else: # send to op s = "Please comment on the %s of %s in %s, use: %scomment %s <comment>" \ %(type, mask, channel, prefix, ban.id) irc.reply(s, to=nick, private=True)
def rsync(self, irc, msg, args): self._updateMonitorList(irc) count = 0 result = self._radioQuery('areirc') for hostmask in result['hostmasks']: hostmask = hostmask.encode('ascii') if ircutils.nickFromHostmask(hostmask) not in self.monitorList: self._radioQuery('authpart', { 'hostmask' : hostmask }) count += 1 else: hostmaskIRC = irc.state.nickToHostmask(ircutils.nickFromHostmask(hostmask)) if (hostmask.split('!')[1] != hostmaskIRC.split('!')[1]): self._radioQuery('authpart', { 'hostmask' : hostmask }) count += 1 reply = u"%i Benutzer entfernt" % count irc.reply(reply.encode('utf-8'))
def doAccount (self,irc,msg): if ircutils.isUserHostmask(msg.prefix): nick = ircutils.nickFromHostmask(msg.prefix) for channel in irc.state.channels: chan = self.getChan(irc,channel) if nick in chan.nicks: a = chan.nicks[nick] account = msg.args[0] if account == '*': account = '' a[1] = account chan.nicks[nick] = a
def _feedMsg(self, query, timeout=None, to=None, frm=None, private=False, usePrefixChar=True): if to is None: if private: to = self.irc.nick else: to = self.channel if frm is None: frm = self.prefix if timeout is None: timeout = self.timeout if self.myVerbose: print # Newline, just like PluginTestCase. prefixChars = conf.supybot.reply.whenAddressedBy.chars() if query[0] not in prefixChars and usePrefixChar: query = prefixChars[0] + query msg = ircmsgs.privmsg(to, query, prefix=frm) if self.myVerbose: print 'Feeding: %r' % msg self.irc.feedMsg(msg) fed = time.time() response = self.irc.takeMsg() while response is None and time.time() - fed < timeout: time.sleep(0.1) drivers.run() response = self.irc.takeMsg() if response is not None: if response.command == 'PRIVMSG': args = list(response.args) # Strip off nick: at beginning of response. if args[1].startswith(self.nick) or \ args[1].startswith(ircutils.nickFromHostmask(self.prefix)): try: args[1] = args[1].split(' ', 1)[1] except IndexError: # Odd. We'll skip this. pass ret = ircmsgs.privmsg(*args) else: ret = response else: ret = None if self.myVerbose: print 'Returning: %r' % ret return ret
def testAddFactoid(self): self.assertNotError('moo is foo') # Check stripping punctuation self.assertError('moo!? is foo') # 'moo' already exists self.assertNotError('foo!? is foo') self.assertResponse('foo', 'foo is foo') self.assertNotError('bar is <reply>moo is moo') self.assertResponse('bar', 'moo is moo') # Check substitution self.assertNotError('who is <reply>$who') self.assertResponse('who', ircutils.nickFromHostmask(self.prefix)) # Check that actions ("\x01ACTION...") don't match m = ircmsgs.action(self.channel, 'is doing something') self.irc.feedMsg(m) self.assertNoResponse(' ', 1)
def _feedMsg(self, query, timeout=None, to=None, frm=None, private=False, usePrefixChar=True): if to is None: if private: to = self.irc.nick else: to = self.channel if frm is None: frm = self.prefix if timeout is None: timeout = self.timeout if self.myVerbose: print # Newline, just like PluginTestCase. prefixChars = conf.supybot.reply.whenAddressedBy.chars() if query[0] not in prefixChars and usePrefixChar: query = prefixChars[0] + query if sys.version_info[0] < 3 and isinstance(query, unicode): query = query.encode('utf8') # unicode->str msg = ircmsgs.privmsg(to, query, prefix=frm) if self.myVerbose: print 'Feeding: %r' % msg self.irc.feedMsg(msg) fed = time.time() response = self.irc.takeMsg() while response is None and time.time() - fed < timeout: time.sleep(0.1) drivers.run() response = self.irc.takeMsg() if response is not None: if response.command == 'PRIVMSG': args = list(response.args) # Strip off nick: at beginning of response. if args[1].startswith(self.nick) or \ args[1].startswith(ircutils.nickFromHostmask(self.prefix)): try: args[1] = args[1].split(' ', 1)[1] except IndexError: # Odd. We'll skip this. pass ret = ircmsgs.privmsg(*args) else: ret = response else: ret = None if self.myVerbose: print 'Returning: %r' % ret return ret
def doTagmsg(self, irc, msg): if REQUEST_TAG not in msg.server_tags: return if "msgid" not in msg.server_tags: return if not self._enabled(irc, msg): return msgid = msg.server_tags["msgid"] text = msg.server_tags[REQUEST_TAG] # using callbacks._addressed instead of callbacks.addressed, as # callbacks.addressed would tag the m payload = callbacks._addressed(irc, msg, payload=text) if not payload: # not addressed return # marks used by '_addressed' are usually prefixes (char, string, # nick), but may also be suffixes (with # supybot.reply.whenAddressedBy.nick.atEnd); but there is no way to # have it in the middle of the message AFAIK. assert payload in text if not text.endswith(payload): # If there is a suffix, it means the end of the text is used to # address the bot, so it can't be a method to be completed. return autocomplete_response = _getAutocompleteResponse(irc, msg, payload) if not autocomplete_response: return target = msg.channel or ircutils.nickFromHostmask(msg.prefix) irc.queueMsg( ircmsgs.IrcMsg( server_tags={ "+draft/reply": msgid, RESPONSE_TAG: autocomplete_response, }, command="TAGMSG", args=[target], ) )
def undo(self, irc, msg, args, nick): """<nick> Removes the latest note you sent to <nick>. """ if nick not in self._notes: irc.error(_('There are no note waiting for %s.') % nick) return self._notes[nick].reverse() for note in self._notes[nick]: if ircutils.nickFromHostmask(note[1]) == msg.nick: self._notes[nick].remove(note) if len(self._notes[nick]) == 0: del self._notes[nick] self._flushNotes() irc.replySuccess() return irc.error(_('There are no note from you waiting for %s.') % nick)
def ungrab(self, irc, msg, args, channel, grab): """[<channel>] <number> Removes the grab <number> (the last by default) on <channel>. <channel> is only necessary if the message isn't sent in the channel itself. You may only ungrab quotes you made or grabbed. """ try: original = self.db.get(channel, grab) if ircutils.nickEqual(ircutils.nickFromHostmask(original.grabber), msg.nick) or ircutils.nickEqual(original.by, msg.nick): self.db.remove(channel, grab) irc.replySuccess() else: irc.error('Can only ungrab quotes made or grabbed by you.') except dbi.NoRecordError: if grab is None: irc.error('Nothing to ungrab.') else: irc.error('Invalid grab number.')
def _doKickban(self, irc, channel, operator, target, kickmsg = None, use_time = None, extra_comment = None): if not self.registryValue('enabled', channel): return n = now() if use_time: n = fromTime(use_time) try: nick = ircutils.nickFromHostmask(operator) except: nick = operator id = self.db_run("INSERT INTO bans (channel, mask, operator, time, log) values(%s, %s, %s, %s, %s)", (channel, target, nick, n, '\n'.join(self.logs[channel])), expect_id=True) if kickmsg and id and not (kickmsg == nick): self.db_run("INSERT INTO comments (ban_id, who, comment, time) values(%s,%s,%s,%s)", (id, nick, kickmsg, n)) if extra_comment: self.db_run("INSERT INTO comments (ban_id, who, comment, time) values(%s,%s,%s,%s)", (id, nick, extra_comment, n)) if channel not in self.bans: self.bans[channel] = [] ban = Ban(mask=target, who=operator, when=time.mktime(time.gmtime()), id=id) self.bans[channel].append(ban) return ban
def unquiet(self, irc, msg, args, channel, nick): """[<channel>] <nick> [<expiry>] Quietens <nick> from <channel> for <expiry>. If <expiry> isn't given, the duration is permanent. <channel> is only necessary if the message isn't sent in the channel itself. """ if irc.isNick(nick): bannedNick = nick try: bannedHostmask = irc.state.nickToHostmask(nick) except KeyError: irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True) else: bannedNick = ircutils.nickFromHostmask(nick) bannedHostmask = nick if not irc.isNick(bannedNick): self.log.warning('%q tried to quiet a non nick: %q', msg.prefix, bannedNick) raise callbacks.ArgumentError banmaskstyle = conf.supybot.protocols.irc.banmask banmask = banmaskstyle.makeBanmask(bannedHostmask) irc.queueMsg(ircmsgs.mode(channel, ("-q", banmask)))
def testNickFromHostmask(self): self.assertEqual( ircutils.nickFromHostmask('[email protected]'), 'nick')
def reviewBans(self, irc=None): reviewTime = int(self.registryValue('request.review') * 86400) if not reviewTime: # time is zero, do nothing return now = time.mktime(time.gmtime()) lastreview = self.pendingReviews.time self.pendingReviews.time = now # update last time reviewed if not lastreview: # initialize last time reviewed timestamp lastreview = now - reviewTime for channel, bans in self.bans.iteritems(): if not self.registryValue('enabled', channel) \ or not self.registryValue('request', channel): continue for ban in bans: if guessBanType(ban.mask) in ('quiet', 'removal'): # skip mutes and kicks continue banAge = now - ban.when reviewWindow = lastreview - ban.when #self.log.debug('review ban: %s ban %s by %s (%s/%s/%s %s)', channel, ban.mask, # ban.who, reviewWindow, reviewTime, banAge, reviewTime - reviewWindow) if reviewWindow <= reviewTime < banAge: # ban is old enough, and inside the "review window" try: # ban.who should be a user hostmask nick = ircutils.nickFromHostmask(ban.who) host = ircutils.hostFromHostmask(ban.who) except: if ircutils.isNick(ban.who, strictRfc=True): # ok, op's nick, use it nick = ban.who host = None else: # probably a ban restored by IRC server in a netsplit # XXX see if something can be done about this continue if nickMatch(nick, self.registryValue('request.ignore', channel)): # in the ignore list continue if not ban.id: ban.id = self.get_banId(ban.mask, channel) if nickMatch(nick, self.registryValue('request.forward', channel)): s = "Hi, please somebody review the ban '%s' set by %s on %s in"\ " %s, link: %s/bans.cgi?log=%s" %(ban.mask, nick, ban.ascwhen, channel, self.registryValue('bansite'), ban.id) self._sendForward(irc, s, channel) else: s = "Hi, please review the ban '%s' that you set on %s in %s, link:"\ " %s/bans.cgi?log=%s" %(ban.mask, ban.ascwhen, channel, self.registryValue('bansite'), ban.id) msg = ircmsgs.privmsg(nick, s) if host in self.pendingReviews \ and (nick, msg) not in self.pendingReviews[host]: self.pendingReviews[host].append((nick, msg)) else: self.pendingReviews[host] = [(nick, msg)] elif banAge < reviewTime: # since we made sure bans are sorted by time, the bans left are more recent break
def testNickFromHostmask(self): self.assertEqual(ircutils.nickFromHostmask('[email protected]'), 'nick')
def _ban(self, irc, msg, args, channel, optlist, target, expiry, 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: 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 expiry > 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, expiry) 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 _formatNote(self, when, whence, note): if not self.registryValue('format.senderHostname'): whence = ircutils.nickFromHostmask(whence) return _('Sent %s: <%s> %s') % (self._timestamp(when), whence, note)
def testNickFromHostmask(self): self.assertEqual(ircutils.nickFromHostmask("[email protected]"), "nick")