Очередной коммит. Стараюсь пофиксить баги.
[nia.git] / jaconn.py
bloba4e073a20538d28b05d4da8c8cc746a2446ec840
1 # -*- coding: utf-8 -*-
2 import xmpp, inspect, re
3 import ConfigParser
5 class bot:
6 def DEBUG(self, text=None):
7 '''Режим отладки и тестирования'''
8 if self.debug:
9 self.config_file = 'nia_test.cfg'
10 print unicode(text)
12 comm_pref = 'nia_'
13 admin_comm_pref = 'admin_'
14 def __init__(self):
15 self.debug = 0
17 self.logging = 0
19 self.config_file = 'nia.cfg'
20 self.resource= 'Nia Teppelin .NET'
21 self.version = '0.666'
22 self.os = 'Windows Vista'
24 self.DEBUG()
26 user, confs, ignore, alias = self.config(False)
27 self.JID = user['jid']
28 self.PASSWD = user['passwd']
29 self.NICK= unicode(user['nick'],'utf-8')
30 self.admin = xmpp.protocol.JID(user['admin'])
31 self.CONFS = confs
32 self.ignore = ignore
33 self.alias = alias
35 self.commands = {}
36 self.admin_commands = {}
37 self.help = {'com':[],'admin':[]}
38 for (name, value) in inspect.getmembers(self):
39 if inspect.ismethod(value) and name.startswith(self.comm_pref):
40 self.commands[name[len(self.comm_pref):]] = value
41 self.help['com'].append(name[len(self.comm_pref):])
42 if inspect.ismethod(value) and name.startswith(self.admin_comm_pref):
43 self.admin_commands[name[len(self.admin_comm_pref):]] = value
44 self.help['admin'].append(name[len(self.admin_comm_pref):])
45 self.help = {'com':', '.join(self.help['com']),'admin':', '.join(self.help['admin'])}
49 def config(self,flag,confs=None,ignore=None):
50 config = ConfigParser.ConfigParser()
51 def config_write():
52 config.add_section('alias')
53 for key in self.alias:
54 config.set('alias', key, self.alias[key])
55 config.add_section('general')
56 config.set('general', 'jid', self.JID)
57 config.set('general', 'passwd', self.PASSWD)
58 config.set('general', 'nick', self.NICK)
59 config.set('general', 'admin', self.admin)
60 config.set('general', 'ignore', ','.join(ignore))
61 config.set('general', 'confs', ','.join(confs) )
62 config.write(open(self.config_file,'w'))
63 def config_read():
64 alias = {}
65 config.read(self.config_file)
66 user = {'jid':config.get('general','jid'),
67 'passwd':config.get('general','passwd'),
68 'nick':config.get('general','nick'),
69 'admin':config.get('general','admin')}
70 confs = config.get('general','confs').decode('utf-8').split(',')
71 ignore = config.get('general','ignore').decode('utf-8').split(',')
72 for key in config.options('alias'):
73 alias[key] = config.get('alias',key)
74 return user, confs, ignore, alias
75 if flag:
76 config_write()
77 else:
78 return config_read()
81 def connect(self):
82 '''Подключение к серверу'''
83 self.jid = xmpp.protocol.JID(self.JID)
84 self.conn=xmpp.Client(self.jid.getDomain(),debug=[])
85 self.conn.connect()
86 self.conn.auth(self.jid.getNode(),self.PASSWD,'nyaa~')
87 self.conn.sendInitPresence()
88 self.conn.RegisterDisconnectHandler(self.conn.reconnectAndReauth)
89 self.conn.RegisterHandler('message',self.get_mes)
90 self.conn.RegisterHandler('iq', self.iq_version, typ='get', ns=xmpp.NS_VERSION)
91 self.conn.RegisterHandler('iq', self.get_iq, typ='result', ns=xmpp.NS_VERSION)
93 def iq_version(self, conn, iq):
94 """Returns reply to iq:version"""
95 iq=iq.buildReply('result')
96 qp=iq.getTag('query')
97 qp.setTagData('name', self.resource)
98 qp.setTagData('version', self.version)
99 qp.setTagData('os', self.os)
100 conn.send(iq)
101 raise xmpp.NodeProcessed
103 def join_room(self, confs):
104 for conf in confs:
105 self.p=xmpp.Presence(to='%s/%s'%(conf,self.NICK))
106 self.p.setTag('Nia',namespace=xmpp.NS_MUC).setTagData('password','')
107 self.p.getTag('Nia').addChild('history',{'maxchars':'0','maxstanzas':'0'})
108 self.conn.send(self.p)
109 def leave_room(self, confs):
110 for conf in confs:
111 to = '%s/%s'%(conf,self.NICK)
112 self.send_system(to,'offline','unavailable')
113 def reconnect(self):
114 self.connect()
115 self.join_room(self.CONFS)
116 def online(self):
117 self.connect()
118 self.join_room(self.CONFS)
119 while True:
120 try:
121 self.conn.Process(1)
122 except xmpp.protocol.XMLNotWellFormed:
123 self.reconnect()
126 def send(self, text, extra=None, flag=True):
128 True - chat
129 False - xml
131 if flag:
132 self.conn.send(xmpp.protocol.Message(self.to,text,self.type))
133 else:
134 '''Отправка сообщения в форме xhtml'''
136 xhtml = '''
137 <html xmlns='http://jabber.org/protocol/xhtml-im'>
138 <body xml:lang='en-US' xmlns='http://www.w3.org/1999/xhtml'>
140 </body></html>
141 '''%extra
143 self.conn.send("<message to='%s' type='%s'><body>%s</body>%s</message>"%(self.to,self.type,text,xhtml))
145 def send_system(self,to,msg,type):
146 '''Отправка системного сообщения. Статусы'''
147 print to, msg, type
148 self.conn.send(xmpp.protocol.Presence(to=to,status=msg,typ=type))
150 def XMLescape(self, text):
151 return xmpp.simplexml.XMLescape(text)
153 def get_mes(self, conn, mess):
154 def parse():
155 if self.type_f:
156 text = re.findall('^%s[\W]{0,2}[\s]{1,3}(.*?)$'%self.NICK,self.text)
157 else:
158 text = re.findall('^(.*?)$',self.text)
159 self.DEBUG(text)
160 if text:
161 tmp = text[0].split(' ',1)
162 if len(tmp) >= 2: cmd, args = tmp[0], tmp[1]
163 elif len(tmp) == 1: cmd, args = tmp[0], ''
164 return cmd, args
166 else: return False, False
167 def alias(cmd, args):
168 text = ' '.join( (self.alias[cmd], args))
169 tmp = text.split(' ',1)
170 if len(tmp) >= 2: cmd, args = tmp[0], tmp[1]
171 elif len(tmp) == 1: cmd, args = tmp[0], ''
172 return cmd, args
174 self.type=mess.getType()
175 self.nick=mess.getFrom()
176 self.text=mess.getBody()
178 nick = self.nick.getResource()
179 if self.type == 'groupchat':
180 self.to = self.nick.getStripped()
181 nick = self.nick.getResource()
182 self.type_f = True
183 elif self.type == 'chat' and self.nick.getDomain().startswith('conference.'):
184 self.to = self.nick
185 nick = self.nick.getResource()
186 self.type_f = False
187 elif self.type == 'chat':
188 self.to = self.nick.getStripped()
189 nick = self.nick.getNode()
190 self.type_f = False
192 if self.type_f:
193 self.LOG(self.to, nick, self.text)
195 self.DEBUG([self.nick,self.text,self.type])
196 self.DEBUG(mess)
197 if self.ignore.count(self.nick) or re.match('%s/%s'%(self.to,self.NICK),'%s/%s'%(self.to,nick) ):
198 pass
199 elif self.text.startswith(self.NICK) or not self.type_f:
200 cmd, args = parse()
201 if self.alias.has_key(cmd):
202 cmd,args = alias(cmd, args)
203 if cmd:
204 if self.commands.has_key(cmd):
205 self.commands[cmd](args)
206 elif self.admin_commands.has_key(cmd):
207 if nick == self.admin.getNode() or self.to == str(self.admin).lower() :
208 self.admin_commands[cmd](self.nick,args)
209 else: self.send('%s~ nyaaa? Access denied...'%nick)
210 else: self.send('%s~ nyaaa? Type "help"...'%nick)
211 else: self.send('%s~ nyaaa? Type "help"...'%nick)
214 def send_iq(self,_type, to):
215 self.conn.send(xmpp.protocol.Iq(to=to,typ=_type ,queryNS=xmpp.NS_VERSION))
216 def get_iq(self,conn,mess):
217 query = mess.getTag('query')
218 client = '%s %s'%(query.getTagData('name'),query.getTagData('version') )
219 os = query.getTagData('os')
220 target = mess.getFrom().getResource()
221 toversion = '%s has client %s at %s'%(target, client, os)
222 self.send(toversion)
230 http://code.google.com/p/robocat/source/browse/trunk/start.py
231 http://www.linux.org.ru/view-message.jsp?msgid=2591531#2591657