7
__copyright__ = 'this file is in the public domain'
8
__depending__ = ['fans', 'quote']
10
from gozerbot.tests import tests
11
from gozerbot.commands import cmnds
12
from gozerbot.examples import examples
13
from gozerbot.redispatcher import rebefore
14
from gozerbot.datadir import datadir
15
from gozerbot.generic import handle_exception, rlog, lockdec
16
from gozerbot.utils.statdict import Statdict
17
from gozerbot.aliases import aliases
18
from gozerbot.plughelp import plughelp
19
from gozerbot.config import config
20
import thread, pickle, time, os
22
from gozerbot.database.alchemy import Base, create_all, engine, query, Session, dblocked
23
from datetime import datetime
24
from time import localtime
25
from sqlalchemy import Column, String, Integer, Text, DateTime, ForeignKey, Sequence
26
import sqlalchemy as sa
29
__tablename__ = 'karma'
30
__table_args__ = {'useexisting': True}
31
item = Column('item', String(255), primary_key=True)
32
value = Column('value', Integer, nullable=False)
34
def __init__(self, item, value):
39
__tablename__ = 'whykarma'
40
__table_args__ = {'useexisting': True}
41
item = Column('item', String(255), nullable=False)
42
updown = Column('updown', String(10), nullable=False)
43
why = Column('why', Text, nullable=False)
44
__mapper_args__ = {'primary_key':[item,updown,why]}
46
def __init__(self, item, updown, why):
52
__tablename__ = 'whokarma'
53
__table_args__ = {'useexisting': True}
54
item = Column('item', String(255), nullable=False)
55
nick = Column('nick', String(255), nullable=False)
56
updown = Column('updown', String(10), nullable=False)
57
__mapper_args__ = {'primary_key': [item, nick, updown]}
59
def __init__(self, item, nick, updown):
68
oldfile = datadir + os.sep + 'old'
69
dbdir = datadir + os.sep + 'db' + os.sep + 'karma.db'
70
if os.path.exists(dbdir):
72
from gozerbot.database.db import Db
73
db = Db(dbtype='sqlite')
74
db.connect('db/karma.db')
75
result = db.execute(""" SELECT * FROM karma """)
80
result = db.execute(""" SELECT * FROM whokarma """)
84
karma.setwhoup(i[0], i[1])
86
karma.setwhodown(i[0], i[1])
87
result = db.execute(""" SELECT * FROM whykarma """)
96
from gozerbot.utils.generic import dosed
97
from gozerbot.database.db import Db
98
from gozerbot.compat.karma import Karma
100
oldkarma = Karma(oldfile)
108
rlog(10, 'karma', 'upgrading karma items')
109
for i,j in k.karma.iteritems():
117
except sa.exc.IntegrityError, ex:
118
#if 'not unique' in str(ex):
122
rlog(10, 'karma', 'upgrading reasonup')
123
for i,j in k.reasonup.iteritems():
125
karma.addwhy(i, 'up', z)
127
rlog(10, 'karma', 'upgrading reasondown')
128
for i,j in k.reasondown.iteritems():
130
karma.addwhy(i, 'down', z)
132
rlog(10, 'karma', 'upgrading whodown')
133
for i,j in k.whodown.iteritems():
135
karma.setwhodown(i, z)
137
rlog(10, 'karma', 'upgrading whoup')
138
for i,j in k.whoup.iteritems():
142
except Exception, ex:
144
rlog(10, 'karma', 'failed to upgrade: %s' % str(ex))
146
rlog(10, 'karma', 'upgraded %s karma items' % str(teller))
150
plughelp.add('karma', 'maintain karma of items .. use ++ to raise karma by 1 \
151
or use -- to lower by 1 .. reason might be given after a "#"')
153
class KarmaDb(object):
161
""" return number of items """
163
count = query(sa.func.count(Karma.item)).first()[0]
167
def add(self, item, value):
169
if Session.query(Karma).filter(Karma.item==item).count():
170
rlog(10, 'karma', '%s item is already in database' % item)
173
k = Karma(item=item, value=value)
180
""" get karma of item """
182
karma = query(Karma).filter(Karma.item==item).first()
187
def delete(self, item):
188
""" delete karma item """
190
whokarma = Session.query(WhoKarma).filter(WhoKarma.item==item).all()
191
whykarma = Session.query(WhyKarma).filter(WhyKarma.item==item).all()
193
for w in whokarma + whykarma:
195
karma = Session.query(Karma).filter(Karma.item==item).first()
197
Session.delete(karma)
203
def addwhy(self, item, updown, reason):
204
""" add why of karma up/down """
207
whykarma = WhyKarma(item, updown, reason)
208
Session.add(whykarma)
213
def upitem(self, item, reason=None):
214
""" up a karma item with/without reason """
216
karma = Session.query(Karma).filter(Karma.item==item).first()
219
karma = Karma(item, 0)
221
karma.value = karma.value + 1
223
whykarma = WhyKarma(item, 'up', reason.strip())
224
Session.add(whykarma)
229
def down(self, item, reason=None):
230
""" lower a karma item with/without reason """
232
karma = Session.query(Karma).filter(Karma.item==item).first()
235
karma = Karma(item, 0)
237
karma.value = karma.value - 1
239
whykarma = WhyKarma(item, 'down', reason.strip())
240
Session.add(whykarma)
244
def whykarmaup(self, item):
245
""" get why of karma ups """
247
karma = query(WhyKarma).filter(WhyKarma.item==item).filter(WhyKarma.updown=='up')
249
return [k.why for k in karma]
251
def whykarmadown(self, item):
252
""" get why of karma downs """
254
karma = query(WhyKarma).filter(WhyKarma.item==item).filter(WhyKarma.updown=='down')
256
return [k.why for k in karma]
259
def setwhoup(self, item, nick):
260
""" set who upped a karma item """
264
wk = WhoKarma(item, nick, 'up')
270
def setwhodown(self, item, nick):
271
""" set who lowered a karma item """
275
wk = WhoKarma(item, nick, 'down')
280
def getwhoup(self, item):
281
""" get list of who upped a karma item """
283
karma = query(WhoKarma).filter(WhoKarma.item==item).filter(WhoKarma.updown=='up').all()
285
return [k.nick for k in karma]
287
def getwhodown(self, item):
288
""" get list of who downed a karma item """
290
karma = query(WhoKarma).filter(WhoKarma.item==item).filter(WhoKarma.updown=='down').all()
292
return [k.nick for k in karma]
294
def search(self, item):
295
""" search for matching karma item """
297
karma = query(Karma).filter(Karma.item.like('%%%s%%' % item))
301
def good(self, limit=10):
302
""" show top 10 of karma items """
303
statdict = Statdict()
304
karma = query(Karma).all()
308
if i.item.startswith('quote '):
310
statdict.upitem(i.item, i.value)
311
return statdict.top(limit=limit)
313
def bad(self, limit=10):
314
""" show lowest 10 of negative karma items """
315
statdict = Statdict()
316
karma = query(Karma).all()
320
if i.item.startswith('quote '):
322
statdict.upitem(i.item, i.value)
323
return statdict.down(limit=limit)
325
def quotegood(self, limit=10):
326
""" show top 10 of karma items """
327
statdict = Statdict()
328
karma = query(Karma).all()
332
if not i.item.startswith('quote '):
334
statdict.upitem(i.item, i.value)
335
return statdict.top(limit=limit)
337
def quotebad(self, limit=10):
338
""" show lowest 10 of negative karma items """
339
statdict = Statdict()
340
karma = query(Karma).all()
344
if not i.item.startswith('quote '):
346
statdict.upitem(i.item, i.value)
347
return statdict.down(limit=limit)
349
def whatup(self, nick):
350
""" show what items are upped by nick """
352
statdict = Statdict()
353
whokarma = query(WhoKarma).filter(WhoKarma.nick==nick).filter(WhoKarma.updown=='up')
357
statdict.upitem(i.item)
358
return statdict.top()
360
def whatdown(self, nick):
361
""" show what items are upped by nick """
363
statdict = Statdict()
364
whokarma = query(WhoKarma).filter(WhoKarma.nick==nick).filter(WhoKarma.updown=='down')
368
statdict.upitem(i.item)
369
return statdict.top()
376
limiterlock = thread.allocate_lock()
377
limlock = lockdec(limiterlock)
381
""" return number of kamra items """
384
def search(what, queue):
385
rlog(10, 'karma', 'searched for %s' % what)
386
result = karma.search(what)
388
queue.put_nowait("%s has karma %s" % (i.item, i.value))
391
def ratelimit(bot, ievent):
392
""" karma rate limiter """
398
name = ievent.userhost
399
# Create a state for this user and his/her karma-state if necessary
400
if not bot.state.has_key(name):
402
if not bot.state[name].has_key('karma'):
403
bot.state[name]['karma'] = {'count': 0, 'time': time.time() }
404
# If the waittime has elapsed, reset the counter
405
if time.time() > (bot.state[name]['karma']['time'] + waittime):
406
bot.state[name]['karma']['count'] = 0
408
bot.state[name]['karma']['count'] += 1
409
# If counter is too high, limit :)
410
if bot.state[name]['karma']['count'] > limit:
411
if name in ratelimited:
413
ievent.reply("karma limit reached, you'll have to wait %s \
414
seconds" % int((bot.state[name]['karma']['time'] + waittime) - time.time()))
415
ratelimited.append(name)
418
bot.state[name]['karma']['time'] = time.time()
419
# Ratelimiting passed :)
421
ratelimited.remove(name)
425
except Exception, ex:
426
handle_exception(ievent)
428
def handle_karmaget(bot, ievent):
429
""" karma-get <item> .. show karma of item """
431
ievent.missing('<item>')
435
result = karma.get(item)
437
ievent.reply("%s has karma %s" % (item, str(result)))
439
ievent.reply("%s has no karma yet" % item)
441
cmnds.add('karma-get', handle_karmaget, ['USER', 'WEB', 'ANONKARMA', 'CLOUD'])
442
examples.add('karma-get', 'karma-get <item> .. show karma of <item>', \
444
aliases.data['karma'] = 'karma-get'
454
tests.start(nolimit).add('gozerbot++').add('karma-get gozerbot', 'gozerbot has karma (\d+)').end(dolimit)
456
def handle_karmadel(bot, ievent):
457
""" karma-del <item> .. delete karma item """
459
ievent.missing('<item>')
462
result = karma.delete(item)
464
ievent.reply("%s deleted" % item)
466
ievent.reply("can't delete %s" % item)
468
cmnds.add('karma-del', handle_karmadel, ['OPER'])
469
examples.add('karma-del', 'karma-del <item> .. delete karma item', \
471
tests.add('boozer--').add('karma-del boozer', 'boozer deleted')
473
def handle_karmaup(bot, ievent):
474
""" <item>++ ['#' <reason>] .. increase karma of item with optional \
476
if not ratelimit(bot, ievent):
478
(item, reason) = ievent.groups
479
item = item.strip().lower()
482
karma.upitem(item, reason=reason)
483
karma.setwhoup(item, ievent.nick)
484
ievent.reply('karma of '+ item + ' is now ' + str(karma.get(item)))
486
rebefore.add(8, '^(.+)\+\+\s+#(.*)$', handle_karmaup, ['USER', 'KARMA', \
487
'ANONKARMA'], allowqueue=False)
488
examples.add('++', "<item>++ ['#' <reason>] .. higher karma of item with 1 \
489
(use optional reason)", '1) gozerbot++ 2) gozerbot++ # top bot')
490
tests.add('gozerbot++', 'karma of gozerbot is now (\d+)')
491
tests.add('gozerbot++ # top bot', 'karma of gozerbot is now (\d+)')
493
def handle_karmaup2(bot, ievent):
494
""" increase karma without reason """
495
ievent.groups += [None, ]
496
handle_karmaup(bot, ievent)
498
rebefore.add(9, '^(.+)\+\+$', handle_karmaup2, ['USER', 'ANONKARMA'], \
501
def handle_karmadown(bot, ievent):
502
""" <item>-- ['#' <reason> .. decrease karma item with reason """
503
if not ratelimit(bot, ievent):
505
(item, reason) = ievent.groups
506
item = item.strip().lower()
509
karma.down(item, reason=reason)
510
karma.setwhodown(item, ievent.nick)
511
ievent.reply('karma of ' + item + ' is now ' + str(karma.get(item)))
513
rebefore.add(8, '^(.+)\-\-\s+#(.*)$', handle_karmadown, ['USER', 'KARMA', \
514
'ANONKARMA'], allowqueue=False)
515
examples.add('--', "<item>-- ['#' <reason>] .. lower karma of item with 1 \
516
(use optional reason)", '1) gozerbot-- 2) gozerbot-- # bad bot')
517
tests.add('miep--', 'karma of miep is now (-\d+)')
518
tests.add('miep-- # top bot', 'karma of miep is now (-\d+)')
520
def handle_karmadown2(bot, ievent):
521
""" decrease karma item without reason """
522
ievent.groups += [None, ]
523
handle_karmadown(bot, ievent)
525
rebefore.add(9, '^(.+)\-\-$', handle_karmadown2, ['USER', 'KARMA', \
526
'ANONKARMA'], allowqueue=False)
528
def handle_karmawhyup(bot, ievent):
529
""" karma-whyup <item> .. show why karma of item has been increased """
531
ievent.missing('<item>')
534
result = karma.whykarmaup(item)
536
ievent.reply('whykarmaup of %s: ' % item, result, dot=True)
538
ievent.reply('%s has no reason for karmaup yet' % item)
540
cmnds.add('karma-whyup', handle_karmawhyup, ['USER', 'WEB', \
542
examples.add('karma-whyup', 'karma-whyup <item> .. show the reason why \
543
karma of <item> was raised', 'karma-whyup gozerbot')
544
aliases.data['wku'] = 'karma-whyup'
545
tests.add('gozerbot++ # top bot').add('karma-whyup gozerbot', 'top bot')
547
def handle_whykarmadown(bot, ievent):
548
""" karma-whydown <item> .. show why karma of item has been decreased """
550
ievent.missing('<item>')
553
result = karma.whykarmadown(item)
555
ievent.reply('whykarmadown of %s: ' % item, result, dot=True)
557
ievent.reply('%s has no reason for karmadown yet' % item)
559
cmnds.add('karma-whydown', handle_whykarmadown, ['USER', 'WEB', \
561
examples.add('karma-whydown', 'karma-whydown <item> .. show the reason why \
562
karma of <item> was lowered', 'karma-whydown gozerbot')
563
aliases.data['wkd'] = 'karma-whydown'
564
tests.add('miep-- # kut bot').add('karma-whydown miep', 'kut bot')
566
def handle_karmagood(bot, ievent):
567
""" karma-good .. show top 10 karma items """
568
result = karma.good(limit=10)
573
res.append("%s=%s" % (i[0], i[1]))
574
ievent.reply('goodness: ', res, dot=True)
576
ievent.reply('karma void')
578
cmnds.add('karma-good', handle_karmagood, ['USER', 'WEB', 'ANONKARMA', 'CLOUD'])
579
examples.add('karma-good', 'show top 10 karma', 'karma-good')
580
aliases.data['good'] = 'karma-good'
581
tests.add('gozerbot++').add('karma-good', 'gozerbot')
583
def handle_karmabad(bot, ievent):
584
""" karma-bad .. show 10 most negative karma items """
585
result = karma.bad(limit=10)
590
res.append("%s=%s" % (i[0], i[1]))
591
ievent.reply('badness: ', res, dot=True)
593
ievent.reply('karma void')
595
cmnds.add('karma-bad', handle_karmabad, ['USER', 'WEB', 'ANONKARMA', 'CLOUD'])
596
examples.add('karma-bad', 'show lowest top 10 karma', 'karma-bad')
597
aliases.data['bad'] = 'karma-bad'
598
tests.add('miep--').add('karma-bad', 'miep')
600
def handle_whokarmaup(bot, ievent):
601
""" karma-whoup <item> .. show who increased a karma item """
603
ievent.missing('<item>')
606
result = karma.getwhoup(item)
608
ievent.reply("whokarmaup of %s: " % item, result, dot=True)
610
ievent.reply('no whokarmaup data available for %s' % item)
612
cmnds.add('karma-whoup', handle_whokarmaup, ['USER', 'WEB', \
613
'ANONKARMA', 'CLOUD'])
614
examples.add('karma-whoup', 'karma-whoup <item> .. show who raised the \
615
karma of <item>', 'karma-whoup gozerbot')
616
tests.add('gozerbot++').add('karma-whoup gozerbot', '{{ me }}')
618
def handle_whokarmadown(bot, ievent):
619
""" karma-whodown <item> .. show who decreased a karma item """
621
ievent.missing('<item>')
624
result = karma.getwhodown(item)
626
ievent.reply("whokarmadown of %s: " % item, result, dot=True)
628
ievent.reply('no whokarmadown data available for %s' % item)
630
cmnds.add('karma-whodown', handle_whokarmadown, ['USER', 'WEB', \
631
'ANONKARMA', 'CLOUD'])
632
examples.add('karma-whodown', 'karma-whodown <item> .. show who lowered \
633
the karma of <item>', 'karma-whodown gozerbot')
634
tests.add('miep--').add('karma-whodown miep', '{{ me }}')
636
def handle_karmasearch(bot, ievent):
637
""" karma-search <txt> .. search for karma items """
640
ievent.missing('<txt>')
642
result = karma.search(what)
646
res.append("%s (%s)" % (i.item, i.value))
647
ievent.reply("karma items matching %s: " % what, res, dot=True)
649
ievent.reply('no karma items matching %s found' % what)
651
cmnds.add('karma-search', handle_karmasearch, ['USER', 'WEB', \
652
'ANONKARMA', 'CLOUD'])
653
examples.add('karma-search', 'karma-search <txt> .. search karma' , \
654
'karma-search gozerbot')
655
tests.add('gozerbot++').add('karma-search gozer', 'gozerbot')
657
def handle_karmawhatup(bot, ievent):
658
""" show what karma items have been upped by nick """
660
nick = ievent.args[0]
662
ievent.missing('<nick>')
664
result = karma.whatup(nick)
668
res.append("%s (%s)" % i)
669
ievent.reply("karma items upped by %s: " % nick, res, dot=True)
671
ievent.reply('no karma items upped by %s' % nick)
673
cmnds.add('karma-whatup', handle_karmawhatup, ['USER', 'WEB', \
674
'ANONKARMA', 'CLOUD'])
675
examples.add('karma-whatup', 'karma-whatup <nick> .. show what karma items \
676
<nick> has upped' , 'karma-whatup dunker')
677
tests.add('gozerbot++').add('karma-whatup {{ me }}', 'gozerbot')
679
def handle_karmawhatdown(bot, ievent):
680
""" show what karma items have been lowered by nick """
682
nick = ievent.args[0]
684
ievent.missing('<nick>')
686
result = karma.whatdown(nick)
690
res.append("%s (%s)" % i)
691
ievent.reply("karma items downed by %s: " % nick, res, dot=True)
693
ievent.reply('no karma items downed by %s' % nick)
695
cmnds.add('karma-whatdown', handle_karmawhatdown, ['USER', 'WEB', \
696
'ANONKARMA', 'CLOUD'])
697
examples.add('karma-whatdown', 'karma-whatdown <nick> .. show what karma \
698
items <nick> has downed' , 'karma-whatdown dunker')
699
tests.add('miep--').add('karma-whatdown {{ me }}', 'miep')