def _reply(self, irc, msg, channel, text): """Send a response to text""" cobeBrain = Brain(self._getBrainDirectoryForChannel(channel)) response = cobeBrain.reply(text).encode('utf-8') response = self._strip_nick(irc, msg, response) for i in range(response.lower().count(self.magicnick.lower())): # If first word is nick, switch with the callers nick. if self.magicnick in response: response = response.replace(self.magicnick, random.choice(list(irc.state.channels[msg.args[0]].users))) if self.magicnick.lower() in response: response = response.replace(self.magicnick.lower(), random.choice(list(irc.state.channels[msg.args[0]].users))) cobeBrain.learn(response) # Let's have the bot learn the wacky things it says self.log.info("Attempting to respond in {0} with message: {1}".format(channel, response)) # delay the response here so we look real? if self.registryValue('responseDelay', channel): self.log.info("Delayed the response in %s." % channel) delayseconds = time.time() + random.randint(2, 5) schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)), delayseconds) else: irc.queueMsg(ircmsgs.privmsg(channel, response))
def np(self, irc, msg, args): """Return a list of a people currently in-game on Steam """ key = self.registryValue('apikey') if not key: irc.replyError('plugins.steamy.apikey has not been set') return self.update(key) ingame = filter(lambda player: player.isInGame(), self.group.members) playerCount = len(ingame) playerlist = map(lambda x: '{0}: {1}'.format(x.steamID.encode('utf8'), x.gameextrainfo.encode('utf8')), ingame) self.log.info(str(playerlist)) if len(playerlist) != 0: reply = 'Now Playing: %s' % (', '.join(playerlist)) else: reply = 'Now Playing: nobody :(' if ircutils.isChannel(msg.args[0]): irc.queueMsg(ircmsgs.privmsg(msg.args[0], reply)) else: irc.queueMsg(ircmsgs.privmsg(msg.nick, reply))
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 doPrivmsg(self, irc, msg): channel = msg.args[0] # Ignore messages that start with the command qualifier if msg.args[1].startswith('@'): return # Don't parse non-command messages if a trivia game isn't running # or if there is no active question if channel not in self.running or channel not in self.curQuestion: return else: self.curQuestion[channel].check(msg.args[1]) if self.curQuestion[channel].isCorrect(msg.args[1]) == False: if self.lastHint[channel] != self.curQuestion[channel].hint: irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + self.curQuestion[channel].hint)) self.lastHint[channel] = self.curQuestion[channel].hint else: # Answer is correct, assign points irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + "%s is correct!!" % self.curQuestion[channel].answer)) irc.queueMsg(ircmsgs.privmsg(channel,"%s gets 5 points!!" % ircutils.bold(msg.nick))) self.scores[channel].add(msg.nick,5) irc.queueMsg(ircmsgs.privmsg(msg.args[0],("Scores: %s" % self.getFormattedScores(msg.args[0])))) self.curQuestion.pop(channel) self.ask(irc,msg) return
def repoadd(self, irc, msg, args, channel, reponame, url, channels): """ <repository name> <url> <channel[,channel...]> Add a new repository with name, url and a comma-separated list of channels which should be connected to this repo. """ def cloning_done_cb(result): ''' Callback invoked after cloning is done. ''' if isinstance(result, _Repository): self.repos.append(result) irc.sendMsg(ircmsgs.privmsg(msg.args[0],"Repository created and cloned")) else: self.log.info("Cannot clone: " + str(result)) irc.sendMsg(ircmsgs.privmsg(msg.args[0],"Error: Cannot clone repo: " + str(result))) if reponame in config.global_option('repolist').value: irc.sendMsg(ircmsgs.privmsg(msg.args[0],'Error: repo exists')) return opts = {'url': url, 'channels': channels} if world.testing: _Repository.create(reponame, cloning_done_cb, opts) irc.sendMsg(ircmsgs.privmsg(msg.args[0],"Repository created and cloned")) return t = threading.Thread(target = _Repository.create, args = (reponame, cloning_done_cb, opts)) t.start() irc.sendMsg(ircmsgs.privmsg(msg.args[0],'Cloning of %s started...' % reponame))
def testAddressedWithMultipleNicks(self): msg = ircmsgs.privmsg("#foo", "bar: baz") self.assertEqual(callbacks.addressed("bar", msg), "baz") # need to recreate the msg objects since the old ones have already # been tagged msg = ircmsgs.privmsg("#foo", "bar: baz") self.assertEqual(callbacks.addressed("biff", msg, nicks=["bar"]), "baz")
def maru(self, irc, msg, args, channel, num=None): """ [<post number>] Prints a blog post to the channel. If no post number is given, returns a random entry. """ if(num == None): self.log.info("Randomly getting a maru post:") latestM = MaruGet.MaruBlog() postNum = randint(2,latestM.latestPost()) else: postNum = num self.log.info("Getting maru post number: " + str(postNum)) m = MaruGet.MaruBlog(postNum) r = m.ircContent() self.log.debug("Maruing %q in %s due to %s.", r, channel, msg.prefix) self.log.debug("Type: %s ", type(r)) r = unicode(r).encode("utf-8") maruList = list() irc.queueMsg(ircmsgs.privmsg(channel, "Maru blog entry #" +\ str(postNum) +" (" + m.maruUrl + ")" +":")) for maruLine in r.split('\n'): try: maruList.append(unicode(maruLine).encode("ascii")) except UnicodeDecodeError: pass for line in maruList: irc.queueMsg(ircmsgs.privmsg(channel, line)) irc.noReply()
def _announcer(self): for server, url in servers: status = self._state[server] new_status = check_status(url) for irc in world.ircs: if CHANNEL in irc.state.channels: for type_ in new_status: if new_status[type_] == status[type_]: continue elif new_status[type_]: msg = '[%s] %s is going up' % (server, type_.capitalize()) else: msg = '[%s] %s is going down' % (server, type_.capitalize()) irc.queueMsg(ircmsgs.privmsg(CHANNEL, msg)) self._state[server] = new_status new_login_status = check_login_status(login) if new_login_status == self._login: pass elif new_login_status: irc.queueMsg(ircmsgs.privmsg(CHANNEL, '[login] Going up')) else: irc.queueMsg(ircmsgs.privmsg(CHANNEL, '[login] Going down')) self._login = new_login_status
def do311(self, irc, msg): nick = msg.args[1] if not nick.startswith('[YOG]') or nick in self.registryValue('nowelcome').split(' '): return realname = msg.args[5] hostname = self._users.pop(nick) try: version = 'Glob2 version %s' % realname.split('-')[1] except: version = 'unknown version' g = GeoIP() country = g.country(hostname)['country_name'] if country == 'France': irc.queueMsg(ircmsgs.privmsg(nick, ('Bonjour %s, bienvenue dans le ' 'salon de jeu Globulation2 en ligne. Il y a actuellement %i ' 'personnes connectées via IRC, elles pourraient se réveiller et ' 'jouer avec vous. Attendez ici au moins quelques minutes, ' 'quelqu\'un pourrait se connecter d\'ici là.') % (nick, len(irc.state.channels['#glob2'].users)))) else: irc.queueMsg(ircmsgs.privmsg(nick, ('Hi %s, welcome to the ' 'globulation online game room. There are currently %i ' 'people connected via IRC, they may awaken and challenge ' 'you to a game. Please stay here at least a few minutes, ' 'someone may connect in the meantime.') % (nick, len(irc.state.channels['#glob2'].users)))) irc.queueMsg(ircmsgs.privmsg('#glob2', ('Welcome to %s, running %s ' 'and connecting from %s.') % (nick, version, country)))
def _checkLogs(self, irc): """Checks the files for new lines and, if there be any, prints them to IRC. Actual work is all done here. """ # Check xlogfile self.xlog.seek(0, os.SEEK_CUR) line = self.xlog.readline() if line: data = parse_xlog(line) report = report_template.format(**data) msg = ircmsgs.privmsg(CONFIG_CHANNEL, report) irc.queueMsg(msg) # Check livelog self.livelog.seek(0, os.SEEK_CUR) line = self.livelog.readline() if line: data = parse_livelog(line) report = livelog_announcement(data) if report: msg = ircmsgs.privmsg(CONFIG_CHANNEL, report) irc.queueMsg(msg)
def testReplyTo(self): prefix = 'foo!bar@baz' msg = ircmsgs.privmsg('#foo', 'bar baz', prefix=prefix) self.assertEqual(callbacks.reply(msg, 'blah', to='blah'), ircmsgs.privmsg('#foo', 'blah: blah')) self.assertEqual(callbacks.reply(msg, 'blah', to='blah', private=True), ircmsgs.notice('blah', 'blah'))
def doNotice(self, irc, msg): if irc.network == self.registryValue('masternetwork'): irc.sendMsg(ircmsgs.privmsg('\x23ElectroBNC.log', "Notice from %s: %s" % (msg.nick, msg.args[1]))) elif irc.network != self.registryValue('masternetwork'): otherIrc = self._getIrc(self.registryValue('masternetwork')) otherIrc.queueMsg(ircmsgs.privmsg("\x23ElectroBNC.log", "Notice from %s@%s: %s" % (msg.nick, irc.network, msg.args[1]))) irc.noReply()
def pingall(self, irc, msg, args, message): """<text> Send a broadcast ping to all users on the channel. An message to be sent along with this ping must also be supplied for this command to work. """ nick = msg.nick channel = msg.args[0] payload = msg.args[1] # We require a message to go out with the ping, we don't want # to waste people's time: if channel[0] != '#': irc.reply("Not joined to any channel.") return if message is None: irc.reply("You must supply a description with the `pingall` command. We don't want to go wasting people's times looking for why they are pinged.") return # Send announcement message irc.sendMsg(ircmsgs.privmsg(channel, message)) # ping all nicks in lines of about 256 nickline = '' nicks = sorted(irc.state.channels[channel].users, key=lambda x: x.lower()) for nick in nicks: nickline = nickline + nick + ' ' if len(nickline) > 256: irc.sendMsg(ircmsgs.privmsg(channel, nickline)) nickline = '' irc.sendMsg(ircmsgs.privmsg(channel, nickline)) # Send announcement message irc.sendMsg(ircmsgs.privmsg(channel, message))
def doPrivmsg(self, irc, msg): if(self.registryValue('enable', msg.args[0])): # If this is a youtube link, commence lookup if(msg.args[1].find("youtube") != -1 or msg.args[1].find("youtu.be") != -1): youtube_pattern = re.compile('(?:www\.)?youtu(?:be\.com/watch\?v=|\.be/)([\w\?=\-]*)(&(amp;)?[\w\?=]*)?') m = youtube_pattern.search(msg.args[1]); if(m): r = requests.get('http://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=json' % m.group(1)) data = json.loads(r.content) likes = float(data['entry']["yt$rating"]['numLikes']) dislikes = float(data['entry']["yt$rating"]['numDislikes']) rating = (likes/(likes+dislikes))*100 message = 'Title: %s, Views: %s, Rating: %s%%' % (ircutils.bold(data['entry']['title']['$t']), ircutils.bold(data['entry']['yt$statistics']['viewCount']), ircutils.bold(round(float(rating)))) message = message.encode("utf-8", "replace") irc.queueMsg(ircmsgs.privmsg(msg.args[0], message)) if(msg.args[1].find("vimeo") != -1): vimeo_pattern = re.compile('vimeo.com/(\\d+)') m = vimeo_pattern.search(msg.args[1]); if(m): r = requests.get("http://vimeo.com/api/v2/video/%s.json" % m.group(1)) data = json.loads(r.content) message = 'Title: %s, Views: %s, Likes: %s' % (ircutils.bold(data[0]['title']), ircutils.bold(data[0]['stats_number_of_plays']), ircutils.bold(data[0]['stats_number_of_likes'])) message = message.encode("utf-8", "replace") irc.queueMsg(ircmsgs.privmsg(msg.args[0], message))
def cutwire(self, irc, cutWire): self.cutWire = cutWire self.responded = True specialWires = False if self.rng.randint(1,len(self.wires)) == 1 or self.victim.lower()=='jacksonmj': specialWires = True if self.cutWire.lower() == 'potato' and specialWires: self.irc.queueMsg(ircmsgs.privmsg(self.channel, '%s has turned the bomb into a potato! This has rendered it mostly harmless, and slightly %s.' % (self.victim, self.goodWire))) self.defuse() elif self.cutWire.lower() == 'pizza' and specialWires: self.irc.queueMsg(ircmsgs.privmsg(self.channel, '%s has turned the bomb into a pizza! %s\'s pants have been ruined by the pizza stuffed into them, but at least they haven\'t exploded.' % (self.victim, self.victim))) self.defuse() elif self.goodWire.lower() == self.cutWire.lower(): self.irc.queueMsg(ircmsgs.privmsg(self.channel, '%s has cut the %s wire! This has defused the bomb!' % (self.victim, self.cutWire))) if self.victim.lower() != self.sender.lower(): self.irc.queueMsg(ircmsgs.privmsg(self.channel, 'He then quickly rearms the bomb and throws it back at %s with just seconds on the clock!' % self.sender)) tmp = self.victim self.victim = self.sender self.sender = tmp self.thrown = True schedule.rescheduleEvent('%s_bomb' % self.channel, time.time() + 10) if self.victim == irc.nick: time.sleep(1) self.irc.queueMsg(ircmsgs.privmsg(self.channel, '@duck')) time.sleep(1) self.duck(self.irc, irc.nick) else: self.defuse() else: schedule.removeEvent('%s_bomb' % self.channel) self.detonate(irc)
def cutwire(self, irc, cutWire): cutWire = cutWire.replace("pink", ircutils.mircColor('pink', '13')) cutWire = cutWire.replace("red", ircutils.mircColor('red', '4')) cutWire = cutWire.replace("orange", ircutils.mircColor('orange', '7')) cutWire = cutWire.replace("yellow", ircutils.mircColor('yellow', '8')) cutWire = cutWire.replace("green", ircutils.mircColor('green', '3')) cutWire = cutWire.replace("blue", ircutils.mircColor('blue', '12')) cutWire = cutWire.replace("grey", ircutils.mircColor('grey', '14')) cutWire = cutWire.replace("purple", ircutils.mircColor('purple', '6')) cutWire = cutWire.replace("lime", ircutils.mircColor('lime', '9')) cutWire = cutWire.replace("teal", ircutils.mircColor('teal', '10')) cutWire = cutWire.replace("brown", ircutils.mircColor('brown', '5')) cutWire = cutWire.replace("cyan", ircutils.mircColor('cyan', '11')) self.cutWire = cutWire self.responded = True if self.thrown == True: self.irc.queueMsg(ircmsgs.privmsg(self.channel, 'You don\'t have the coordination to cut wires on bombs in midair while they\'re flying towards your head! Ducking might be a better idea.')) else: if self.goodWire.lower() == self.cutWire.lower(): self.irc.queueMsg(ircmsgs.privmsg(self.channel, '%s has cut the %s wire! This has defused the bomb!' % (self.victim, self.cutWire))) self.irc.queueMsg(ircmsgs.privmsg(self.channel, '%s then quickly rearms the bomb and throws it back at %s with just seconds on the clock!' % (self.victim, self.sender))) self.victim = self.sender self.thrown = True schedule.rescheduleEvent('%s_bomb' % self.channel, time.time() + 10) if self.victim == irc.nick: time.sleep(1) self.irc.queueMsg(ircmsgs.privmsg(self.channel, '@duck')) time.sleep(1) self.duck(self.irc, irc.nick) else: schedule.removeEvent('%s_bomb' % self.channel) self.detonate(irc)
def doJoin(self, irc, msg): #irc.reply("hello") if ircutils.strEqual(irc.nick, msg.nick): return # It's us channel = msg.args[0] if channel != "#code4lib" and channel not in test_channels: return #if self.db[channel, msg.nick] is None: try: self.db.get(channel, msg.nick) except KeyError: # The except means that we only message people not yet in the db. irc.queueMsg(ircmsgs.privmsg(msg.nick, joinmsg % ( irc.nick ) )) irc.noReply() #self.db.add(channel, msg.nick) self.db.add(channel, msg.nick) # Also notify the helpers privately if a potential newbie shows up, # so that we can roll out the welcome mat human-style. for helper in self._get_helpers(channel): # Sometimes the helpers db stores blank lines, which we should # ignore. if helper: irc.queueMsg(ircmsgs.privmsg(helper, helpermsg % ( msg.nick ) )) irc.noReply()
def _trust_updates(self, irc): try: added, removed = self.deeds.trust_notify.get(block=False) txt = '[trust-update]' if added or removed: if added: txt += ' added: {0}'.format(', '.join(added)) if removed: if added: txt += ' |' txt += ' removed: {0}'.format(', '.join(removed)) else: txt += ' no changes' msg = ircmsgs.privmsg('#punkbot', txt) irc.queueMsg(msg) return # announce trust updates for channel in irc.state.channels: msg = ircmsgs.privmsg(channel, txt) irc.queueMsg(msg) except Queue.Empty: pass
def doJoin(self, irc, msg): """give voice to users that join and meet requirements.""" if msg.args[0] != self.registryValue('targetChannel') or irc.network != 'freenode': return if msg.nick == irc.nick: # ignore our own join msgs. return gpgauth = self._checkGPGAuth(irc, msg.prefix) if gpgauth is None: try: if (not world.testing) and self.registryValue('msgOnJoinVoice') != "" and msg.nick not in irc.state.channels['#bitcoin-otc-foyer'].users: irc.queueMsg(ircmsgs.privmsg(msg.nick, self.registryValue('msgOnJoinVoice'))) except KeyError: pass if (not world.testing) and self.registryValue('msgOnJoinIdent') != "": irc.queueMsg(ircmsgs.privmsg(msg.nick, self.registryValue('msgOnJoinIdent'))) return info = self._getGPGInfo(irc, gpgauth['nick']) if info is not None: regtimestamp = info[4] else: # this should not happen return trust_nanotube = self._gettrust(irc, 'nanotube', gpgauth['nick']) trust_keefe = self._gettrust(irc, 'keefe', gpgauth['nick']) mintrust = min(trust_nanotube[0][0] + trust_nanotube[1][0], trust_keefe[0][0] + trust_keefe[1][0]) if mintrust >= self.registryValue('ratingThreshold') and \ time.time() - regtimestamp > self.registryValue('accountAgeThreshold'): irc.queueMsg(ircmsgs.voice('#bitcoin-otc', msg.nick))
def run(self): while not self.stopped: time.sleep(10) for url, desc, chan in self.urls: try: f = urllib.urlopen(url) s = f.read() f.close() s = filter(s) except Exception, e: msg = privmsg("hc", "Wwwdiff: error(1): %s" % e) self.plugin.irc.queueMsg(msg) continue try: old = self.texts[url] self.texts[url] = s except: self.texts[url] = s continue try: diffs = difflib.ndiff(old.split("\n"), s.split("\n")) for diff in diffs: if unwanted(diff): continue if diff[0] == "+": msg = privmsg(chan, "C [%s] %s" % (desc, diff)) self.plugin.irc.queueMsg(msg) except Exception, e: msg = privmsg("hc", "Wwwdiff: error(2): %s" % e) self.plugin.irc.queueMsg(msg) continue
def testAddressedWithMultipleNicks(self): msg = ircmsgs.privmsg('#foo', 'bar: baz') self.assertEqual(callbacks.addressed('bar', msg), 'baz') # need to recreate the msg objects since the old ones have already # been tagged msg = ircmsgs.privmsg('#foo', 'bar: baz') self.assertEqual(callbacks.addressed('biff', msg, nicks=['bar']), 'baz')
def cloning_done_cb(result): ''' Callback invoked after cloning is done. ''' if isinstance(result, _Repository): self.repos.append(result) irc.sendMsg(ircmsgs.privmsg(msg.args[0],"Repository created and cloned")) else: self.log.info("Cannot clone: " + str(result)) irc.sendMsg(ircmsgs.privmsg(msg.args[0],"Error: Cannot clone repo: " + str(result)))
def sayHello(): irc.queueMsg(ircmsgs.privmsg("DonVitoCorleone", "Function _sayHello is called")) eventNumber = self.read_timer_number() eventNumber = eventNumber["n"] irc.queueMsg(ircmsgs.privmsg("DonVitoCorleone", "eventN is %i" % eventNumber)) if eventNumber <= 1: irc.queueMsg(ircmsgs.privmsg("DonVitoCorleone", "It's diferent")) self.write_timer_number() """if eventNumber <= 5:
def size(self, irc, msg, args, channel, db): """<db> Returns size of the ln DB. """ if db.lower() == "ln": irc.queueMsg(ircmsgs.privmsg(channel, "Size of Ln: %s" % self.db.getLnSize())) elif db.lower() == "tiny": irc.queueMsg(ircmsgs.privmsg(channel, "Size of Tiny: %s" % self.db.getTinySize()))
def dodaj(self, irc, msg, args, well): """Takes no arguments Upisuje vas nick u bazu vojnika za trenutni udar.""" nick = string.lower(msg.nick) url = conf.supybot.plugins.ERep.url() channel = msg.args[0] if channel not in allowed_channels: irc.reply("Ova komanda nije moguca na ovom kanalu, molimo pokusajte da je kucate na kanalu vase Vojne Jedinice.") else: #with open('RSDJ/Udar_tok.json', 'r') as tok_udara: #b = json.loads(tok_udara.read()) tok_udara = self.read_udar_tok_database(msg) udar_traje = tok_udara['Udar'] vodja_udara = tok_udara['Vodja'] if udar_traje == 1: #with open('RSDJ/Vojnici.json', 'r') as vojnici: #b = json.loads(vojnici.read()) vojnici = self.read_vojnici_database(msg) if nick in vojnici.keys(): id = vojnici[nick]['id'] data = json.load(utils.web.getUrlFd('%scitizen/profile/%s.json' % (url, id))) rank_points = data['military']['rank']['points'] base = data['military']['base_hit'] true_patriot_damage = data['true_patriot']['damage'] if data['true_patriot'] else 0 q1 = base * 1.2000373204 q2 = q1 * 1.1666925828 q3 = q2 * 1.14287618286 q4 = q3 * 1.12501457726 q5 = q4 * 1.1111226288 q6 = q5 * 1.10000932923 q7 = q6 * 1.36358239335 nick_za_upis = {} nick_za_upis['rpts'] = rank_points nick_za_upis['q7'] = q7 nick_za_upis['id'] = id nick_za_upis['tp'] = true_patriot_damage #with open('RSDJ/Udar_vojnici.json', 'r') as vojnici_udar: #b = json.loads(vojnici_udar.read()) udar_vojnici = self.read_udar_vojnici_database(msg) if nick in udar_vojnici.keys(): irc.reply("Vec se nalazite u bazi za ovaj udar, nije moguce duplo upisivanje.") else: udar_vojnici[nick] = nick_za_upis #with open('RSDJ/Udar_vojnici.json', 'w') as vojnici_udar_upis: #vojnici_udar_upis.write(json.dumps(b)) udar_vojnici_upis = self.write_udar_vojnici_database(channel, udar_vojnici) if udar_vojnici_upis == "Done": irc.reply("Uspesno ste se upisali u bazu vojnika za ovaj udar.") irc.queueMsg(ircmsgs.privmsg(vodja_udara, "\x02%s\x02 se prijavio za podelu, on ima \x02%s\x02 well -a, i njegov donate link je: \x02http://www.erepublik.com/en/economy/donate-items/%s\x02" % (nick, well, id))) irc.queueMsg(ircmsgs.privmsg('#grom_komanda', "\x02%s\x02 se prijavio za podelu, on ima \x02%s\x02 well -a, i njegov donate link je: \x02http://www.erepublik.com/en/economy/donate-items/%s\x02" % (nick, well, id))) else: irc.reply("Nesto je poslo po zlu, baza je ostala ista. Sintaksa komande je \x02+dodaj BROJ-WELLa\x02.") else: irc.reply("Vi niste jedan od vojnika RSDj -a, ili mozda jeste ali se ne nalazite u bazi vojnika. Ako mislite da je u pitanju greska javite nekome iz komande.") else: irc.reply("Udar nije u toku, ne mozete da se upisete sada.")
def stop(self,irc,msg,args): """Stop a round of trivia""" if (self.running.get(msg.args[0]) == False): irc.error('There is no game started!') return self.running[msg.args[0]] = False self.curQuestion.pop(msg.args[0]) irc.queueMsg(ircmsgs.privmsg(msg.args[0],'Quitting Trivia')) irc.queueMsg(ircmsgs.privmsg(msg.args[0],("Scores: %s" % self.getFormattedScores(msg.args[0])))) return
def ask(self, irc, msg): channel = msg.args[0] if channel not in self.curQuestion: self.curQuestion[channel] = self.getQuestion() irc.queueMsg(ircmsgs.privmsg(channel,u"%s: %s?" % (ircutils.bold(self.curQuestion[channel].id), self.curQuestion[channel].question))) irc.queueMsg(ircmsgs.privmsg(channel,ircutils.bold("Answer: ") + self.curQuestion[channel].hint)) # Print answer to log for debugging purposes only log.critical(self.curQuestion[channel].answer) return
def request(self, irc, msg, args, username, server, port, net, email): """<username> <server> <port> <net> <email> One BNC per person, if you want another network/server use !addserver // If you would like to remove your account use !remove // Not implemented at the present time, if you need to do either, highlight an op+""" # dbpath = self.registryValue(dbpath) irc.queueMsg(ircmsgs.privmsg('\x23ElectroBNC', "Request relayed to staff channel. Info: Username: %s Server: %s Port: %s NetName: %s Email: %s // Please note that if you break the rules, your bnc will be removed with no hesitation." % (username, server, port, net, email))) if irc.network == "ElectroCode": irc.queueMsg(ircmsgs.privmsg('\x23ElectroBNC-Relay', '!add %s %s %s %s %s' % (username, server, port, net, email))) elif irc.network != "ElectroCode": otherIrc = self._getIrc("ElectroCode") otherIrc.queueMsg(ircmsgs.privmsg("\x23ElectroBNC-Relay", "!add %s %s %s %s %s" % (username, server, port, net, email)))
def _mention(self, irc): statuses = self.api.GetMentions(since_id=self.mentionSince) if len(statuses) > 0: self.mentionSince = statuses[0].id for channel in self.registryValue('channelList').split(): irc.queueMsg(ircmsgs.privmsg(channel, self.registryValue('replyAnnounceMsg'))) for status in statuses: msg = status.user.screen_name + ' -- ' + status.text irc.queueMsg(ircmsgs.privmsg(channel, msg)) irc.noReply()
def timebomb(self, irc, msg, args, channel, victim): """<nick> For bombing people!""" channel = ircutils.toLower(channel) if not self.registryValue('allowBombs', channel): irc.reply('Timebombs aren\'t allowed in this channel. Set plugins.Timebomb.allowBombs to true if you want them.') return try: if self.bombs[channel].active: irc.reply('There\'s already an active bomb, in %s\'s pants!' % self.bombs[channel].victim) return except KeyError: pass if victim.lower() == irc.nick.lower() and not self.registryValue('allowSelfBombs', channel): irc.reply('You really expect me to bomb myself? Stuffing explosives into my own pants isn\'t exactly my idea of fun.') return victim = string.lower(victim) found = False for nick in list(irc.state.channels[channel].users): if victim == string.lower(nick): victim = nick found = True if not found: irc.reply('Error: nick not found.') return if string.lower(victim) in self.registryValue('exclusions', channel): irc.reply('Error: that nick can\'t be timebombed') return # not (victim == msg.nick and victim == 'mniip') and if not ircdb.checkCapability(msg.prefix, 'admin') and not self._canBomb(irc, channel, msg.nick, victim, True): return detonateTime = self.rng.randint(self.registryValue('minTime', channel), self.registryValue('maxTime', channel)) wireCount = self.rng.randint(self.registryValue('minWires', channel), self.registryValue('maxWires', channel)) #if victim.lower() == 'halite' or (victim == msg.nick and victim == 'mniip'): # wireCount = self.rng.randint(11,20) if wireCount < 12: colors = self.registryValue('shortcolors') else: colors = self.registryValue('colors') wires = self.rng.sample(colors, wireCount) goodWire = self.rng.choice(wires) self.log.info("TimeBomb: Safewire is %s"%goodWire) if self.registryValue('debug'): irc.reply('I\'m about to create a bomb in %s' % channel) #if not (victim == msg.nick and victim == 'mniip'): self._logBomb(irc, channel, msg.nick, victim) self.bombs[channel] = self.Bomb(irc, victim, wires, detonateTime, goodWire, channel, msg.nick, self.registryValue('showArt', channel), self.registryValue('showCorrectWire', channel), self.registryValue('debug')) irc.queueMsg(ircmsgs.privmsg("jacksonmj", "TIMEBOMB: Safe wire is %s"%goodWire)) #irc.queueMsg(ircmsgs.privmsg("##jacksonmj-test", "TIMEBOMB: Safe wire is %s"%goodWire)) irc.queueMsg(ircmsgs.privmsg("##jacksonmj-test", "TIMEBOMB: Safe wire is %s"%self.rng.choice(wires))) if self.registryValue('debug'): irc.reply('This message means that I got past the bomb creation line in the timebomb command')
def _getlogs(self, irc): while self.loopthread: logfile_ = io.open(self.logpath_, mode="r", encoding="utf-8") count = 0 for line in logfile_: count += 1 if count > self.lastknowline: iline_ = line.rstrip("\n") if 'FLUSHERS FLUSHED' not in iline_.upper(): holdCheck = True while holdCheck: if conf.supybot.plugins.Loglogger.Channel( ) not in irc.state.channels: time.sleep(5) else: irc.queueMsg( ircmsgs.privmsg( conf.supybot.plugins.Loglogger.Channel( ), iline_)) time.sleep(0.3) holdCheck = False self.lastknowline += 1 logfile_.close() time.sleep(5)
def announce(self, irc, msg, args, text): """<text> Sends <text> to all channels the bot is currently on and not lobotomized in. """ u = ircdb.users.getUser(msg.prefix) template = self.registryValue('announceFormat') text = ircutils.standardSubstitute(irc, msg, template, env={ 'owner': u.name, 'text': text }) for channel in irc.state.channels: c = ircdb.channels.getChannel(channel) if not c.lobotomized: irc.queueMsg(ircmsgs.privmsg(channel, text)) irc.noReply()
def doPrivmsg(self, irc, msg): channel = msg.args[0] text = msg.args[1] if not self.registryValue('enabled', channel): return # Disabled in this channel url = find_url(text) if url is None: return # No URL found domain = get_domain(url) preview = None # Find previewer previewer = self.previewers.get_previewer(domain) if previewer is not None: preview = previewer.get_preview(self, url) elif generic.can_handle(domain): if self.registryValue('generic_enabled'): preview = generic.handle(url) # Handle the result if preview is None: return irc.queueMsg(ircmsgs.privmsg(channel, preview))
def _outFilterThread(self, irc, msg): (channel, text) = msg.args network = irc.network for m in utils.web.httpUrlRe.finditer(text): url = m.group(1) if len(url) > self.registryValue('minimumLength', channel, network): try: cmd = self.registryValue('serviceRotation', channel, network, value=False) cmd = cmd.getService().capitalize() except ValueError: cmd = self.registryValue('default', channel, network) \ .capitalize() try: shortUrl = getattr(self, '_get%sUrl' % cmd)(url) text = text.replace(url, shortUrl) except (utils.web.Error, AttributeError, ShrinkError): pass newMsg = ircmsgs.privmsg(channel, text, msg=msg) newMsg.tag('shrunken') irc.queueMsg(newMsg)
def fetch_updates(self, count=None): r = self.api_session.get(self.url) # Way chatty # logger.debug("Request headers") # logger.debug(pp.pformat(self.api_session.headers)) # logger.debug("Response headers") # logger.debug(pp.pformat(r.headers)) if r.status_code == 304: # No updates since last fetch return elif r.ok: if 'etag' in r.headers: # Update ETag to keep position self.api_session.headers['If-None-Match'] = r.headers['etag'] # Handle updates self.announce_updates(updates=r.json, count=count) else: err = 'Unable to retrieve updates for %s, error: %s (%s)' % ( self, r.text, r.reason) logger.error('GEA: %s' % err) for ch in self.channels: msg = ircmsgs.privmsg(ch, err) self.irc.queueMsg(msg)
def testAddressedLegacy(self): """Checks callbacks.addressed still accepts the 'nick' argument instead of 'irc'.""" irc = getTestIrc() oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars) nick = 'supybot' conf.supybot.reply.whenAddressedBy.chars.set('~!@') inChannel = [ '~foo', '@foo', '!foo', '%s: foo' % nick, '%s foo' % nick, '%s: foo' % nick.capitalize(), '%s: foo' % nick.upper() ] inChannel = [ircmsgs.privmsg('#foo', s) for s in inChannel] badmsg = ircmsgs.privmsg('#foo', '%s:foo' % nick) with self.assertWarnsRegex(DeprecationWarning, 'Irc object instead'): self.assertFalse(callbacks.addressed(nick, badmsg)) badmsg = ircmsgs.privmsg('#foo', '%s^: foo' % nick) with self.assertWarnsRegex(DeprecationWarning, 'Irc object instead'): self.assertFalse(callbacks.addressed(nick, badmsg)) for msg in inChannel: with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg), msg) msg = ircmsgs.privmsg(nick, 'foo') irc._tagMsg(msg) with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg)) conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars) msg = ircmsgs.privmsg('#foo', '%s::::: bar' % nick) with self.assertWarns(DeprecationWarning): self.assertEqual('bar', callbacks.addressed(nick, msg)) msg = ircmsgs.privmsg('#foo', '%s: foo' % nick.upper()) with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg)) badmsg = ircmsgs.privmsg('#foo', '%s`: foo' % nick) with self.assertWarns(DeprecationWarning): self.assertFalse(callbacks.addressed(nick, badmsg))
def testAddressed(self): oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars) nick = 'supybot' conf.supybot.reply.whenAddressedBy.chars.set('~!@') inChannel = ['~foo', '@foo', '!foo', '%s: foo' % nick, '%s foo' % nick, '%s: foo' % nick.capitalize(), '%s: foo' % nick.upper()] inChannel = [ircmsgs.privmsg('#foo', s) for s in inChannel] badmsg = ircmsgs.privmsg('#foo', '%s:foo' % nick) self.failIf(callbacks.addressed(nick, badmsg)) badmsg = ircmsgs.privmsg('#foo', '%s^: foo' % nick) self.failIf(callbacks.addressed(nick, badmsg)) for msg in inChannel: self.assertEqual('foo', callbacks.addressed(nick, msg), msg) msg = ircmsgs.privmsg(nick, 'foo') self.assertEqual('foo', callbacks.addressed(nick, msg)) conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars) msg = ircmsgs.privmsg('#foo', '%s::::: bar' % nick) self.assertEqual('bar', callbacks.addressed(nick, msg)) msg = ircmsgs.privmsg('#foo', '%s: foo' % nick.upper()) self.assertEqual('foo', callbacks.addressed(nick, msg)) badmsg = ircmsgs.privmsg('#foo', '%s`: foo' % nick) self.failIf(callbacks.addressed(nick, badmsg))
def bcverify(self, irc, msg, args, data): """<signedmessage> Verify the latest authentication request by providing the <signedmessage> which contains the challenge string signed with your bitcoin address of record. If verified, you'll be authenticated for the duration of the bot's or your IRC session on channel (whichever is shorter). """ self._removeExpiredRequests() if not self._testPresenceInChannels(irc, msg.nick): irc.error("In order to authenticate, you must be present in one " "of the following channels: %s" % (self.registryValue('channels'), )) return try: authrequest = self.pending_auth[msg.prefix] except KeyError: irc.error( "Could not find a pending authentication request from your hostmask. " "Either it expired, or you changed hostmask, or you haven't made one." ) return if authrequest['type'] not in ['bcregister', 'bcauth', 'bcchangekey']: irc.error("No outstanding bitcoin-signature-based request found.") return try: result = bitcoinsig.verify_message(authrequest['bitcoinaddress'], data, authrequest['challenge']) if not result: irc.error("Signature verification failed.") return except: irc.error("Authentication failed. Please try again.") self.log.info("bcverify traceback: \n%s" % (traceback.format_exc())) return response = "" if authrequest['type'] == 'bcregister': if self.db.getByNick(authrequest['nick']) or self.db.getByAddr( authrequest['bitcoinaddress']): irc.error("Username or key already in the database.") return self.db.register(None, None, authrequest['bitcoinaddress'], time.time(), authrequest['nick']) response = "Registration successful. " elif authrequest['type'] == 'bcchangekey': gpgauth = self._ident(msg.prefix) if gpgauth is None: irc.error( "You must be authenticated in order to change your registered address." ) return if self.db.getByAddr(authrequest['bitcoinaddress']): irc.error( "This address is already registered. Try a different one.") return self.db.changeaddress(gpgauth['nick'], gpgauth['bitcoinaddress'], authrequest['bitcoinaddress']) response = "Successfully changed address for user %s from %s to %s. " %\ (gpgauth['nick'], gpgauth['bitcoinaddress'], authrequest['bitcoinaddress'],) userdata = self.db.getByNick(authrequest['nick']) self.authed_users[msg.prefix] = { 'timestamp': time.time(), 'keyid': userdata[0][1], 'nick': authrequest['nick'], 'bitcoinaddress': authrequest['bitcoinaddress'], 'fingerprint': userdata[0][2] } del self.pending_auth[msg.prefix] logmsg = "bcverify success from hostmask %s for user %s, address %s." %\ (msg.prefix, authrequest['nick'], authrequest['bitcoinaddress'],) + response self.authlog.info(logmsg) if not world.testing: irc.queueMsg(ircmsgs.privmsg("#bitcoin-otc-auth", logmsg)) irc.reply(response + "You are now authenticated for user '%s' with address %s" %\ (authrequest['nick'], authrequest['bitcoinaddress']))
def _send(self, irc, channel, line): msg = ircmsgs.privmsg(channel, line) irc.queueMsg(msg)
def testNoMsgLongerThan512(self): self.irc.queueMsg(ircmsgs.privmsg('whocares', 'x' * 1000)) msg = self.irc.takeMsg() self.failUnless(len(msg) <= 512, 'len(msg) was %s' % len(msg))
def reply(self, s): self.irc.queueMsg(ircmsgs.privmsg(self.channel, s))
def imdb(self, irc, msg, args, query): """ Queries OMDB api for query """ encoded_query = quote_plus(query) omdb_url = "http://www.omdbapi.com/?t=%s&y=&plot=short&r=json&tomatoes=true" % ( encoded_query) channel = msg.args[0] result = None headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.60 Safari/537.36" } self.log.info("IMDB: requesting %s" % omdb_url) try: request = requests.get(omdb_url, timeout=10, headers=headers) if request.status_code == requests.codes.ok: response = json.loads(request.text) not_found = "Error" in response unknown_error = response["Response"] != "True" if not_found or unknown_error: self.log.info("IMDB: OMDB error for %s" % (omdb_url)) else: imdb_template = self.registryValue("template") imdb_template = imdb_template.replace( "$title", response["Title"]) imdb_template = imdb_template.replace( "$year", response["Year"]) imdb_template = imdb_template.replace( "$country", response["Country"]) imdb_template = imdb_template.replace( "$director", response["Director"]) imdb_template = imdb_template.replace( "$plot", response["Plot"]) imdb_template = imdb_template.replace( "$imdbID", response["imdbID"]) imdb_template = imdb_template.replace( "$imdbRating", response["imdbRating"]) imdb_template = imdb_template.replace( "$tomatoMeter", response["tomatoMeter"]) imdb_template = imdb_template.replace( "$metascore", response["Metascore"]) result = imdb_template else: self.log.error("IMDB OMDB API %s - %s" % (request.status_code, request.text)) except requests.exceptions.Timeout as e: self.log.error("IMDB Timeout: %s" % (str(e))) except requests.exceptions.ConnectionError as e: self.log.error("IMDB ConnectionError: %s" % (str(e))) except requests.exceptions.HTTPError as e: self.log.error("IMDB HTTPError: %s" % (str(e))) finally: if result is not None: irc.sendMsg(ircmsgs.privmsg(channel, result)) else: irc.error(self.registryValue("noResultsMessage"))
def testIsCtcp(self): self.assertTrue(ircmsgs.isCtcp(ircmsgs.privmsg('foo', '\x01VERSION\x01'))) self.assertFalse(ircmsgs.isCtcp(ircmsgs.privmsg('foo', '\x01')))
def rate(self, irc, msg, args, nick, rating, notes): """<nick> <rating> [<notes>] Enters a rating for <nick> in the amount of <rating>. Use optional <notes> field to enter any notes you have about this user. <nick> must be the user's GPG-registered username, Your previously existing rating, if any, will be overwritten. """ if nick.upper() in self.registryValue('blockedNicks'): irc.noReply() return if irc.nested: irc.error("This command cannot be used in a nested context.") return gpgauth = self._checkGPGAuth(irc, msg.prefix) if gpgauth is None: irc.error("For identification purposes, you must be authenticated " "to use the rating system.") return userrating = self.db.get(gpgauth['nick']) if len(userrating) == 0: irc.error( "You have to have received some ratings in order to rate " "other users.") return trust = self._gettrust('nanotube', gpgauth['nick']) sumtrust = sum([t for t, n in trust]) if self.registryValue('requirePositiveRating') and sumtrust < 0: irc.error("You do not meet qualifications for entering ratings.") return if gpgauth['nick'].lower() == nick.lower(): irc.error("You cannot rate yourself.") return validratings = range(self.registryValue('ratingMin'), self.registryValue('ratingMax') + 1) validratings.remove(0) if rating not in validratings: irc.error("Rating must be in the interval [%s, %s] and cannot be zero." % \ (min(validratings), max(validratings))) return result = "Your rating of %s for user %s has been recorded." % ( rating, nick, ) sourceid = userrating[0][0] targetuserdata = self.db.get(nick) if len(targetuserdata) == 0: targetgpgdata = irc.getCallback('GPG').db.getByNick(nick) if len(targetgpgdata) == 0: irc.error( "User doesn't exist in the Rating or GPG databases. User must be " "GPG-registered to receive ratings.") return targetid = None replacementflag = False else: targetid = targetuserdata[0][0] priorrating = self.db.getExistingRating(sourceid, targetid) if len(priorrating) == 0: replacementflag = False else: replacementflag = True result = "Your rating for user %s has changed from %s to %s." % \ (nick, priorrating[0][4], rating,) self.db.rate(gpgauth['nick'], sourceid, nick, targetid, rating, replacementflag, notes) if not world.testing: if not replacementflag: logmsg = "New rating | %s > %s > %s | %s" % ( gpgauth['nick'], rating, nick, notes) else: logmsg = "Rating change | Old rating %s | New rating: %s > %s > %s | %s" % \ (priorrating[0][4], gpgauth['nick'], rating, nick, notes,) irc.queueMsg(ircmsgs.privmsg("#bitcoin-otc-ratings", logmsg)) irc.reply("Rating entry successful. %s" % (result, ))
def announce_entry(self, irc, channel, feed, entry): if self.should_send_entry(channel, entry): s = self.format_entry(channel, feed, entry, True) irc.queueMsg(ircmsgs.privmsg(channel, s))
def _reply(self, irc, msg, channel, text): """Send a response to text""" cobeBrain = Brain(self._getBrainDirectoryForChannel(channel)) response = cobeBrain.reply(text).encode('utf-8') response = self._strip_nick(irc, msg, response) for i in range(response.lower().count(self.magicnick.lower())): # If first word is nick, switch with the callers nick. if self.magicnick in response: response = response.replace( self.magicnick, re.sub( r'[Kk]', r'κ', re.sub(r'^(.)', r'\1', random.choice( list( irc.state.channels[msg.args[0]].users)), count=1))) if self.magicnick.lower() in response: response = response.replace( self.magicnick.lower(), re.sub( r'[Kk]', r'κ', re.sub(r'^(.)', r'\1', random.choice( list( irc.state.channels[msg.args[0]].users)), count=1))) if self.magicnick in response: response = response.replace( self.magicnick, re.sub( r'[Ee]', r'ε', re.sub(r'^(.)', r'\1', random.choice( list( irc.state.channels[msg.args[0]].users)), count=1))) if self.magicnick.lower() in response: response = response.replace( self.magicnick.lower(), re.sub( r'[Ee]', r'ε', re.sub(r'^(.)', r'\1', random.choice( list( irc.state.channels[msg.args[0]].users)), count=1))) cobeBrain.learn( response) # Let's have the bot learn the wacky things it says self.log.info("Attempting to respond in {0} with message: {1}".format( channel, response)) # lowercase first letter of the string. response = response[0].lower() + response[1:] # delay the response here so we look real? if self.registryValue('responseDelay', channel): self.log.info("Delayed the response in %s." % channel) delayseconds = time.time() + random.randint(2, 5) schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)), delayseconds) else: irc.queueMsg(ircmsgs.privmsg(channel, response))
def relay(self, irc, msg, channel=None): channel = (channel or msg.args[0]).lower() self.log.debug("RelayNext (%s): got channel %s", irc.network, channel) if not channel in irc.state.channels: return # Check for ignored events first. Checking for "'.' not in msg.nick" is for skipping # ignore checks from servers. ignoredevents = map(str.upper, self.registryValue('events.userIgnored', channel)) if msg.command in ignoredevents and msg.nick != irc.nick and '.' not in msg.nick and\ ircdb.checkIgnored(msg.prefix, channel): self.log.debug("RelayNext (%s): ignoring message from %s", irc.network, msg.prefix) return # Get the source channel source = "%s@%s" % (channel, irc.network) source = source.lower() out_s = self._format(irc, msg, channel) if out_s: for relay in self.db.values(): self.log.debug("RelayNext (%s): check if %s in %s", irc.network, source, relay) if source in relay: # If our channel is in a relay self.log.debug("RelayNext: found %s to be in relay %s", source, relay) # Remove ourselves from the target channels so we don't get duplicated messages targets = list(relay) targets.remove(source) self.log.debug("RelayNext: found targets %s for relay %s", targets, relay) if self.registryValue("antiflood.enable", channel): # Flood prevention timeout - how long commands of a certain type # should cease being relayed after flood prevention triggers timeout = self.registryValue("antiflood.timeout", channel) # If <maximum> messages of the same kind on one channel is # received in <seconds> seconds, flood prevention timeout is # triggered. maximum = self.registryValue("antiflood.maximum", channel) seconds = self.registryValue("antiflood.seconds", channel) # Store the message in a counter, with the keys taking the # form of (source channel@network, command name). If the counter # doesn't already exist, create one here. try: self.msgcounters[(source, msg.command)].enqueue(msg.prefix) except KeyError: self.msgcounters[( source, msg.command)] = TimeoutQueue(seconds) # Two different limits: one for messages and one for all others if msg.command == "PRIVMSG": maximum = self.registryValue( "antiflood.maximum", channel) else: maximum = self.registryValue( "antiflood.maximum.nonPrivmsgs", channel) if len(self.msgcounters[(source, msg.command)]) > maximum: # Amount of messages in the counter surpassed our limit, # announce the flood and block relaying messages of the # same type for X seconds self.log.debug( "RelayNext (%s): message from %s blocked by " "flood protection.", irc.network, channel) if self.floodTriggered.get((source, msg.command)): # However, only send the announcement once. return c = msg.command e = format( "Flood detected on %s (%s %ss/%s seconds), " "not relaying %ss for %s seconds!", channel, maximum, c, seconds, c, timeout) out_s = self._format(irc, msg, channel, announcement=e) self.floodTriggered[(source, msg.command)] = True self.log.info("RelayNext (%s): %s", irc.network, e) else: self.floodTriggered[(source, msg.command)] = False for cn in targets: # Iterate over all the relay targets for this message: # each target is stored internally as a #channel@netname # string. target, net = cn.split("@") otherIrc = world.getIrc(net) if otherIrc is None: self.log.debug( "RelayNext: message to network %r" " dropped, we are not connected " "there!", net) return target_chanobj = otherIrc.state.channels.get(target) if (not target_chanobj ) or otherIrc.nick not in target_chanobj.users: # We're not in the target relay channel! self.log.debug( "RelayNext: message to %s@%s " "dropped, we are not in that " "channel!", target, net) else: out_msg = ircmsgs.privmsg(target, out_s) # Tag the message as relayed so we (and other relayers) don't # try to relay it again. out_msg.tag('relayedMsg') otherIrc.queueMsg(out_msg)
def _announce(self, chan, msg): self.irc.sendMsg(ircmsgs.privmsg(chan, msg, "[trac]"))
def doPrivmsg(self, irc, msg): def beginswith(text, strings): for string in strings: if text.startswith(string): return True return False # Filter CTCP if chr(1) in msg.args[1]: return if checkIgnored(msg.prefix, msg.args[0]): return # Are we being queried? recipient, text = msg.args text = self.addressed(recipient, text, irc, msg) if not text: return doChanMsg = True display_info = False display_raw = False target = msg.args[0] if target[0] != '#': target = msg.nick channel = msg.args[0] # Strip leading nonalnums while text and not text[0].isalnum(): if text[0] == '-': if not display_raw: display_info = True if text[0] == '+': if not display_info: display_raw = True text = text[1:] if not text: return # Now switch between actions orig_text = text lower_text = text.lower() if "please see" in lower_text: if "from %s" % irc.nick.lower( ) in lower_text or "from the bot" in lower_text: doChanMsg = False ret = '' retmsg = '' term = self.get_target(msg.nick, orig_text, target) if term[0] == "search": # Usage info for the !search command ret = "Search factoids for term: !search <term>" retmsg = term[2] elif beginswith( lower_text, self.registryValue('ignores', channel) ): # Make sure ignores can ignore these built-in "facts" return elif term[0] in ("what", "whats", "what's") or term[0].startswith( "what ") or term[0].startswith("what ") or term[0].startswith( "whats ") or term[0].startswith( "what's " ): # Try and catch people saying "ubottu: what is ...?" ret = "I suck balls" retmsg = term[2] else: # Lookup, search or edit? if lower_text.startswith('search '): ret = self.search_factoid(lower_text[7:].strip(), channel) elif (' is ' in lower_text and lower_text[:3] in ('no ', 'no,')) or '<sed>' in lower_text or '=~' in lower_text \ or '~=' in lower_text or '<alias>' in lower_text or lower_text.startswith('forget') or lower_text.startswith('unforget'): if not (capab(msg.prefix, 'editfactoids') \ or channel in self.registryValue('editchannel') \ and capab(msg.prefix, 'restricted-editor')): irc.reply( "Your edit request has been forwarded to %s. Thank you for your attention to detail" % self.registryValue('relaychannel', channel), private=True) irc.queueMsg( ircmsgs.privmsg( self.registryValue('relaychannel', channel), "In %s, %s said: %s" % (msg.args[0], msg.nick, msg.args[1]))) self.logRequest(msg.args[0], msg.nick, text) return ret = self.factoid_edit(text, channel, msg.prefix) elif (' is ' in lower_text and '|' in lower_text and lower_text.index('|') > lower_text.index(' is ')) or ( ' is ' in lower_text and '|' not in lower_text): if not (capab(msg.prefix, 'editfactoids') \ or channel in self.registryValue('editchannel') \ and capab(msg.prefix, 'restricted-editor')): if len(text[:text.find('is')]) > 15: irc.error("I suck balls") else: irc.reply( "Your edit request has been forwarded to %s. Thank you for your attention to detail" % self.registryValue('relaychannel', channel), private=True) irc.queueMsg( ircmsgs.privmsg( self.registryValue('relaychannel', channel), "In %s, %s said: %s" % (msg.args[0], msg.nick, msg.args[1]))) self.logRequest(msg.args[0], msg.nick, text) return ret = self.factoid_add(text, channel, msg.prefix) else: text, target, retmsg = self.get_target(msg.nick, orig_text, target) if text.startswith('bug ') and text != ('bug 1'): return ret = self.factoid_lookup(text, channel, display_info, display_raw) if not ret: if len(text) > 15: irc.error("I suck balls") return retmsg = '' ret = self.registryValue('notfoundmsg') if ret.count('%') == ret.count('%s') == 1: ret = ret % repr(text) if channel.lower() == irc.nick.lower(): queue(irc, msg.nick, ret) elif self.registryValue('privateNotFound', channel): queue(irc, msg.nick, ret) else: queue(irc, channel, ret) return # check if retmsg has urls (possible spam) if checkUrl(retmsg): if self.alert and (target[0] == '#' and not target.endswith('bots')): # !ops factoid called with an url, most likely spam. # we filter the msg, but we still warn in -ops. queue( irc, self.registryValue('relayChannel', channel), '%s called the ops in %s (%s)' % (msg.nick, msg.args[0], retmsg[:-2])) self.alert = False # do nothing return if doChanMsg and channel.lower() != irc.nick.lower( ) and target[0] != '#': # not /msg if target in irc.state.channels[channel].users: queue(irc, channel, "%s, please see my private message" % target) if type(ret) != list: queue(irc, target, retmsg + ret) else: queue(irc, target, retmsg + ret[0]) if self.alert: if target.startswith('#') and not target.endswith('bots'): queue( irc, self.registryValue('relayChannel', channel), '%s called the ops in %s (%s)' % (msg.nick, msg.args[0], retmsg[:-2])) self.alert = False for r in ret[1:]: queue(irc, target, r)
def process_data(data, channel=None, eventType=None): brackets = parseBrackets(configValue('brackets')) themeName = configValue('theme') alphanumericPattern = re.compile('[\W_]+') themeClass = ''.join( [alphanumericPattern.sub('', themeName).title(), 'Theme']) # Find the theme's class try: mod = getattr(themes, themeClass) klass = getattr(mod, themeClass) except AttributeError: # The theme was not found log.error("The '%s' theme was not found" % themeName) klass = themes.DefaultTheme.DefaultTheme repo = {} repo['unknown'] = 'repository' not in data repo['name'] = data.get('repository', {}).get('name') repo['owner'] = data.get('repository', {}).get('owner', {}).get('login') repo['fork'] = data.get('repository', {}).get('fork', False) repo['id'] = data.get('repository', {}).get('id', "%s/%s" % (repo['owner'], repo['name'])) theme = klass(repo, brackets) # # Handle different event types # msgs = [] theme.msgs = msgs if 'matrix' in data: TravisHandler.handle(data, theme) elif 'pages' in data: WikiHandler.handle(data, theme) elif 'object_kind' in data and 'event_name' in data: if data['event_name'] == "push": GitlabPushHandler.handle(data, theme) else: data['eventType'] = data['event_name'] UnknownHandler.handle(data, theme) elif 'screenshot_url' in data: NetlifyHandler.handle(data, theme) elif 'state' in data: StatusHandler.handle(data, theme) elif 'commits' in data: PushHandler.handle(data, theme) elif 'issue' in data or 'pull_request' in data: if 'comment' in data: IssueCommentHandler.handle(data, theme) else: IssueHandler.handle(data, theme) elif 'ref_type' in data: CreateDeleteHandler.handle(data, theme) elif 'release' in data: ReleaseHandler.handle(data, theme) elif 'zen' in data: PingHandler.handle(data, theme) elif 'message' in data: MessageHandler.handle(data, theme) elif 'eventName' in data: AppVeyorHandler.handle(data, theme) else: data['eventType'] = eventType UnknownHandler.handle(data, theme) theme.finalize() saveMessages(msgs) if not world.testing: for msg in msgs: for irc in world.ircs: irc.queueMsg( ircmsgs.privmsg(channel or globals.channel, msg))
def testIsActionIsntStupid(self): m = ircmsgs.privmsg('#x', '\x01NOTANACTION foo\x01') self.assertFalse(ircmsgs.isAction(m)) m = ircmsgs.privmsg('#x', '\x01ACTION foo bar\x01') self.assertTrue(ircmsgs.isAction(m))
def _announce_build_status(self, status): msg = '\x02[Nightly builds]\x02 %s' % status for (server, channel) in (('freenode', '#limnoria'),): world.getIrc(server).sendMsg(ircmsgs.privmsg(channel, msg))
def testPrivmsg(self): self.assertEqual(str(ircmsgs.privmsg('foo', 'bar')), 'PRIVMSG foo :bar\r\n') self.assertEqual(str(ircmsgs.privmsg('foo,bar', 'baz')), 'PRIVMSG foo,bar :baz\r\n')
def detonate(self, irc): self.active = False self.thrown = False if self.showCorrectWire: self.irc.reply('Should\'ve gone for the %s wire!' % self.goodWire) if self.showArt: self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1.....\x0315,1_.\x0314,1-^^---....,\x0315,1,-_\x031,1.......' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1.\x0315,1_--\x0314,1,.\';,`.,\';,.;;`;,.\x0315,1--_\x031,1...' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x0315,1<,.\x0314,1;\'`".,;`..,;`*.,\';`.\x0315,1;\'>)\x031,1.' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x0315,1I.:;\x0314,1.,`;~,`.;\'`,.;\'`,..\x0315,1\';`I\x031,1.' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1.\x0315,1\\_.\x0314,1`\'`..`\';.,`\';,`\';,\x0315,1_../\x031,1..' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1....\x0315,1```\x0314,1--. . , ; .--\x0315,1\'\'\'\x031,1.....' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1..........\x034,1I\x031,1.\x038,1I\x037,1I\x031,1.\x038,1I\x034,1I\x031,1...........' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1..........\x034,1I\x031,1.\x037,1I\x038,1I\x031,1.\x037,1I\x034,1I\x031,1...........' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1.......,\x034,1-=\x034,1II\x037,1..I\x034,1.I=-,\x031,1........' )) self.irc.sendMsg( ircmsgs.privmsg( self.channel, '\x031,1.......\x034,1`-=\x037,1#$\x038,1%&\x037,1%$#\x034,1=-\'\x031,1........' )) else: self.irc.sendMsg(ircmsgs.privmsg(self.channel, 'KABOOM!')) #self.irc.queueMsg(ircmsgs.kick(self.channel, self.victim, 'BOOM!')) def reinvite(): if not self.victim in irc.state.channels[self.channel].users: self.irc.queueMsg(ircmsgs.invite(self.victim, self.channel)) if not self.responded: schedule.addEvent(reinvite, time.time() + 5)
def privmsg(self, network, personorchannel, message): target_irc, target = self._get_irc_and_target(network, personorchannel) msg = ircmsgs.privmsg(target, message) target_irc.sendMsg(msg)
def verify(self, irc, msg, args, url): """<url> Verify the latest authentication request by providing a pastebin <url> which contains the challenge string clearsigned with your GPG key of record. If verified, you'll be authenticated for the duration of the bot's or your IRC session on channel (whichever is shorter). """ self._removeExpiredRequests() if not self._checkURLWhitelist(url): irc.error("Only these pastebins are supported: %s" % \ self.registryValue('pastebinWhitelist')) return if not self._testPresenceInChannels(irc, msg.nick): irc.error("In order to authenticate, you must be present in one " "of the following channels: %s" % (self.registryValue('channels'), )) return try: authrequest = self.pending_auth[msg.prefix] except KeyError: irc.error( "Could not find a pending authentication request from your hostmask. " "Either it expired, or you changed hostmask, or you haven't made one." ) return if authrequest['type'] not in ['register', 'auth', 'changekey']: irc.error("No outstanding GPG signature-based request found.") return try: rawdata = utils.web.getUrl(url) m = re.search( r'-----BEGIN PGP SIGNED MESSAGE-----\r?\nHash.*?\n-----END PGP SIGNATURE-----', rawdata, re.S) data = m.group(0) except: irc.error("Failed to retrieve clearsigned data. Check your url.") return if authrequest['challenge'] not in data: irc.error("Challenge string not present in signed message.") return try: vo = self.gpg.verify(data) if not vo.valid: irc.error("Signature verification failed.") self.log.info("Signature verification from %s failed. Details: %s" % \ (msg.prefix, vo.stderr)) return if vo.key_id != authrequest['keyid'] and vo.pubkey_fingerprint[ -16:] != authrequest['keyid']: irc.error( "Signature is not made with the key on record for this nick." ) return except: irc.error("Authentication failed. Please try again.") return response = "" if authrequest['type'] == 'register': if self.db.getByNick(authrequest['nick']) or self.db.getByKey( authrequest['keyid']): irc.error("Username or key already in the database.") return self.db.register(authrequest['keyid'], authrequest['fingerprint'], None, time.time(), authrequest['nick']) response = "Registration successful. " elif authrequest['type'] == 'changekey': gpgauth = self._ident(msg.prefix) if gpgauth is None: irc.error( "You must be authenticated in order to change your registered key." ) return if self.db.getByKey(authrequest['keyid']): irc.error( "This key id already registered. Try a different key.") return self.db.changekey(gpgauth['nick'], gpgauth['keyid'], authrequest['keyid'], authrequest['fingerprint']) response = "Successfully changed key for user %s from %s to %s. " %\ (gpgauth['nick'], gpgauth['keyid'], authrequest['keyid'],) userdata = self.db.getByNick(authrequest['nick']) self.authed_users[msg.prefix] = { 'timestamp': time.time(), 'keyid': authrequest['keyid'], 'nick': authrequest['nick'], 'bitcoinaddress': userdata[0][3], 'fingerprint': authrequest['fingerprint'] } del self.pending_auth[msg.prefix] logmsg = "verify success from hostmask %s for user %s, keyid %s." %\ (msg.prefix, authrequest['nick'], authrequest['keyid'],) + response self.authlog.info(logmsg) if not world.testing: irc.queueMsg(ircmsgs.privmsg("#bitcoin-otc-auth", logmsg)) irc.reply(response + "You are now authenticated for user '%s' with key %s" %\ (authrequest['nick'], authrequest['keyid']))
class IrcMsgQueueTestCase(SupyTestCase): mode = ircmsgs.op('#foo', 'jemfinch') msg = ircmsgs.privmsg('#foo', 'hey, you') msgs = [ircmsgs.privmsg('#foo', str(i)) for i in range(10)] kick = ircmsgs.kick('#foo', 'PeterB') pong = ircmsgs.pong('123') ping = ircmsgs.ping('123') topic = ircmsgs.topic('#foo') notice = ircmsgs.notice('jemfinch', 'supybot here') join = ircmsgs.join('#foo') who = ircmsgs.who('#foo') def testInit(self): q = irclib.IrcMsgQueue([self.msg, self.topic, self.ping]) self.assertEqual(len(q), 3) def testLen(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) self.assertEqual(len(q), 1) q.enqueue(self.mode) self.assertEqual(len(q), 2) q.enqueue(self.kick) self.assertEqual(len(q), 3) q.enqueue(self.topic) self.assertEqual(len(q), 4) q.dequeue() self.assertEqual(len(q), 3) q.dequeue() self.assertEqual(len(q), 2) q.dequeue() self.assertEqual(len(q), 1) q.dequeue() self.assertEqual(len(q), 0) def testContains(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) q.enqueue(self.msg) q.enqueue(self.msg) self.failUnless(self.msg in q) q.dequeue() self.failUnless(self.msg in q) q.dequeue() self.failUnless(self.msg in q) q.dequeue() self.failIf(self.msg in q) def testRepr(self): q = irclib.IrcMsgQueue() self.assertEqual(repr(q), 'IrcMsgQueue([])') q.enqueue(self.msg) try: repr(q) except Exception as e: self.fail('repr(q) raised an exception: %s' % utils.exnToString(e)) def testEmpty(self): q = irclib.IrcMsgQueue() self.failIf(q) def testEnqueueDequeue(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) self.failUnless(q) self.assertEqual(self.msg, q.dequeue()) self.failIf(q) q.enqueue(self.msg) q.enqueue(self.notice) self.assertEqual(self.msg, q.dequeue()) self.assertEqual(self.notice, q.dequeue()) for msg in self.msgs: q.enqueue(msg) for msg in self.msgs: self.assertEqual(msg, q.dequeue()) def testPrioritizing(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) q.enqueue(self.mode) self.assertEqual(self.mode, q.dequeue()) self.assertEqual(self.msg, q.dequeue()) q.enqueue(self.msg) q.enqueue(self.kick) self.assertEqual(self.kick, q.dequeue()) self.assertEqual(self.msg, q.dequeue()) q.enqueue(self.ping) q.enqueue(self.msgs[0]) q.enqueue(self.kick) q.enqueue(self.msgs[1]) q.enqueue(self.mode) self.assertEqual(self.kick, q.dequeue()) self.assertEqual(self.mode, q.dequeue()) self.assertEqual(self.ping, q.dequeue()) self.assertEqual(self.msgs[0], q.dequeue()) self.assertEqual(self.msgs[1], q.dequeue()) def testNoIdenticals(self): configVar = conf.supybot.protocols.irc.queuing.duplicates original = configVar() try: configVar.setValue(True) q = irclib.IrcMsgQueue() q.enqueue(self.msg) q.enqueue(self.msg) self.assertEqual(self.msg, q.dequeue()) self.failIf(q) finally: configVar.setValue(original) def testJoinBeforeWho(self): q = irclib.IrcMsgQueue() q.enqueue(self.join) q.enqueue(self.who) self.assertEqual(self.join, q.dequeue()) self.assertEqual(self.who, q.dequeue()) ## q.enqueue(self.who) ## q.enqueue(self.join) ## self.assertEqual(self.join, q.dequeue()) ## self.assertEqual(self.who, q.dequeue()) def testTopicBeforePrivmsg(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) q.enqueue(self.topic) self.assertEqual(self.topic, q.dequeue()) self.assertEqual(self.msg, q.dequeue()) def testModeBeforePrivmsg(self): q = irclib.IrcMsgQueue() q.enqueue(self.msg) q.enqueue(self.mode) self.assertEqual(self.mode, q.dequeue()) self.assertEqual(self.msg, q.dequeue()) q.enqueue(self.mode) q.enqueue(self.msg) self.assertEqual(self.mode, q.dequeue()) self.assertEqual(self.msg, q.dequeue())
def everify(self, irc, msg, args, otp): """<otp> Verify the latest encrypt-authentication request by providing your decrypted one-time password. If verified, you'll be authenticated for the duration of the bot's or your IRC session on channel (whichever is shorter). """ self._removeExpiredRequests() if not self._testPresenceInChannels(irc, msg.nick): irc.error("In order to authenticate, you must be present in one " "of the following channels: %s" % (self.registryValue('channels'), )) return try: authrequest = self.pending_auth[msg.prefix] except KeyError: irc.error( "Could not find a pending authentication request from your hostmask. " "Either it expired, or you changed hostmask, or you haven't made one." ) return if authrequest['type'] not in ['eregister', 'eauth', 'echangekey']: irc.error("No outstanding encryption-based request found.") return if authrequest['challenge'] != otp: irc.error("Incorrect one-time password. Try again.") return response = "" if authrequest['type'] == 'eregister': if self.db.getByNick(authrequest['nick']) or self.db.getByKey( authrequest['keyid']): irc.error("Username or key already in the database.") return self.db.register(authrequest['keyid'], authrequest['fingerprint'], None, time.time(), authrequest['nick']) response = "Registration successful. " elif authrequest['type'] == 'echangekey': gpgauth = self._ident(msg.prefix) if gpgauth is None: irc.error( "You must be authenticated in order to change your registered key." ) return if self.db.getByKey(authrequest['keyid']): irc.error( "This key id already registered. Try a different key.") return self.db.changekey(gpgauth['nick'], gpgauth['keyid'], authrequest['keyid'], authrequest['fingerprint']) response = "Successfully changed key for user %s from %s to %s. " %\ (gpgauth['nick'], gpgauth['keyid'], authrequest['keyid'],) userdata = self.db.getByNick(authrequest['nick']) self.authed_users[msg.prefix] = { 'timestamp': time.time(), 'keyid': authrequest['keyid'], 'nick': authrequest['nick'], 'bitcoinaddress': userdata[0][3], 'fingerprint': authrequest['fingerprint'] } del self.pending_auth[msg.prefix] logmsg = "everify success from hostmask %s for user %s, keyid %s." %\ (msg.prefix, authrequest['nick'], authrequest['keyid'],) + response self.authlog.info(logmsg) if not world.testing: irc.queueMsg(ircmsgs.privmsg("#bitcoin-otc-auth", logmsg)) irc.reply(response + "You are now authenticated for user %s with key %s" %\ (authrequest['nick'], authrequest['keyid']))
def cbb(self, irc, msg, args, options, team=None): """[--date] [--all] [team] Fetches college basketball scores/schedule for given date and/or team. Defaults to today and top 25 teams (if playing, otherwise shows all games). Use --all to show results for all teams. """ channel = msg.args[0] if channel == irc.nick: channel = msg.nick options = dict(options) date = options.get('date') if 'all' in options: all = True else: all = False if date: if date.lower() in ['yesterday', 'tomorrow', 'today']: if date.lower() in 'yesterday': date = pendulum.yesterday().format('YYYYMMDD') elif date.lower() in 'tomorrow': date = pendulum.tomorrow().format('YYYYMMDD') else: date = pendulum.now().format('YYYYMMDD') else: try: date = pendulum.parse(date, strict=False).format('YYYYMMDD') except: irc.reply('Invalid date format') return SCORES = self._checkscores(date) if date not in SCORES: niceDate = pendulum.parse(date) niceDate = "{0}/{1}/{2}".format(niceDate.month, niceDate.day, niceDate.year) irc.reply('No games found for {}.'.format(date)) else: today = pendulum.now().format('YYYYMMDD') yesterday = pendulum.yesterday().format('YYYYMMDD') tomorrow = date = pendulum.tomorrow().format('YYYYMMDD') SCORES = self._checkscores() if today in SCORES: date = today elif yesterday in SCORES: date = yesterday elif tomorrow in SCORES: date = tomorrow else: irc.reply('No games found.') return if team: if len(team) > 2: reply = [] # single team for key, value in SCORES[date].items(): if team.lower() in value['lookup']['abbr'].lower(): #print(team.lower(), '\t', value['lookup']['abbr'].lower()) reply.append(value['long']) #break if not reply: for key, value in SCORES[date].items(): if team.lower() in value['lookup']['full'].lower(): reply.append(value['long']) #break if not reply: irc.reply( 'ERROR: no match found for your input: {}'.format( team)) return else: if len(reply) <= 4: for item in reply: irc.sendMsg(ircmsgs.privmsg(channel, item)) else: for item in reply: irc.reply(item) return else: irc.reply('ERROR: search string too short') return else: niceDate = pendulum.parse(date) niceDate = "{0}/{1}/{2}".format(niceDate.month, niceDate.day, niceDate.year) reply = ' | '.join(value['short'] for item, value in SCORES[date].items() if value['top25']) if reply and not all: irc.reply( "Showing teams in the top 25 for {0}. Use --all to see more games." .format(niceDate), prefixNick=False) irc.reply(reply, prefixNick=False) else: reply = ' | '.join(value['short'] for item, value in SCORES[date].items()) irc.reply("Showing all games for {0}.".format(niceDate), prefixNick=False) irc.reply(reply, prefixNick=False) return return
def _msg(self, recip, msg): self.irc.queueMsg(ircmsgs.privmsg(recip, msg))