~m4v/+junk/Urldb

« back to all changes in this revision

Viewing changes to plugin.py

  • Committer: Elián Hanisch
  • Date: 2010-08-17 21:38:55 UTC
  • Revision ID: lambdae2@gmail.com-20100817213855-qpgh7sh5dnnm7jrk
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Encoding: UTF-8 -*-
 
2
###
 
3
# Copyright (c) 2010, Elián Hanisch
 
4
# All rights reserved.
 
5
#
 
6
#
 
7
###
 
8
 
 
9
import supybot.conf as conf
 
10
import supybot.utils as utils
 
11
from supybot.commands import *
 
12
import supybot.plugins as plugins
 
13
import supybot.ircutils as ircutils
 
14
import supybot.callbacks as callbacks
 
15
from supybot.ircutils import bold
 
16
 
 
17
from storm.locals import *
 
18
from storm.sqlobject import AutoUnicode
 
19
 
 
20
import re
 
21
from datetime import datetime
 
22
today = datetime.today
 
23
 
 
24
 
 
25
urls_schema = \
 
26
"""CREATE TABLE urls (\
 
27
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
 
28
    channel TEXT COLLATE NOCASE,\
 
29
    nick TEXT COLLATE NOCASE,\
 
30
    url TEXT COLLATE NOCASE,\
 
31
    date DATETIME,
 
32
    UNIQUE (channel, url))
 
33
"""
 
34
 
 
35
others_schema = \
 
36
"""CREATE TABLE other_urls (\
 
37
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
 
38
    channel TEXT COLLATE NOCASE,\
 
39
    nick TEXT COLLATE NOCASE,\
 
40
    url_id INTEGER references urls(id),\
 
41
    date DATETIME)
 
42
"""
 
43
 
 
44
 
 
45
class Url(object):
 
46
    __storm_table__ = 'urls'
 
47
 
 
48
    id = Int(primary=True)
 
49
    channel = AutoUnicode()
 
50
    nick = AutoUnicode()
 
51
    url = RawStr()
 
52
    date = DateTime()
 
53
 
 
54
    def __init__(self, url, nick, channel):
 
55
        self.url = url
 
56
        self.nick = nick
 
57
        self.channel = channel
 
58
        self.date = today()
 
59
 
 
60
 
 
61
class OtherUrl(object):
 
62
    __storm_table__ = 'other_urls'
 
63
 
 
64
    id = Int(primary=True)
 
65
    channel = AutoUnicode()
 
66
    nick = AutoUnicode()
 
67
    url_id = Int()
 
68
    date = DateTime()
 
69
 
 
70
    url = Reference(url_id, Url.id)
 
71
 
 
72
    def __init__(self, nick, channel):
 
73
        self.nick = nick
 
74
        self.channel = channel
 
75
        self.date = today()
 
76
 
 
77
 
 
78
octet = r'(?:2(?:[0-4]\d|5[0-5])|1\d\d|\d{1,2})'                      
 
79
ipAddr = r'%s(?:\.%s){3}' % (octet, octet)                            
 
80
label = r'[0-9a-z][-0-9a-z]*[0-9a-z]?'                                
 
81
domain = r'%s(?:\.%s)*\.[a-z][-0-9a-z]*[a-z]?' % (label, label)       
 
82
urlre = r'(\w+://(?:%s|%s)(?::\d+)?(?:/[^\])>\s]*)?)' % (domain, ipAddr)
 
83
urlre = re.compile(urlre, re.I)
 
84
 
 
85
 
 
86
import os
 
87
path = conf.supybot.directories.data()
 
88
filename = os.path.join(path, 'Urldb.sqlite.db')
 
89
db = create_database('sqlite:%s' %filename)
 
90
global store
 
91
store = Store(db)
 
92
try:
 
93
    store.execute(urls_schema)
 
94
    store.execute(others_schema)
 
95
    store.commit()
 
96
except:
 
97
    pass
 
98
 
 
99
 
 
100
def makePattern(p):
 
101
    s = ''
 
102
    for c in p:
 
103
        if c == '%':
 
104
            s += '\%'
 
105
        elif c == '_':
 
106
            s += '\_'
 
107
        elif c == '*':
 
108
            s += '%'
 
109
        elif c == '?':
 
110
            s += '_'
 
111
        else:
 
112
            s += c
 
113
    return s
 
114
 
 
115
 
 
116
class Urldb(callbacks.Plugin):
 
117
    """Add the help for "@plugin help Urldb" here
 
118
    This should describe *how* to use this plugin."""
 
119
 
 
120
    def die(self):
 
121
        store.commit()
 
122
 #       store.close()
 
123
 
 
124
    def doPrivmsg(self, irc, msg):
 
125
        message = msg.args[1]
 
126
        #self.log.debug(message)
 
127
        match = urlre.findall(message)
 
128
        if not match:
 
129
            return
 
130
        #self.log.debug('MATCH: %s' %match)
 
131
        for url in match:
 
132
            _url = store.find(Url, Url.url.like(url)).one()
 
133
            if _url:
 
134
                other = OtherUrl(msg.nick, msg.args[0])
 
135
                other.url = _url
 
136
                store.add(other)
 
137
            else:
 
138
                url = Url(url, msg.nick, msg.args[0])
 
139
                store.add(url)
 
140
        store.commit()
 
141
 
 
142
 
 
143
    class url(callbacks.Commands):
 
144
        def search(self, irc, msg, args, channel, pattern, optlist):
 
145
            """[<channel>] <pattern> [--nick <pattern]
 
146
            
 
147
            Search urls that matches *pattern*, use '*' or '?' for wildcards, '\\' for escapes."""
 
148
 
 
149
            nick = None
 
150
            for k, v in optlist:
 
151
                if k == 'nick':
 
152
                    nick = makePattern(v)
 
153
 
 
154
            if pattern[0] != '*' and pattern[-1] != '*':
 
155
                pattern = '*%s*' %pattern
 
156
 
 
157
            #self.log.debug(s)
 
158
            expressions = [
 
159
                    Url.url.like(makePattern(pattern), escape='\\'),
 
160
                    Url.channel.like(channel)]
 
161
            
 
162
            if nick:
 
163
                expressions.append(Url.nick.like(nick, escape='\\'))
 
164
 
 
165
            result = store.find(Url, And(*expressions))
 
166
            result.order_by(Desc(Url.date))
 
167
 
 
168
            if result.is_empty():
 
169
                irc.reply("Nothing found with '%s' in %s." %(pattern, channel))
 
170
            else:
 
171
                L = []
 
172
                for url in result:
 
173
                    L.append("#%s %s by %s" %(url.id, bold(url.url), url.nick))
 
174
                irc.reply('Found %s urls: %s' %(len(L), ', '.join(L)))
 
175
 
 
176
        search = wrap(search, ['channel', 'something', getopts({'nick': 'something'})])
 
177
 
 
178
        def info(self, irc, msg, args, channel, id):
 
179
            """[<channel>] <id|exact url>
 
180
            
 
181
            Displays information about an url, like who and when it was posted.
 
182
            Url's id must be an integer."""
 
183
            
 
184
            if id.isdigit():
 
185
                id = int(id)
 
186
                url = store.find(Url, Url.id == id)
 
187
            else:
 
188
                url = store.find(Url, Url.url == id, Url.channel.like(channel))
 
189
 
 
190
            if url.is_empty():
 
191
                irc.reply("Nothing found.")
 
192
            else:
 
193
                url = url.one()
 
194
                irc.reply('#%s %s posted by %s in %s on %s' %(url.id,
 
195
                    bold(url.url), bold(url.nick),
 
196
                    url.channel, url.date))
 
197
 
 
198
        info = wrap(info, ['channel', 'text'])
 
199
 
 
200
        def last(self, irc, msg, args, channel, nick):
 
201
            """[<channel>] [<nick>]
 
202
 
 
203
            Displays the last url posted by <nick> or seen in channel."""
 
204
            expressions = [ Url.channel.like(channel) ]
 
205
            if nick:
 
206
                expressions.append(Url.nick.like(makePattern(nick)))
 
207
 
 
208
            result = store.find(Url, And(*expressions))
 
209
            result.order_by(Url.date)
 
210
 
 
211
            if result.is_empty():
 
212
                irc.reply("Nothing found.")
 
213
            else:
 
214
                url = result.last()
 
215
                irc.reply("#%s %s" %(url.id, bold(url.url)))
 
216
 
 
217
        last = wrap(last, ['channel', optional('something')])
 
218
 
 
219
 
 
220
Class = Urldb
 
221
 
 
222
 
 
223
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: