source: trunk/amazonbot/amazonbot.py @ 11

Revision 11, 5.5 KB checked in by atzm, 18 years ago (diff)

debug

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4__version__ = '$Revision$'
5__author__ = 'Atzm WATANABE <sitosito@p.chan.ne.jp>'
6__date__ = '$Date$'
7__copyright__ = 'Copyright(C) 2006 Atzm WATANABE, all rights reserved.'
8__license__ = 'Python'
9
10import re
11import sys
12import time
13import random
14import MeCab
15import nkf
16
17from ircbot import SingleServerIRCBot
18from irclib import nm_to_n
19
20import config
21config.init()
22
23import my_amazon
24my_amazon.setLocale(config.get('amazon', 'locale'))
25my_amazon.setLicense(config.get('amazon', 'access_key'))
26
27try:
28        set, frozenset
29except NameError:
30        from sets import Set as set, ImmutableSet as frozenset
31
32def uniq(sequence):
33        """リストから重耇を取り陀く (順番が狂うので泚意)
34        """
35        return list(set(sequence))
36
37def unicoding(text):
38        """text を匷制的に unicode オブゞェクトに倉換
39        """
40        if type(text) is unicode:
41                return text
42        return unicode(nkf.nkf('-w', text), 'utf-8')
43
44def ununicoding(text, encoding='iso-2022-jp'):
45        """text を指定された encoding で゚ンコヌドしraw str に匷制倉換
46        """
47        if type(text) is not unicode:
48                return unicoding(text).encode(encoding)
49        return text.encode(encoding)
50
51def mecab_parse(text):
52        """MeCab を䜿っお圢態玠解析し固有名詞ず䞀般名詞だけを抜出する
53        """
54        def choice_nominal(wlist):
55                res = []
56                for word, wtype in wlist:
57                        wtypes = wtype.split('-')
58                        if '固有名詞' in wtypes or ('名詞' in wtypes and '䞀般' in wtypes):
59                                res.append(unicoding(word))
60                return res
61
62        text = ununicoding(text, 'utf-8')
63        result = []
64        tag = MeCab.Tagger('-Ochasen')
65        for line in tag.parse(text).split('\n'):
66                if not line or line == 'EOS':
67                        break
68                words = line.split()
69                result.append((words[0], words[-1])) # word, word-type
70
71        result = uniq(choice_nominal(result))
72        return result
73
74class AmazonBotBase(SingleServerIRCBot):
75        """アマゟンボットのベヌスクラス
76        こい぀単䜓では受け取ったメッセヌゞの圢態玠解析ず名詞抜出たでしかやらない
77        サブクラスで process_keyword を実装しお Amazon ぞク゚リを投げるべし
78        """
79        def __init__(self):
80                _server = [(config.get('irc', 'server'), config.get('irc', 'port', 'int'))]
81                _nick = config.get('bot', 'nick')
82
83                self._prev_time = time.time()
84                self._silent = False
85                SingleServerIRCBot.__init__(self, _server, _nick, _nick)
86
87        def start(self):
88                try:
89                        SingleServerIRCBot.start(self)
90                except KeyboardInterrupt:
91                        self.die(ununicoding(config.get('bot', 'bye')))
92
93        def on_welcome(self, c, e):
94                c.join(config.get('irc', 'channel'))
95                if __debug__:
96                        print >> sys.stderr, 'DEBUG> Joined %s' % config.get('irc', 'channel')
97
98        def on_nicknameinuse(self, c, e):
99                c.nick(c.get_nickname() + '_')
100
101        def on_privmsg(self, c, e):
102                return self.on_pubmsg(c, e)
103
104        def on_pubmsg(self, c, e):
105                _current_time = time.time()
106                if _current_time < self._prev_time + config.get('bot', 'freq', 'int'):
107                        if __debug__:
108                                prev = time.strftime('%y/%m/%d %H:%M:%S', time.localtime(self._prev_time))
109                                print >> sys.stderr, 'DEBUG> Not expired: prev time is %s' % prev
110                        return False
111
112                self._prev_time = _current_time
113                msg = unicoding(e.arguments()[0])
114
115                self.silence(msg, c, e)
116                if self._silent:
117                        return False
118
119                nominals = mecab_parse(msg)
120                if not nominals:
121                        if __debug__:
122                                print >> sys.stderr, "DEBUG> Couldn't find nominal words"
123                        return False
124
125                title, url = self.process_keyword(' '.join(nominals))
126                if title and url:
127                        channel = e.target()
128                        content = unicoding(config.get('bot', 'content'))
129                        try:
130                                message = ununicoding(': '.join([content, title, url]))
131                        except UnicodeError, e:
132                                # なぜかたたに unicode オブゞェクトを iso-2022-jp で゚ンコヌドできない
133                                if __debug__:
134                                        print >> sys.stderr, 'DEBUG> %s' % str(e)
135                                return False
136
137                        c.privmsg(channel, message)
138                        return True
139                return False
140
141        ACTIVE_PATTERN = re.compile(unicoding(config.get('bot', 'active_pattern')))
142        SILENT_PATTERN = re.compile(unicoding(config.get('bot', 'silent_pattern')))
143        def silence(self, msg, c, e):
144                ch = e.target()
145                active = self.ACTIVE_PATTERN.search(msg)
146                silent = self.SILENT_PATTERN.search(msg)
147                if __debug__:
148                        print >> sys.stderr, 'DEBUG> ACT_PATT: %s, SIL_PATT: %s' % (str(active), str(silent))
149
150                if active:
151                        self._silent = False
152                        c.privmsg(ch, ununicoding(config.get('bot', 'thanks')))
153                elif silent:
154                        self._silent = True
155                        c.privmsg(ch, ununicoding(config.get('bot', 'sorry')))
156
157        def process_keyword(self, keyword):
158                return [None, None]
159
160class AmazonBot(AmazonBotBase):
161        """アマゟンボットの実装クラス
162        process_keyword メ゜ッドで Amazon ぞク゚リを投げお結果を返す
163        """
164        def __init__(self):
165                AmazonBotBase.__init__(self)
166
167        def get_version(self):
168                return 'AmazonBot by %s, based on python-irclib' % __author__
169
170        def process_keyword(self, keyword):
171                keyword = ununicoding(keyword, 'utf-8')
172                if __debug__:
173                        print >> sys.stderr, 'DEBUG> KEYWORD: %s' % ununicoding(keyword, 'euc-jp')
174
175                try:
176                        data = my_amazon.searchByBlended(keyword)
177                        if type(data.ProductLine) is not type([]):
178                                data.ProductLine = [data.ProductLine]
179                except my_amazon.AmazonError, e:
180                        if __debug__:
181                                print >> sys.stderr, 'DEBUG> Caught AmazonError: %s' % str(e)
182                        return [None, None]
183
184                product_line = random.choice(data.ProductLine)
185                detail = random.choice(product_line.ProductInfo.Details)
186
187                url = unicoding(getattr(detail, 'URL', None))
188                product_name = unicoding(getattr(detail, 'ProductName', None))
189
190                return [product_name, url]
191
192if __name__ == '__main__':
193        bot = AmazonBot()
194        bot.start()
Note: See TracBrowser for help on using the repository browser.