summaryrefslogtreecommitdiff
path: root/modules/quotes.py
blob: b648d7bdb4a9ab3a60c027eec86e0d15323ceb24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
info = {
	'author': 'Jon Bergli Heier',
	'title': 'IRC Quotes',
	'description': 'Allows users to access a quote database.',
}

import random, time, re
import psycopg2

class Quotes:
	def __init__(self, db = None):
		self.randseed = False
		self.connect(db)

	def format_quote(self, q):
		return q

	def connect(self, db):
		self.db = psycopg2.connect(database = 'fot')
		self.updatecount()

	def updatecount(self):
		cur = self.db.cursor()
		cur.execute('select count(id) from quotes')
		self.count = int(cur.fetchone()[0])
		cur.close()

	def add(self, nick, quote):
		cur = self.db.cursor()
		cur.execute('insert into quotes (nick, date, quote) values (%s, %s, %s)', (nick, int(time.time()), quote))
		cur.execute('select currval(\'quotes_id_seq\')')
		lastrowid = cur.fetchone()[0]
		cur.close()
		self.db.commit()
		return lastrowid

	def delete(self, qid = None):
		cur = self.db.cursor()
		cur.execute('delete from quotes where id = %s limit 1', (qid,))
		cur.close()
		self.db.commit()

	def find(self, search, func = None):
		search = re.compile(search) if func == 'rfind' else search.lower() if func == 'efind' else [x.lower() for x in search.split(' ')]
		dosearch = lambda quote: search.search(quote) != None if func == 'rfind' else search in quote if func == 'efind' else len([x for x in search if x in quote]) if func == 'afind' else len([x for x in search if x in quote]) == len(search)
		cur = self.db.cursor()
		cur.execute('select id, quote from quotes order by id asc')
		ret = []
		i = 0
		for q in cur.fetchall():
			i += 1
			if dosearch(q[1].lower()):
				ret.append((q[0], self.format_quote(q[1])))
		cur.close()
		return ret

	def get(self, qid = None):
		cur = self.db.cursor()
		if not qid:
			if not self.randseed:
				random.seed()
				self.randseed = True
			n = random.randint(1, self.count)
			cur.execute('select id, quote from quotes order by id asc limit 1 offset %s', (n - 1,))
		else:
			qid = int(qid)
			cur.execute('select quote from quotes where id = %s limit 1', (qid,))
		s = cur.fetchone()
		cur.close()
		if s and len(s) == 2:
			qid, s = s
		elif s:
			s = s[0]
		return (qid, self.format_quote(s)) if s else (None, None)

	def info(self, qid):
		cur = self.db.cursor()
		cur.execute('select id, nick, date, quote from quotes where id = %s limit 1', (qid,))
		s = cur.fetchone()
		cur.close()
		return s if s else None

	def range(self, p, pp):
		cur = self.db.cursor()
		cur.execute('select id from quotes order by id asc limit %s offset %s', (pp, (p - 1) * pp))
		s = cur.fetchall()
		cur.close()
		return [x[0] for x in s]

	def format_date(self, d):
		return time.strftime('%c', time.localtime(d)) if d else '(Unknown date)'

class IRCHandler(Quotes):
	def add(self, *args):
		'Add a quote to the database.'
		quote = ' '.join(args)
		qid = Quotes.add(self, self.nick, quote)
		yield '\002Quote #%d\002 has been added' % (qid)

	def format_quote(self, quote):
		return quote

	def output(self, quotes):
		for n, q in quotes:
			yield '\002Quote #%d:\002 %s' % (n, q)

	def _find(self, args, func = 'find'):
		if not len(args):
			yield 'Quote: Missing search pattern.'
			return
		args = ' '.join(args)
		results = Quotes.find(self, args, func)
		leftovers = []
		if len(results) > 1:
			yield 'Quote: Found \002%d\002 results for "%s"%s' % (len(results), args, ', here are the last two:' if len(results) > 3 else ':' if len(results) else '')
		if len(results):
			if len(results) > 3:
				leftovers, results = results[:-2], results[-2:]
			for l in self.output(results):
				yield l
			if leftovers:
				yield 'Other quotes: %s' % ', '.join(['#%d' % x[0] for x in leftovers])

	def find(self, *args):
		'Find quotes containing all given words.'
		return self._find(args)

	def afind(self, *args):
		'Find quotes containing any given word.'
		return self._find(args, 'afind')

	def efind(self, *args):
		'Find quotes containing the exact given phrase.'
		return self._find(args, 'efind')

	def rfind(self, *args):
		'Find quotes using regexp search.'
		return self._find(args, 'rfind')

	def get(self, *args):
		'Print a quote.'
		if not len(args):
			yield 'Quote: Missing quote number.'
			return
		args = args[0]
		if args[0] == '#':
			args = args[1:]
		if not args.isdigit():
			yield 'Quote: Identifier must be a number.'
			return
		qid = int(args)
		qid, q = Quotes.get(self, qid)
		if not q:
			yield 'Quote: That quote does not exist.'
		else:
			for l in self.output(((qid, q),)):
				yield l

	def help(self, *args):
		'Show this help.'
		funcs = ('random', 'get id', 'info id', 'find text', 'afind text', 'efind text', 'rfind regexp', 'add text', 'stats', 'help')
		l = []
		maxlen = 0
		for i in funcs:
			name = i.split(' ')
			if len(name) == 2:
				name, arg = name
			else:
				name, arg = name[0], None
			l.append(('%s <%s>' % (name, arg) if arg else name, getattr(self, name).__doc__))
			if len(l[-1][0]) > maxlen:
				maxlen = len(l[-1][0])
		return ('%s%s%s' % (x[0], ' ' * (maxlen - len(x[0]) + 1), x[1]) for x in l)

	def info(self, *args):
		'Print stored information about a quote.'
		if not len(args):
			yield 'Quote: Missing quote number.'
			return
		elif not args[0].isdigit():
			yield 'Quote: Identifier must by a number.'
			return
		n = int(args[0])
		info = Quotes.info(self, n)
		if not info:
			yield 'Quote: That quote does not exist.'
		else:
			yield '\002Quote #%d\002 was added by %s at %s.' % (n, str(info[1]) if info[1] else '(unknown nick)', self.format_date(info[2]) if info[2] else '(unknown date)')

	def random(self, *args):
		'Print a random quote. (Default)'
		return self.output((Quotes.get(self), ))

	def stats(self, *args):
		'Print quote stats.'
		yield 'There are \002%d\002 quotes in the database.' % (self.count)


quote_handler = IRCHandler()

class Module:
	def __init__(self, bot):
		self.irc = bot
		self.irc.register_keyword('!quote', self)

	def keyword(self, nick, channel, kw, msg):
		args = msg.split(' ')
		cmd = args[0] if len(args) and len(args[0].strip()) else 'random'
		args = args[1:]
	
		if cmd.isdigit() or (cmd[0] == '#' and cmd[1:].isdigit()):
			cmd, args = 'get', [cmd]
	
		quote_handler.nick = nick.split('!')[0]
		if hasattr(quote_handler, cmd) and callable(getattr(quote_handler, cmd)):
			for line in getattr(quote_handler, cmd)(*args):
				self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], line)
		else:
			self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], '%s, invalid command "%s"' % (nick.split('!')[0], cmd))