From 90cb234d1aff2154cab4bb11ce7ce30e483c4686 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Mon, 2 Jan 2012 21:18:32 -0500 Subject: [PATCH 01/14] reply instead of say, for some reason apparently --- .gitignore | 2 ++ modules/oblique.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f3d74a9a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*~ diff --git a/modules/oblique.py b/modules/oblique.py index 7bd67188b..b3059717f 100755 --- a/modules/oblique.py +++ b/modules/oblique.py @@ -43,7 +43,7 @@ def service(phenny, input, command, args): lines = bytes.splitlines() if not lines: return phenny.reply("Sorry, the service didn't respond any output.") - phenny.say(lines[0][:350]) + phenny.reply(lines[0][:350]) def refresh(phenny): if hasattr(phenny.config, 'services'): From 43516667d4d4df749baa436712f8ca0ac8ee3eb1 Mon Sep 17 00:00:00 2001 From: "Sean B. Palmer" Date: Tue, 15 Nov 2011 21:56:43 +0800 Subject: [PATCH 02/14] Fix to line length limit code. --- irc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/irc.py b/irc.py index e6008e0e8..767aa27f6 100755 --- a/irc.py +++ b/irc.py @@ -49,8 +49,9 @@ def __write(self, args, text=None): # print '%r %r %r' % (self, args, text) try: if text is not None: - self.push((' '.join(args) + ' :' + text)[:512] + '\r\n') - else: self.push(' '.join(args)[:512] + '\r\n') + # 510 because CR and LF count too, as nyuszika7h points out + self.push((' '.join(args) + ' :' + text)[:510] + '\r\n') + else: self.push(' '.join(args)[:510] + '\r\n') except IndexError: pass From 1c48c811724e678e876208e1458bb81390c8bdf5 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Tue, 3 Jan 2012 10:25:23 -0500 Subject: [PATCH 03/14] Fix to translate.py (from sbp commit 3724ba37cd02a2bf57012839f84c627eb5df65a2, with fix) --- modules/translate.py | 47 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/modules/translate.py b/modules/translate.py index d5ae41f27..968cd63ba 100755 --- a/modules/translate.py +++ b/modules/translate.py @@ -11,22 +11,30 @@ import re, urllib import web -def detect(text): - uri = 'http://ajax.googleapis.com/ajax/services/language/detect' - q = urllib.quote(text) - bytes = web.get(uri + '?q=' + q + '&v=1.0') - result = web.json(bytes) - try: return result['responseData']['language'] - except Exception: return None - -def translate(text, input, output): - uri = 'http://ajax.googleapis.com/ajax/services/language/translate' - q = urllib.quote(text) - pair = input + '%7C' + output - bytes = web.get(uri + '?q=' + q + '&v=1.0&langpair=' + pair) - result = web.json(bytes) - try: return result['responseData']['translatedText'].encode('cp1252') - except Exception: return None +def translate(text, input='auto', output='en'): + import urllib2, json + opener = urllib2.build_opener() + opener.addheaders = [( + 'User-Agent', 'Mozilla/5.0' + + '(X11; U; Linux i686)' + + 'Gecko/20071127 Firefox/2.0.0.11' + )] + + input, output = urllib.quote(input), urllib.quote(output) + text = urllib.quote(text) + + result = opener.open('http://translate.google.com/translate_a/t?' + + ('client=t&hl=en&sl=%s&tl=%s&multires=1' % (input, output)) + + ('&otf=1&ssel=0&tsel=0&uptl=en&sc=1&text=%s' % text)).read() + + while ',,' in result: + result = result.replace(',,', ',null,') + data = json.loads(result) + + try: language = data[-2][0][0] + except: language = '?' + + return ''.join(x[0] for x in data[0]), language def tr(phenny, context): """Translates a phrase, with an optional language hint.""" @@ -37,15 +45,12 @@ def tr(phenny, context): if (len(phrase) > 350) and (not context.admin): return phenny.reply('Phrase must be under 350 characters.') - input = input or detect(phrase) - if not input: - err = 'Unable to guess your crazy moon language, sorry.' - return phenny.reply(err) + input = input or 'auto' input = input.encode('utf-8') output = (output or 'en').encode('utf-8') if input != output: - msg = translate(phrase, input, output) + msg, input = translate(phrase, input, output) if isinstance(msg, str): msg = msg.decode('utf-8') if msg: From 24db1caad5c63cb6ac451169acd7232691910d08 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Mon, 9 Jan 2012 10:18:53 -0500 Subject: [PATCH 04/14] Attempt to combat mysterious phenny-hangs. Don't know if it's working. --- bot.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ irc.py | 2 ++ 2 files changed, 47 insertions(+) diff --git a/bot.py b/bot.py index 453dbc4d7..2be8188d6 100755 --- a/bot.py +++ b/bot.py @@ -27,6 +27,7 @@ def __init__(self, config): self.config = config self.doc = {} self.stats = {} + self.internals = {} self.setup() def setup(self): @@ -70,6 +71,50 @@ def setup(self): print >> sys.stderr, 'Registered modules:', ', '.join(modules) else: print >> sys.stderr, "Warning: Couldn't find any modules" + if hasattr(self.config, 'refresh_delay'): + # Ping repeatedly to make sure we're still connected, and if + # not, disconnect and wait to be restarted. + # I haven't gotten this to test properly yet. I tended to have + # a problem that phenny would sort of hang after a long idle, + # and this was supposed to correct that. But now I'm not getting + # the hanging problem, so this hasn't been triggered to check + # if it works. It's probably the pings. --clsn + refresh_delay=300.0 + try: + refresh_delay=float(self.config.refresh_delay) + except: + pass + + def pingloop(): + self.internals['phennydeath']=threading.Timer(refresh_delay,killme,()) + # Should be in its own member, really. + self.internals['phennydeath'].start() + print "\tsending ping" + self.write(('PING', self.config.host)) + + self.internals['pingloop']=pingloop + + def killme(): + # can we restart from scratch this way? + print "RESTARTING PHENNY." + self.handle_close() + # Then the Watcher should restart, yes? + + import time + def pong(phen, inp): + print "Been ponged" + try: + self.internals['phennydeath'].cancel() + time.sleep(refresh_delay+60.0) + pingloop() + except: + pass + pong.event='PONG' + pong.priority='high' + pong.thread=True + pong.rule=r'.*' + self.variables['pong']=pong + self.bind_commands() def register(self, variables): diff --git a/irc.py b/irc.py index 767aa27f6..4d21ec710 100755 --- a/irc.py +++ b/irc.py @@ -88,6 +88,8 @@ def handle_connect(self): self.write(('PASS', self.password)) self.write(('NICK', self.nick)) self.write(('USER', self.user, '+iw', self.nick), self.name) + if hasattr(self,'internals') and self.internals.get('pingloop'): + self.internals['pingloop']() def handle_close(self): self.close() From ef5d8caf78d9a157d0d5ed7c238b0129376b7113 Mon Sep 17 00:00:00 2001 From: "Sean B. Palmer" Date: Wed, 11 Jan 2012 22:18:34 +0800 Subject: [PATCH 05/14] New .tr syntax for translations --- modules/clock.py | 1 + modules/search.py | 2 ++ modules/translate.py | 48 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/clock.py b/modules/clock.py index f8484234d..91f2d5b57 100755 --- a/modules/clock.py +++ b/modules/clock.py @@ -280,6 +280,7 @@ def tock(phenny, input): def npl(phenny, input): """Shows the time from NPL's SNTP server.""" + # for server in ('ntp1.npl.co.uk', 'ntp2.npl.co.uk'): client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) client.sendto('\x1b' + 47 * '\0', ('ntp1.npl.co.uk', 123)) data, address = client.recvfrom(1024) diff --git a/modules/search.py b/modules/search.py index bfc50bd24..13fadbb36 100755 --- a/modules/search.py +++ b/modules/search.py @@ -20,6 +20,8 @@ def http_error_default(self, url, fp, errcode, errmsg, headers): def google_ajax(query): """Search using AjaxSearch, and return its JSON.""" + if isinstance(query, unicode): + query = query.encode('utf-8') uri = 'http://ajax.googleapis.com/ajax/services/search/web' args = '?v=1.0&safe=off&q=' + web.urllib.quote(query) handler = web.urllib._urlopener diff --git a/modules/translate.py b/modules/translate.py index 968cd63ba..ec59db0e8 100755 --- a/modules/translate.py +++ b/modules/translate.py @@ -12,6 +12,11 @@ import web def translate(text, input='auto', output='en'): + raw = False + if output.endswith('-raw'): + output = output[:-4] + raw = True + import urllib2, json opener = urllib2.build_opener() opener.addheaders = [( @@ -31,7 +36,10 @@ def translate(text, input='auto', output='en'): result = result.replace(',,', ',null,') data = json.loads(result) - try: language = data[-2][0][0] + if raw: + return str(data), 'en-raw' + + try: language = data[2] # -2][0][0] except: language = '?' return ''.join(x[0] for x in data[0]), language @@ -61,10 +69,46 @@ def tr(phenny, context): phenny.reply(msg) else: phenny.reply('Language guessing failed, so try suggesting one!') -tr.rule = ('$nick', ur'(?:([a-z]{2}) +)?(?:([a-z]{2}) +)?["“](.+?)["”]\? *$') +tr.rule = ('$nick', ur'(?:([a-z]{2}) +)?(?:([a-z]{2}|en-raw) +)?["“](.+?)["”]\? *$') tr.example = '$nickname: "mon chien"? or $nickname: fr "mon chien"?' tr.priority = 'low' +def tr2(phenny, input): + """Translates a phrase, with an optional language hint.""" + command = input.group(2).encode('utf-8') + + def langcode(p): + return p.startswith(':') and (2 < len(p) < 10) and p[1:].isalpha() + + args = ['auto', 'en'] + + for i in xrange(2): + if not ' ' in command: break + prefix, cmd = command.split(' ', 1) + if langcode(prefix): + args[i] = prefix[1:] + command = cmd + phrase = command + + if (len(phrase) > 350) and (not context.admin): + return phenny.reply('Phrase must be under 350 characters.') + + src, dest = args + if src != dest: + msg, src = translate(phrase, src, dest) + if isinstance(msg, str): + msg = msg.decode('utf-8') + if msg: + msg = web.decode(msg) # msg.replace(''', "'") + msg = '"%s" (%s to %s, translate.google.com)' % (msg, src, dest) + else: msg = 'The %s to %s translation failed, sorry!' % (src, dest) + + phenny.reply(msg) + else: phenny.reply('Language guessing failed, so try suggesting one!') + +tr2.commands = ['tr'] +tr2.priority = 'low' + def mangle(phenny, input): phrase = input.group(2).encode('utf-8') for lang in ['fr', 'de', 'es', 'it', 'ja']: From 2601923640f4402e908c455eb6af87179db44dc1 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Thu, 12 Jan 2012 09:06:19 -0500 Subject: [PATCH 06/14] Moved the refresh stuff into startup, so it isn't messing up the class defs. --- bot.py | 44 ---------------------------------------- irc.py | 2 -- modules/startup.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/bot.py b/bot.py index 2be8188d6..b71270ccd 100755 --- a/bot.py +++ b/bot.py @@ -71,50 +71,6 @@ def setup(self): print >> sys.stderr, 'Registered modules:', ', '.join(modules) else: print >> sys.stderr, "Warning: Couldn't find any modules" - if hasattr(self.config, 'refresh_delay'): - # Ping repeatedly to make sure we're still connected, and if - # not, disconnect and wait to be restarted. - # I haven't gotten this to test properly yet. I tended to have - # a problem that phenny would sort of hang after a long idle, - # and this was supposed to correct that. But now I'm not getting - # the hanging problem, so this hasn't been triggered to check - # if it works. It's probably the pings. --clsn - refresh_delay=300.0 - try: - refresh_delay=float(self.config.refresh_delay) - except: - pass - - def pingloop(): - self.internals['phennydeath']=threading.Timer(refresh_delay,killme,()) - # Should be in its own member, really. - self.internals['phennydeath'].start() - print "\tsending ping" - self.write(('PING', self.config.host)) - - self.internals['pingloop']=pingloop - - def killme(): - # can we restart from scratch this way? - print "RESTARTING PHENNY." - self.handle_close() - # Then the Watcher should restart, yes? - - import time - def pong(phen, inp): - print "Been ponged" - try: - self.internals['phennydeath'].cancel() - time.sleep(refresh_delay+60.0) - pingloop() - except: - pass - pong.event='PONG' - pong.priority='high' - pong.thread=True - pong.rule=r'.*' - self.variables['pong']=pong - self.bind_commands() def register(self, variables): diff --git a/irc.py b/irc.py index 4d21ec710..767aa27f6 100755 --- a/irc.py +++ b/irc.py @@ -88,8 +88,6 @@ def handle_connect(self): self.write(('PASS', self.password)) self.write(('NICK', self.nick)) self.write(('USER', self.user, '+iw', self.nick), self.name) - if hasattr(self,'internals') and self.internals.get('pingloop'): - self.internals['pingloop']() def handle_close(self): self.close() diff --git a/modules/startup.py b/modules/startup.py index 6fc7faef8..2549f67a2 100755 --- a/modules/startup.py +++ b/modules/startup.py @@ -7,6 +7,56 @@ http://inamidst.com/phenny/ """ +import threading + +def setup(phenny): + if hasattr(phenny.config, 'refresh_delay'): + # Ping repeatedly to make sure we're still connected, and if + # not, disconnect and wait to be restarted. + refresh_delay=300.0 + try: + refresh_delay=float(phenny.config.refresh_delay) + except: + pass + + def pingloop(): + phenny.internals['phennydeath']=threading.Timer(refresh_delay,killme,()) + phenny.internals['phennydeath'].start() + print "\tsending ping" + phenny.write(('PING', phenny.config.host)) + + phenny.internals['pingloop']=pingloop + + def killme(): + # can we restart from scratch this way? + print "RESTARTING PHENNY." + phenny.handle_close() + # Then the Watcher should restart, yes? + + import time + def pong(phen, inp): + print "Been ponged" + try: + phenny.internals['phennydeath'].cancel() + time.sleep(refresh_delay+60.0) + pingloop() + except: + pass + pong.event='PONG' + pong.priority='high' + pong.thread=True + pong.rule=r'.*' + phenny.variables['pong']=pong + + # Need to wrap handle_connect to start the loop. + hc=phenny.handle_connect + def new_hc(): + hc() + if hasattr(phenny,'internals') and phenny.internals.get('pingloop'): + phenny.internals['pingloop']() + phenny.handle_connect=new_hc + + def startup(phenny, input): if hasattr(phenny.config, 'serverpass'): phenny.write(('PASS', phenny.config.serverpass)) From 8390cc673dfb3150766e0dd1598b455f7e774622 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Thu, 12 Jan 2012 12:13:25 -0500 Subject: [PATCH 07/14] Add cute joke for timotimo. --- modules/codepoints.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/codepoints.py b/modules/codepoints.py index eb9c8bfa8..cfca1edf6 100755 --- a/modules/codepoints.py +++ b/modules/codepoints.py @@ -74,6 +74,10 @@ def u(phenny, input): if len(arg) > 1: return phenny.reply('%s SPACEs (U+0020)' % len(arg)) return phenny.reply('1 SPACE (U+0020)') + # Request from timotimo: + if arg.strip() == 'm': + return phenny.say("U+006D LATIN SMALL LIGATURE RN (m)") + # @@ space if set(arg.upper()) - set( 'ABCDEFGHIJKLMNOPQRSTUVWYXYZ0123456789- .?+*{}[]\\/^$'): From b370095ef132f817d52ad28ebfea9a75b231e4f7 Mon Sep 17 00:00:00 2001 From: "Sean B. Palmer" Date: Sun, 15 Jan 2012 06:55:59 +0800 Subject: [PATCH 08/14] Making the PING-loop optional --- modules/startup.py | 56 ++++++++++++++++++++++---------------------- modules/translate.py | 2 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/modules/startup.py b/modules/startup.py index e65017062..48c5fc9e4 100755 --- a/modules/startup.py +++ b/modules/startup.py @@ -18,39 +18,39 @@ def setup(phenny): try: refresh_delay = float(phenny.config.refresh_delay) except: pass - def close(): - print "Nobody PONGed our PING, restarting" - phenny.handle_close() + def close(): + print "Nobody PONGed our PING, restarting" + phenny.handle_close() - def pingloop(): - timer = threading.Timer(refresh_delay, close, ()) - phenny.data['startup.setup.timer'] = timer - phenny.data['startup.setup.timer'].start() - # print "PING!" - phenny.write(('PING', phenny.config.host)) - phenny.data['startup.setup.pingloop'] = pingloop + def pingloop(): + timer = threading.Timer(refresh_delay, close, ()) + phenny.data['startup.setup.timer'] = timer + phenny.data['startup.setup.timer'].start() + # print "PING!" + phenny.write(('PING', phenny.config.host)) + phenny.data['startup.setup.pingloop'] = pingloop - def pong(phenny, input): - try: - # print "PONG!" - phenny.data['startup.setup.timer'].cancel() - time.sleep(refresh_delay + 60.0) - pingloop() - except: pass - pong.event = 'PONG' - pong.thread = True - pong.rule = r'.*' - phenny.variables['pong'] = pong + def pong(phenny, input): + try: + # print "PONG!" + phenny.data['startup.setup.timer'].cancel() + time.sleep(refresh_delay + 60.0) + pingloop() + except: pass + pong.event = 'PONG' + pong.thread = True + pong.rule = r'.*' + phenny.variables['pong'] = pong - # Need to wrap handle_connect to start the loop. - inner_handle_connect = phenny.handle_connect + # Need to wrap handle_connect to start the loop. + inner_handle_connect = phenny.handle_connect - def outer_handle_connect(): - inner_handle_connect() - if phenny.data.get('startup.setup.pingloop'): - phenny.data['startup.setup.pingloop']() + def outer_handle_connect(): + inner_handle_connect() + if phenny.data.get('startup.setup.pingloop'): + phenny.data['startup.setup.pingloop']() - phenny.handle_connect = outer_handle_connect + phenny.handle_connect = outer_handle_connect def startup(phenny, input): if hasattr(phenny.config, 'serverpass'): diff --git a/modules/translate.py b/modules/translate.py index ec59db0e8..94e5f6458 100755 --- a/modules/translate.py +++ b/modules/translate.py @@ -90,7 +90,7 @@ def langcode(p): command = cmd phrase = command - if (len(phrase) > 350) and (not context.admin): + if (len(phrase) > 350) and (not input.admin): return phenny.reply('Phrase must be under 350 characters.') src, dest = args From 9b463346c678d459bc4e5e1de15bdf8235052609 Mon Sep 17 00:00:00 2001 From: Ori Rawlings Date: Wed, 30 Mar 2011 04:03:29 +0800 Subject: [PATCH 09/14] Added karma module --- modules/karma.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 modules/karma.py diff --git a/modules/karma.py b/modules/karma.py new file mode 100644 index 000000000..949057db2 --- /dev/null +++ b/modules/karma.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +""" +karma.py - Phenny karma module +By Ori Rawlings +""" + +from itertools import imap + +points = {} + +def karma_point(phenny, input): + """ + This rule will detect and apply karma operations. + Usage: (++|--) + Example: + + orirawlings++ + Increases nick, orirawlings, karma score by 1 point + + foobar-- + Decreases nick, foobar, karma score by 1 point + """ + user = input.group(1) + op = input.group(2) + if op == '++': + if input.nick == user: + phenny.say('Silly ' + input.nick + ", you can't award yourself karma...") + return + f = lambda x: x+1 + elif op == '--': + if input.nick == user: + phenny.say('Wow ' + input.nick + ", you must have really been bad to take karma from yourself...") + f = lambda x: x-1 + else: + f = lambda x: x + try: + points[user] = f(points[user]) + except KeyError: + points[user] = f(0) +karma_point.rule = '^(\w+)(\+{2}|-{2})$' + +def karma(phenny, input): + """ + .karma - prints all stored karma scores for various nicks to the channel + """ + for entry in points.items(): + phenny.say('\t'.join(imap(str,entry))) +karma.commands = ['karma'] +karma.priority = 'medium' + +if __name__ == '__main__': + print __doc__.strip() From a8377953f97746ccf544747c77a54322b430bcb3 Mon Sep 17 00:00:00 2001 From: Ori Rawlings Date: Thu, 7 Apr 2011 22:59:43 +0800 Subject: [PATCH 10/14] Added sqlite3 persistence to karma data. Added additional ways of specifiying karma rewards or punishment. --- modules/karma.py | 59 ++++++++++++++++++++++++++++++++++-------------- phenny | 2 +- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/modules/karma.py b/modules/karma.py index 949057db2..827cc5c9a 100644 --- a/modules/karma.py +++ b/modules/karma.py @@ -4,9 +4,32 @@ By Ori Rawlings """ +import sqlite3 +import os from itertools import imap +from functools import partial +from operator import add -points = {} + +ops = { '++':partial(add, 1), '+1':partial(add, 1), '--':partial(add, -1), '-1':partial(add, -1) } + +class KarmaDAO: + def __init__(self, path): + self.db_path = path + + def karmas(self, conn): + return conn.execute('select name,score from karma order by score desc') + + def update_karma(self, conn, user, f, default=0): + user = str(user) + score = conn.execute('select score from karma where name = ?', (user,)).fetchone() + if score: + score = f(score[0] or default) + conn.execute('update karma set score=? where name=?', (score,user)) + else: + score = f(default) + conn.execute('insert into karma (name,score) values (?,?)', (user,score)) + conn.commit() def karma_point(phenny, input): """ @@ -22,31 +45,33 @@ def karma_point(phenny, input): """ user = input.group(1) op = input.group(2) - if op == '++': - if input.nick == user: - phenny.say('Silly ' + input.nick + ", you can't award yourself karma...") + if input.nick == user: + if '+' in op: + phenny.reply("Silly, you can't award yourself karma...") return - f = lambda x: x+1 - elif op == '--': - if input.nick == user: - phenny.say('Wow ' + input.nick + ", you must have really been bad to take karma from yourself...") - f = lambda x: x-1 - else: - f = lambda x: x - try: - points[user] = f(points[user]) - except KeyError: - points[user] = f(0) -karma_point.rule = '^(\w+)(\+{2}|-{2})$' + elif '-' in op: + phenny.reply("Wow, you must have really been bad to take karma from yourself...") + f = ops.get(op, lambda x: x) + conn = sqlite3.connect(phenny.karma_dao.db_path) + phenny.karma_dao.update_karma(conn, user, f, 0) +karma_point.rule = '^(\w+)(?:: )?(\+{2}|\+1|-{2}|-1)\s*(.*)$' def karma(phenny, input): """ .karma - prints all stored karma scores for various nicks to the channel """ - for entry in points.items(): + conn = sqlite3.connect(phenny.karma_dao.db_path) + for entry in phenny.karma_dao.karmas(conn): phenny.say('\t'.join(imap(str,entry))) + conn.close() karma.commands = ['karma'] karma.priority = 'medium' +def path(self): + return os.path.join(os.path.expanduser('~/.phenny'),'karma','karma.db') + +def setup(phenny): + phenny.karma_dao = KarmaDAO(path(phenny)) + if __name__ == '__main__': print __doc__.strip() diff --git a/phenny b/phenny index 6cb096140..fe705f134 100755 --- a/phenny +++ b/phenny @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2.6 """ phenny - An IRC Bot Copyright 2008, Sean B. Palmer, inamidst.com From 44fec10ca893320dadff5d418b7e3ce3485be8f7 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Wed, 22 Feb 2012 00:21:00 -0500 Subject: [PATCH 11/14] Added command to check a single person's karma --- modules/karma.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/karma.py b/modules/karma.py index 827cc5c9a..579dd689f 100644 --- a/modules/karma.py +++ b/modules/karma.py @@ -31,6 +31,12 @@ def update_karma(self, conn, user, f, default=0): conn.execute('insert into karma (name,score) values (?,?)', (user,score)) conn.commit() + def get_karma(self, conn, user): + user=str(user) + score = conn.execute('select score from karma where name = ?', (user,)).fetchone() + score=(score and score[0]) or 0 + return score + def karma_point(phenny, input): """ This rule will detect and apply karma operations. @@ -54,17 +60,22 @@ def karma_point(phenny, input): f = ops.get(op, lambda x: x) conn = sqlite3.connect(phenny.karma_dao.db_path) phenny.karma_dao.update_karma(conn, user, f, 0) -karma_point.rule = '^(\w+)(?:: )?(\+{2}|\+1|-{2}|-1)\s*(.*)$' +karma_point.rule = '^(\w+)(?::\s*)?(\+{2}|-{2})\s*$' def karma(phenny, input): """ .karma - prints all stored karma scores for various nicks to the channel """ - conn = sqlite3.connect(phenny.karma_dao.db_path) - for entry in phenny.karma_dao.karmas(conn): - phenny.say('\t'.join(imap(str,entry))) - conn.close() -karma.commands = ['karma'] + if not input.group(1): + conn = sqlite3.connect(phenny.karma_dao.db_path) + for entry in phenny.karma_dao.karmas(conn): + phenny.say('\t'.join(imap(str,entry))) + conn.close() + else: + conn = sqlite3.connect(phenny.karma_dao.db_path) + score = phenny.karma_dao.get_karma(conn, input.group(1)) + phenny.say("Karma for %s: %d"%(input.group(1), score)) +karma.rule = '^\.karma\s*(\w*)' karma.priority = 'medium' def path(self): From 1e48c87245a160bee18d7fc147153e6f96b72048 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Tue, 13 Mar 2012 21:50:27 -0400 Subject: [PATCH 12/14] Fixed karma module so as not to spam. --- modules/karma.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/modules/karma.py b/modules/karma.py index 579dd689f..50e0e06a5 100644 --- a/modules/karma.py +++ b/modules/karma.py @@ -17,8 +17,11 @@ class KarmaDAO: def __init__(self, path): self.db_path = path - def karmas(self, conn): - return conn.execute('select name,score from karma order by score desc') + def karmas(self, conn, limit=None): + comm='select name,score from karma order by abs(score) desc ' + if limit and int(limit)>0: + comm += 'limit %d'%int(limit) + return conn.execute(comm) def update_karma(self, conn, user, f, default=0): user = str(user) @@ -66,15 +69,22 @@ def karma(phenny, input): """ .karma - prints all stored karma scores for various nicks to the channel """ - if not input.group(1): - conn = sqlite3.connect(phenny.karma_dao.db_path) - for entry in phenny.karma_dao.karmas(conn): - phenny.say('\t'.join(imap(str,entry))) - conn.close() + who=input.group(1) + conn = sqlite3.connect(phenny.karma_dao.db_path) + if not who or (who.isdigit() and int(who)>5): + phenny.say("Sending you the list in private messages, "+input.nick) + for entry in phenny.karma_dao.karmas(conn,who): + # List of all is IMed to the questioner, so as not + # to spam the channel. + phenny.msg(input.nick,'\t'.join(imap(str,entry))) + elif who.isdigit(): + for entry in phenny.karma_dao.karmas(conn,who): + phenny.say("\t".join(imap(str,entry))) else: - conn = sqlite3.connect(phenny.karma_dao.db_path) score = phenny.karma_dao.get_karma(conn, input.group(1)) phenny.say("Karma for %s: %d"%(input.group(1), score)) + conn.close() + karma.rule = '^\.karma\s*(\w*)' karma.priority = 'medium' From 1023f383b2f320eb8de0c3e7be78a3fd61901244 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Tue, 7 Aug 2012 16:29:11 -0400 Subject: [PATCH 13/14] Add ability to "tell" more than one person. --- modules/tell.py | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/modules/tell.py b/modules/tell.py index d3ee609ed..c676055a4 100755 --- a/modules/tell.py +++ b/modules/tell.py @@ -72,32 +72,37 @@ def f_remind(phenny, input): if not os.path.exists(phenny.tell_filename): return - if len(tellee) > 20: - return phenny.reply('That nickname is too long.') - timenow = time.strftime('%d %b %H:%MZ', time.gmtime()) - if not tellee in (teller.lower(), phenny.nick, 'me'): # @@ - # @@ and year, if necessary - warn = False - if not phenny.reminders.has_key(tellee): - phenny.reminders[tellee] = [(teller, verb, timenow, msg)] - else: - # if len(phenny.reminders[tellee]) >= maximum: - # warn = True - phenny.reminders[tellee].append((teller, verb, timenow, msg)) - # @@ Stephanie's augmentation - response = "I'll pass that on when %s is around." % tellee_original - # if warn: response += (" I'll have to use a pastebin, though, so " + - # "your message may get lost.") - + whogets=[] + for tellee in tellee.split(','): + if len(tellee) > 20: + phenny.say('Nickname %s is too long.'%tellee) + continue + if not tellee in (teller.lower(), phenny.nick, 'me'): # @@ + warn = False + whogets.append(tellee) + if not phenny.reminders.has_key(tellee): + phenny.reminders[tellee] = [(teller, verb, timenow, msg)] + else: + # if len(phenny.reminders[tellee]) >= maximum: + # warn = True + phenny.reminders[tellee].append((teller, verb, timenow, msg)) + if not whogets: # Only get cute if there are no legits rand = random.random() if rand > 0.9999: response = "yeah, yeah" elif rand > 0.999: response = "yeah, sure, whatever" - - phenny.reply(response) elif teller.lower() == tellee: phenny.say('You can %s yourself that.' % verb) - else: phenny.say("Hey, I'm not as stupid as Monty you know!") + elif teller.lower() == phenny.nick.lower(): + phenny.say("Hey, I'm not as stupid as Monty you know!") + else: + response="I'll pass that on when %s is around." + if len(whogets)>1: + listing=", ".join(whogets[:-1])+" or "+whogets[-1] + response=response%listing + else: + response=response%whogets[0] + phenny.reply(response) dumpReminders(phenny.tell_filename, phenny.reminders) # @@ tell f_remind.rule = ('$nick', ['tell', 'ask'], r'(\S+) (.*)') From af980f94ab2273fdcf434aa8a55f6130b8d89e80 Mon Sep 17 00:00:00 2001 From: Mark Shoulson Date: Tue, 7 Aug 2012 20:38:25 -0400 Subject: [PATCH 14/14] Fixed issue with "tell person,person,person" when it's the same person! --- modules/tell.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/tell.py b/modules/tell.py index c676055a4..d90ce4b16 100755 --- a/modules/tell.py +++ b/modules/tell.py @@ -80,13 +80,14 @@ def f_remind(phenny, input): continue if not tellee in (teller.lower(), phenny.nick, 'me'): # @@ warn = False - whogets.append(tellee) - if not phenny.reminders.has_key(tellee): - phenny.reminders[tellee] = [(teller, verb, timenow, msg)] - else: - # if len(phenny.reminders[tellee]) >= maximum: - # warn = True - phenny.reminders[tellee].append((teller, verb, timenow, msg)) + if not tellee in whogets: + whogets.append(tellee) + if not phenny.reminders.has_key(tellee): + phenny.reminders[tellee] = [(teller, verb, timenow, msg)] + else: + # if len(phenny.reminders[tellee]) >= maximum: + # warn = True + phenny.reminders[tellee].append((teller, verb, timenow, msg)) if not whogets: # Only get cute if there are no legits rand = random.random() if rand > 0.9999: response = "yeah, yeah"