This only works on the second database interaction, since psycopg2 only notices that the connection is gone, when a query is executed. So in the common case reconnect works as follows: - some bot method calls a cursor function like .execute(), .fetchone(), etc. - this raises an error if the connection is broken - if following code then requests a new cursor, this will also fail since psycopg2 now knows that the connection is gone - the error is caught in storage.DBConn.cursor(), a new connection will be set up of which a new cursor is yielded If the error happens in connection.commit() or .rollback() instead we can instantly reconnect since these methods are wrapped. So why not wrap the cursor methods as well? Consider the following example: A query is the last thing that was executed on a cursor. The database connection is lost. Now .fetchone() is called on the cursor. We could wrap .fetchone() and reconnect, but we'd have to use a new cursor since cursors are linked to connections. And on this new cursor .fetchone() wouldn't make any sense, since we haven't executed a query on this cursor.
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
import random
|
|
|
|
from docopt import Dict
|
|
from irc3.plugins.command import command
|
|
from irc3.utils import IrcString
|
|
|
|
from . import DatabasePlugin
|
|
|
|
|
|
class Rape(DatabasePlugin):
|
|
@command
|
|
def owe(self, mask: IrcString, target: IrcString, args: Dict):
|
|
"""Shows how much a nick owes
|
|
|
|
%%owe [<nick>]
|
|
"""
|
|
nick = args.get('<nick>', mask.nick)
|
|
|
|
# Fetch result from database
|
|
with self.con.cursor() as cur:
|
|
cur.execute('''
|
|
SELECT
|
|
fines
|
|
FROM
|
|
users
|
|
WHERE
|
|
lower(nick) = lower(%s)
|
|
''', [nick])
|
|
owes = cur.fetchone()
|
|
|
|
# Colorize owe amount and return string
|
|
if owes:
|
|
fines = '4${}'.format(owes['fines'])
|
|
else:
|
|
fines = '3$0'
|
|
|
|
# Return total owes
|
|
return '{nick} owes: \x03{fines}\x03'.format(nick=nick, fines=fines)
|
|
|
|
@command
|
|
def rape(self, mask: IrcString, target: IrcString, args: Dict):
|
|
"""Rapes a nick and eventually charge for it
|
|
|
|
%%rape <nick>
|
|
"""
|
|
nick = args.get('<nick>', mask.nick)
|
|
rand = random.randint(0, 3)
|
|
|
|
if rand not in (0, 1):
|
|
self.bot.action(target, 'rapes {}'.format(nick))
|
|
else:
|
|
fine = random.randint(1, 500)
|
|
|
|
# Get reason based on rand value
|
|
fined = (mask.nick, nick)[rand]
|
|
reason = ('raping', 'being too lewd and getting raped')[rand]
|
|
|
|
# Insert or add fine to database and return total owe
|
|
with self.con.cursor() as cur:
|
|
cur.execute('''
|
|
INSERT INTO
|
|
users (nick, fines)
|
|
VALUES
|
|
(lower(%s), %s)
|
|
ON CONFLICT (nick) DO UPDATE SET
|
|
fines = users.fines + excluded.fines
|
|
RETURNING
|
|
fines
|
|
''', [fined, fine])
|
|
self.con.commit()
|
|
|
|
# Print fine and total owe
|
|
self.bot.action(target, 'fines {nick} \x02${fine}\x02 for {reason}. You owe: \x0304${total}\x03'.format(
|
|
nick=fined,
|
|
fine=fine,
|
|
reason=reason,
|
|
total=cur.fetchone()['fines'],
|
|
))
|