1

add: initial AI support

This commit is contained in:
diSabler
2014-05-01 14:07:44 +04:00
parent 5ffac3efcf
commit e5295eb994
217 changed files with 78827 additions and 1 deletions

369
plugins/acl.py Normal file
View File

@@ -0,0 +1,369 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
acl_acts = ['msg','prs','prs_change','prs_join','role','role_change','role_join','aff','aff_change','aff_join',
'nick','nick_change','nick_join','all','all_change','all_join','jid','jidfull','res','age','ver','vcard']
acl_actions = ['show','del','clear'] + acl_acts
acl_ver_tmp = {}
acl_vcard_tmp = {}
acl_actions.sort()
def acl_show(jid,nick,text):
a = cur_execute_fetchall('select * from acl where jid=%s and action ilike %s order by level,action',(jid,text))
if len(a):
msg = L('Acl:','%s/%s'%(jid,nick))
for tmp in a:
if text == '%': t4 = tmp[4].replace('\n',' // ')
else: t4 = tmp[4].replace('\n','\n ')
if tmp[6] == 9:
if tmp[5]: st,tp = '\n[%s] %s %s %s -> %s', (disp_time(tmp[5],'%s/%s'%(jid,nick)),) + tmp[1:4] + (t4,)
else: st,tp = '\n%s %s %s -> %s', tmp[1:4] + (t4,)
else:
if tmp[5]: st,tp = '\n%s | [%s] %s %s %s -> %s', (L(unlevl[tmp[6]],'%s/%s'%(jid,nick)),disp_time(tmp[5],'%s/%s'%(jid,nick)),) + tmp[1:4] + (t4,)
else: st,tp = '\n%s | %s %s %s -> %s', (L(unlevl[tmp[6]],'%s/%s'%(jid,nick)),) + tmp[1:4] + (t4,)
msg += st % tp
else: msg = L('Acl not found','%s/%s'%(jid,nick))
return msg
def acl_add_del(jid,nick,text,flag):
global conn
time_mass,atime = {'s':1,'m':60,'h':3600,'d':86400,'w':604800,'M':2592000,'y':31536000},0
silent,level = False,9
try:
while text[0][0] == '/':
if text[0] == '/silent': silent = True
else:
try: atime = int(time.time()) + int(text[0][1:-1]) * time_mass[text[0][-1:]]
except: return L('Time format error!','%s/%s'%(jid,nick))
text = text[1:]
except: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
if text[0].isdigit():
level = int(text[0])
if level <= 0: level = 9
elif level > 9: level = 9
text = text[1:]
ttext = ' '.join(text)
if operator.xor(ttext.count('${EXP}') <= 1,ttext.count('${/EXP}') <= 1) and flag: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
elif ttext.find('${EXP}',ttext.find('${/EXP}')) > 0 and flag: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
elif '${EXP}' in ttext and '${/EXP}' in ttext:
try: re.compile(ttext.split('${EXP}',1)[1].split('${/EXP}',1)[0].replace('%20','\ ').replace('*','*?'))
except: return L('Error in RegExp!','%s/%s'%(jid,nick))
try:
acl_cmd = text[0]
text = text[1:]
except: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
if not acl_cmd in acl_acts: msg = L('Items: %s','%s/%s'%(jid,nick)) % ', '.join(acl_acts)
else:
try:
if text[0].lower() in ['sub','!sub','exp','!exp','cexp','!cexp','=','!=','<','>','<=','>=']: acl_sub_act,text = text[0].lower(),text[1:]
else: acl_sub_act = '='
except: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
if acl_cmd != 'age' and acl_sub_act in ['<','>','<=','>=']: return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
if acl_sub_act in ['=','!=','sub','!sub']: text[0] = text[0].replace('%20',' ')
else: text[0] = text[0].replace('%20','\ ')
if acl_cmd == 'age' and not text[0].isdigit(): return L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
if acl_sub_act in ['exp','!exp','cexp','!cexp']:
try: re.compile(text[0].replace('*','*?'))
except: return L('Error in RegExp!','%s/%s'%(jid,nick))
if flag and len(text) >= 2:
no_command = True
for tmp in comms:
if tmp[1] == text[1]:
no_command = False
break
if no_command: return L('Unknown command: %s','%s/%s'%(jid,nick)) % text[1]
tmp = cur_execute_fetchall('select * from acl where jid=%s and action=%s and type=%s and text=%s and level=%s',(jid,acl_cmd, acl_sub_act, text[0], level))
if tmp:
cur_execute('delete from acl where jid=%s and action=%s and type=%s and text=%s and level=%s',(jid,acl_cmd, acl_sub_act, text[0], level))
msg = [L('Removed:','%s/%s'%(jid,nick)),L('Updated:','%s/%s'%(jid,nick))][flag]
else: msg = [L('Not found:','%s/%s'%(jid,nick)),L('Added:','%s/%s'%(jid,nick))][flag]
if flag: cur_execute('insert into acl values (%s,%s,%s,%s,%s,%s,%s)', (jid, acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ '), atime, level))
if level == 9:
if atime: msg += ' [%s] %s %s %s -> %s' % (disp_time(atime,'%s/%s'%(jid,nick)),acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ ').replace('\n',' // '))
else: msg += ' %s %s %s -> %s' % (acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ ').replace('\n',' // '))
else:
if atime: msg += ' %s | [%s] %s %s %s -> %s' % (L(unlevl[level],'%s/%s'%(jid,nick)), disp_time(atime,'%s/%s'%(jid,nick)),acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ ').replace('\n',' // '))
else: msg += ' %s | %s %s %s -> %s' % (L(unlevl[level],'%s/%s'%(jid,nick)), acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ ').replace('\n',' // '))
if not reduce_spaces_all(msg).split('->',1)[1]: msg = msg.split('->',1)[0]
if flag and acl_cmd != 'msg':
mb = [t[1:] for t in megabase if t[0] == jid and getRoom(t[4]) != getRoom(Settings['jid'])]
a = [(acl_cmd, acl_sub_act, text[0], ' '.join(text[1:]).replace('%20','\ '), 0, level)]
was_joined = True
for t in mb:
room, realjid, nick = jid, t[3], t[0]
mass = cur_execute_fetchone('select message from age where jid=%s and room=%s and nick=%s',(getRoom(realjid),room,nick))[0].split('\n',4)
mass = (mass[4], mass[0], mass[1])
acl_selector(a,room,realjid,nick,mass,was_joined)
if silent: return L('done','%s/%s'%(jid,nick))
else: return msg
def acl_add(jid,nick,text): return acl_add_del(jid,nick,text,True)
def acl_del(jid,nick,text): return acl_add_del(jid,nick,text,False)
def acl_clear(room,nick):
if get_level(room,nick)[0] < 8: return L('You have no rights to do it!','%s/%s'%(room,nick))
acl_back = cur_execute_fetchall('select * from acl where jid=%s',(room,))
if acl_back:
fname = back_folder % '%s_%s.acl' % (unicode(room),''.join(['%02d' % t for t in time.localtime()[:6]]))
writefile(fname,json.dumps(acl_back))
cur_execute('delete from acl where jid=%s',(room,))
return L('ACL cleared. Removed %s action(s).','%s/%s'%(room,nick)) % len(acl_back)
def muc_acl(type, jid, nick, text):
text = text.replace('\ ','%20').replace(' // ','\n').replace(' \/\/ ',' // ').split(' ')
if len(text) >= 3 and text[2] == '->': text[2] = ''
elif len(text) >= 4 and text[3] == '->': text[3] = ''
elif text[0].isdigit() and len(text) >= 5 and text[4] == '->': text[4] = ''
elif text[0].lower() == 'del' and len(text) >= 5 and text[4] == '->': text[4] = ''
while '' in text: text.remove('')
if len(text): acl_cmd = text[0]
else: acl_cmd = '!'
if not acl_cmd in acl_actions and acl_cmd[0] != '/' and not acl_cmd.isdigit(): msg = L('Items: %s','%s/%s'%(jid,nick)) % ', '.join(acl_actions)
elif acl_cmd == 'clear': msg = acl_clear(jid,nick)
elif acl_cmd == 'show':
try: t = text[1]
except: t = '%'
msg = acl_show(jid,nick,t)
elif acl_cmd == 'del': msg = acl_del(jid,nick,text[1:])
else: msg = acl_add(jid,nick,text)
send_msg(type, jid, nick, msg)
def acl_action(cmd,nick,jid,room,text):
global last_command
if len(last_command):
if last_command[6] == Settings['jid']: last_command = []
cmd = cmd.replace('${NICK}',nick).replace('${JID}',jid).replace('${SERVER}',getServer(jid))
if text and '${EXP}' in cmd and '${/EXP}' in cmd:
regex = cmd.split('${EXP}',1)[1].split('${/EXP}',1)[0]
mt = re.findall(regex, text, re.S|re.I|re.U)
if mt != []: txt = ''.join(mt[0])
else: txt = ''
cmd = cmd.split('${EXP}',1)[0] + txt + cmd.split('${/EXP}',1)[1]
nowname = get_xnick(room)
return com_parser(7, nowname, 'groupchat', room, nick, cmd, Settings['jid'])
def acl_message(room,jid,nick,type,text):
global conn
#if not no_comm: return
lvl = get_level(room,nick)[0]
if lvl < 0: return
if getRoom(jid) == getRoom(Settings['jid']): return
a = cur_execute_fetchall('select action,type,text,command,time,level from acl where jid=%s and (action=%s or action ilike %s) order by level',(room,'msg','all%'))
no_comm = True
if a:
acl_ma = get_config(room,'acl_multiaction')
for tmp in a:
if tmp[5] == 9 or lvl == tmp[5]:
if tmp[4] <= time.time() and tmp[4]: cur_execute('delete from acl where jid=%s and action=%s and type=%s and text=%s',(room,tmp[0],tmp[1],tmp[2]))
was_match = False
if tmp[1] in ['exp','!exp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),text,re.S|re.I|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),text,re.S|re.I|re.U): was_match = True
elif tmp[1] in ['cexp','!cexp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),text,re.S|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),text,re.S|re.U): was_match = True
elif tmp[1] in ['sub','!sub']:
if tmp[1][0] == '!' and not tmp[2].lower() in text.lower(): was_match = True
elif tmp[2].lower() in text.lower(): was_match = True
elif tmp[1] in ['=','!=']:
if tmp[1][0] == '!' and text.lower() != tmp[2].lower(): was_match = True
elif text.lower() == tmp[2].lower(): was_match = True
if was_match:
no_comm = acl_action(tmp[3],nick,jid,room,text)
if not acl_ma: break
return not no_comm
def bool_compare(a,b,c):
a,c = int(a),int(c)
return (b == '=' and a == c)\
or (b == '<' and a < c)\
or (b == '>' and a > c)\
or (b == '<=' and a >= c)\
or (b == '>=' and a >= c)
def acl_presence(room,jid,nick,type,mass):
global iq_request,acl_ver_tmp,acl_vcard_tmp
#if get_level(room,nick)[0] < 0: return
if getRoom(jid) == getRoom(Settings['jid']): return
was_joined = not mass[7] or is_start
if type == 'error': return
elif type == 'unavailable':
try: acl_ver_tmp.pop('%s/%s' % (room,nick))
except: pass
try: acl_vcard_tmp.pop('%s/%s' % (room,nick))
except: pass
return
# actions only on joins
#if was_joined: return
a = cur_execute_fetchall('select action,type,text,command,time,level from acl where jid=%s and (action ilike %s or action ilike %s or action ilike %s or action ilike %s or action ilike %s or action ilike %s or action=%s or action=%s or action=%s or action=%s or action=%s) order by level',(room,'prs%','nick%','all%','role%','aff%','jid','jidfull','res','age','ver','vcard'))
if a: acl_selector(a,room,jid,nick,mass,was_joined)
def acl_selector(a,room,jid,nick,mass,was_joined):
global iq_request,acl_ver_tmp,acl_vcard_tmp
lvl = get_level(room,nick)[0]
for tmp in a:
if (tmp[5] == 9 or lvl == tmp[5]) and tmp[0] == 'age':
r_age = cur_execute_fetchone('select sum(%s-time+age) from age where room=%s and jid=%s',(int(time.time()),room,getRoom(jid)))[0]
if not r_age: r_age = 0
break
r_ver,r_vcard = None,None
for tmp in a:
if (tmp[5] == 9 or lvl == tmp[5]) and tmp[0] == 'ver' and was_joined:
try:
r_ver = acl_ver_tmp['%s/%s' % (room,nick)]
break
except:
iqid,who = get_id(), '%s/%s' % (room,nick)
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_VERSION},[])])
iq_request[iqid]=(time.time(),acl_version_async,[a, nick, jid, room, mass[0], lvl],xmpp.NS_VERSION)
sender(i)
pprint('*** ACL version request for [%s] %s/%s' % (tmp[5],room,nick),'purple')
break
for tmp in a:
if (tmp[5] == 9 or lvl == tmp[5]) and tmp[0] == 'vcard' and was_joined:
try:
r_vcard = acl_vcard_tmp['%s/%s' % (room,nick)]
break
except:
iqid,who = get_id(), '%s/%s' % (room,nick)
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('vCard', {'xmlns': xmpp.NS_VCARD},[])])
iq_request[iqid]=(time.time(),acl_vcard_async,[a, nick, jid, room, mass[0], lvl],xmpp.NS_VCARD)
sender(i)
pprint('*** ACL vcard request for [%s] %s/%s' % (tmp[5],room,nick),'purple')
break
acl_ma = get_config(room,'acl_multiaction')
for tmp in a:
if tmp[5] == 9 or lvl == tmp[5]:
itm = ''
if tmp[4] <= time.time() and tmp[4]: cur_execute('delete from acl where jid=%s and action=%s and type=%s and text=%s',(room,tmp[0],tmp[1],tmp[2]))
if tmp[0].split('_')[0] == 'prs' and (('_join' in tmp[0] and was_joined) or ('_change' in tmp[0] and not was_joined) or ('_join' not in tmp[0] and '_change' not in tmp[0])): itm = mass[0]
elif tmp[0].split('_')[0] == 'nick' and (('_join' in tmp[0] and was_joined) or ('_change' in tmp[0] and not was_joined) or ('_join' not in tmp[0] and '_change' not in tmp[0])): itm = nick
elif tmp[0].split('_')[0] == 'role' and (('_join' in tmp[0] and was_joined) or ('_change' in tmp[0] and not was_joined) or ('_join' not in tmp[0] and '_change' not in tmp[0])): itm = mass[1]
elif tmp[0].split('_')[0] == 'aff' and (('_join' in tmp[0] and was_joined) or ('_change' in tmp[0] and not was_joined) or ('_join' not in tmp[0] and '_change' not in tmp[0])): itm = mass[2]
elif tmp[0].split('_')[0] == 'all' and (('_join' in tmp[0] and was_joined) or ('_change' in tmp[0] and not was_joined) or ('_join' not in tmp[0] and '_change' not in tmp[0])): itm = '|'.join((jid,nick,mass[0],mass[1],mass[2]))
elif tmp[0] == 'jid' and was_joined: itm = getRoom(jid)
elif tmp[0] == 'jidfull' and was_joined: itm = jid
elif tmp[0] == 'res' and was_joined: itm = getResourse(jid)
elif tmp[0] == 'ver' and was_joined and r_ver: itm = r_ver
elif tmp[0] == 'vcard' and was_joined and r_vcard: itm = r_vcard
elif tmp[0] == 'age' and was_joined and bool_compare(r_age,tmp[1],tmp[2]):
acl_action(tmp[3],nick,jid,room,None)
if not acl_ma: break
if itm:
was_match = False
if tmp[1] in ['exp','!exp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif tmp[1] in ['cexp','!cexp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif tmp[1] in ['sub','!sub']:
if tmp[1][0] == '!' and tmp[2].lower() not in itm.lower(): was_match = True
elif tmp[2].lower() in itm.lower(): was_match = True
elif tmp[1] in ['=','!=']:
if tmp[1][0] == '!' and not (itm.lower() == tmp[2].lower() or (tmp[0] == 'all' and tmp[2].lower() in (jid.lower(),nick.lower(),mass[0].lower()))): was_match = True
elif itm.lower() == tmp[2].lower() or (tmp[0] == 'all' and tmp[2].lower() in (jid.lower(),nick.lower(),mass[0].lower())): was_match = True
if was_match:
acl_action(tmp[3],nick,jid,room,None)
if not acl_ma: break
def acl_version_async(a, nick, jid, room, mass, lvl, is_answ):
global acl_ver_tmp
itm = is_answ[1][0]
acl_ver_tmp['%s/%s' % (room,nick)] = itm.replace('\r','[LF]').replace('\n','[CR]').replace('\t','[TAB]')
for tmp in a:
if tmp[0] == 'ver' and (tmp[5] == 9 or lvl == tmp[5]):
was_match = False
if tmp[1] in ['exp','!exp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif tmp[1] in ['cexp','!cexp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif tmp[1] in ['sub','!sub']:
if tmp[1][0] == '!' and tmp[2].lower() not in itm.lower(): was_match = True
elif tmp[2].lower() in itm.lower(): was_match = True
elif tmp[1] in ['=','!=']:
if tmp[1][0] == '!' and (itm.lower() != tmp[2].lower() or tmp[0] == 'all' and tmp[2].lower() not in (jid.lower(),nick.lower(),'\n'.join(mass).lower())): was_match = True
elif itm.lower() == tmp[2].lower() or (tmp[0] == 'all' and tmp[2].lower() in (jid.lower(),nick.lower(),'\n'.join(mass).lower())): was_match = True
if was_match: acl_action(tmp[3],nick,jid,room,None)
def acl_vcard_async(a, nick, jid, room, mass, lvl, is_answ):
global acl_vcard_tmp
try: vc,err = is_answ[1][1].getTag('vCard',namespace=xmpp.NS_VCARD),False
except: vc,err = is_answ[1][0],True
if not vc or unicode(vc) == '<vCard xmlns="vcard-temp" />': itm = 'empty'
elif err: itm = vc[:VCARD_LIMIT_LONG]
else:
data = []
for t in vc.getChildren():
if t.getChildren():
cm = []
for r in t.getChildren():
if r.getData(): cm.append(('%s.%s' % (t.getName(),r.getName()),unicode(r.getData())))
data += cm
elif t.getData(): data.append((t.getName(),t.getData()))
if data:
try:
photo_size = sys.getsizeof(get_value_from_array2(data,'PHOTO.BINVAL').decode('base64'))
photo_type = get_value_from_array2(data,'PHOTO.TYPE')
data_photo = '%s, %s' % (photo_type,get_size_human(photo_size))
data = [t for t in list(data) if t[0] not in ['PHOTO.BINVAL','PHOTO.TYPE']]
data.append(('PHOTO',data_photo))
except: pass
data.sort()
itm = '\n'.join(['%s:%s' % (t[0],t[1].replace('\r','[LF]').replace('\n','[CR]').replace('\t','[TAB]')) for t in data])
else: itm = 'empty'
acl_vcard_tmp['%s/%s' % (room,nick)] = itm
for tmp in a:
if tmp[0] == 'vcard' and (tmp[5] == 9 or lvl == tmp[5]):
was_match = False
if tmp[1] in ['exp','!exp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.I|re.U): was_match = True
elif tmp[1] in ['cexp','!cexp']:
if tmp[1][0] == '!' and not re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif re.findall(tmp[2].replace('*','*?'),itm,re.S|re.U): was_match = True
elif tmp[1] in ['sub','!sub']:
if tmp[1][0] == '!' and tmp[2].lower() not in itm.lower(): was_match = True
elif tmp[2].lower() in itm.lower(): was_match = True
elif tmp[1] in ['=','!=']:
if tmp[1][0] == '!' and (itm.lower() != tmp[2].lower() or tmp[0] == 'all' and tmp[2].lower() not in (jid.lower(),nick.lower(),'\n'.join(mass).lower())): was_match = True
elif itm.lower() == tmp[2].lower() or (tmp[0] == 'all' and tmp[2].lower() in (jid.lower(),nick.lower(),'\n'.join(mass).lower())): was_match = True
if was_match: acl_action(tmp[3],nick,jid,room,None)
global execute, presence_control, message_act_control
presence_control = [acl_presence]
message_act_control = [acl_message]
execute = [(7, 'acl', muc_acl, 2, 'Actions list.\nacl show - show list\nacl del [/silent] item - remove item from list\nacl [/time] [/silent] msg|prs|role|aff|nick|jid|jidfull|res|age|ver|vcard|all [sub|exp|cexp] pattern command - execute command by condition\nallowed variables in commands: ${NICK}, ${JID}, ${SERVER}, ${EXP} and ${/EXP}\nsub = substring, exp = regular expression, cexp = case sensitive regular expression\ntime format is /number+identificator. s = sec, m = min, d = day, w = week, M = month, y = year. only one identificator allowed!')]

49
plugins/adminmail.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) dr.Schmurge <dr.schmurge@isida-bot.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def adminmail(type, jid, nick, text):
if len(text):
if len(text) > GT('amsg_limit_size'): text = text[:GT('amsg_limit_size')]+u'[…]'
ga = get_level(jid, nick)
fjid = getRoom(ga[1])
tmp_lim = GT('amsg_limit')[ga[0]]
am = cur_execute_fetchone('select time from saytoowner where jid=%s;',(fjid,))
if am:
wt = int(am[0]-time.time())
if wt >= 0:
send_msg(type, jid, nick, L('Time limit exceeded. Wait: %s','%s/%s'%(jid,nick)) % un_unix(wt,'%s/%s'%(jid,nick)))
return None
else: cur_execute('delete from saytoowner where jid=%s;',(fjid,))
cur_execute('insert into saytoowner values (%s,%s)',(fjid,int(time.time())+tmp_lim))
msg = L('User %s (%s) from %s at %s send massage to you: %s','%s/%s'%(jid,nick)) % (nick,fjid,jid,time.strftime("%H:%M %d.%m.%y", time.localtime (time.time())),text)
own = cur_execute_fetchall('select * from bot_owner;')
if own:
for ajid in own: send_msg('chat', ajid[0], '', msg)
send_msg(type, jid, nick, L('Sent','%s/%s'%(jid,nick)))
else: send_msg(type, jid, nick, L('Owner list is empty!','%s/%s'%(jid,nick)))
else: send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
global execute
execute = [(4, 'msgtoadmin', adminmail, 2, 'Send message to bot\'s owner\nmsgtoadmin text')]

221
plugins/age.py Normal file
View File

@@ -0,0 +1,221 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
AGE_DEFAULT_LIMIT = 10
AGE_MAX_LIMIT = 100
TIME_OF_LOGGING_JOINS = 1357231720
def join_time_stat(type, jid, nick, text):
text = text.strip()
if text and text.isdigit(): llim = int(text)
else:
try: llim = GT('age_default_limit')
except: llim = AGE_DEFAULT_LIMIT
if llim not in range(1,AGE_MAX_LIMIT): llim = AGE_DEFAULT_LIMIT
t_age_tmp = cur_execute_fetchall(' select jid,time from first_join where room=%s and jid in (select jid from age where room=%s and status=0 order by time) order by time limit %s;',(jid,jid,llim))
t_age = []
for t in t_age_tmp:
tmp = cur_execute_fetchone('select nick from age where room=%s and jid=%s order by status,-time',(jid,t[0]))
t_age.append((tmp[0],t[1]))
msg = L('Joins statistic:\n%s','%s/%s'%(jid,nick)) % '\n'.join(['%s\t %s%s' % (t[0],['','~'][t[1]<TIME_OF_LOGGING_JOINS],nice_time(t[1],'%s/%s'%(jid,nick))[2].split(', GMT',1)[0]) for t in t_age])
send_msg(type, jid, nick, msg)
def join_time(type, jid, nick, text):
if not text: text = nick
lvl,r_jid = get_level(jid,text)
if lvl != -2:
j_time = cur_execute_fetchone('select time from first_join where room=%s and jid=%s;',(jid,getRoom(r_jid)))[0]
msg = L('First %s\'s join is %s%s (%s ago)','%s/%s'%(jid,nick)) % (text,['','~'][j_time<TIME_OF_LOGGING_JOINS],nice_time(j_time,'%s/%s'%(jid,nick))[2],un_unix(int(time.time())-j_time,'%s/%s'%(jid,nick)))
else: msg = L('Not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def true_age_stat(type, jid, nick, text):
text = text.strip()
if text and text.isdigit(): llim = int(text)
else:
try: llim = GT('age_default_limit')
except: llim = AGE_DEFAULT_LIMIT
if llim not in range(1,AGE_MAX_LIMIT): llim = AGE_DEFAULT_LIMIT
if base_type == 'pgsql': reqv = 'select jid,sum(age+(status = 0)::boolean::int*(%s-time)) as sum_age from age where room=%s group by jid order by sum_age desc limit %s;'
elif base_type in ['sqlite3','mysql']: reqv = 'select jid,sum(age+(status = 0)*(%s-time)) as sum_age from age where room=%s group by jid order by sum_age desc limit %s;'
else: return
t_age_tmp = cur_execute_fetchall(reqv,(int(time.time()),jid,llim))
t_age = []
for t in t_age_tmp:
tmp = cur_execute_fetchone('select nick from age where room=%s and jid=%s order by status,-time',(jid,t[0]))
t_age.append((tmp[0],t[1]))
msg = L('Age statistic:\n%s','%s/%s'%(jid,nick)) % '\n'.join(['%s\t%s' % (t[0],un_unix(t[1],'%s/%s'%(jid,nick))) for t in t_age])
send_msg(type, jid, nick, msg)
def true_age_split(type, jid, nick, text):
true_age_raw(type, jid, nick, text, True)
def true_age(type, jid, nick, text):
true_age_raw(type, jid, nick, text, None)
def true_age_raw(type, jid, nick, text, xtype):
text = text.rstrip().split('\n')
llim = 10
if len(text) > 1:
try: llim = int(text[1])
except: llim = GT('age_default_limit')
text = text[0]
if not text: text = nick
if llim > GT('age_max_limit'): llim = GT('age_max_limit')
real_jid = cur_execute_fetchone('select jid from age where room=%s and (nick=%s or jid=%s) order by -time,status',(jid,text,text.lower()))
if not real_jid:
text = '%%%s%%' % text.lower()
real_jid = cur_execute_fetchone('select jid from age where room=%s and (no_case_nick ilike %s or jid ilike %s) order by -time,status',(jid,text,text))
try:
if xtype: sbody = cur_execute_fetchall('select * from age where room=%s and jid=%s order by -time,status limit %s',(jid,real_jid[0],llim))
else:
t_age = cur_execute_fetchone('select sum(age) from age where room=%s and jid=%s',(jid,real_jid[0]))
sbody = cur_execute_fetchone('select * from age where room=%s and jid=%s order by -time,status',(jid,real_jid[0]))
sbody = [sbody[:4] + t_age + sbody[5:]]
except: sbody = None
if sbody:
msg = L('I see:','%s/%s'%(jid,nick))
for cnt, tmp in enumerate(sbody):
if tmp[5]: r_age = tmp[4]
else: r_age = int(time.time()) - tmp[3] + tmp[4]
if xtype: msg += '\n%s. %s' % (cnt + 1, tmp[1])
else: msg += ' %s' % tmp[1]
msg += '\t%s, ' % un_unix(r_age,'%s/%s'%(jid,nick))
if tmp[5]:
if tmp[6]: msg += L('%s %s ago','%s/%s'%(jid,nick)) % (tmp[6], un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick)))
else: msg += L('Leave %s ago','%s/%s'%(jid,nick)) % un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick))
t7sp = tmp[7].split('\r')[0]
if t7sp.count('\n') > 3:
stat = t7sp.split('\n', 4)[4]
if stat: msg += ' (%s)' % stat
elif t7sp: msg += ' (%s)' % t7sp
if '\r' in tmp[7]: msg += ', %s %s' % (L('Client:','%s/%s'%(jid,nick)),' // '.join(tmp[7].split('\r')[-1].split(' // ')[:-1]))
else: msg += L('Is here: %s','%s/%s'%(jid,nick)) % un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick))
if not xtype: msg = msg.replace('\t', ' - ')
else: msg = L('Not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def seen(type, jid, nick, text):
seen_raw(type, jid, nick, text, None)
def seen_split(type, jid, nick, text):
seen_raw(type, jid, nick, text, True)
def seen_raw(type, jid, nick, text, xtype):
text = text.rstrip().split('\n')
llim = GT('age_default_limit')
if len(text)>1:
try: llim = int(text[1])
except: llim = GT('age_default_limit')
text = text[0]
if not text: text = nick
if llim > GT('age_max_limit'): llim = GT('age_max_limit')
real_jid = cur_execute_fetchone('select jid from age where room=%s and (nick=%s or jid=%s) order by status,-time',(jid,text,text.lower()))
if not real_jid:
textt = '%%%s%%' % text.lower()
real_jid = cur_execute_fetchone('select jid from age where room=%s and (no_case_nick ilike %s or jid ilike %s) order by status,-time',(jid,textt,textt))
if real_jid:
if xtype: sbody = cur_execute_fetchall('select * from age where room=%s and jid=%s order by status,-time limit %s',(jid,real_jid[0],llim))
else: sbody = [cur_execute_fetchone('select * from age where room=%s and jid=%s order by status,-time',(jid,real_jid[0]))]
else: sbody = None
if sbody:
msg = L('I see:','%s/%s'%(jid,nick))
for cnt, tmp in enumerate(sbody):
if xtype: msg += '\n%s. ' % (cnt+1)
else: msg += ' '
if text != tmp[1]: msg += L('%s (with nick: %s)','%s/%s'%(jid,nick)) % (text,tmp[1])
else: msg += tmp[1]
if tmp[5]:
if tmp[6]: msg += ' - ' + L('%s %s ago','%s/%s'%(jid,nick)) % (tmp[6], un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick)))
else: msg += ' - ' + L('Leave %s ago','%s/%s'%(jid,nick)) % un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick))
t7sp = tmp[7].split('\r')[0]
if t7sp.count('\n') > 3:
stat = t7sp.split('\n',4)[4]
if stat: msg += ' (%s)' % stat
elif t7sp: msg += ' (%s)' % t7sp
if '\r' in tmp[7]: msg += ', %s %s' % (L('Client:','%s/%s'%(jid,nick)),' // '.join(tmp[7].split('\r')[-1].split(' // ')[:-1]))
else: msg += ' - '+ L('Is here: %s','%s/%s'%(jid,nick)) % un_unix(int(time.time()-tmp[3]),'%s/%s'%(jid,nick))
else: msg = L('Not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def seenjid(type, jid, nick, text):
seenjid_raw(type, jid, nick, text, None)
def seenjid_split(type, jid, nick, text):
seenjid_raw(type, jid, nick, text, True)
def seenjid_raw(type, jid, nick, text, xtype):
text = text.rstrip().split('\n')
llim = GT('age_default_limit')
if len(text)>1:
try: llim = int(text[1])
except: llim = GT('age_default_limit')
text = text[0]
ztype = None
if not text: text = nick
if llim > GT('age_max_limit'): llim = GT('age_max_limit')
real_jid = cur_execute_fetchall('select jid from age where room=%s and (nick ilike %s or jid ilike %s) group by jid,status,time order by status,-time',(jid,text,text.lower()))
if not real_jid:
txt = '%%%s%%' % text.lower()
real_jid = cur_execute_fetchall('select jid from age where room=%s and (no_case_nick ilike %s or jid ilike %s) group by jid,status,time order by status,-time',(jid,txt,txt))
sbody = []
if real_jid:
for rj in real_jid:
if xtype: tmpbody = cur_execute_fetchall('select * from age where room=%s and jid=%s order by status, jid limit %s',(jid,rj[0],llim))
else: tmpbody = [cur_execute_fetchone('select * from age where room=%s and jid=%s order by status',(jid,rj[0]))]
if tmpbody:
for t in tmpbody:
if t not in sbody: sbody.append(t)
if sbody:
ztype = True
msg = L('I saw %s:','%s/%s'%(jid,nick)) % text
for cnt, tmp in enumerate(sbody):
msg += '\n%s. %s (%s)' % (cnt + 1, tmp[1], tmp[2])
if tmp[5]:
if tmp[6]: msg += '\t' + L('%s %s ago','%s/%s'%(jid,nick)) % (tmp[6], un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick)))
else: msg += '\t' + L('Leave %s ago','%s/%s'%(jid,nick)) % un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick))
t7sp = tmp[7].split('\r')[0]
if t7sp.count('\n') > 3:
stat = t7sp.split('\n', 4)[4]
if stat: msg += ' (%s)' % stat
elif t7sp: msg += ' (%s)' % t7sp
if '\r' in tmp[7]: msg += ', %s %s' % (L('Client:','%s/%s'%(jid,nick)), tmp[7].split('\r')[-1])
else: msg += '\t' + L('Is here: %s','%s/%s'%(jid,nick)) % un_unix(int(time.time() - tmp[3]),'%s/%s'%(jid,nick))
if not xtype: msg = msg.replace('\t', ' - ')
else: msg = L('Not found!','%s/%s'%(jid,nick))
if type == 'groupchat' and ztype:
send_msg(type, jid, nick, L('Send for you in private','%s/%s'%(jid,nick)))
send_msg('chat', jid, nick, msg)
else: send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'age', true_age, 2, 'Show age of jid in conference.'),
(3, 'age_split', true_age_split, 2, 'Show age of jid in conference splitted by nicks.'),
(3, 'seen', seen, 2, 'Show time of join/leave.'),
(3, 'seen_split', seen_split, 2, 'Show time of join/leave splitted by nicks.'),
(3, 'agestat', true_age_stat, 2, 'Show age statistic for conference.'),
(7, 'seenjid', seenjid, 2, 'Show time of join/leave + jid.'),
(7, 'seenjid_split', seenjid_split, 2, 'Show time of join/leave + jid splitted by nicks.'),
(3, 'when', join_time, 2, 'Show time of first join into room.'),
(3, 'whenstat', join_time_stat, 2, 'Show statistic for time of first join into room.')]

108
plugins/ai.py Normal file
View File

@@ -0,0 +1,108 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# [u'devel@conference.jabber.ru', u'sulci', u'moderator', u'admin', u'sulci@jabber.ru/Ocaml']
AI_PREV = {}
AI_PHRASES_FOLDER = data_folder % 'ai/%s'
AI_PHRASES_FILES = [t for t in os.listdir(AI_PHRASES_FOLDER % '') if t.endswith('.txt') and os.path.isfile(AI_PHRASES_FOLDER % t)]
AI_PHRASES = {}
for PH_LANG in AI_PHRASES_FILES:
PH_L = PH_LANG.split('.',1)[0]
PHRASES = readfile(AI_PHRASES_FOLDER % PH_LANG).decode('utf-8').replace('\r','').split('\n')
for LINE in PHRASES:
if LINE.strip() and not LINE.strip().startswith('#') and '\t' in LINE:
if not AI_PHRASES.has_key(PH_L): AI_PHRASES[PH_L] = [LINE.split('\t',1)]
else: AI_PHRASES[PH_L].append(LINE.split('\t',1))
def AI_PARSE(room, jid, nick, type, text):
if not get_config(room,'ai'): return
LOC = get_L_('%s/%s' % (room,nick))
TEXT = ' %s ' % text.lower()
SCORE, CMD = 1.0, []
for PHRASES in AI_PHRASES[LOC]:
CUR_SCORE = AI_RATING(PHRASES[1].split('||')[0], TEXT, room)
if CUR_SCORE > SCORE: SCORE, CMD = CUR_SCORE, [PHRASES]
elif CUR_SCORE == SCORE: CMD.append(PHRASES)
if not CMD: return
pprint('AI score %s|%s|%s' % (SCORE, '|'.join([t[0] for t in CMD]), text),'cyan')
CMD = random.choice(CMD)
CMD_RAW = CMD[0].split()[0]
pprint('AI selected %s' % CMD_RAW,'cyan')
nowname = getResourse(cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%room,))[0])
access_mode = get_level(room,nick)[0]
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(room,CMD_RAW)): return
ptype = ''
for t in comms:
if t[1] == CMD_RAW:
ptype = t[-1]
break
if 'nick' in ptype and '||' in CMD[1]:
for t in CMD[1].split('||')[1].split('|'):
text = text.replace(t,nick)
PRM = AI_PARAMETER(text, ptype, room)
if 'nick' in ptype:
PP = None
for t in PRM:
if t:
PP = True
break
if not PP: PRM.append(nick)
for PARAM in PRM:
if PARAM:
COMMAND = CMD[0].replace('{PAR}',PARAM)
print COMMAND
com_parser(access_mode, nowname, type, room, nick, COMMAND, jid)
def AI_RATING(s, text, room):
r,s = 0.0,s.split('|')
for k in s:
if k in text: r += 0.5
if k in AI_PREV.get(room, ''): r += 0.34
return r
def AI_PARAMETER(body, type, room):
P_NICK, P_JID, P_SERVER = None, None, None
if 'nick' in type:
NICKS = [t[1] for t in megabase if t[0]==room]
for NICK in NICKS:
if NICK in body:
P_NICK = NICK
break
if 'jid' in type:
JID = re.findall(u'[-a-z0-9а-яё_]+@[-0-9a-z\.]+',body,re.S|re.I|re.U)
if JID: P_JID = JID[0]
if 'server' in type:
SERVER = re.findall(u'[-0-9a-zа-яё\.]+\.[-a-zа-я]{2,}',body,re.S|re.I|re.U)
if SERVER: P_SERVER = SERVER[0]
return [P_NICK, P_JID, P_SERVER]
gmessage.append(AI_PARSE)

44
plugins/anek.py Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) ferym <ferym@jabbim.org.ru> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def anek(type, jid, nick):
try:
target = load_page('http://anekdot.odessa.ua/rand-anekdot.php')
od = re.search('background-color:#FFFFFF\'>',target)
message = target[od.end():]
message = message[:re.search('<br>',message).start()]
message = message.replace('<br />','')
message = message.strip()
message = rss_replace(unicode(message,'windows-1251'))
if type=='groupchat':
if len(message) < GT('anek_private_limit'): send_msg(type, jid, nick, message)
else:
send_msg(type, jid, nick, L('Send for you in private','%s/%s'%(jid,nick)))
send_msg('chat', jid, nick, message)
return
else: send_msg(type, jid, nick, message)
except: send_msg(type, jid, nick, L('Something broken.','%s/%s'%(jid,nick)))
global execute
execute = [(3, 'anek', anek, 1, 'Show random anecdote | Author: ferym')]

54
plugins/answers.py Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def answers_ie(type, jid, nick, text):
if text.lower().strip().split(' ',1)[0] == 'export':
try: fname = text.lower().split(' ',1)[1]
except: fname = answers_file
base_size = len(cur_execute_fetchall('select * from answer'))
fnd = cur_execute_fetchall('select body from answer where body ilike %s group by body order by body',('%',))
answer = ''
msg = L('Export to file: %s | Total records: %s | Unique records: %s','%s/%s'%(jid,nick)) % (fname,base_size,len(fnd))
for i in fnd:
if i[0] != '': answer += i[0].strip() +'\n'
writefile(fname,answer.encode('utf-8'))
elif text.lower().strip().split(' ',1)[0] == 'import':
try: fname = text.lower().split(' ',1)[1]
except: fname = answers_file
if os.path.isfile(fname):
answer = readfile(fname).decode('utf-8')
answer = answer.split('\n')
cur_execute('delete from answer where body ilike %s',('%',))
msg = L('Import from file: %s | Total records: %s','%s/%s'%(jid,nick)) % (fname,len(answer))
idx = 1
for i in answer:
if i != '':
cur_execute('insert into answer values (%s,%s)', (idx,unicode(i.strip())))
idx += 1
else: msg = L('File %s not found!','%s/%s'%(jid,nick)) % fname
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(9, 'answers', answers_ie, 2, 'Import/Export answers base.\nanswers import [filename] - import from file\nanswers export [filename] - export to file')]

45
plugins/antitroll.py Normal file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def troll(type, jid, nick, text):
text = text.split('\n')
r = unicode(text[0])
try: count = int(text[2])
except: count = GT('troll_default_limit')
if count > GT('troll_max_limit'): count = GT('troll_max_limit')
otake = xmpp.JID(node=getName(jid), domain=getServer(jid), resource=r)
otake = unicode(otake)
if len(text)>1: message = text[1]
else: message = L('You troll!','%s/%s'%(jid,nick))
tst = GT('troll_sleep_time')
while count != 0:
sender(xmpp.Message(otake, message, "chat"))
time.sleep(tst)
count -= 1
send_msg(type, jid, nick, L('Done','%s/%s'%(jid,nick)))
global execute, timer
timer = []
execute = [(9, 'troll', troll, 2, 'Repeat message to private.\ntroll nick\n[text]\n[number]')]

166
plugins/backup.py Normal file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
backup_async = {}
def getMucItems(jid,affil,ns,back_id):
iqid = get_id()
if ns == xmpp.NS_MUC_ADMIN: i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':getRoom(jid)}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':affil})])])
else: i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':getRoom(jid)}, payload = [xmpp.Node('query', {'xmlns': ns},[])])
iq_request[iqid]=(time.time(),getMucItems_async,[ns,affil,back_id],ns)
sender(i)
def getMucItems_async(ns,affil,back_id,iq_stanza):
global backup_async
iq_stanza = iq_stanza[1][0]
if ns == xmpp.NS_MUC_ADMIN: backup_async[back_id][affil] = [[tmp.getAttr('jid'),['',tmp.getTagData('reason')][tmp.getTagData('reason') != None]] for tmp in iq_stanza.getTag('query',namespace=xmpp.NS_MUC_ADMIN).getTags('item')]
else: backup_async[back_id]['room_config'] = [[tmp.getAttr('var'),tmp.getAttr('type'),tmp.getTagData('value')] for tmp in iq_stanza.getTag('query',namespace=xmpp.NS_MUC_OWNER).getTag('x',namespace=xmpp.NS_DATA).getTags('field')]
def make_stanzas_array(raw_back,jid,affil):
stanza_array = []
try: make_stanza_jid_count = get_config_int(jid,'make_stanza_jid_count')
except: make_stanza_jid_count = 1
for tmp in range(0,len(raw_back),make_stanza_jid_count):
i = xmpp.Iq(typ='set',to=jid,xmlns=xmpp.NS_CLIENT)
i.setTag('query',namespace=xmpp.NS_MUC_ADMIN)
for t in raw_back[tmp:tmp+make_stanza_jid_count]:
i.getTag('query',namespace=xmpp.NS_MUC_ADMIN).\
setTag('item',attrs={'affiliation':affil,'jid':t[0]}).\
setTagData('reason',t[1])
stanza_array.append(i)
return stanza_array
def conf_backup(type, jid, nick, text):
global backup_async,conn
if len(text):
text = text.split(' ')
mode = text[0]
if mode == 'show':
a = os.listdir(back_folder % '')
b = []
for c in a:
if not c.endswith('.txt') and not c.endswith('.back'): b.append((c,os.path.getmtime(back_folder % c)))
if len(b): msg = '%s %s' % (L('Available copies:','%s/%s'%(jid,nick)), ', '.join(['%s (%s)' % (c[0],disp_time(c[1],'%s/%s'%(jid,nick))) for c in b]))
else: msg = L('Backup copies not found.','%s/%s'%(jid,nick))
elif mode == 'now':
if get_xtype(jid) != 'owner': msg = L('I need an owner affiliation for backup settings!','%s/%s'%(jid,nick))
else:
back_id = get_id()
backup_async[back_id] = {}
getMucItems(jid,'outcast',xmpp.NS_MUC_ADMIN,back_id)
getMucItems(jid,'member',xmpp.NS_MUC_ADMIN,back_id)
getMucItems(jid,'admin',xmpp.NS_MUC_ADMIN,back_id)
getMucItems(jid,'owner',xmpp.NS_MUC_ADMIN,back_id)
getMucItems(jid,'',xmpp.NS_MUC_OWNER,back_id)
bst = GT('backup_sleep_time')
while len(backup_async[back_id]) != 5 and not game_over: time.sleep(bst)
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'admin', 'jid':getRoom(str(selfjid))},[])])])
sender(i)
backup_async[back_id]['alias'] = cur_execute_fetchall('select match ,cmd from alias where room=%s',(jid,))
backup_async[back_id]['bot_config'] = cur_execute_fetchall('select option ,value from config_conf where room=%s',(jid,))
backup_async[back_id]['acl'] = cur_execute_fetchall('select action,type,text,command,time,level from acl where jid=%s',(jid,))
backup_async[back_id]['rss'] = cur_execute_fetchall('select url, update ,type,time,hash from feed where room=%s',(jid,))
msg = L('Copying completed!','%s/%s'%(jid,nick))
msg += L('\nOwners: %s | Admins: %s | Members: %s | Banned: %s','%s/%s'%(jid,nick)) % (\
len(backup_async[back_id]['owner'])-1,\
len(backup_async[back_id]['admin'])+1,\
len(backup_async[back_id]['member']),\
len(backup_async[back_id]['outcast']))
msg += L('\nRoom config: %s | Bot config: %s | Aliases: %s | Acl\'s: %s | RSS: %s','%s/%s'%(jid,nick)) % (\
len(backup_async[back_id]['room_config']),\
len(backup_async[back_id]['bot_config']),\
len(backup_async[back_id]['alias']),\
len(backup_async[back_id]['acl']),\
len(backup_async[back_id]['rss']))
writefile(back_folder % unicode(jid),json.dumps(backup_async[back_id]))
elif mode == 'restore':
if len(text)>1:
if text[1] in os.listdir(back_folder % ''):
if text[1].endswith('.acl'):
raw_back = json.loads(readfile(back_folder % unicode(text[1])))
cnt = 0
for tmp in raw_back:
isit = cur_execute_fetchall('select action,type,text,command,time from acl where jid=%s and action=%s and type=%s and text=%s and level=%s',(jid,tmp[0],tmp[1],tmp[2],tmp[5]))
if not isit:
cur_execute('insert into acl values (%s,%s,%s,%s,%s,%s,%s)', tmp)
cnt += 1
msg = L('Restored %s action(s).','%s/%s'%(jid,nick)) % cnt
elif get_xtype(jid) != 'owner': msg = L('I need an owner affiliation for restore settings!','%s/%s'%(jid,nick))
else:
bst = GT('backup_sleep_time')
raw_back=json.loads(readfile(back_folder % unicode(text[1])))
for tmp in ['outcast','member','admin','owner']:
for t in make_stanzas_array(raw_back[tmp],jid,tmp):
sender(t)
time.sleep(bst)
i = xmpp.Iq(typ='set',to=jid,xmlns=xmpp.NS_CLIENT)
i.setTag('query',namespace=xmpp.NS_MUC_OWNER)
i.getTag('query',namespace=xmpp.NS_MUC_OWNER).setTag('x',namespace=xmpp.NS_DATA).setAttr('type','submit')
for tmp in raw_back['room_config']:
i.getTag('query',namespace=xmpp.NS_MUC_OWNER).getTag('x',namespace=xmpp.NS_DATA).\
setTag('field',attrs={'var':tmp[0],'type':tmp[1]}).\
setTagData('value',tmp[2])
sender(i)
time.sleep(bst)
sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'admin', 'jid':getRoom(unicode(selfjid))},[])])]))
time.sleep(bst)
cur_execute_fetchall('delete from config_conf where room=%s',(jid,))
for tmp in raw_back['bot_config']: cur_execute('insert into config_conf (room, option ,value) values (%s,%s,%s)',(jid,tmp[0],tmp[1]))
for tmp in raw_back['alias']:
cur_execute('delete from alias where room=%s and match =%s',(jid,tmp[0]))
cur_execute('insert into alias (room, match ,cmd) values (%s,%s,%s)',(jid,tmp[0],tmp[1]))
for tmp in raw_back['acl']:
isit = cur_execute_fetchall('select action,type,text,command,time from acl where jid=%s and action=%s and type=%s and text=%s and level=%s',(jid,tmp[0],tmp[1],tmp[2],tmp[5]))
if not isit: cur_execute('insert into acl values (%s,%s,%s,%s,%s,%s,%s)', tuple([jid]+list(tmp)))
for tmp in raw_back['rss']:
isit = cur_execute_fetchone('select * from feed where room=%s and url=%s',(jid,tmp[0]))
if not isit: cur_execute('insert into feeed (url, update ,type,time,room,hash) values (%s,%s,%s,%s,%s,%s)',(tmp[0],tmp[1],tmp[2],tmp[3],jid,tmp[4]))
msg = L('Restore completed.','%s/%s'%(jid,nick))
msg += L('\nOwners: %s | Admins: %s | Members: %s | Banned: %s','%s/%s'%(jid,nick)) % (\
len(raw_back['owner'])-1,\
len(raw_back['admin'])+1,\
len(raw_back['member']),\
len(raw_back['outcast']))
msg += L('\nRoom config: %s | Bot config: %s | Aliases: %s | Acl\'s: %s | RSS: %s','%s/%s'%(jid,nick)) % (\
len(raw_back['room_config']),\
len(raw_back['bot_config']),\
len(raw_back['alias']),\
len(raw_back['acl']),\
len(raw_back['rss']))
else: msg = L('Copy not found. Use key "show" for lisen available copies.','%s/%s'%(jid,nick))
else: msg = L('What do you want to restore?','%s/%s'%(jid,nick))
else: msg = L('Unknown item!','%s/%s'%(jid,nick))
else: msg = 'backup now|show|restore'
send_msg(type, jid, nick, msg)
global execute
execute = [(8, 'backup', conf_backup, 2, 'Backup/restore conference settings.\nbackup show|now|restore\nshow - show available copies\nnow - backup current conference\nrestore name_conference - restore settings name_conference in current conference')]

51
plugins/bash.py Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def bash_org_ru(type, jid, nick, text):
text = text.strip()
if not text: url = 'http://bash.org.ru/random'
elif re.match('\d+$', text): url = 'http://bash.org.ru/quote/%s' % text
else: url = 'http://bash.org.ru/?text=%s' % urllib.quote(text.encode('cp1251'))
body = html_encode(load_page(url))
body = re.findall('<span class="date">(.*?)</span>.*?class="id">(.*?)</a>.*?<div class="text">(.*?)</div>',body,re.S|re.I|re.U)
try: msg = rss_del_nn(rss_replace('%s %s\n%s' % body[0]))
except: msg = L('Quote not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def ibash_org_ru(type, jid, nick, text):
reg_title = '<div class="quothead">.*?<b>#(.*?)</b>'
reg_body = '<div class="quotbody">(.*?)</div>'
url_id = 'http://ibash.org.ru/quote.php?id='
try: url = url_id+str(int(text))
except: url = 'http://ibash.org.ru/random.php'
body = html_encode(load_page(url))
msg = url_id + re.findall(reg_title, body, re.S)[0]
if msg[-3:] == '???': msg = L('Quote not found!','%s/%s'%(jid,nick))
else: msg += '\n'+rss_replace(re.findall(reg_body, body, re.S)[0])
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'bash', bash_org_ru, 2, 'Quote from bash.org.ru\nbash [number]'),
(3, 'ibash', ibash_org_ru, 2, 'Quote from ibash.org.ru\nibash [number]')]

75
plugins/bing.py Normal file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def bing_translate(type, jid, nick, text):
text = text.strip()
trlang = {'id':L('Indonesian','%s/%s'%(jid,nick)), 'it':L('Italian','%s/%s'%(jid,nick)), 'ar':L('Arabic','%s/%s'%(jid,nick)),
'ja':L('Japanese','%s/%s'%(jid,nick)), 'bg':L('Bulgarian','%s/%s'%(jid,nick)), 'ko':L('Korean','%s/%s'%(jid,nick)),
'ca':L('Catalan','%s/%s'%(jid,nick)), 'lv':L('Latvian','%s/%s'%(jid,nick)), 'zh-chs':L('Chinese Simplified','%s/%s'%(jid,nick)),
'lt':L('Lithuanian','%s/%s'%(jid,nick)), 'zh-cht':L('Chinese Traditional','%s/%s'%(jid,nick)), 'no':L('Norwegian','%s/%s'%(jid,nick)),
'cs':L('Czech','%s/%s'%(jid,nick)), 'pl':L('Polish','%s/%s'%(jid,nick)), 'da':L('Danish','%s/%s'%(jid,nick)),
'pt':L('Portuguese','%s/%s'%(jid,nick)), 'nl':L('Dutch','%s/%s'%(jid,nick)), 'ro':L('Romanian','%s/%s'%(jid,nick)),
'en':L('English','%s/%s'%(jid,nick)), 'ru':L('Russian','%s/%s'%(jid,nick)), 'et':L('Estonian','%s/%s'%(jid,nick)),
'sk':L('Slovak','%s/%s'%(jid,nick)), 'fi':L('Finnish','%s/%s'%(jid,nick)), 'sl':L('Slovenian','%s/%s'%(jid,nick)),
'fr':L('French','%s/%s'%(jid,nick)), 'es':L('Spanish','%s/%s'%(jid,nick)), 'de':L('German','%s/%s'%(jid,nick)),
'sv':L('Swedish','%s/%s'%(jid,nick)), 'el':L('Greek','%s/%s'%(jid,nick)), 'th':L('Thai','%s/%s'%(jid,nick)),
'ht':L('Haitian Creole','%s/%s'%(jid,nick)), 'tr':L('Turkish','%s/%s'%(jid,nick)), 'he':L('Hebrew','%s/%s'%(jid,nick)),
'uk':L('Ukrainian','%s/%s'%(jid,nick)), 'hi':L('Hindi','%s/%s'%(jid,nick)), 'vi':L('Vietnamese','%s/%s'%(jid,nick)),
'hu':L('Hungarian','%s/%s'%(jid,nick))}
if text.lower() == 'list': msg = L('Available languages for translate:','%s/%s'%(jid,nick)) + ' ' + ', '.join(sorted(trlang.keys()))
elif text[:5].lower() == 'info ':
text = text.lower().split(' ')
msg = ''
for tmp in text:
if tmp in trlang: msg += '%s - %s, ' % (tmp,trlang[tmp])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg[:-2]
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
elif text[:5].lower() == 'lang ' and text.count(' ')==1:
text = text.lower().split(' ')[1]
msg = ', '.join(['%s - %s' % (k,trlang[k]) for k in trlang.keys() if text in trlang[k].lower()])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
else:
if ' ' in text:
text = text.split(' ',2)
url = 'http://api.microsofttranslator.com/V2/Ajax.svc/Translate?'
bing_api = GT('bing_api_key')
if bing_api == 'no api': msg = L('Not found Api-key for Bing translator','%s/%s'%(jid,nick))
elif len(text)>1 and trlang.has_key(text[0].lower()):
if len(text)>2 and trlang.has_key(text[1].lower()): lfrom,lto,tr_text = text[0].lower(),text[1].lower(),text[2]
else: lfrom,lto,tr_text = '',text[0].lower(),' '.join(text[1:])
translate_results = html_encode(load_page(url, {'oncomplete':'responseData',\
'appId':bing_api,\
'text':tr_text.encode("utf-8"),\
'from':lfrom,\
'to':lto}))
try: msg = re.findall('responseData\(\"(.*?)\"\)\;$',unicode(translate_results),re.S|re.I|re.U)[0]
except: msg = L('I can\'t translate it!','%s/%s'%(jid,nick))
else: msg = L('Incorrect language settings for translate. bt list - available languages.','%s/%s'%(jid,nick))
else: msg = L('Command\'s format: bt [from] to text','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'bt', bing_translate, 2, 'Bing translator.\nbt [from_language] to_language text - translate text\nbt list - list for available languages for translate\nbt info <reduction> - get info about language reduction\nbt lang <expression> - get languages by expression')]

67
plugins/blacklist.py Normal file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def leave_room(rjid, reason):
msg = ''
cnf = cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%rjid,))
if cnf:
cur_execute('delete from conference where room ilike %s;', ('%s/%%'%rjid,))
leave(rjid, reason)
msg = L('Leave conference %s\n') % rjid
return msg
def blacklist(type, jid, nick, text):
text, msg = unicode(text.lower()), ''
reason = L('Conference was added in blacklist','%s/%s'%(jid,nick))
try: cmd,room = text.split(' ',1)
except: cmd,room = text,''
if room and '@' not in room: room = '%s@%s' % (room,lastserver)
if cmd == 'show':
bl = cur_execute_fetchall('select room from blacklist;')
if not bl: msg = L('List is empty.','%s/%s'%(jid,nick))
else: msg = '%s%s' % (L('List of conferences:\n','%s/%s'%(jid,nick)),'\n'.join(['%s. %s' % (t[0]+1,t[1][0]) for t in enumerate(bl)]))
elif cmd == 'clear':
msg = L('Cleared.','%s/%s'%(jid,nick))
cur_execute('delete from blacklist;')
elif room and cmd == 'add':
if cur_execute_fetchone('select * from blacklist where room=%s', (room,)): msg = L('This conference already exist in blacklist.','%s/%s'%(jid,nick))
elif cur_execute_fetchone('select count(*) from conference;')[0]==1 and getRoom(cur_execute_fetchone('select room from conference;')[0]) == room:
msg =L('You can\'t add last conference in blacklist.','%s/%s'%(jid,nick))
else:
msg = leave_room(room, reason)
cur_execute('insert into blacklist values (%s)', (room,))
msg += L('Add to blacklist: %s','%s/%s'%(jid,nick)) % room
elif room and cmd == 'del':
if cur_execute_fetchone('select * from blacklist where room=%s', (room,)):
cur_execute('delete from blacklist where room=%s', (room,))
msg = L('Removed from blacklist: %s','%s/%s'%(jid,nick)) % room
else: msg = L('Address not in blacklist.','%s/%s'%(jid,nick))
else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(9, 'blacklist', blacklist, 2, 'Manage of conferences blacklist.\nblacklist add|del|show|clear\nblacklist add|del room@conference.server.tld - add|remove address from blacklist\nblacklist show - show blacklist\nblacklist clear - clear blacklist')]

177
plugins/bomb.py Normal file
View File

@@ -0,0 +1,177 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
bomb_colors = [L('blue'),L('red'),L('magenta'),L('green'),L('cyan'),L('yellow'),L('white'),L('black')]
bomb_current = {}
bomb_random_list = {}
bomb_random_timer_check_period = 10
bomb_random_sleep = 600
bomb_deny_access = [-1,9]
bomb_last_activity = {}
bomb_access_level = {}
def bomb_idle(jid,nick):
global idle_base
for tmp in idle_base:
if tmp[0] == jid and tmp[1] == nick:
bid = get_config_int(getRoom(jid),'bomb_idle')
if int(time.time())-tmp[3] >= bid: break
else: return False
return True
def boom_bomb(room,type,nick,bc,mode):
global bomb_access_level
b_fault = None
if get_config(getRoom(room),'bomb_fault'):
bfp = get_config_int(getRoom(room),'bomb_fault_persent')
if bfp < 0 or bfp > 100: bfp = int(config_prefs['bomb_fault_persent'][3])
b_fault = random.randint(0,100) < bfp
if b_fault: send_msg(type, room, nick, L('It\'s a lucky day for you! Bomb is fault! Right wide is %s','%s/%s'%(room,nick)) % bc)
else:
if mode: send_msg(type, room, nick, L('You were wrong! Right wire is %s','%s/%s'%(room,nick)) % bc)
try:
if get_config(getRoom(room),'bomb_action') == 'kick' and bomb_access_level.pop(room+nick) >= get_config_int(getRoom(room),'bomb_action_level'): muc_role(type, room, nick, '%s\n%s' % (nick,get_config(getRoom(room),'bomb_reason')), 'none',0)
except: pass
def get_next_random(room):
btm = get_config_int(room,'bomb_random_timer')
if btm < 0: btm = int(config_prefs['bomb_random_timer'][3])
btmp = get_config_int(room,'bomb_random_timer_persent')
if btmp <= 0 or btmp > 99: btmp = int(config_prefs['bomb_random_timer_persent'][3])
btm_pers = int(btm/100*btmp)
bskp = get_config_int(room,'bomb_random_timer_skip_persent')
if bskp <= 0 or bskp > 99: bskp = int(config_prefs['bomb_random_timer_skip_persent'][3])
if random.randint(0,100) > bskp: btm *= 2
return time.time() + btm + random.randint(-btm_pers,btm_pers)
def bomb_joke(type, jid, nick, text):
global bomb_current,bomb_random_list,bomb_access_level
if type == 'chat':
send_msg(type, jid, nick, L('Not allowed in private!','%s/%s'%(jid,nick)))
return
if len(text) == 0 or len(text) == text.count(' ')+text.count('\n'):
rlist,tconf = [],getRoom(jid)
for tm in megabase:
if tm[0] == tconf and not bomb_idle(jid,text) and not (get_level(tconf,tm[1])[0] in bomb_deny_access) and not (getRoom(get_level(tconf,tm[1])[1]) in ['None',getRoom(selfjid)]): rlist.append(tm[1])
if len(rlist): text = rlist[random.randrange(len(rlist))]
else:
if not (nick == text == ''): send_msg(type, jid, nick, L('Here is no candidate to take a bomb!','%s/%s'%(jid,nick)))
return
bmb = False
if not get_config(getRoom(jid),'bomb'): msg = L('In this room not allowed take a bomb!','%s/%s'%(jid,nick))
elif jid in bomb_current.keys(): msg = L('This room alredy boombed!','%s/%s'%(jid,nick))
elif bomb_idle(jid,text) or get_level(jid,text)[0] in bomb_deny_access or getRoom(get_level(jid,text)[1]) in ['None',getRoom(selfjid)]: msg = L('I can\'t take a bomb to %s','%s/%s'%(jid,nick)) % text
else:
bomb_access_level[jid+text] = get_level(jid,nick)[0]
b_timer = get_config_int(getRoom(jid),'bomb_timer')
if b_timer < 0: b_timer = (config_prefs['bomb_timer'][3])
b_wire = get_config_int(getRoom(jid),'bomb_wire')
if b_wire < 3 or b_wire > len(bomb_colors): b_wire = int(config_prefs['bomb_wire'][3])
b_clrs = []
while len(b_clrs) < b_wire:
bc = bomb_colors[random.randrange(len(bomb_colors))]
if bc not in b_clrs: b_clrs.append(bc)
bomb_current[getRoom(jid)] = [text,b_clrs,b_clrs[random.randrange(len(b_clrs))]]
msg,bmb = L('/me take a bomb to %s with wires %s. Time to deactivate is %s sec.','%s/%s'%(jid,nick)) % (text,', '.join(b_clrs),b_timer),True
send_msg(type, jid, '', msg)
if bmb:
while b_timer > 0 and not game_over:
time.sleep(1)
b_timer -= 1
if jid not in bomb_current.keys(): break
if b_timer <= 0 and not game_over:
if bomb_current.has_key(getRoom(jid)): bc = bomb_current.pop(getRoom(jid))
else: bc = L('unknown','%s/%s'%(jid,nick))
b_fault = None
if get_config(getRoom(jid),'bomb_fault'):
bfp = get_config_int(getRoom(jid),'bomb_fault_persent')
if bfp < 0 or bfp > 100: bfp = int(config_prefs['bomb_fault_persent'][3])
b_fault = random.randint(0,100) < bfp
if b_fault: send_msg(type, jid, text, L('It\'s a lucky day for you! Bomb is fault! Right wide is %s','%s/%s'%(jid,nick)) % bc[2])
else:
send_msg(type, jid, '', L('/me explode %s','%s/%s'%(jid,nick)) % text)
if get_config(getRoom(jid),'bomb_action') == 'kick' and bomb_access_level.pop(jid+text) >= get_config_int(getRoom(jid),'bomb_action_level'): muc_role(type, jid, nick, '%s\n%s' % (text,get_config(getRoom(jid),'bomb_reason')), 'none',0)
bomb_random_list[getRoom(jid)] = get_next_random(getRoom(jid))
def bomb_presence(room,jid,nick,type,mass):
global bomb_current
if not get_config(getRoom(room),'bomb'): return
try: bc = bomb_current[getRoom(room)]
except: return
if nick != bc[0]: return
if type == 'unavailable':
if bomb_current.has_key(getRoom(room)): bc = bomb_current.pop(getRoom(room))
else: bc = L('unknown','%s/%s'%(room,nick))
if mass[8]:
time.sleep(1)
boom_bomb(room,'groupchat',mass[8],bc[2],None)
bomb_random_list[getRoom(room)] = get_next_random(getRoom(room))
def bomb_message(room,jid,nick,type,text):
global bomb_current,bomb_random_list
gr = getRoom(room)
if not get_config(gr,'bomb'): return
try: bc = bomb_current[gr]
except: return
if nick != bc[0]: return
if text.lower() not in bc[1]: return
if bomb_current.has_key(gr): bomb_current.pop(gr)
type = 'groupchat'
if text.lower() == bc[2]: send_msg(type, room, nick, L('Bomb is deactivated! Congratulations!','%s/%s'%(room,nick)))
else: boom_bomb(room,type,nick,bc[2],True)
bomb_random_list[gr] = get_next_random(gr)
def bomb_random():
global bomb_current,bomb_random_list
bt = bomb_random_sleep
while not game_over and bt > 0:
time.sleep(1)
bt -= 1
while not game_over:
ntime = time.time()
cb = [t[0] for t in cur_execute_fetchall("select split_part(room,'/',1) from conference;") if t]
for tmp in cb:
try: bla = get_config(tmp,'bomb_random_active') and (ntime - bomb_last_activity[tmp]) < get_config_int(tmp,'bomb_random_active_timer')
except: bla = True
if get_config(tmp,'bomb') and get_config(tmp,'bomb_random') and bla:
try: bsets = bomb_random_list[tmp]
except: bomb_random_list[tmp],bsets = ntime,ntime
if bsets < ntime:
bomb_joke('groupchat', tmp, '', '')
bomb_random_list[tmp] = get_next_random(tmp)
bt = bomb_random_timer_check_period
while not game_over and bt > 0:
time.sleep(1)
bt -= 1
def bomb_message_active(room,jid,nick,type,mass):
global bomb_last_activity
if jid != 'None': bomb_last_activity[getRoom(room)] = int(time.time())
global execute, presence_control, message_control
presence_control = [bomb_presence]
message_act_control = [bomb_message,bomb_message_active]
execute = [(4, 'bomb', bomb_joke, 2, 'Take a bomb joke!')]

99
plugins/bugmenot.py Normal file
View File

@@ -0,0 +1,99 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
bmn_last_res = {}
def dec(data):
b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
enc = ''
for i in range(0, len(data)/4):
h1 = b64.index(data[4*i])
h2 = b64.index(data[4*i+1])
h3 = b64.index(data[4*i+2])
h4 = b64.index(data[4*i+3])
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4
o1 = bits >> 16 & 255
o2 = bits >> 8 & 255
o3 = bits & 255
if h3 == 64: enc += chr(o1)
elif h4 == 64: enc += chr(o1) + chr(o2)
else: enc += chr(o1) + chr(o2) + chr(o3)
return enc
def d(strInput, key):
strInput = dec(strInput)
strOutput = ''
intOffset = (key + 112) / 12
for i in range(4, len(strInput)):
thisCharCode = ord(strInput[i])
newCharCode = thisCharCode - intOffset
strOutput += chr(newCharCode)
return strOutput
def decrypt(i, key):
i = list(i)
return map(lambda x: d(x, key), i[:3]) + i[-2:]
def bugmenot(type, jid, nick,text):
global bmn_last_res
result = ''
text = text.strip()
if text:
connct = httplib.HTTPConnection('www.bugmenot.com')
connct.request('GET', '/view/' + text.encode("utf-8"))
r = connct.getresponse().read()
try: key = int(re.findall('var key = (\d+)',r)[0])
except: key = ''
blocked = '<h2>Site Blocked</h2>' in r
if key and not blocked:
l = re.findall('<tr><th>Username </th><td><script>d\(\'(.+)\'\);</script></td></tr>\s+?<tr><th>Password </th><td><script>d\(\'(.+?)\'\);</script></td></tr>\s+?<tr><th>Other</th><td><script>d\(\'(.+?)\'\);</script></td></tr>\s+?<tr><th>Stats</th><td class="stats"><em class=".+?">(\d+?)% success rate</em> \((\d+?) votes\)</td></tr>', r)
l = [decrypt(i, key) for i in l]
logins = [i[0] for i in l]
passwords = [i[1] for i in l]
other = [i[2] for i in l]
stats = [L('%s%% (%s votes)','%s/%s'%(jid,nick)) % (i[3],i[4]) for i in l]
data = zip(logins, passwords, other, stats)
if data:
first = data[0]
if bmn_last_res.has_key(jid): bmn_last_res[jid].update({nick: data[1:]})
else: bmn_last_res[jid] = {nick: data[1:]}
else: result = L('What?','%s/%s'%(jid,nick))
elif blocked: result = L('Site Blocked','%s/%s'%(jid,nick))
else: result = L('What?','%s/%s'%(jid,nick))
else:
if bmn_last_res.has_key(jid) and bmn_last_res[jid].has_key(nick) and bmn_last_res[jid][nick]:
first = bmn_last_res[jid][nick][0]
bmn_last_res[jid][nick] = bmn_last_res[jid][nick][1:]
else: result = L('No results!','%s/%s'%(jid,nick))
if not result: result = rss_replace(L('Login: %s, Pass: %s - %s %s','%s/%s'%(jid,nick)) % first)
send_msg(type, jid, nick, result)
def bmn_clear(room,jid,nick,type,arr):
if type == 'unavailable' and bmn_last_res.has_key(room) and bmn_last_res[room].has_key(nick): del bmn_last_res[room][nick]
global execute, presence_control
presence_control = [bmn_clear]
execute = [(3, 'bugmenot', bugmenot, 2, 'Search in bugmenot.com')]

41
plugins/calendar.py Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) dr.Schmurge <dr.schmurge@isida-bot.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def month_cal(type, jid, nick, text):
text = text.split()
try: month = int(text[0])
except: month = tuple(time.localtime())[1]
try: year = int(text[1])
except: year = tuple(time.localtime())[0]
try: smbl = text[2]
except: smbl = GT('calendar_default_splitter')
try:
msg = L('\nMon Tue Wed Thu Fri Sat Sun\n','%s/%s'%(jid,nick)) + '\n'.join([' '.join([['%2d' % r,' '][r==0] for r in t]) for t in calendar.monthcalendar(year,month)])
msg = L('Now: %s%s','%s/%s'%(jid,nick)) % (timeadd(tuple(time.localtime())), msg.replace(' ',smbl))
except: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'calendar', month_cal, 2, 'Calendar. Without parameters show calendar for current month.\ncalendar [month][year][symbol_splitter]')]

159
plugins/chat.py Normal file
View File

@@ -0,0 +1,159 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
ANSW_PREV = {}
FLOOD_STATS = {}
LAST_PHRASE = {}
autophrases_time = {}
list_of_answers, list_of_empty, list_of_phrases_with_highlight, list_of_phrases_no_highlight, dict_of_mind = {}, {}, {}, {}, {}
llist = ['en'] + [tmp[:-4] for tmp in os.listdir(loc_folder[:-6]) if tmp[-4:]=='.txt']
for t in llist:
if os.path.isfile(loc_folder % t): cur_lang = t
else: cur_lang = 'en'
chat_folder = data_folder % 'chat/%s/' % cur_lang
MIND_FILE = chat_folder + 'mind.txt'
EMPTY_FILE = chat_folder + 'empty.txt'
ANSWER_FILE = chat_folder + 'answer.txt'
PHRASES_FILE = chat_folder + 'phrases.txt'
list_of_answers[cur_lang] = readfile(ANSWER_FILE).decode('utf-8').split('\n')
list_of_empty[cur_lang] = readfile(EMPTY_FILE).decode('utf-8').split('\n')
list_of_phrases_with_highlight[cur_lang] = []
list_of_phrases_no_highlight[cur_lang] = []
for phrase in readfile(PHRASES_FILE).split('\n'):
if 'NICK' in phrase: list_of_phrases_with_highlight[cur_lang].append(phrase.decode('utf-8'))
else: list_of_phrases_no_highlight[cur_lang].append(phrase.decode('utf-8'))
dict_of_mind[cur_lang] = {}
for p in readfile(MIND_FILE).decode('utf-8').split('\n'):
if '||' in p:
tmp1, tmp2 = p.strip().split('||')
dict_of_mind[cur_lang][tmp1] = tmp2.split('|')
def addAnswerToBase(tx):
if not len(tx) or tx.count(' ') == len(tx): return
lent = len(cur_execute_fetchall('select ind from answer'))+1
cur_execute('insert into answer values (%s,%s)', (lent,tx))
if base_type not in ['sqlite3','mysql']:
conn.commit()
def getRandomAnswer(tx,room):
if not tx.strip(): return None
lent = len(cur_execute_fetchall('select ind from answer'))
mrand = random.randint(1,lent)
answ = to_censore(cur_execute_fetchone('select body from answer where ind=%s', (mrand,))[0],room)
return answ
def getSmartAnswer(type, room, nick, text):
loc = get_L_('%s/%s' % (room,nick))
if '?' in text: answ = random.choice(list_of_answers[loc]).strip()
else: answ = random.choice(list_of_empty[loc]).strip()
score,sc, var = 1.0,0,[answ]
text = ' %s ' % text.upper()
for answer in dict_of_mind[loc]:
sc = rating(answer, text, room)
if sc > score: score,var = sc,dict_of_mind[loc][answer]
elif sc == score: var += dict_of_mind[loc][answer]
return random.choice(var)
def rating(s, text, room):
r,s = 0.0,s.split('|')
for k in s:
if k in text: r += 1
if k in ANSW_PREV.get(room, ''): r += 0.5
return r
def getAnswer(type, room, nick, text):
text = text.strip()
if get_config(getRoom(room),'flood') in ['random',True]: answ = getRandomAnswer(text,room)
else:
answ = getSmartAnswer(type, room, nick, text)
ANSW_PREV[room] = text.upper()
if type == 'groupchat' and text == to_censore(text,room): addAnswerToBase(text)
return answ
def flood_action(room,jid,nick,type,text):
if get_config(room,'autoflood'):
jjid = getRoom(jid)
tm = time.time()
prefix = get_local_prefix(room)
first_word = text.split(' ', 1)[0]
cur_alias = cur_execute_fetchall('select match from alias where room=%s',(room,))
if cur_alias: cur_alias = [t[0] for t in cur_alias]
else: cur_alias = []
if nick in [get_xnick(room), ''] or cur_execute_fetchone('select pattern from bot_ignore where %s ilike pattern',(jjid,)) or ddos_ignore.has_key(jjid): return
if first_word in [prefix + i[1] for i in comms] + cur_alias or first_word[:-1] in [d[1] for d in megabase if d[0]==room]:
if FLOOD_STATS.has_key(room) and FLOOD_STATS[room][0] != jjid: FLOOD_STATS[room] = ['', 0, 0]
return
if not FLOOD_STATS.has_key(room) or FLOOD_STATS[room][0] != jjid: FLOOD_STATS[room] = [jjid, tm, 1]
else: FLOOD_STATS[room][2] += 1
if FLOOD_STATS.has_key(room) and FLOOD_STATS[room][2] >= get_config_int(room,'floodcount') and tm - FLOOD_STATS[room][1] > get_config_int(room,'floodtime'):
pprint('Send msg human: %s/%s [%s] <<< %s' % (room,nick,type,text),'dark_gray')
try:
msg = getAnswer(type, room, nick, text)
if text: send_msg_human(type, room, nick, msg, 'msg_human_auto')
else: return False
except: return False
return True
if get_config(room,'floodrepeat') != 'off' and get_level(room,nick)[0] > 0:
text = text.strip()
if LAST_PHRASE.has_key(room) and LAST_PHRASE[room][0] != jid and LAST_PHRASE[room][2] == text:
if LAST_PHRASE[room][1] >= get_config_int(room,'floodrepeat') - 1:
try: LAST_PHRASE.pop(room)
except: pass
pprint('Send msg human repeat: %s/%s [%s] <<< %s' % (room,nick,type,text),'dark_gray')
try: send_msg_human(type, room, '', text, 'msg_human_repeat')
except: return False
return True
else: LAST_PHRASE[room] = [jid,LAST_PHRASE[room][1] + 1,text]
else: LAST_PHRASE[room] = [jid,1,text]
return False
def phrases_timer():
for room in list(set([i[0] for i in megabase])):
if get_config(room,'autophrases') != 'off':
a_time = int(get_config(room,'autophrasestime'))
if not room in autophrases_time:
autophrases_time[room] = time.time() + random.normalvariate(a_time, a_time/12.0)/2
if time.time() > autophrases_time[room]:
autophrases_time[room] = time.time() + random.normalvariate(a_time, a_time/12.0)
if get_config(room,'autophrases') == 'all':
rand_nicks = [d[1] for d in megabase if d[0]==room if not cur_execute_fetchone('select pattern from bot_ignore where %s ilike pattern',(getRoom(d[4]),)) and d[1] not in [get_xnick(room), '']]
if rand_nicks:
nick = random.choice(rand_nicks)
loc = get_L_('%s/%s' % (room,nick))
msg = random.choice(list_of_phrases_with_highlight[loc] + list_of_phrases_no_highlight[loc])
msg = msg.replace('NICK', nick)
if get_config(room,'autophrases') == 'without highlight' or not rand_nicks: msg = random.choice(list_of_phrases_no_highlight[CURRENT_LOCALE])
pprint('Send autophrase: %s >>> %s' % (room, msg), 'dark_gray')
send_msg('groupchat', room, '', msg)
global execute, message_act_control, timer
message_act_control = [flood_action]
timer = [phrases_timer]
execute = []

44
plugins/clear.py Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def hidden_clear(type, jid, nick, text):
try: cntr = int(text)
except: cntr = GT('clear_default_count')
if cntr > GT('clear_max_count'): cntr = GT('clear_max_count')
elif cntr < 2: cntr = 2
cdel,cmode = GT('clear_delay'),get_config(getRoom(jid),'clear_answer') == 'presence'
clear_msg = L('Clean by %s messages in approximately %s sec.','%s/%s'%(jid,nick)) % (cntr,int(cntr*cdel))
if cmode: caps_and_send(xmpp.Presence(jid,show=Settings['status'], status=clear_msg, priority=Settings['priority']))
else: send_msg(type, jid, nick, clear_msg)
time.sleep(cdel)
for tmp in range(0,cntr):
msg = xmpp.Message(jid, '', "groupchat")
msg.setTag('body')
sender(msg)
time.sleep(cdel)
if cmode: caps_and_send(xmpp.Presence(jid,show=Settings['status'], status=Settings['message'], priority=Settings['priority']))
else: send_msg(type, jid, nick, L('Cleaned!','%s/%s'%(jid,nick)))
global execute
execute = [(7, 'clear', hidden_clear, 2, 'Hidden cleaning of conference history.')]

128
plugins/clients.py Normal file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def clients_stats_old(type, jid, nick, text):
text = reduce_spaces_all(text).lower().split()
if text:
is_short = 'short' in text
is_os = 'os' in text
is_global = 'global' in text or 'total' in text or 'all' in text
if is_short or is_global or is_os:
for t in ['all','total','global','short','os']:
if t in text: text.remove(t)
if text: match = '%%\r%%%s%%' % ' '.join(text)
else: match = '%\r%'
else:
match = '%\r%'
is_short = is_global = is_os = False
if is_global: req,par = 'select message from age where message ilike %s',(match,)
else: req,par = 'select message from age where room=%s and message ilike %s',(jid,match)
st = cur_execute_fetchall(req,par)
if st:
ns = {}
et = L('Error! %s','%s/%s'%(jid,nick))%''
for t in st:
if is_os:
k = t[0].split('\r',1)[1].split(' // ',1)
if len(k) == 2: k = k[1]
else: k = ''
else: k = t[0].split('\r',1)[1].split(' // ',1)[0]
k = k.replace('\r','[LF]').replace('\n','[CR]').replace('\t','[TAB]')
if is_short and k: k = k.split()[0]
if not k or k == 'None': k = 'Unknown'
if not k.startswith(et.strip()):
if ns.has_key(k): ns[k] += 1
else: ns[k] = 1
ns = [(ns[t],t) for t in ns.keys()]
ns.sort(reverse=True)
msg = L('Client statistic:%s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join(['%s. %s\t- %s' % (ns.index(t)+1,t[1],t[0]) for t in ns[:10]])
else: msg = L('Clients statistic not available.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def clients_stats(type, jid, nick, text):
text2 = text.split(' ')
text = text.lower().split(' ')
match = '%'
if text:
is_short = 'short' in text
is_os = 'os' in text
is_user = 'user' in text
is_global = 'global' in text or 'total' in text or 'all' in text
if is_short or is_global or is_os or is_user:
for t in ['all','total','global','short','os','user']:
if t in text: text.remove(t)
for t2 in text2:
if t2.lower() == t.lower():
text2.remove(t2)
break
if is_user:
if text2:
cnick = text = ' '.join(text2)
for t in megabase:
if t[0] == jid and t[1] in text:
match,cnick = '%%%s%%' % reduce_spaces_all(text.replace(t[1],'')),t[1]
break
else: cnick = nick
cjid = getRoom(get_level(jid,cnick)[1])
if cjid == 'None':
send_msg(type, jid, nick, L('I could be wrong, but %s not is here...','%s/%s'%(jid,nick)) % cnick)
return
elif text: match = '%%%s%%' % reduce_spaces_all(' '.join(text))
else: is_short = is_global = is_os = is_user = False
if is_global:
if is_user: req,par = 'select client,version,os from versions where jid=%s and (client ilike %s or version ilike %s or os ilike %s)',(cjid,match,match,match)
else: req,par = 'select client,version,os from versions where client ilike %s or version ilike %s or os ilike %s',(match,match,match)
elif is_user: req,par = 'select client,version,os from versions where room=%s and jid=%s',(jid,cjid)
else: req,par = 'select client,version,os from versions where room=%s and (client ilike %s or version ilike %s or os ilike %s)',(jid,match,match,match)
st = cur_execute_fetchall(req,par)
if st:
ns = {}
for t in st:
if is_os:
k = t[2]
if k and k.strip() and is_short:
if '/' in k: k = k.split('/')[0]
elif k.lower().startswith('microsoft') or k.lower().startswith('(c)') or k.startswith(u'©'): k = k.split()[1]
else: k = k.split()[0]
if '=' in k: k = k.split('=')[1]
else:
if is_short: k = t[0]
else: k = '%s %s' % (t[:2])
if not k or k == 'None': k = 'Unknown'
k = k.replace('\r','[LF]').replace('\n','[CR]').replace('\t','[TAB]')
if ns.has_key(k): ns[k] += 1
else: ns[k] = 1
ns = [(ns[t],t) for t in ns.keys()]
ns.sort(reverse=True)
if is_user:
if is_short: msg = L('Client statistic:%s','%s/%s'%(jid,nick)) % ' %s' % ', '.join(['%s (%s)' % (t[1],t[0]) for t in ns])
else: msg = L('Client statistic:%s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join([t[1] for t in ns])
else: msg = L('Client statistic:%s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join(['%s. %s\t- %s' % (ns.index(t)+1,t[1],t[0]) for t in ns[:10]])
else: msg = L('Clients statistic not available.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(4, 'clients_old', clients_stats_old, 2, 'Show clients statistic when available.\nclients [total|global|all[ short][ os]] [string]'),
(4, 'clients', clients_stats, 2, 'Show clients statistic when available.\nclients [total|global|all[ short][ os]] [string]')]

74
plugins/convert.py Normal file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
currency_conv_list = ['ATS','AUD','BEF','BYR','CAD','CHF','CNY','DEM','DKK','EEK',\
'EGP','ESP','EUR','FIM','FRF','GBP','GRD','IEP','ISK','ITL',\
'JPY','KGS','KWD','KZT','LTL','NLG','NOK','PTE','SDR','SEK',\
'SGD','TRL','TRY','UAH','USD','XDR','YUN','RUB']
def currency_converter(type, jid, nick, text):
msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
text = text.strip().upper()
if text == 'LIST': msg = L('Available values:\n%s','%s/%s'%(jid,nick)) % ', '.join(currency_conv_list).replace('RUB','RUR')
else:
repl_curr = ((u'RUR','RUB'),(u'€','EUR'),('$','USD'),(u'¥','JPY'),(u'£','GBP'),(',','.'))
for tmp in repl_curr: text = text.replace(tmp[0],' %s ' % tmp[1])
c_from,c_to,c_summ = '','',''
val = [t for t in re.findall('[A-Z]{3,4}', text, re.S) if t in currency_conv_list]
if len(val) >= 2: c_from,c_to = val[:2]
val = ''.join(re.findall('[0-9\.]',text))
if val.replace('.','').isdigit() and val.count('.') <= 1:
if val.startswith('.'): c_summ = '0%s' % val
elif val.endswith('.'): c_summ = '%s0' % val
else: c_summ = val
if c_from and c_to and c_summ:
date = tuple(time.localtime())[:3]
mname = ['%D0%AF%D0%BD%D0%B2%D0%B0%D1%80%D1%8C','%D0%A4%D0%B5%D0%B2%D1%80%D0%B0%D0%BB%D1%8C',
'%D0%9C%D0%B0%D1%80%D1%82','%D0%90%D0%BF%D1%80%D0%B5%D0%BB%D1%8C',
'%D0%9C%D0%B0%D0%B9','%D0%98%D1%8E%D0%BD%D1%8C',
'%D0%98%D1%8E%D0%BB%D1%8C','%D0%90%D0%B2%D0%B3%D1%83%D1%81%D1%82',
'%D0%A1%D0%B5%D0%BD%D1%82%D1%8F%D0%B1%D1%80%D1%8C','%D0%9E%D0%BA%D1%82%D1%8F%D0%B1%D1%80%D1%8C',
'%D0%9D%D0%BE%D1%8F%D0%B1%D1%80%D1%8C','%D0%94%D0%B5%D0%BA%D0%B0%D0%B1%D1%80%D1%8C']
url = 'http://quote.rbc.ru/cgi-bin/conv/external/converter.shtml?source=cb.0&tid_from=%s&commission=1.0&tid_to=%s&summa=%s&day=%s&mon=%s&year=%s' % (c_from,c_to,c_summ,date[2],mname[date[1]-1],date[0])
body = html_encode(load_page(url))
try:
curr = body.split('<select name="tid_from" class="n">')[1].split('</select>')[0]
curr_list = dict(re.findall('<option value="(.*?)".*?>(.*?)</option>',curr,re.S|re.I|re.U))
except: curr_list = {}
try: body = body.split('<table id="rTable" class="table">',1)[1]
except: body = ''
regex = '<tbody>.*?<td>(.*?)</td>.*?<td class="b">(.*?)</td>.*?<td class="b">(.*?)</td>.*?<td>(.*?)</td>.*?<td class="b">(.*?)</td>'
mt = re.findall(regex, body, re.S)
if mt != []:
mt = [t.strip() for t in mt[0]]
if curr_list.has_key(mt[0]): frv = curr_list[mt[0]]
else: frv = mt[0]
if curr_list.has_key(mt[3]): tov = curr_list[mt[3]]
else: tov = mt[3]
msg = '%s %s (%s) = %s %s (%s) | 1 %s = %s %s' % (c_summ,c_from,frv,mt[4],c_to,tov,c_from,mt[2],c_to)
msg = msg.replace('RUB','RUR')
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'convert', currency_converter, 2, 'Currency converter\nconvert from to count\nconvert list')]

133
plugins/cron.py Normal file
View File

@@ -0,0 +1,133 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# cron * * * * * \n command
def time_cron(type, jid, nick, text):
ar = text.split(' ',1)[0].lower()
try: par = text.split(' ',1)[1]
except: par = ''
if ar == 'show': msg = time_cron_show(jid,nick,par)
elif ar == 'del': msg = time_cron_del(jid,nick,par)
else: msg = time_cron_add(text,jid,nick)
send_msg(type, jid, nick, msg)
def time_cron_show(jid,nick,ar):
al = get_level(jid,nick)[0]
if ar:
if al == 9 and ar.lower().split()[0] in ['all','global','total']: room = '%'
else: room = jid
else: room = jid
c = cur_execute_fetchall('select * from cron where room ilike %s order by room, time',(room,))
if c:
tmp, idx = [], 1
for t in c:
if t[2] == '\n': mode = '[silent]'
elif not t[2]: mode = '[anonim]'
else: mode = ''
if room=='%': msg = '%s|%s' % (t[0],disp_time(t[3],'%s/%s'%(jid,nick)))
else: msg = '%s. %s' % (idx,disp_time(t[3],'%s/%s'%(jid,nick)))
if mode: msg = '%s %s' % (msg,mode)
if t[4]: msg += ' [%s]' % t[4]
msg += ' -> %s' % t[5]
tmp.append(msg)
idx += 1
return L('Cron rules:\n%s','%s/%s'%(jid,nick)) % '\n'.join(tmp)
else: return L('There is no cron rules.','%s/%s'%(jid,nick))
def time_cron_add(ar,jid,nick):
try: cron_time, cron_cmd = ar.split('\n',1)
except: return L('Not enough parameters!','%s/%s'%(jid,nick))
try:
SM,RM,NM = 'silent','once','anonim'
CMD = [SM,RM,NM]
ct = cron_time.lower().split()
rm,sm,nm = RM in ct,SM in ct,NM in ct
if rm or sm or nm:
for t in CMD:
try: ct.remove(t)
except: pass
ct = ' '.join(ct)
if rm: cron_time,repeat_time = ct,''
else: cron_time,repeat_time = ct,ct
next_time = crontab.CronTab(cron_time).next() + time.time()
except: return L('Error in time format!','%s/%s'%(jid,nick))
lvl,rj = get_level(jid,nick)
amm,tcmd = -1,cron_cmd.split(' ')[0]
for tmp in comms:
if tmp[1] == tcmd:
amm = tmp[0]
break
if amm < 0: return L('Command not found: %s','%s/%s'%(jid,nick)) % tcmd
elif amm > lvl: return L('Not allowed launch: %s','%s/%s'%(jid,nick)) % tcmd
else:
if sm: nick = '\n'
elif nm: nick = ''
cur_execute('insert into cron values (%s,%s,%s,%s,%s,%s,%s)', (jid,getRoom(rj),nick,next_time,repeat_time,cron_cmd,lvl))
return '%s -> %s' % (disp_time(next_time,'%s/%s'%(jid,nick)),cron_cmd)
def time_cron_del(jid,nick,ar):
al = get_level(jid,nick)[0]
if al == 9 and ar.lower() == 'all':
cur_execute('delete from cron where room=%s',(jid,))
return L('All cron rules removed!','%s/%s'%(jid,nick))
elif not ar: return L('Need choise record number.','%s/%s'%(jid,nick))
elif not ar.isdigit(): return L('Record ID is numeric.','%s/%s'%(jid,nick))
else:
c = cur_execute_fetchall('select * from cron where room ilike %s order by room, time',(jid,))
try: rec = c[int(ar)-1]
except: return L('Record #%s not found!','%s/%s'%(jid,nick)) % ar
cur_execute('delete from cron where room=%s and jid=%s and nick=%s and time=%s and repeat=%s and command=%s and level=%s',rec)
msg = disp_time(rec[3],'%s/%s'%(jid,nick))
if rec[2] == '\n': mode = '[silent]'
elif not rec[2]: mode = '[anonim]'
else: mode = ''
if mode: msg = '%s %s' % (msg,mode)
if rec[4]: msg += ' [%s]' % rec[4]
msg += ' -> %s' % rec[5]
return L('Removed: %s','%s/%s'%(jid,nick)) % msg
def cron_action():
itt = int(time.time())
c = cur_execute_fetchall('select distinct * from cron where %s >= time',(itt,))
if c:
cur_execute('delete from cron where %s >= time',(itt,))
for t in c:
if t[4]:
tm = crontab.CronTab(t[4]).next() + time.time()
m = list(t[:3]) + [tm] + list(t[4:7])
cur_execute('insert into cron values (%s,%s,%s,%s,%s,%s,%s)', m)
tmp = cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%t[0],))
if not tmp:
pprint('Can\'t execute by cron: %s in %s' % (t[5].split()[0],t[0]),'red')
return
else: nowname = getResourse(tmp[0])
if t[2] == '\n': tmp_nick,tmp_type = '%s_cron_%d' % (nowname,time.time()),'chat'
else: tmp_nick,tmp_type = t[2],'groupchat'
com_parser(t[6], nowname, tmp_type, t[0], tmp_nick, t[5], Settings['jid'])
global execute, timer
timer = [cron_action]
execute = [(7, 'cron', time_cron, 2, 'Execute command by cron. Used unix-type time format.\ncron [once] [anonim|silent] * * * * *\ncommand')]

994
plugins/disco.py Normal file
View File

@@ -0,0 +1,994 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
whereis_answers = {}
whereis_regx = re.compile('<item .*?name=[\'"](.*?)[\'"]',re.S|re.I|re.U)
whereis_lock = None
disco_excl = []
disco_features_list = {'dnssrv':'Support for DNS SRV lookups of XMPP services., RFC 3920: XMPP Core, RFC 3921: XMPP IM',
'fullunicode':'Support for Unicode characters, including in displayed text, JIDs, and passwords.',
'gc-1.0':'Support for the "groupchat 1.0" protocol. (XEP-0045)',
'http://jabber.org/protocol/activity':'User Activity (XEP-0108)',
'http://jabber.org/protocol/address':'Extended Stanza Addressing (XEP-0033)',
'http://jabber.org/protocol/amp':'Advanced Message Processing (XEP-0079)',
'http://jabber.org/protocol/amp#errors':'Advanced Message Processing (XEP-0079)',
'http://jabber.org/protocol/amp?action=alert':'Support for the "alert" action in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?action=drop':'Support for the "drop" action in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?action=error':'Support for the "error" action in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?action=notify':'Support for the "notify" action in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?condition=deliver':'Support for the "deliver" condition in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?condition=expire-at':'Support for the "expire-at" condition in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/amp?condition=match-resource':'Support for the "match-resource" condition in Advanced Message Processing. (XEP-0079)',
'http://jabber.org/protocol/bytestreams':'SOCKS5 Bytestreams (XEP-0065)',
'http://jabber.org/protocol/bytestreams#udp':'SOCKS5 Bytestreams (XEP-0065)',
'http://jabber.org/protocol/caps':'Entity Capabilities (XEP-0115)',
'http://jabber.org/protocol/chatstates':'Chat State Notifications (XEP-0085)',
'http://jabber.org/protocol/commands':'Ad-Hoc Commands (XEP-0050)',
'http://jabber.org/protocol/compress':'Stream Compression (XEP-0138)',
'http://jabber.org/protocol/disco#info':'Service Discovery Info (XEP-0030)',
'http://jabber.org/protocol/disco#items':'Service Discovery Items (XEP-0030)',
'http://jabber.org/protocol/feature-neg':'Feature Negotiation (XEP-0020)',
'http://jabber.org/protocol/geoloc':'User Geolocation (XEP-0080)',
'http://jabber.org/protocol/http-auth':'Verifying HTTP Requests via XMPP (XEP-0070)',
'http://jabber.org/protocol/httpbind':'Bidirectional-streams Over Synchronous HTTP (XEP-0124)',
'http://jabber.org/protocol/ibb':'In-Band Bytestreams (XEP-0047)',
'http://jabber.org/protocol/mood':'User Mood (XEP-0107)',
'http://jabber.org/protocol/muc':'Multi-User Chat (XEP-0045)',
'http://jabber.org/protocol/muc#admin':'Multi-User Chat Admin (XEP-0045)',
'http://jabber.org/protocol/muc#owner':'Multi-User Chat Owner (XEP-0045)',
'http://jabber.org/protocol/muc#register':'Support for the muc#register FORM_TYPE in Multi-User Chat. (XEP-0045)',
'http://jabber.org/protocol/muc#roomconfig':'Support for the muc#roomconfig FORM_TYPE in Multi-User Chat. (XEP-0045)',
'http://jabber.org/protocol/muc#roominfo':'Support for the muc#roominfo FORM_TYPE in Multi-User Chat. (XEP-0045)',
'http://jabber.org/protocol/muc#user':'Multi-User Chat User (XEP-0045)',
'http://jabber.org/protocol/offline':'Flexible Offline Message Retrieval (XEP-0013)',
'http://jabber.org/protocol/pubsub#access-authorize':'The default node access model is authorize. (XEP-0060)',
'http://jabber.org/protocol/pubsub#access-open':'The default node access model is open. (XEP-0060)',
'http://jabber.org/protocol/pubsub#access-presence':'The default node access model is presence. (XEP-0060)',
'http://jabber.org/protocol/pubsub#access-roster':'The default node access model is roster. (XEP-0060)',
'http://jabber.org/protocol/pubsub#access-whitelist':'The default node access model is whitelist. (XEP-0060)',
'http://jabber.org/protocol/pubsub#auto-create':'The service supports automatic creation of nodes on first publish. (XEP-0060)',
'http://jabber.org/protocol/pubsub#auto-subscribe':'The service supports automatic subscription to a nodes based on presence subscription. (XEP-0060)',
'http://jabber.org/protocol/pubsub#collections':'Collection nodes are supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#config-node':'Configuration of node options is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#create-and-configure':'Simultaneous creation and configuration of nodes is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#create-nodes':'Creation of nodes is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#delete-any':'Any publisher may delete an item (not only the originating publisher). (XEP-0060)',
'http://jabber.org/protocol/pubsub#delete-nodes':'Deletion of nodes is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#filtered-notifications':'The service supports filtering of notifications based on Entity Capabilities. (XEP-0060)',
'http://jabber.org/protocol/pubsub#get-pending':'Retrieval of pending subscription approvals is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#instant-nodes':'Creation of instant nodes is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#item-ids':'Publishers may specify item identifiers. (XEP-0060)',
'http://jabber.org/protocol/pubsub#last-published':'The service supports sending of the last published item to new subscribers and to newly available resources. (XEP-0060)',
'http://jabber.org/protocol/pubsub#leased-subscription':'Time-based subscriptions are supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#manage-subscription':'Node owners may manage subscriptions. (XEP-0060)',
'http://jabber.org/protocol/pubsub#member-affiliation':'The member affiliation is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#meta-data':'Node meta-data is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#modify-affiliations':'Node owners may modify affiliations. (XEP-0060)',
'http://jabber.org/protocol/pubsub#multi-collection':'A single leaf node may be associated with multiple collections. (XEP-0060)',
'http://jabber.org/protocol/pubsub#multi-subscribe':'A single entity may subscribe to a node multiple times. (XEP-0060)',
'http://jabber.org/protocol/pubsub#outcast-affiliation':'The outcast affiliation is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#persistent-items':'Persistent items are supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#presence-notifications':'Presence-based delivery of event notifications is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#presence-subscribe':'Implicit presence-based subscriptions are supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#publish':'Publishing items is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#publish-options':'Publication with publish options is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#publisher-affiliation':'The publisher affiliation is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#purge-nodes':'Purging of nodes is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#retract-items':'Item retraction is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#retrieve-affiliations':'Retrieval of current affiliations is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#retrieve-default':'Retrieval of default node configuration is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#retrieve-items':'Item retrieval is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#retrieve-subscriptions':'Retrieval of current subscriptions is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#subscribe':'Subscribing and unsubscribing are supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#subscription-options':'Configuration of subscription options is supported. (XEP-0060)',
'http://jabber.org/protocol/pubsub#subscription-notifications':'Notification of subscription state changes is supported. (XEP-0060)',
'http://jabber.org/protocol/rosterx':'Roster Item Exchange (XEP-0144)',
'http://jabber.org/protocol/sipub':'Publishing SI Requests (XEP-0137)',
'http://jabber.org/protocol/soap':'SOAP Over XMPP (XEP-0072)',
'http://jabber.org/protocol/soap#fault':'SOAP Over XMPP (XEP-0072)',
'http://jabber.org/protocol/waitinglist':'Waiting Lists (XEP-0130)',
'http://jabber.org/protocol/waitinglist/schemes/mailto':'Waiting list service supports the mailto: URI scheme. (XEP-0130)',
'http://jabber.org/protocol/waitinglist/schemes/tel':'Waiting list service supports the tel: URI scheme. (XEP-0130)',
'http://jabber.org/protocol/xhtml-im':'XHTML-IM (XEP-0071)',
'http://jabber.org/protocol/xdata-layout':'Data Forms Layout (XEP-0141)',
'http://jabber.org/protocol/xdata-validate':'Data Forms Validation (XEP-0122)',
'ipv6':'Application supports IPv6.',
'jabber:client':'Client, XMPP IM (RFC 3921)',
'jabber:component:accept':'Existing Component Protocol Accept(XEP-0114)',
'jabber:component:connect':'Existing Component Protocol Connect (XEP-0114)',
'jabber:iq:auth':'Non-SASL Authentication (XEP-0078)',
'jabber:iq:browse':'Iq browse (XEP-0011, Deprecated)',
'jabber:iq:gateway':'Gateway Interaction (XEP-0100)',
'jabber:iq:last':'Last Activity (XEP-0012)',
'jabber:iq:oob':'Out of Band Data (XEP-0066)',
'jabber:iq:pass':'DEPRECATED (XEP-0003)',
'jabber:iq:privacy':'Privacy Lists (XEP-0016) / XMPP IM (RFC 3921)',
'jabber:iq:private':'Private XML Storage (XEP-0049)',
'jabber:iq:register':'In-Band Registration (XEP-0077)',
'jabber:iq:roster':'Roster, XMPP IM (RFC 3921)',
'jabber:iq:rpc':'Jabber-RPC (XEP-0009)',
'jabber:iq:search':'Jabber Search (XEP-0055)',
'jabber:iq:version':'Software Version (XEP-0092)',
'jabber:server':'Server, XMPP IM (RFC 3921)',
'jabber:x:data':'Data Forms (XEP-0004)',
'jabber:x:delay':'Delayed Delivery (XEP-0091, Deprecated)',
'jabber:x:encrypted':'Current OpenPGP Usage (XEP-0027)',
'jabber:x:event':'X:Event (XEP-0022, Deprecated)',
'jabber:x:expire':'X:Expire (XEP-0023, Deprecated)',
'jabber:x:oob':'Out of Band Data (XEP-0066)',
'jabber:x:roster':'X:Roster (XEP-0093, Deprecated)',
'jabber:x:signed':'Current OpenPGP Usage (XEP-0027)',
'msglog':'Application performs logging or archiving of messages.',
'msgoffline':'Server stores messages offline for later delivery. (XEP-0160)',
'muc_hidden':'Hidden room in Multi-User Chat (MUC) (XEP-0045)',
'muc_membersonly':'Members-only room in Multi-User Chat (MUC) (XEP-0045)',
'muc_moderated':'Moderated room in Multi-User Chat (MUC) (XEP-0045)',
'muc_nonanonymous':'Non-anonymous room in Multi-User Chat (MUC) (XEP-0045)',
'muc_open':'Open room in Multi-User Chat (MUC) (XEP-0045)',
'muc_passwordprotected':'Password-protected room in Multi-User Chat (MUC) (XEP-0045)',
'muc_persistent':'Persistent room in Multi-User Chat (MUC) (XEP-0045)',
'muc_public':'Public room in Multi-User Chat (MUC) (XEP-0045)',
'muc_rooms':'List of MUC rooms (each as a separate item) (XEP-0045)',
'muc_semianonymous':'Semi-anonymous room in Multi-User Chat (MUC) (XEP-0045)',
'muc_temporary':'Temporary room in Multi-User Chat (MUC) (XEP-0045)',
'muc_unmoderated':'Unmoderated room in Multi-User Chat (MUC) (XEP-0045)',
'muc_unsecured':'Unsecured room in Multi-User Chat (MUC) (XEP-0045)',
'roster:delimiter':'Nested Roster Groups (XEP-0083)',
'sslc2s':'Application supports old-style (pre-TLS) SSL connections on a dedicated port.',
'stringprep':'Application supports the nameprep, nodeprep, and resourceprep profiles of stringprep. (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-bind':'XMPP Core Bind (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-e2e':'XMPP E2E (RFC 3921)',
'urn:ietf:params:xml:ns:xmpp-sasl':'XMPP Core Sasl (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-sasl#c2s':'Application supports client-to-server SASL. (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-sasl#s2s':'Application supports server-to-server SASL. (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-session':'XMPP IM (RFC 3921)',
'urn:ietf:params:xml:ns:xmpp-stanzas':'XMPP Core Stanzas (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-streams':'XMPP Core Streams (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-tls':'XMPP Core TLS (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-tls#c2s':'Application supports client-to-server TLS. (RFC 3920)',
'urn:ietf:params:xml:ns:xmpp-tls#s2s':'Application supports server-to-server TLS. (RFC 3920)',
'urn:ietf:rfc:3264':'Jingle ICE-UDP Transport Method (XEP-0176)',
'urn:xmpp:archive:auto':'Server supports automatic message archiving (XEP-0136)',
'urn:xmpp:archive:manage':'Server supports management of archived messages (XEP-0136)',
'urn:xmpp:archive:manual':'Server supports manual message archiving (XEP-0136)',
'urn:xmpp:archive:pref':'Server supports message archiving preferences (XEP-0136)',
'urn:xmpp:avatar:data':'User Avatars (XEP-0084)',
'urn:xmpp:avatar:metadata':'User Avatars (XEP-0084)',
'urn:xmpp:avatar:metadata+notify':'User Avatars and notify (XEP-0084)',
'http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify':'User Avatars and notify (XEP-0084)',
'urn:xmpp:delay':'Delayed Delivery (XEP-0203)',
'urn:xmpp:jingle:apps:rtp:audio':'Jingle RTP Sessions (XEP-0167)',
'urn:xmpp:jingle:apps:rtp:video':'Jingle RTP Sessions (XEP-0167)',
'urn:xmpp:ping':'XMPP Ping (XEP-0199)',
'urn:xmpp:receipts':'Message Receipts (XEP-0184)',
'urn:xmpp:ssn':'Support for Stanza Session Negotiation and its FORM_TYPE (XEP-0155)',
'urn:xmpp:time':'Entity Time (XEP-0202)',
'xmllang':'Application supports the \'xml:lang\' attribute as described in RFC 3920. (RFC 3920)',
'vcard-temp':'vCard-temp (XEP-0054)',
'http://jabber.org/protocol/admin':'Admin (XEP-0133)',
'http://jabber.org/protocol/admin#add-user':'Add-user (XEP-0133)',
'http://jabber.org/protocol/admin#delete-user':'Delete-user (XEP-0133)',
'http://jabber.org/protocol/admin#disable-user':'Disable-user (XEP-0133)',
'http://jabber.org/protocol/admin#reenable-user':'Reenable-user (XEP-0133)',
'http://jabber.org/protocol/admin#end-user-session':'End-user-session (XEP-0133)',
'http://jabber.org/protocol/admin#get-user-password':'Get-user-password (XEP-0133)',
'http://jabber.org/protocol/admin#change-user-password':'Change-user-password (XEP-0133)',
'http://jabber.org/protocol/admin#get-user-roster':'Get-user-roster (XEP-0133)',
'http://jabber.org/protocol/admin#get-user-lastlogin':'Get-user-lastlogin (XEP-0133)',
'http://jabber.org/protocol/admin#user-stats':'User-stats (XEP-0133)',
'http://jabber.org/protocol/admin#edit-blacklist':'Edit-blacklist (XEP-0133)',
'http://jabber.org/protocol/admin#edit-whitelist':'Edit-whitelist (XEP-0133)',
'http://jabber.org/protocol/admin#get-registered-users-num':'Get-registered-users-num (XEP-0133)',
'http://jabber.org/protocol/admin#get-disabled-users-num':'Get-disabled-users-num (XEP-0133)',
'http://jabber.org/protocol/admin#get-online-users-num':'Get-online-users-num (XEP-0133)',
'http://jabber.org/protocol/admin#get-active-users-num':'Get-active-users-num (XEP-0133)',
'http://jabber.org/protocol/admin#get-idle-users-num':'Get-idle-users-num (XEP-0133)',
'http://jabber.org/protocol/admin#get-registered-users-list':'Get-registered-users-list (XEP-0133)',
'http://jabber.org/protocol/admin#get-disabled-users-list':'Get-disabled-users-list (XEP-0133)',
'http://jabber.org/protocol/admin#get-online-users-list':'Get-online-users-list (XEP-0133)',
'http://jabber.org/protocol/admin#get-active-users-list':'Get-active-users-list (XEP-0133)',
'http://jabber.org/protocol/admin#get-idle-users-list':'Get-idle-users-list (XEP-0133)',
'http://jabber.org/protocol/admin#announce':'Announce (XEP-0133)',
'http://jabber.org/protocol/admin#set-motd':'Set-motd (XEP-0133)',
'http://jabber.org/protocol/admin#edit-motd':'Edit-motd (XEP-0133)',
'http://jabber.org/protocol/admin#delete-motd':'Delete-motd (XEP-0133)',
'http://jabber.org/protocol/admin#set-welcome':'Set-welcome (XEP-0133)',
'http://jabber.org/protocol/admin#delete-welcome':'Delete-welcome (XEP-0133)',
'http://jabber.org/protocol/admin#edit-admin':'Edit-admin (XEP-0133)',
'http://jabber.org/protocol/admin#restart':'Restart (XEP-0133)',
'http://jabber.org/protocol/admin#shutdown':'Shutdown (XEP-0133)',
'jabber:iq:agents':'Agents (XEP-0094, Historical)',
'jabber:iq:avatar':'Avatar (XEP-0008, Historical)',
'http://jabberd.jabberstudio.org/ns/component/1.0':'Jabberstudio Component (Jabberd2)',
'jabber:server:dialback':'Dialback (RFC 3921)',
'http://jabber.org/protocol/si/profile/file-transfer':'File Transfer (XEP-0096)',
'presence-invisible':'Presence invisible (Jabberd2)',
'iq':'Iq (Jabberd2)',
'message':'Message (Jabberd2)',
'http://jabber.org/protocol/muc#unique':'Muc Unicue (XEP-0045)',
'http://jabber.org/protocol/muc#request':'Muc Request (XEP-0045)',
'http://jabber.org/protocol/muc#rooms':'Muc Rooms (XEP-0045)',
'http://jabber.org/protocol/muc#traffic':'Muc Traffic (XEP-0045)',
'http://jabber.org/protocol/nick':'User Nickname (XEP-0172)',
'http://jabber.org/protocol/nick+notify':'Nick and notify (XEP-0172)',
'http://jabber.org/protocol/physloc':'Physloc User Geolocation (XEP-0112)',
'presence':'Presence (Jabberd2)',
'http://jabber.org/protocol/pubsub':'PubSub (XEP-0060)',
'http://jabber.org/protocol/rc':'Remote Controllling Clients (XEP-0146)',
'http://jabber.org/protocol/si':'SI File Transfer (XEP-0096)',
'http://etherx.jabber.org/streams':'Etherx streams (RFC 3920)',
'jabber:iq:time':'Iq:time (XEP-0090, Deprecated)',
'http://jabber.org/protocol/vacation':'Vacalation (XEP-0109)',
'vcard-temp:x:update':'vCard-Based Avatars (XEP-0153)',
'http://jabber.org/protocol/stats':'Stats (XEP-0039)',
'http://jabber.ru/muc-filter':'Muc-filter (Experimental!)',
'jabber:x:avatar':'Avatar (XEP-0008)',
'http://jabber.org/protocol/activity+notify':'User activity and notify (XEP-0108)',
'http://jabber.org/protocol/geoloc+notify':'User Geolocation (XEP-0080)',
'http://jabber.org/protocol/iqibb':'IqIBB (Unknown)',
'http://jabber.org/protocol/mood+notify':'User mood and notify (XEP-0107)',
'http://jabber.org/protocol/tune':'User tune (XEP-0118)',
'http://jabber.org/protocol/tune+notify':'User tune (XEP-0118)',
'games:board':'Games board (No XEP)',
'http://jabber.org/protocol/mute#ancestor':'Multi-User Text Editing Ancestor (XEP-0058)',
'http://jabber.org/protocol/mute#editor':'Multi-User Text Editing Editor (XEP-0058)',
'plugins:alarm':'Plugins Alarm (No XEP)',
'http://www.w3.org/2000/svg':'Whiteboard (XEP-XXXX)',
'urn:xmpp:attention:0':'Attention (XEP-0224)',
'urn:xmpp:bob':'Bits of Binary (XEP-0231)',
'urn:xmpp:jingle:1':'Jingle (XEP-0166)',
'urn:xmpp:jingle:error:1':'Jingle Error (XEP-0166)',
'urn:xmpp:jingle:apps:rtp:1':'Jingle RTP Session (XEP-0167)',
'urn:xmpp:jingle:apps:rtp:errors:1':'Jingle RTP Session Errors (XEP-0167)',
'urn:xmpp:jingle:apps:rtp:info:1':'Jingle RTP Session Info (XEP-0167)',
'urn:xmpp:jingle:transports:ice-udp:1':'Jingle ICE-UDP Transport Method (XEP-0176)',
'urn:xmpp:jingle:transports:raw-udp:1':'Jingle RAW-UDP Transport Method (XEP-0176)',
'http://jabber.org/protocol/pubsub#errors':'Publish-Subscribe (XEP-0060)',
'http://jabber.org/protocol/pubsub#event':'Publish-Subscribe (XEP-0060)',
'http://jabber.org/protocol/pubsub#owner':'Publish-Subscribe (XEP-0060)',
'jabber:x:conference':'Direct MUC Invitations (XEP-0249)',
'urn:xmpp:archive':'Message Archiving (XEP-0136)',
'urn:xmpp:captcha':'CAPTCHA Forms (XEP-0158)',
'urn:xmpp:errors':'Application-Specific Error Conditions (XEP-0182)',
'urn:xmpp:langtrans':'Language Translation (XEP-0171)',
'urn:xmpp:langtrans#items':'Language Translation Items (XEP-0171)',
'urn:xmpp:media-element':'Data Forms Media Element (XEP-0221)',
'urn:xmpp:pie':'Portable Import/Export Format for XMPP-IM Servers (XEP-0227)',
'urn:xmpp:sm:2':'Stream Management (XEP-0198)',
'urn:xmpp:xbosh':'XMPP Over BOSH (XEP-0206)',
'http://jabber.org/protocol/sxe':'http://jabber.org/protocol/sxe',
'http://miranda-im.org/caps/secureim':'http://miranda-im.org/caps/secureim',
'bugs':'bugs',
'http://qip.ru/x-status':'http://qip.ru/x-status',
'http://www.xmpp.org/extensions/xep-0116.html#ns':'Encrypted Session Negotiation (XEP-0116)',
'urn:xmpp:sec-label:0':'urn:xmpp:sec-label:0',
'jabber:iq:dtcp':'jabber:iq:dtcp',
'jabber:iq:filexfer':'jabber:iq:filexfer',
'jabber:iq:ibb':'jabber:iq:ibb',
'jabber:iq:inband':'jabber:iq:inband',
'jabber:iq:jidlink':'jabber:iq:jidlink',
'urn:xmpp:message-correct:0':'Last Message Correction (XEP-0308)'}
def disco_features_add(i):
for t in bot_features: i.getTag('query').setTag('feature',attrs={'var':t})
return i
def disco_ext_info_add(i):
i.getTag('query').setTag('identity',attrs={'xml:lang':CURRENT_LOCALE,'category':id_category,'type':id_type,'name':id_name})
i.getTag('query').setTag('x',namespace=xmpp.NS_DATA,attrs={'type':'result'})
i.getTag('query').getTag('x',namespace=xmpp.NS_DATA).setTag('field',attrs={'var':'FORM_TYPE','type':'hidden'})
i.getTag('query').getTag('x',namespace=xmpp.NS_DATA).getTag('field',attrs={'var':'FORM_TYPE','type':'hidden'}).setTagData('value',xmpp.NS_SOFTWAREINFO)
for t in bot_softwareinfo.keys():
i.getTag('query').getTag('x',namespace=xmpp.NS_DATA).setTag('field',attrs={'var':t})
i.getTag('query').getTag('x',namespace=xmpp.NS_DATA).getTag('field',attrs={'var':t}).setTagData('value',bot_softwareinfo[t])
return i
def disco_iq_get(iq,id,room,acclvl,query,towh,al):
if iq.getTag(name='query', namespace=xmpp.NS_DISCO_INFO):
node=get_tag_item(unicode(query),'query','node')
if node.split('#')[0] in ['', disco_config_node, xmpp.NS_COMMANDS] or node in [xmpp.NS_MUC_ROOMS, '%s#%s' % (capsNode,capsHash)]:
pprint('*** iq:disco_info from %s node "%s"' % (unicode(room),node),'magenta')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
if node == '': i.setQueryNS(namespace=xmpp.NS_DISCO_INFO)
else: i.setTag('query',namespace=xmpp.NS_DISCO_INFO,attrs={'node':node})
if node == '' or node == '%s#%s' % (capsNode,capsHash):
i = disco_features_add(i)
sender(disco_ext_info_add(i))
raise xmpp.NodeProcessed
elif node == xmpp.NS_MUC_ROOMS:
#i.getTag('query').setTag('feature',attrs={'var':xmpp.NS_MUC_ROOMS})
return i
elif node.split('#')[0] == disco_config_node or node == xmpp.NS_COMMANDS:
if node != xmpp.NS_COMMANDS:
i.getTag('query').setTag('feature',attrs={'var':xmpp.NS_COMMANDS})
#i.getTag('query').setTag('feature',attrs={'var':disco_config_node})
#i.getTag('query').setTag('feature',attrs={'var':xmpp.NS_DATA})
try: tn = '#' + node.split('#')[1]
except: tn = ''
if tn:
if tn.split('-',1)[0] == '#owner': settz = owner_groups
elif tn.split('-',1)[0] == '#room': settz = config_groups
else: settz = None
if settz:
for tmp in settz:
if tn == tmp[1]:
i.getTag('query').setTag('identity',attrs={'category':'automation','type':'command-node','name':tmp[0]})
break
return i
elif iq.getTag(name='query', namespace=xmpp.NS_DISCO_ITEMS):
node=get_tag_item(unicode(query),'query','node')
pprint('*** iq:disco_items from %s node "%s"' % (unicode(room),node),'magenta')
if node == xmpp.NS_MUC_ROOMS and GT('iq_show_rooms_disco'):
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setTag('query',namespace=xmpp.NS_DISCO_ITEMS,attrs={'node':node})
if al == 9: cnf = cur_execute_fetchall("select room from conference;")
else: cnf = cur_execute_fetchall("select room from conference where split_part(room,'/',1) not in (select room from hiden_rooms as hrr);")
trooms = [t[0] for t in cnf]
trooms.sort()
trooms = [xmpp.Node('item',attrs={'jid':t}) for t in trooms]
i.getTag('query',namespace=xmpp.NS_DISCO_ITEMS).setPayload(trooms)
return i
elif node.split('#')[0] in [disco_config_node, xmpp.NS_COMMANDS] and acclvl:
try: tn = '#' + node.split('#')[1]
except: tn = ''
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
if node == '': i.setQueryNS(namespace=xmpp.NS_DISCO_ITEMS)
else: i.setTag('query',namespace=xmpp.NS_DISCO_ITEMS,attrs={'node':node})
if node == '' or node == xmpp.NS_COMMANDS:
if towh == selfjid: settings_set = owner_groups
else: settings_set = config_groups
for tmp in settings_set: i.getTag('query').setTag('item',attrs={'node':disco_config_node+tmp[1], 'name':L(tmp[0],room),'jid':towh})
return i
elif node == '' and al > 3:
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setQueryNS(namespace=xmpp.NS_DISCO_ITEMS)
if acclvl: i.getTag('query').setTag('item',attrs={'node':xmpp.NS_COMMANDS, 'name':L('AD-Hoc commands'),'jid':towh})
i.getTag('query').setTag('item',attrs={'node':xmpp.NS_MUC_ROOMS, 'name':L('Current bot rooms'),'jid':towh})
return i
return None
def disco_iq_set(iq,id,room,acclvl,query,towh,al):
if iq.getTag(name='command', namespace=xmpp.NS_COMMANDS) and acclvl:
node=get_tag_item(unicode(iq),'command','node')
if get_tag_item(unicode(iq),'command','action') == 'execute' and (node.split('#')[0] in ['', disco_config_node, xmpp.NS_COMMANDS] or node == xmpp.NS_MUC_ROOMS):
pprint('*** iq:ad-hoc commands from %s node "%s"' % (unicode(room),node),'magenta')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
if node == '': i.setQueryNS(namespace=xmpp.NS_DISCO_INFO)
else: i.setTag('query',namespace=xmpp.NS_DISCO_ITEMS,attrs={'node':node})
if node == '':
i = disco_features_add(i)
sender(disco_ext_info_add(i))
raise xmpp.NodeProcessed
elif node == xmpp.NS_MUC_ROOMS and GT('iq_show_rooms_disco'):
if al == 9: cnf = cur_execute_fetchall("select room from conference;")
else: cnf = cur_execute_fetchall("select room from conference where split_part(room,'/',1) not in (select room from hiden_rooms as hrr);")
trooms = [t[0] for t in cnf]
trooms.sort()
trooms = [xmpp.Node('item',attrs={'jid':t}) for t in trooms]
i.getTag('query',namespace=xmpp.NS_DISCO_ITEMS).setPayload(trooms)
return i
elif node.split('#')[0] == disco_config_node or node == xmpp.NS_COMMANDS:
if node != xmpp.NS_COMMANDS:
i.getTag('query').setTag('feature',attrs={'var':xmpp.NS_COMMANDS})
#i.getTag('query').setTag('feature',attrs={'var':xmpp.NS_DATA})
#i.getTag('query').setTag('feature',attrs={'var':disco_config_node})
try: tn = '#' + node.split('#')[1]
except: tn = ''
try: tmpn = tn.split('-',1)[1]
except: tmpn = ''
if tmpn:
action=get_tag_item(unicode(iq),'command','action')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
if action == 'cancel': i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'canceled', 'node':disco_config_node+tn,'sessionid':id})
elif towh == selfjid:
if get_tag_item(unicode(iq),'x','type') == 'submit':
varz = iq.getTag('command').getTag('x')
sucess_label,unsucess = True,[]
for t in owner_prefs.keys():
try:
tp = owner_prefs[t][1]
tm = varz.getTag('field',attrs={'var':t}).getTags('value')
tm = '\n'.join([tm2.getData() for tm2 in tm])
old_tm = GT(t)
try:
if tp[0] == 'b': tm = [False,True][int(tm)]
elif tp[0] == 'f': tm = float(tm)
elif tp[0] == 'i': tm = int(tm)
elif tp[0] == 't': tm = tm[:int(tp.replace('e','')[1:])]
elif tp[0] == 'm': tm = tm[:int(tp.replace('e','')[1:])]
elif tp[0] == 'l' and len(json.loads(tm)) == int(tp.replace('e','')[1:]): tm = json.loads(tm)
elif tp[0] == 'd' and tm not in owner_prefs[t][3]: tm = owner_prefs[t][2]
except:
tm,sucess_label = GT(t),False
unsucess.append(L(owner_prefs[t][0],room))
PT(t,tm)
if tp[-1] == 'e' and old_tm != tm: eval(owner_prefs[t][-1])
except: pass
sucess_answer = [L('Settings unsuccesfully accepted:\n%s',room) % '\n'.join(unsucess),L('Settings succesfully accepted',room)][sucess_label]
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'completed', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('note',attrs={'type':'info'})
i.getTag('command').setTagData('note',sucess_answer)
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA)
i.getTag('command').getTag('x').setTagData('title',L('Settings',room))
i.getTag('command').getTag('x').setTagData('instrustion',sucess_answer)
pprint('*** bot reconfigure by %s' % unicode(room),'purple')
else:
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'executing', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA,attrs={'type':'form'})
#i.getTag('command').getTag('x').setTag('item',attrs={'node':disco_config_node+tn, 'name':'Configuration','jid':selfjid})
#i.getTag('command').getTag('x').setTagData('instructions',L('For configure required x:data-compatible client',room))
tkeys = []
for tmp in owner_groups: tkeys.append(tmp[1])
if tn in tkeys:
for tmp in owner_groups:
if tn == tmp[1]:
c_prefs,c_name = tmp[2],tmp[0]
break
i.getTag('command').getTag('x').setTagData('title',L(c_name,room))
cnf_prefs = {}
for tmp in c_prefs: cnf_prefs[tmp] = owner_prefs[tmp]
tmp = cnf_prefs.keys()
tt = []
for t in tmp: tt.append((L(owner_prefs[t][0],room),t))
tt.sort()
tmp = []
for t in tt: tmp.append(t[1])
for t in tmp:
itm = owner_prefs[t]
itm_label = L(itm[0],room).replace('%s','').replace(':','').strip()
if itm[1][0] == 'b':
dc = GT(t) in [True,1,'1','on']
i.getTag('command').getTag('x').setTag('field',attrs={'type':'boolean','label':itm_label,'var':t})\
.setTagData('value',[0,1][dc])
elif itm[1][0] in ['t','i','f','l']:
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-single','label':itm_label,'var':t})\
.setTagData('value',unicode(GT(t)))
elif itm[1][0] == 'm':
tprm = [xmpp.Node('value',payload=prm) for prm in unicode(GT(t)).split('\n')]
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-multi','label':itm_label,'var':t})\
.setPayload(tprm)
else:
i.getTag('command').getTag('x').setTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTagData('value',GT(t))
for t2 in itm[3]:
i.getTag('command').getTag('x').getTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTag('option',attrs={'label':L(t2,room)})\
.setTagData('value',t2)
else:
if get_tag_item(unicode(iq),'x','type') == 'submit':
varz = iq.getTag('command').getTag('x')
for t in config_prefs.keys():
try:
tmtype = varz.getTagAttr('field','type')
tm = varz.getTag('field',attrs={'var':t}).getTags('value')
tm = '\n'.join([tm2.getData() for tm2 in tm])
if tmtype == 'boolean' and tm in ['0','1']: tm = [False,True][int(tm)]
elif config_prefs[t][2] != None:
if config_prefs[t][2] == [True,False] and tm in ['0','1']: tm = [False,True][int(tm)]
elif tm in config_prefs[t][2]: pass
else: tm = config_prefs[t][3]
put_config(getRoom(room),t,tm)
except: pass
sucess_answer = L('Settings succesfully accepted',room)
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'completed', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('note',attrs={'type':'info'})
i.getTag('command').setTagData('note',sucess_answer)
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA)
i.getTag('command').getTag('x').setTagData('title',L('Settings',room))
i.getTag('command').getTag('x').setTagData('instrustion',sucess_answer)
pprint('*** reconfigure by %s' % unicode(room),'purple')
else:
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'executing', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA,attrs={'type':'form'})
#i.getTag('command').getTag('x').setTag('item',attrs={'node':disco_config_node+tn, 'name':'Configuration','jid':selfjid})
#i.getTag('command').getTag('x').setTagData('instructions',L('For configure required x:data-compatible client',room))
tkeys = []
for tmp in config_groups: tkeys.append(tmp[1])
if tn in tkeys:
for tmp in config_groups:
if tn == tmp[1]:
c_prefs,c_name = tmp[2],tmp[0]
break
i.getTag('command').getTag('x').setTagData('title',L(c_name,room))
cnf_prefs = {}
for tmp in c_prefs: cnf_prefs[tmp] = config_prefs[tmp]
tmp = cnf_prefs.keys()
tmp.sort()
for t in tmp:
itm = config_prefs[t]
itm_label = L(itm[0],room).replace('%s','').replace(':','').strip()
itm_desc = L(itm[1],room).strip()
if itm[2] == [True,False]:
dc = get_config(getRoom(room),t) in [True,1,'1','on']
i.getTag('command').getTag('x').setTag('field',attrs={'type':'boolean','label':itm_label,'var':t})\
.setTagData('value',[0,1][dc])
elif itm[2] == None:
if '\n' in itm[3]:
tprm = [xmpp.Node('value',payload=prm) for prm in get_config(getRoom(room),t).split('\n')]
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-multi','label':itm_label,'var':t})\
.setPayload(tprm)
else:
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-single','label':itm_label,'var':t})\
.setTagData('value',get_config(getRoom(room),t))
else:
i.getTag('command').getTag('x').setTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTagData('value',get_config(getRoom(room),t))
for t2 in itm[2]:
i.getTag('command').getTag('x').getTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTag('option',attrs={'label':onoff(t2,room)})\
.setTagData('value',t2)
i.getTag('command').getTag('x').getTag('field',attrs={'label':itm_label,'var':t})\
.setTagData('desc',itm_desc)
else: i.getTag('command').getTag('x').setTagData('title',L('Unknown configuration request!',room))
return i
else:
if tn:
if tn.split('-',1)[0] == '#owner': settz = owner_groups
elif tn.split('-',1)[0] == '#room': settz = config_groups
else: settz = None
if settz:
for tmp in settz:
if tn == tmp[1]:
i.getTag('query').setTag('identity',attrs={'category':'automation','type':'command-node','name':tmp[0]})
break
return i
else:
pprint('*** iq:disco_set from %s node "%s"' % (unicode(room),node),'magenta')
try: tn = '#' + node.split('#')[1]
except: tn = ''
if node.split('#')[0] == disco_config_node or node == xmpp.NS_COMMANDS:
action=get_tag_item(unicode(iq),'command','action')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
if action == 'cancel': i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'canceled', 'node':disco_config_node+tn,'sessionid':id})
elif towh == selfjid:
if get_tag_item(unicode(iq),'x','type') == 'submit':
varz = iq.getTag('command').getTag('x')
sucess_label,unsucess = True,[]
for t in owner_prefs.keys():
try:
tp = owner_prefs[t][1]
tm = varz.getTag('field',attrs={'var':t}).getTags('value')
tm = '\n'.join([tm2.getData() for tm2 in tm])
old_tm = GT(t)
try:
if tp[0] == 'b': tm = [False,True][int(tm)]
elif tp[0] == 'f': tm = float(tm)
elif tp[0] == 'i': tm = int(tm)
elif tp[0] == 't': tm = tm[:int(tp.replace('e','')[1:])]
elif tp[0] == 'm': tm = tm[:int(tp.replace('e','')[1:])]
elif tp[0] == 'l' and len(json.loads(tm)) == int(tp.replace('e','')[1:]): tm = json.loads(tm)
elif tp[0] == 'd' and tm not in owner_prefs[t][3]: tm = owner_prefs[t][2]
except:
tm,sucess_label = GT(t),False
unsucess.append(L(owner_prefs[t][0],room))
PT(t,tm)
if tp[-1] == 'e' and old_tm != tm: eval(owner_prefs[t][-1])
except: pass
sucess_answer = [L('Settings unsuccesfully accepted:\n%s',room) % '\n'.join(unsucess),L('Settings succesfully accepted',room)][sucess_label]
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'completed', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('note',attrs={'type':'info'})
i.getTag('command').setTagData('note',sucess_answer)
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA)
i.getTag('command').getTag('x').setTagData('title',L('Settings',room))
i.getTag('command').getTag('x').setTagData('instrustion',sucess_answer)
pprint('*** bot reconfigure by %s' % unicode(room),'purple')
else:
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'executing', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA,attrs={'type':'form'})
#i.getTag('command').getTag('x').setTag('item',attrs={'node':disco_config_node+tn, 'name':'Configuration','jid':selfjid})
#i.getTag('command').getTag('x').setTagData('instructions',L('For configure required x:data-compatible client',room))
tkeys = []
for tmp in owner_groups: tkeys.append(tmp[1])
if tn in tkeys:
for tmp in owner_groups:
if tn == tmp[1]:
c_prefs,c_name = tmp[2],tmp[0]
break
i.getTag('command').getTag('x').setTagData('title',L(c_name,room))
cnf_prefs = {}
for tmp in c_prefs: cnf_prefs[tmp] = owner_prefs[tmp]
tmp = cnf_prefs.keys()
tt = []
for t in tmp: tt.append((L(owner_prefs[t][0],room),t))
tt.sort()
tmp = []
for t in tt: tmp.append(t[1])
for t in tmp:
itm = owner_prefs[t]
itm_label = L(itm[0],room).replace('%s','').replace(':','').strip()
if itm[1] == 'b':
dc = GT(t) in [True,1,'1','on']
i.getTag('command').getTag('x').setTag('field',attrs={'type':'boolean','label':itm_label,'var':t})\
.setTagData('value',[0,1][dc])
elif itm[1][0] in ['t','i','f','l']:
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-single','label':itm_label,'var':t})\
.setTagData('value',unicode(GT(t)))
elif itm[1][0] == 'm':
tprm = [xmpp.Node('value',payload=prm) for prm in unicode(GT(t)).split('\n')]
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-multi','label':itm_label,'var':t})\
.setPayload(tprm)
else:
i.getTag('command').getTag('x').setTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTagData('value',GT(t))
for t2 in itm[3]:
i.getTag('command').getTag('x').getTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTag('option',attrs={'label':L(t2,room)})\
.setTagData('value',t2)
else:
if get_tag_item(unicode(iq),'x','type') == 'submit':
varz = iq.getTag('command').getTag('x')
for t in config_prefs.keys():
try:
tmtype = varz.getTagAttr('field','type')
tm = varz.getTag('field',attrs={'var':t}).getTags('value')
tm = '\n'.join([tm2.getData() for tm2 in tm])
if tmtype == 'boolean' and tm in ['0','1']: tm = [False,True][int(tm)]
elif config_prefs[t][2] != None:
if config_prefs[t][2] == [True,False] and tm in ['0','1']: tm = [False,True][int(tm)]
elif tm in config_prefs[t][2]: pass
else: tm = config_prefs[t][3]
put_config(getRoom(room),t,tm)
except: pass
sucess_answer = L('Settings succesfully accepted',room)
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'completed', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('note',attrs={'type':'info'})
i.getTag('command').setTagData('note',sucess_answer)
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA)
i.getTag('command').getTag('x').setTagData('title',L('Settings',room))
i.getTag('command').getTag('x').setTagData('instrustion',sucess_answer)
pprint('*** reconfigure by %s' % unicode(room),'purple')
else:
i.setTag('command',namespace=xmpp.NS_COMMANDS,attrs={'status':'executing', 'node':disco_config_node+tn,'sessionid':id})
i.getTag('command').setTag('x',namespace=xmpp.NS_DATA,attrs={'type':'form'})
#i.getTag('command').getTag('x').setTag('item',attrs={'node':disco_config_node+tn, 'name':'Configuration','jid':selfjid})
#i.getTag('command').getTag('x').setTagData('instructions',L('For configure required x:data-compatible client',room))
tkeys = []
for tmp in config_groups: tkeys.append(tmp[1])
if tn in tkeys:
for tmp in config_groups:
if tn == tmp[1]:
c_prefs,c_name = tmp[2],tmp[0]
break
i.getTag('command').getTag('x').setTagData('title',L(c_name,room))
cnf_prefs = {}
for tmp in c_prefs: cnf_prefs[tmp] = config_prefs[tmp]
tmp = cnf_prefs.keys()
tmp.sort()
for t in tmp:
itm = config_prefs[t]
itm_label = L(itm[0],room).replace('%s','').replace(':','').strip()
itm_desc = L(itm[1],room).strip()
if itm[2] == [True,False]:
dc = get_config(getRoom(room),t) in [True,1,'1','on']
i.getTag('command').getTag('x').setTag('field',attrs={'type':'boolean','label':itm_label,'var':t})\
.setTagData('value',[0,1][dc])
elif itm[2] == None:
if '\n' in itm[3]:
tprm = [xmpp.Node('value',payload=prm) for prm in get_config(getRoom(room),t).split('\n')]
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-multi','label':itm_label,'var':t})\
.setPayload(tprm)
else:
i.getTag('command').getTag('x').setTag('field',attrs={'type':'text-single','label':itm_label,'var':t})\
.setTagData('value',get_config(getRoom(room),t))
else:
i.getTag('command').getTag('x').setTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTagData('value',get_config(getRoom(room),t))
for t2 in itm[2]:
i.getTag('command').getTag('x').getTag('field',\
attrs={'type':'list-single','label':itm_label,'var':t})\
.setTag('option',attrs={'label':onoff(t2,room)})\
.setTagData('value',t2)
i.getTag('command').getTag('x').getTag('field',attrs={'label':itm_label,'var':t})\
.setTagData('desc',itm_desc)
else: i.getTag('command').getTag('x').setTagData('title',L('Unknown configuration request!',room))
return i
return None
def disco_exclude_update():
global disco_excl
excl = GT('disco_exclude').replace('\r','').replace('\t','').split('\n')
disco_excl = []
for c in excl:
if '#' not in c and len(c): disco_excl.append(c)
def disco_validate(item):
for c in disco_excl:
if re.findall(c,' %s ' % item,re.S|re.I|re.U): return None
return item
def smart_sort(item):
itm1,itm2,cnt = [],[],0
for t in item:
itm1.append([t.lower(),cnt])
cnt += 1
itm1.sort()
for t in itm1: itm2.append(item[t[1]])
return itm2
def features(type, jid, nick, text):
global iq_answer,iq_request
text = text.strip()
if text == '': where,what = '%s/%s' % (getRoom(jid),nick),''
else:
text = text.split('\n')
where = text[0]
try: what = text[1]
except: what = ''
for mega1 in megabase:
if mega1[0] == jid and mega1[1] == text[0]:
where = '%s/%s' % (getRoom(jid),text[0])
break
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':where}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_DISCO_INFO},[])])
iq_request[iqid]=(time.time(),features_async,[type, jid, nick, what, where],xmpp.NS_DISCO_INFO)
sender(i)
def features_async(type, jid, nick, what, where, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
isa, ftr, client_features = isa[1], [], []
for f in [t.getAttr('var') for t in isa.getTag('query',namespace=xmpp.NS_DISCO_INFO).getTags('feature')]:
client_features.append(f)
if disco_features_list.has_key(f): ft = '- %s' % disco_features_list[f]
else: ft = L('- Unknown feature: %s','%s/%s'%(jid,nick)) % f
if (what and (what.lower() in ft.lower() or what.lower() in f.lower())) or not what: ftr.append(ft)
ftrs,erc,q_features = {},0,['os_version','os','software_version','software']
client_softwareinfo = {}
for t in q_features:
try:
res = isa.getTag('query').getTag('x',namespace=xmpp.NS_DATA).getTag('field',attrs={'var':t}).getTagData('value')
client_softwareinfo[t] = res
except:
res = 'N/A'
erc += 1
ftrs[t] = res
if erc != len(q_features):
f = L('Software: %s | Version: %s\nOS: %s | Version: %s','%s/%s'%(jid,nick)) % (ftrs['software'],ftrs['software_version'],ftrs['os'],ftrs['os_version'])
if (what and what.lower() in f.lower()) or not what: ftr.append(f)
id_category,id_type,id_name,id_lang = '','','',''
try:
ids_t = isa.getTag('query').getTags('identity')
idk = {'type':L('Type: %s','%s/%s'%(jid,nick)), 'name':L('Name: %s','%s/%s'%(jid,nick)), 'category':L('Category: %s','%s/%s'%(jid,nick)), 'xml:lang':L('Language: %s','%s/%s'%(jid,nick))}
for tg in ids_t:
ids = tg.getAttrs()
idf = []
for t in idk.keys():
if ids.has_key(t):
idf.append(idk[t] % ids[t])
if t == 'type': id_type = ids[t]
elif t == 'name': id_name = ids[t]
elif t == 'category': id_category = ids[t]
elif t == 'xml:lang': id_lang = ids[t]
if idf:
f = ' | '.join(idf)
if (what and what.lower() in f.lower()) or not what: ftr.append(f)
except: pass
if ftr:
f = []
for tmp in ftr:
if tmp not in f: f.append(tmp)
f.sort()
msg = L('Features list:\n%s','%s/%s'%(jid,nick)) % '\n'.join(f)
_hash = '%s<' % '/'.join([t.replace('/','//') for t in [id_category,id_type,id_lang,id_name]])
client_features.sort()
_hash += ''.join(['%s<' % t for t in client_features])
if client_softwareinfo:
_hash += '%s<' % xmpp.NS_SOFTWAREINFO
tmp = ['%s<%s' % (t,client_softwareinfo[t]) for t in client_softwareinfo.keys()]
tmp.sort()
_hash += ''.join(['%s<' % t for t in tmp])
_hash = _hash.encode('utf-8')
_hash_sha1 = 'SHA1: %s' % hashlib.sha1(_hash).digest().encode('base64').replace('\n','')
_hash_md5 = 'MD5: %s' % hashlib.md5(_hash).digest().encode('base64').replace('\n','')
_hashes = '%s | %s' % (_hash_sha1,_hash_md5)
if (what and what.lower() in _hashes.lower()) or not what: msg = '%s\n%s' % (msg, _hashes)
else: msg = L('Unable to get features list','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def disco(type, jid, nick, text): disco_r(type, jid, nick, text, True)
def disco_raw(type, jid, nick, text): disco_r(type, jid, nick, text, False)
def disco_r(type, jid, nick, text, raw_type):
global iq_answer,iq_request
text = text.strip()
if text == '':
send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
return
where = text.lower().split('\n',1)[0].split(' ',1)[0]
try: what = text.lower().split('\n',1)[0].split(' ',1)[1]
except: what = ''
try: hm = int(text.lower().split('\n',1)[1])
except: hm = GT('disco_max_limit')
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':where}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_DISCO_INFO},[])])
iq_request[iqid]=(time.time(),disco_features_async,[type, jid, nick, what, where, hm, raw_type],xmpp.NS_DISCO_INFO)
sender(i)
def disco_features_async(type, jid, nick, what, where, hm, raw_type, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error':
msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
return
else:
disco_type = xmpp.NS_MUC in [t.getAttr('var') for t in isa[1].getTag('query',namespace=xmpp.NS_DISCO_INFO).getTags('feature')]
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':where}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_DISCO_ITEMS},[])])
iq_request[iqid]=(time.time(),disco_async,[type, jid, nick, what, where, hm, disco_type, raw_type, isa[1]],xmpp.NS_DISCO_ITEMS)
sender(i)
def disco_async(type, jid, nick, what, where, hm, disco_type, raw_type, isa_prev, is_answ):
if len(is_answ[1]) >= 2 and is_answ[1][1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(is_answ[1][0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
if disco_type and '@' not in where:
cm = []
for ii in [[t.getAttr('name'),t.getAttr('jid')] for t in is_answ[1][1].getTag('query',namespace=xmpp.NS_DISCO_ITEMS).getTags('item')]:
dname,djid = ii
if not dname: dname = ''
elif '(' in dname and ')' in dname:
try: dsize = int(dname.split('(')[-1].split(')')[0])
except: dsize = -1
dname = '('.join(dname.split('(')[:-1])
else: dsize = -1
if dname == djid: djid = ''
if not what or what in dname.lower() or what in djid.lower():
if raw_type and disco_validate(dname) and disco_validate(djid): cm.append(('%04d' % dsize, dname, djid))
elif not raw_type: cm.append(('%04d' % dsize, dname, djid))
if len(cm):
cm.sort(reverse=True)
msg,cnt = L('Total: %s','%s/%s'%(jid,nick)) % len(cm),1
for i in cm[:hm]:
vl = [int(i[0]),'n/a'][int(i[0]) == -1]
if len(i[2]): msg += '\n%s. %s [%s] . %s' % (cnt,i[1],i[2],vl)
else: msg += '\n%s. %s . %s' % (cnt,i[1],vl)
cnt += 1
while ' ' in msg: msg = msg.replace(' ',' ')
elif len(what): msg = L('\"%s\" not found','%s/%s'%(jid,nick)) % what
else: msg = L('Not found.','%s/%s'%(jid,nick))
elif disco_type and '@' in where:
cm = []
for ii in [t.getAttr('name') for t in is_answ[1][1].getTag('query',namespace=xmpp.NS_DISCO_ITEMS).getTags('item')]:
if ii and (not what or what in ii.lower()): cm.append(ii)
cm = smart_sort(cm)
if len(cm):
d_name = reduce_spaces_all(isa_prev.getTag('query',namespace=xmpp.NS_DISCO_INFO).getTagAttr('identity','name'))
d_deskr = reduce_spaces_all(isa_prev.getTag('query',namespace=xmpp.NS_DISCO_INFO).getTag('x',namespace=xmpp.NS_DATA).getTag('field',attrs={'var':'muc#roominfo_description'}).getTagData('value'))
d_occup = isa_prev.getTag('query',namespace=xmpp.NS_DISCO_INFO).getTag('x',namespace=xmpp.NS_DATA).getTag('field',attrs={'var':'muc#roominfo_occupants'}).getTagData('value')
if d_name == d_deskr or not d_deskr: msg = '%s\n%s' % (d_name,L('Total: %s%s','%s/%s'%(jid,nick)) % (d_occup,' - %s' % ', '.join(cm)))
else: msg = '%s [%s]\n%s' % (d_name,d_deskr,L('Total: %s%s','%s/%s'%(jid,nick)) % (d_occup,' - %s' % ', '.join(cm)))
elif len(what): msg = L('\"%s\" not found','%s/%s'%(jid,nick)) % what
else: msg = L('Not found.','%s/%s'%(jid,nick))
else:
cm = [t.getAttrs() for t in is_answ[1][1].getTag('query',namespace=xmpp.NS_DISCO_ITEMS).getTags('item')]
if len(cm):
cm.sort()
cnt = 1
msg = L('Total: %s','%s/%s'%(jid,nick)) % len(cm)
for i in cm[:hm]:
msg += '\n%s. ' % cnt
if i.has_key('name'):
msg += '%s ' % i['name']
if i.has_key('node'): msg += '[%s] ' % i['node']
msg += '%s' % i['jid']
cnt += 1
else: msg = L('Not found.','%s/%s'%(jid,nick))
msg = rss_replace(msg)
send_msg(type, jid, nick, msg)
def whereis(type, jid, nick, text):
global iq_request,whereis_lock
if whereis_lock: send_msg(type, jid, nick, L('This command in use somewhere else. Please try later.','%s/%s'%(jid,nick)))
else:
if len(text):
text = text.split('\n')
who = text[0]
else: who = nick
if len(text)<2: where = getServer(jid)
else:
if 'conference' in text[1]: where = text[1]
else: where = 'conference.'+text[1]
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':where}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_DISCO_ITEMS},[])])
iq_request[iqid]=(time.time(),whereis_async,[type, jid, nick, who, where],xmpp.NS_DISCO_ITEMS)
sender(i)
def whereis_async(type, jid, nick, who, where, is_answ):
global iq_request, whereis_answers, whereis_lock
isan = unicode(is_answ[1][0])
isa = isan.split('<item ')
djids = []
for ii in isa[1:]:
dname = get_subtag(ii,'name').split('(')[-1][:-1]
if dname.isdigit() and dname != '0': djids.append(get_subtag(ii,'jid'))
send_msg(type, jid, nick, L('Please wait. Result you will be receive in private message approximately %s %s','%s/%s'%(jid,nick)) % (int(len(djids)*(time_nolimit+0.05)), L('sec.','%s/%s'%(jid,nick))))
curr_id = 'whereis_%s' % get_id()
whereis_lock = True
wtd = GT('whereis_time_dec')
whereis_id = get_id()
whereis_answers[whereis_id] = []
for ii in djids:
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':ii}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_DISCO_ITEMS},[])])
iq_request[iqid]=(time.time(),whereis_collect_async,[whereis_id,who],xmpp.NS_DISCO_ITEMS)
sender(i)
if game_over: return
while len(whereis_answers[whereis_id]) != len(djids) and not game_over: time.sleep(wtd)
if game_over: return
result = []
for t in whereis_answers[whereis_id]:
if t: result += t
whereis_answers.pop(whereis_id)
result.sort()
if result:
msgg = L('matches with nick \"%s\": %s','%s/%s'%(jid,nick)) % (who, len(result))
for i in result: msgg += '\n%s\t%s' % (esc_min(i[0]),esc_min(i[1]))
else: msgg = L('nick \"%s\" not found.','%s/%s'%(jid,nick)) % who
msg = L('Total conferences: %s, available: %s','%s/%s'%(jid,nick)) % (len(isa)-1, '%s, %s' % (len(djids),msgg))
send_msg('chat', jid, nick, msg)
whereis_lock = None
def whereis_collect_async(whereis_id,who,is_answ):
global whereis_answers
try:
result = []
if is_answ[1][0]:
names = re.findall(whereis_regx,is_answ[1][0])
if names:
conf = get_tag_item(is_answ[1][0],'iq','from')
for tmp in names:
if who.lower() in tmp.lower(): result.append([tmp,conf])
whereis_answers[whereis_id].append(result)
except: whereis_answers[whereis_id].append([])
global execute, iq_hook
iq_hook = [[100,'get',disco_iq_get],[100,'set',disco_iq_set]]
disco_exclude_update()
execute = [(3, 'disco', disco, 2, 'Service discovery.\ndisco server.tld - request information about server\ndisco conference.server.tld [body [size]] - find body string in conference list and show size results\ndisco room@conference.server.tld [body [size]] - find body string in disco room conference and show size results.'),
(3, 'disco_raw', disco_raw, 2, 'Service discovery.\ndisco_raw server.tld - request information about server\ndisco_raw conference.server.tld [body [size]] - find body string in conference list and show size results\ndisco_raw room@conference.server.tld [body [size]] - find body string in disco room conference and show size results.'),
(4, 'features', features, 2, 'Show features of object'),
(7, 'whereis', whereis, 2, 'Find nick on conference server\nwhereis - find your nick on current conference server\nwhereis nick - find nick on current conference server\nwhereis nick\n[conference.]server.tld - find nick on server server.tld')]

158
plugins/dist.py Normal file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
dist_max_search_limit = 100
dist_default_search_count = 10
def points2distance(start, end):
"""
Calculate distance (in kilometers) between two points given as (latt, long) pairs
based on Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula).
"""
start_latt = math.radians(start[0])
start_long = math.radians(start[1])
end_latt = math.radians(end[0])
end_long = math.radians(end[1])
d_long = end_long - start_long
a = (math.cos(end_latt) * math.sin(d_long))**2 + (math.cos(start_latt)*math.sin(end_latt)-math.sin(start_latt)*math.cos(end_latt)*math.cos(d_long))**2
b = math.sin(start_latt)*math.sin(end_latt) + math.cos(start_latt)*math.cos(end_latt)*math.cos(d_long)
dist = math.atan2(math.sqrt(a), b) * 6372.795
dist = int(dist + 0.5)
return dist
def city_capitalize(s):
s = s.capitalize()
for k in re.findall('[ -].', s): s = s.replace(k,k.upper())
for tmp in [u'-На-', u' На ', u'-Де-', u' Де ']: s = s.replace(tmp, tmp.lower())
return s
def city(type, jid, nick, text):
parameters = text.strip().split(' ', 1)
if parameters[0] == 'add' and get_level(jid,nick)[0] == 9:
try:
tmp = parameters[1].split('\n', 1)
place = tmp[0].strip().lower().replace(' - ', '-')
if len(tmp) == 2:
coords = re.sub('[^-\.\d]+', ' ', tmp[1]).strip().split()
if abs(float(coords[0])) < 90 and abs(float(coords[1])) < 180:
if not cur_execute_fetchone('select * from dist_user where point ilike %s',(place,)):
cur_execute('insert into dist_user values (%s,%s,%s)',(place,coords[1],coords[0]))
if base_type not in ['sqlite3','mysql']:
conn.commit()
msg = L('Added!','%s/%s'%(jid,nick))
else: msg = L('This point is in database!','%s/%s'%(jid,nick))
elif len(GT('yandex_api_key')) > 60:
text = place.encode('utf-8')
url = 'http://geocode-maps.yandex.ru/1.x/?geocode=%s&key=%s&format=json&results=1' % (urllib.quote_plus(text), GT('yandex_api_key'))
j = json.loads(load_page(url))
place_ext = j['response']['GeoObjectCollection']['featureMember'][0]['GeoObject']['metaDataProperty']['GeocoderMetaData']['text']
coords = j['response']['GeoObjectCollection']['featureMember'][0]['GeoObject']['Point']['pos'].split()
if not cur_execute_fetchone('select * from dist_user where point ilike %s',(place,)):
cur_execute('insert into dist_user values (%s,%s,%s)',(place,coords[1],coords[0]))
if base_type not in ['sqlite3','mysql']:
conn.commit()
msg = L('Added: ','%s/%s'%(jid,nick)) + place_ext + L(' as ','%s/%s'%(jid,nick)) + '"%s"' % place
else: msg = L('This point is in database!','%s/%s'%(jid,nick))
else: msg = L('Not found Yandex.Map API. Get API-key on http://api.yandex.ru/maps/form.xml','%s/%s'%(jid,nick))
except: msg = L('What?','%s/%s'%(jid,nick))
elif parameters[0] == 'del' and get_level(jid,nick)[0] == 9:
if cur_execute_fetchone('select * from dist_user where point ilike %s',(parameters[1].lower(),)):
cur_execute('delete from dist_user where point=%s',(parameters[1].lower(),))
if base_type not in ['sqlite3','mysql']:
conn.commit()
msg = L('Deleted!','%s/%s'%(jid,nick))
else: msg = L('This point isn\'t in database!','%s/%s'%(jid,nick))
elif parameters[0] == 'map':
t = cur_execute_fetchone('select * from dist_user where point ilike %s',(parameters[1].lower(),))
if not t: t = cur_execute_fetchone('select * from dist where point ilike %s',(parameters[1].lower(),))
if t:
tmp = 'http://maps.google.com/maps?ll=%s,%s&spn=0.01,0.01&t=h&q=%s,%s' % (t[1], t[2], t[1], t[2])
try: msg = city_capitalize(parameters[1]) + L(' on the map: ','%s/%s'%(jid,nick)) + load_page(SHORT_TINYURL % enidna(tmp).decode('utf-8'))
except: msg = city_capitalize(parameters[1]) + L(' on the map: ','%s/%s'%(jid,nick)) + tmp
else: msg = L('What?','%s/%s'%(jid,nick))
elif parameters[0] == 'search':
if len(GT('yandex_api_key')) > 60:
text = parameters[1].encode('utf-8')
text_tmp = text.split(' ', 1)
if re.match('\d+$', text_tmp[0]):
results = text_tmp[0]
text = text_tmp[1]
skip = '0'
elif re.match('\d+[-: |]\d+$', text_tmp[0]):
tmp = re.sub('[-: |]', ' ', text_tmp[0]).split()
results = int(tmp[1]) - int(tmp[0]) + 1
skip = int(tmp[0]) - 1
text = text_tmp[1]
else: results, skip = '5', '0'
url = 'http://geocode-maps.yandex.ru/1.x/?geocode=%s&key=%s&format=json&results=%s&skip=%s' % (urllib.quote_plus(text), GT('yandex_api_key'), results, skip)
j = json.loads(load_page(url))
msg = ''
for object in j['response']['GeoObjectCollection']['featureMember']:
msg += object['GeoObject']['metaDataProperty']['GeocoderMetaData']['text']
msg += ' - (%s)\n' % ', '.join(object['GeoObject']['Point']['pos'].split()[::-1])
if msg: msg = '\n' + msg
else: msg = L('Not found!','%s/%s'%(jid,nick))
else: msg = L('Not found Yandex.Map API. Get API-key on http://api.yandex.ru/maps/form.xml','%s/%s'%(jid,nick))
else:
t = cur_execute_fetchone('select * from dist_user where point ilike %s',(text.strip().lower(),))
if not t:
t = cur_execute_fetchone('select * from dist where point ilike %s',(text.strip().lower(),))
if t: msg = L(u'%s - latitude: %s, longtitude: %s') % (city_capitalize(t[0]), t[1], t[2])
else: msg = L('Not found!','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
def dist(type, jid, nick, text):
text,splitter,splitted,points = text.strip(),[' - ','|','\n',' '],False,''
if ' ' in text and text.split(' ',1)[0].lower() == 'search':
try:
dist_count = int(text.split(' ',2)[2])
dist_count = 1 if dist_count < 1 else dist_max_search_limit if dist_count > dist_max_search_limit else dist_count
except: dist_count = dist_default_search_count
tmp = cur_execute_fetchall('select point from dist_user where point ilike %s order by point limit %s',('%%%s%%' % text.split(' ',2)[1].lower(),dist_count))
if not tmp: tmp = cur_execute_fetchall('select point from dist where point ilike %s order by point limit %s',('%%%s%%' % text.split(' ',2)[1].lower(),dist_count))
if tmp: msg = L('Found: %s','%s/%s'%(jid,nick)) % ', '.join(map(city_capitalize, [t[0] for t in tmp]))
else: msg = L('City %s not found','%s/%s'%(jid,nick)) % city_capitalize(text.split(' ',2)[1])
else:
for tmp in splitter:
if tmp in text:
points,splitted = text.split(tmp),True
break
if splitted and len(points)==2:
t1 = cur_execute_fetchone('select * from dist_user where point ilike %s',(points[0].lower(),))
t2 = cur_execute_fetchone('select * from dist_user where point ilike %s',(points[1].lower(),))
if not t1 or not t2:
if not t1: t1 = cur_execute_fetchone('select * from dist where point ilike %s',(points[0].lower(),))
if not t2: t2 = cur_execute_fetchone('select * from dist where point ilike %s',(points[1].lower(),))
if t1 and t2: msg = L('%s km','%s/%s'%(jid,nick)) % points2distance((float(t1[1]), float(t1[2])), (float(t2[1]), float(t2[2])))
elif t1: msg = L('City %s not found','%s/%s'%(jid,nick)) % city_capitalize(points[1])
elif t2: msg = L('City %s not found','%s/%s'%(jid,nick)) % city_capitalize(points[0])
else: msg = L('Cities not found','%s/%s'%(jid,nick))
else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(3, 'dist', dist, 2, 'Distance between cities.\ndist search city [count of cities]\ndist city1 - city2'),
(3, 'city', city, 2, 'Cities and other place-name of the world. Examples:\ncity add place-name\n[latitude, longtitude] - add city to database\ncity del place-name - delete city from database\ncity search [count of results|range of results] place-name - search city\ncity map place-name - city on the map\ncity place-name - coordinates of city')]

72
plugins/domain.py Normal file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def domaininfo_raw(type, jid, nick, text):
text = text.strip().lower()
while ' \n' in text: text = text.replace(' \n','\n')
if ''.join(re.findall(u'[-0-9a-zа-я. ]+',text,re.U+re.I)) == text and text.count('.') >= 1 and len(text) > 4:
if text.startswith('sites '): t, text, regex = 2, text.split(' ')[1], '<h3>(.*?)<br></font><br><br>'
else: t, regex = 1, '</a><br /><h3>(.*?)<br /></font></blockquote>'
url = 'http://1whois.ru/index.php?url=%s&t=%s' % (text.encode('idna'),t)
body = deidna(html_encode(load_page(url).replace('&nbsp;', ' ')))
try:
body = re.findall(regex, body, re.S)
if body: msg = unhtml_hard(''.join(body[0]))
else: msg = L('No data!','%s/%s'%(jid,nick))
except: msg = L('Unexpected error','%s/%s'%(jid,nick))
else: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def domaininfo(type, jid, nick, text):
text = text.strip().lower()
while ' \n' in text: text = text.replace(' \n','\n')
if ''.join(re.findall(u'[-0-9a-zа-я. ]+',text,re.U+re.I)) == text and text.count('.') >= 1 and len(text) > 4:
if 'sites' in text: t, text, regex, msg = 2, text.split(' ')[1], '<font color="black" size="2">(.*?)</font>', L('Sites at Domain/IP address: %s','%s/%s'%(jid,nick)) % text.split(' ')[1]
else: t, regex, msg = 1, '<blockquote><font.*?>(.*?)</font></blockquote>', L('Domain/IP address info:','%s/%s'%(jid,nick))
url = 'http://1whois.ru/index.php?url=%s&t=%s' % (text.encode('idna'),t)
body = deidna(html_encode(load_page(url).replace('&nbsp;', ' ')))
try:
body = re.findall(regex, body, re.S)[0]
if u'Нет данных!' in body: msg += ' '+ L('No data!','%s/%s'%(jid,nick))
else:
tmp_body = {}
body = replacer(body).split('\n')
newbody = []
for tmp in body:
if ':' in tmp:
if len(tmp.split(':')[0].split()) <= 2 and len(tmp.split(':')[1]) >= 2:
if not tmp_body.has_key(tmp.split(':')[1]):
tmp_body[tmp.split(':')[1]]=tmp.split(':')[0]
newbody.append(tmp)
elif tmp.count(' ') <= 4 and not tmp_body.has_key(tmp):
tmp_body[tmp] = tmp
newbody.append(tmp)
msg += '\n'+'\n'.join(newbody)
except: msg = L('Unexpected error','%s/%s'%(jid,nick))
else: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'domain_info_raw', domaininfo_raw, 2, 'Domain/IP address whois info.'),
(3, 'domain_info', domaininfo, 2, 'Domain/IP address whois info.')]

110
plugins/drink.py Normal file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def to_drink(type, jid, nick, text):
dmas = [L('first','%s/%s'%(jid,nick)),L('second','%s/%s'%(jid,nick)),L('third','%s/%s'%(jid,nick)),L('fourth','%s/%s'%(jid,nick)),
L('fifth','%s/%s'%(jid,nick)),L('sixth','%s/%s'%(jid,nick)),L('seventh','%s/%s'%(jid,nick)),L('eighth','%s/%s'%(jid,nick)),
L('nineth','%s/%s'%(jid,nick)),L('tenth','%s/%s'%(jid,nick)),L('eleventh','%s/%s'%(jid,nick)),L('twelveth','%s/%s'%(jid,nick)),
L('thirteenth','%s/%s'%(jid,nick)),L('fourteenth','%s/%s'%(jid,nick)),L('fivteenth','%s/%s'%(jid,nick)),L('sixteenth','%s/%s'%(jid,nick)),
L('seventeenth','%s/%s'%(jid,nick)),L('eighteenth','%s/%s'%(jid,nick)),L('nineteenth','%s/%s'%(jid,nick)),('twentieth'),
L('twenty-first','%s/%s'%(jid,nick)),L('twenty-second','%s/%s'%(jid,nick)),L('twenty-third','%s/%s'%(jid,nick)),
L('twenty-fourth','%s/%s'%(jid,nick)),L('twenty-fifth','%s/%s'%(jid,nick)),L('twenty-sixth','%s/%s'%(jid,nick)),L('twenty-seventh','%s/%s'%(jid,nick)),
L('twenty-eighth','%s/%s'%(jid,nick)),L('twenty-nineth','%s/%s'%(jid,nick)),L('thirtieth','%s/%s'%(jid,nick)),L('thirty-first','%s/%s'%(jid,nick))]
mmas1 = [L('january','%s/%s'%(jid,nick)),L('february','%s/%s'%(jid,nick)),L('march','%s/%s'%(jid,nick)),L('april','%s/%s'%(jid,nick)),
L('may','%s/%s'%(jid,nick)),L('june','%s/%s'%(jid,nick)),L('july','%s/%s'%(jid,nick)),L('august','%s/%s'%(jid,nick)),
L('september','%s/%s'%(jid,nick)),L('october','%s/%s'%(jid,nick)),L('november','%s/%s'%(jid,nick)),L('december','%s/%s'%(jid,nick))]
mmas2 = [L('January','%s/%s'%(jid,nick)),L('February','%s/%s'%(jid,nick)),L('March','%s/%s'%(jid,nick)),L('April','%s/%s'%(jid,nick)),
L('May','%s/%s'%(jid,nick)),L('June','%s/%s'%(jid,nick)),L('July','%s/%s'%(jid,nick)),L('August','%s/%s'%(jid,nick)),
L('September','%s/%s'%(jid,nick)),L('October','%s/%s'%(jid,nick)),L('November','%s/%s'%(jid,nick)),L('December','%s/%s'%(jid,nick))]
wday = [L('monday','%s/%s'%(jid,nick)),L('tuesday','%s/%s'%(jid,nick)),L('wendesday','%s/%s'%(jid,nick)),L('thirsday','%s/%s'%(jid,nick)),
L('friday','%s/%s'%(jid,nick)),L('saturday','%s/%s'%(jid,nick)),L('sunday','%s/%s'%(jid,nick))]
lday = [L('last','%s/%s'%(jid,nick)),L('last','%s/%s'%(jid,nick)),L('Last','%s/%s'%(jid,nick)),L('last','%s/%s'%(jid,nick)),
L('Last','%s/%s'%(jid,nick)),L('Last','%s/%s'%(jid,nick)),L('lAst','%s/%s'%(jid,nick))]
if os.path.isfile(date_file):
ddate = readfile(date_file).decode('UTF')
week1 = ''
week2 = ''
if not ddate: msg = L('Read file error.','%s/%s'%(jid,nick))
else:
if len(text) <= 2:
ltim = tuple(time.localtime())
text = '%s %s' % (ltim[2], mmas2[ltim[1]-1])
week1 = '%s %s %s' % (ltim[2]/7+(ltim[2]%7 > 0), wday[ltim[6]], mmas2[ltim[1]-1])
if ltim[2]+7 > calendar.monthrange(ltim[0], ltim[1])[1]: week2 = '%s %s %s' % (lday[ltim[6]].lower(), wday[ltim[6]], mmas2[ltim[1]-1])
or_text = text
if text.count('.')==1: text = text.split('.')
elif text.count(' ')==1: text = text.split(' ')
else: text = [text]
msg = ''
ddate = ddate.split('\n')
ltxt = len(text)
for tmp in ddate:
if or_text.lower() in tmp.lower(): msg += '\n'+tmp
elif week1.lower() in tmp.lower() and week1 != '': msg += '\n'+tmp
elif week2.lower() in tmp.lower() and week2 != '': msg += '\n'+tmp
else:
try:
ttmp = tmp.split(' ')[0].split('.')
tday = [ttmp[0]]
tday.append(dmas[int(ttmp[0])-1])
tmonth = [ttmp[1]]
tmonth.append(mmas1[int(ttmp[1])-1])
tmonth.append(mmas2[int(ttmp[1])-1])
tmonth.append(str(int(ttmp[1])))
t = tday.index(text[0])
t = tmonth.index(text[1])
msg += '\n'+tmp
except: pass
if msg == '': msg = L('Holiday: %s not found.','%s/%s'%(jid,nick)) % or_text
else: msg = L('I know holidays: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('Database doesn\'t exist.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def calend(type, jid, nick, text):
msg, url, text = '', '', text.strip()
if not text: url = 'http://www.calend.ru/day/%s-%s/' % tuple(time.localtime())[1:3]
elif re.match('\d+\.\d+$', text): url = 'http://www.calend.ru/day/%s-%s/' % tuple(text.split('.')[::-1])
elif len(text) > 1: url = 'http://www.calend.ru/search/?search_str=' + urllib.quote(text.encode('cp1251'))
if url:
data = html_encode(load_page(url))
t = get_tag(data,'title')
if t == u'Поиск':
hl = re.findall('<a href="(/holidays(?:/\d*?)+?)" title=".+?">(.+?)</a>(?:.|\s)+?/>\s+?(\d+ .+?)\s', data)
if len(hl) == 1:
d = re.search('class="img_small" /></a></td>\s+?<td>\s+?(.+?\.)\s+?</td>', data, re.S).group(1)
d = unescape(re.sub('\s+', ' ', d.strip()))
msg += '%s (%s) - %s\nhttp://www.calend.ru%s' % (hl[0][1], hl[0][2], d, hl[0][0])
elif hl:
for a in hl: msg += '\n%s (%s)' % (a[1], a[2])
else:
d = get_tag(data,'h1')
hl = re.findall('<a href="/holidays(?:/\d*?)+?" title=".+?">(.+?)</a>', data)
if hl: msg = '%s:\n%s' % (d, '\n'.join(hl))
else: msg = L('What?','%s/%s'%(jid,nick))
if not msg: msg = L('Holiday: %s not found.','%s/%s'%(jid,nick)) % text
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'drink', to_drink, 2, 'Find holiday\ndrink [name_holiday/date]'),
(3, 'calend', calend, 2, 'Find holiday\ncalend [name_holiday/date]')]

48
plugins/dumpz.py Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
dumpz_var = {'sh':'bash', 'bash':'bash', 'c':'c', 'h':'c', 'html':'html', 'htm':'html', 'python':'python', 'py':'python', 'php':'php', 'css':'css', 'sql':'sql', 'cpp':'cpp', 'hpp':'cpp'}
def dumpz(type, jid, nick, text):
try:
p = text.split(' ',1)
if p[0].lower() in dumpz_var.keys():
highlighting = dumpz_var[p[0].lower()]
code = p[1]
else:
highlighting = 'text'
code = text
values = {'lexer': highlighting, 'code': code.encode('utf-8'),}
data = urllib.urlencode(values)
req = urllib2.Request('http://dumpz.org/' ,data,{'Content-type':'application/x-www-form-urlencoded'})
res = urllib2.urlopen(req)
link = res.url
msg = L('Posting by URL: %s','%s/%s'%(jid,nick)) % link
except:
msg = L('Unexpected error','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'dumpz', dumpz, 2, 'Posting text&code on dedicated server for easy sharing.\ndumpz text - posting plain text,\ndumpz [sh|c|html|py|php|css|sql|cpp] - posting text with highlighting')]

92
plugins/execute.py Normal file
View File

@@ -0,0 +1,92 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
calc_last_res = {}
def exec_ute(type, jid, nick, text):
try: text = remove_sub_space(unicode(eval(text)))
except Exception, SM:
try: SM = str(SM)
except: SM = unicode(SM)
text = L('I can\'t execute it! Error: %s','%s/%s'%(jid,nick)) % SM[:int(msg_limit/2)]
send_msg(type, jid, nick, text)
def calc(type, jid, nick, text):
global calc_last_res
if 'Ans' in text and calc_last_res.has_key(jid) and calc_last_res[jid].has_key(nick) and calc_last_res[jid][nick]:
text = text.replace('Ans', calc_last_res[jid][nick])
legal = string.digits + string.letters + '*/+-()=^!<>. '
ppc = 1
if '**' in text or 'pow' in text or 'factorial' in text: ppc = 0
else:
for tt in text:
if tt not in legal:
ppc = 0
break
if ppc:
text = re.sub('([^.0-9]\d+)(?=([^.0-9]|$))', r'\1.0', text)
try:
text = remove_sub_space(str(eval(re.sub('([^a-zA-Z]|\A)([a-zA-Z])', r'\1math.\2', text))))
if text[-2:] == '.0': text = text[:-2]
if calc_last_res.has_key(jid): calc_last_res[jid][nick] = text
else: calc_last_res[jid] = {nick: text}
except:
text = L('I can\'t calculate it','%s/%s'%(jid,nick))
if calc_last_res.has_key(jid): calc_last_res[jid][nick] = None
else: calc_last_res[jid] = {nick: None}
else:
text = L('Expression unacceptable!','%s/%s'%(jid,nick))
if calc_last_res.has_key(jid): calc_last_res[jid][nick] = None
else: calc_last_res[jid] = {nick: None}
send_msg(type, jid, nick, text)
def dpi_calc(type, jid, nick, text):
text = text.strip().replace(',','.')
if text:
tupl = re.findall('([0-9.]+)',text)[:3]
if len(tupl) == 3:
if '.' in tupl[0] or '.' in tupl[1]: msg = L('Width and height must be integer!','%s/%s'%(jid,nick))
elif not float(tupl[2]): msg = L('Incorrect diagonal value!','%s/%s'%(jid,nick))
else:
dpi_type = [0,'L'],[160,'M'],[240,'H'],[320,'XH']
dpi = int((math.sqrt(int(tupl[0])**2+int(tupl[1])**2))/float(tupl[2]))
dpi_name = 'unknown'
for t in dpi_type:
if dpi > t[0]: dpi_name = '%sDPI' % t[1]
msg = u'%s %s×%s×%s\" - %sdpi [%s]' % (L('Screen','%s/%s'%(jid,nick)),tupl[0],tupl[1],tupl[2],dpi,dpi_name)
else: msg = L('Not enough parameters!','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def calc_clear(room,jid,nick,type,arr):
if type == 'unavailable' and calc_last_res.has_key(room) and calc_last_res[room].has_key(nick): del calc_last_res[room][nick]
global execute, presence_control
presence_control = [calc_clear]
if not GT('paranoia_mode'): execute = [(3, 'calc', calc, 2, 'Calculator.'),
(9, 'exec', exec_ute, 2, 'Execution of external code.')]
else: execute = []
execute.append((3, 'dpi', dpi_calc, 2, 'DPI calculator.\ndpi <width height size>'))

97
plugins/flibusta.py Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
from xml.dom.minidom import parseString
def flibusta(type, jid, nick, text):
text = re.sub(' +', ' ', text).strip()
msg = ''
if text == 'new':
c=urllib.urlopen('http://xpresslib.mobile-master.org/new').read()
xml=parseString(c)
nodes=xml.getElementsByTagName('book')
for el in nodes:
f=el.getAttribute('file')
size=el.getAttribute('size')
author=unicode(el.getAttribute('author'))
title=unicode(el.firstChild.data)
msg += u'\n%s - %s, %s кБ, http://flibusta.net/b/%s' % (author,title,round(float(size)/1024,1),f.split('.')[0]+'/fb2')
if not msg: msg = L('No news','%s/%s'%(jid,nick))
else:
opt = [i for i in (' ' + text).split(' -') if len(i)>2 and i[1]==' ']
opt = dict([i.split(' ', 1) for i in opt])
if opt.has_key('n'):
if re.match('\d+$', opt['n']): a = b = int(opt['n'])
elif re.match('\d+-\d+$', opt['n']): a, b = map(int,opt['n'].split('-'))
else: a, b = 1, 5
else: a, b = 1, 5
if opt.has_key('t'):
i={}
i['search']=opt['t'].encode('utf-8')
d=urllib.urlencode(i)
s=urllib.urlopen('http://xpresslib.mobile-master.org/search',d).read()
xml=parseString(s)
nodes=xml.getElementsByTagName('book')
t_book=[]
for el in nodes:
f0=el.getAttribute('file')
size=el.getAttribute('size')
author=unicode(el.getAttribute('author'))
title=unicode(el.firstChild.data)
t_book.append([author,title,size,f0])
if opt.has_key('a'): t_book = filter(lambda x: opt['a'].lower() in x[0].lower(), t_book)
if t_book:
c = len(t_book)
if b > c:
if b != a: b = c
else: a = b = c
msg += L('Total found %s matches. Result(s) %s:\n','%s/%s'%(jid,nick)) % (c, a if a == b else '%s-%s' % (a,b))
for i in t_book[a-1:b]:
msg += u'%s- %s, %s кБ, http://flibusta.net/b/%s\n' % (i[0],i[1],round(float(i[2])/1024,1),i[3].split('.')[0]+'/fb2')
elif opt.has_key('a'):
i={}
i['search']=opt['a'].encode('utf-8')
d=urllib.urlencode(i)
s=urllib.urlopen('http://xpresslib.mobile-master.org/authors',d).read()
xml=parseString(s)
nodes=xml.getElementsByTagName('author')
a_book=[]
for el in nodes:
id=el.getAttribute('id')
title=unicode(el.firstChild.data)
a_book.append([id,title])
if a_book:
c = len(a_book)
if b > c:
if b != a: b = c
else: a = b = c
msg += L('Total found %s matches. Result(s) %s:\n','%s/%s'%(jid,nick)) % (c, a if a == b else '%s-%s' % (a,b))
for i in a_book[a-1:b]:
msg += '%s- http://flibusta.net/a/%s\n' % (i[1], i[0])
if not msg: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'flibusta', flibusta, 2, 'Search books and authors on flibusta.net.\nflibusta [-a author] [-t title] [-n number of result]')]

252
plugins/fun.py Normal file
View File

@@ -0,0 +1,252 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
LAST_RANDOM_POKE = {}
LAST_POKE_PHRASE = {}
def poem(type, jid, nick):
dict = [[u'я помню',u'не помню',u'забыть бы',u'купите',u'очкуешь',u'какое',u'угробил',u'открою',u'ты чуешь?'],
[u'чудное',u'странное',u'некое',u'вкусное',u'пьяное',u'свинское',u'чоткое',u'сраное',u'нужное',u'конское'],
[u'мгновенье,',u'затменье,',u'хотенье,',u'варенье,',u'творенье,',u'везенье,',u'рожденье,',u'смущенье,',u'печенье,',u'ученье,'],
[u'\n'],
[u'передомной',u'под косячком',u'на кладбище',u'в моих мечтах',u'под скальпилем',u'в моих штанах',u'из-за угла',u'в моих ушах',u'в ночном горшке',u'из головы',],
[u'явилась ты,',u'добилась ты,',u'торчат кресты,',u'стихов листы,',u'забилась ты,',u'мои трусы,',u'поют дрозды,',u'из темноты,',u'помылась ты,',u'дают пизды,'],
[u'\n'],
[u'как'],
[u'мимолётное',u'детородное',u'психотропное',u'кайфоломное',u'очевидное',u'у воробушков',u'эдакое вот',u'нам не чуждое',u'благородное',u'ябывдульское'],
[u'виденье,',u'сиденье,',u'паренье,',u'сужденье,',u'вращенье,',u'сношенье,',u'смятенье,',u'теченье,',u'паденье,',u'сплетенье,'],
[u'\n'],
[u'как'],
[u'гений',u'сторож',u'символ',u'спарта',u'правда',u'ангел',u'водка',u'пиво',u'ахтунг',u'жопа'],
[u'чистой',u'вечной',u'тухлой',u'просит',u'грязной',u'липкой',u'на хрен',u'в пене',u'женской',u'жаждет'],
[u'красоты',u'мерзлоты',u'суеты',u'наркоты',u'срамоты',u'школоты',u'типа ты',u'простоты',u'хуеты',u'наготы']]
send_msg(type, jid, nick, '\n %s' % ' '.join([random.choice(t) for t in dict]))
def oracle(type, jid, nick, text):
if not text.strip() or text.strip()[-1] != '?': msg = L('What?','%s/%s'%(jid,nick))
else: msg = random.choice([L('Yes','%s/%s'%(jid,nick)),
L('Yes - definitely','%s/%s'%(jid,nick)),
L('You may rely on it','%s/%s'%(jid,nick)),
L('Without a doubt','%s/%s'%(jid,nick)),
L('Signs point to yes','%s/%s'%(jid,nick)),
L('Outlook good','%s/%s'%(jid,nick)),
L('Most likely','%s/%s'%(jid,nick)),
L('It is decidedly so','%s/%s'%(jid,nick)),
L('It is certain','%s/%s'%(jid,nick)),
L('As I see it, yes','%s/%s'%(jid,nick)),
L('Reply hazy, try again','%s/%s'%(jid,nick)),
L('Ask again later','%s/%s'%(jid,nick)),
L('Better not tell you now','%s/%s'%(jid,nick)),
L('Cannot predict now','%s/%s'%(jid,nick)),
L('Concentrate and ask again','%s/%s'%(jid,nick)),
L('Don\'t count on it','%s/%s'%(jid,nick)),
L('My reply is no','%s/%s'%(jid,nick)),
L('Outlook not so good','%s/%s'%(jid,nick)),
L('My sources say no','%s/%s'%(jid,nick))])
send_msg(type, jid, nick, msg)
def coin(type, jid, nick, text):
msg = random.choice([L('Head','%s/%s'%(jid,nick)), L('Tail','%s/%s'%(jid,nick))])
send_msg(type, jid, nick, msg)
def to_poke(type, jid, nick, text):
if len(text): text = text.strip()
if type == 'chat' and get_level(jid,nick)[0] < 7:
send_msg(type, jid, nick, L('For members this command not available in private!','%s/%s'%(jid,nick)))
return
predef_poke = [L('gave NICK ... just gave ... :-\"','%s/%s'%(jid,nick)),
L('poked a stick NICK in the eye ...','%s/%s'%(jid,nick)),
L('suggested NICK shrimp :-[','%s/%s'%(jid,nick)),
L('fed NICK laxative with powdered glass!','%s/%s'%(jid,nick)),
L('whispered in his ear softly NICK LOL!','%s/%s'%(jid,nick)),
L('trying kick the ass NICK','%s/%s'%(jid,nick)),
L('threw the crowbar aside NICK','%s/%s'%(jid,nick)),
L('gave NICK strawberry poison','%s/%s'%(jid,nick)),
L('jumped around with a tambourine NICK','%s/%s'%(jid,nick)),
L('sticking NICK with the words "buy ice cream, you creep!"','%s/%s'%(jid,nick))]
owner = get_level(jid,nick)[0] == 9
dpoke = getFile(poke_file,predef_poke)
t_cmd = text.lower()
if t_cmd == 'show' and owner:
if type == 'groupchat':
send_msg(type, jid, nick, L('Sent in private message','%s/%s'%(jid,nick)))
type = 'chat'
msg = '%s\n%s' % (L('Phrases:','%s/%s'%(jid,nick)),'\n'.join(['%s. %s' % (c+1,t) for c,t in enumerate(dpoke)]))
elif t_cmd.startswith('del ') and owner:
text = text[4:]
try: pos = int(text)-1
except: pos = len(dpoke)+1
if pos < 0 or pos > len(dpoke): msg = L('The record doesn\'t exist!','%s/%s'%(jid,nick))
else:
remove_body = dpoke[pos]
dpoke.remove(remove_body)
writefile(poke_file, str(dpoke))
msg = L('Removed: %s','%s/%s'%(jid,nick)) % remove_body
elif t_cmd.startswith('add ') and owner:
text = text[4:]
if 'NICK' in text:
dpoke.append(text)
writefile(poke_file, str(dpoke))
msg = L('Added','%s/%s'%(jid,nick))
else: msg = L('I can\'t add it! No keyword "NICK"!','%s/%s'%(jid,nick))
elif get_level(jid,text)[1] == selfjid: msg = L('I ban a ip for such jokes!','%s/%s'%(jid,nick))
else:
if not text:
nick_list = [d[1] for d in megabase if d[0]==jid and d[4] != Settings['jid'] and d[1] != nick]
if nick_list:
curr_nick = random.choice(nick_list)
try: last_nick = LAST_RANDOM_POKE[jid]
except: last_nick = ''
if len(nick_list) > 1:
while curr_nick == last_nick: curr_nick = random.choice(nick_list)
LAST_RANDOM_POKE[jid] = curr_nick
text, is_found = curr_nick, True
else: is_found = False
else:
is_found = False
for tmp in megabase:
if tmp[0] == jid and tmp[1] == text:
is_found = True
break
if is_found:
try: hl_pokes = list_of_phrases_with_highlight[get_L_('%s/%s'%(jid,nick))]
except: hl_pokes = []
dp = ['/me %s' % t for t in dpoke]
for t in hl_pokes:
if t and t not in dp: dp.append(t)
try: last_poke = LAST_POKE_PHRASE[jid]
except: last_poke = ''
msg = random.choice(dp)
while last_poke == msg: msg = random.choice(dp)
LAST_POKE_PHRASE[jid] = msg
msg,nick,type = msg.replace('NICK',text),'','groupchat'
elif text: msg = L('I could be wrong, but %s not is here...','%s/%s'%(jid,nick)) % text
else: msg = L('Masochist? 8-D','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def life(type, jid, nick, text):
text = reduce_spaces_all(text)
try:
tmp = text.split(' ')
d,m,y = tmp[0].strip().split('.')
y = int(y)
if y<20: y += 2000
elif y<100: y += 1900
y = str(y)
if len(tmp)>1: hour, minute, sec = tmp[1].strip().split(':')
else: hour, minute, sec = '00','00','00'
BDate = time.mktime(time.strptime(' '.join([y, m, d, hour, minute, sec]), '%Y %m %d %H %M %S'))
CDate = time.time()
Age = CDate-BDate
yrs = int(round(Age/31557600))
dys = int(round(Age/86400))
hrs = int(round(Age/3600))
mins = int(round(Age/60))
secs = int(round(Age))
spal = int(round(Age*3285/31557600))
spal24 = int(round(Age*136.9/31557600))
morgnyl = int(round(Age*4160000/31557600))
serdcelit = int(round(Age*2372500/31557600))
serdceraz = int(round(Age*36500000/31557600))
vodal = int(round(Age*750/31557600))
voda = int(round(Age*21/31557600))
volosicm = int(round(Age*18/31557600))
volosi = int(round(Age*25550/31557600))
volosivse = int(round(Age*14/31557600))
nogtiryk = int(round(Age*5.2/31557600))
nogtinog = int(round(Age*1.4/31557600))
vozdyx = int(round(Age*3784320/31557600))
vozdyxkg = int(round(Age*4881/31557600))
pot = int(round(Age*252/31557600))
mochalit = int(round(Age*489/31557600))
sluni = int(round(Age*337/31557600))
nervi = int(round(Age*136/31557600))
smex = int(round(Age*5475/31557600))
km = int(round(Age*1857/31557600))
msg = L('You live %s years or %s days or %s hours or %s minutes or %s seconds.\nYou slept %s hours, or %s days.\nYou blink about %s times.\nYour heart pumped %s liters of blood and made %s strikes.\nYou drank %s liters of water and drank it %s hours.\nYou have increased by %s centimeters in my head of hair, dropped %s pieces, all of the hair %s kilometers.\nYou grew up in the hands %s centimeters and in the feet %s centimeters nails.\nYou breathed %s liters of air a total weight of %s kilograms.\nYou have stood out %s liters of sweat, and %s liters of urine, and %s liters of saliva.\nYou lost %s billion nerve cells.\nYou laughed %s times.\nYou\'ve gone %s kilometers','%s/%s'%(jid,nick)) % (yrs, dys, hrs, mins, secs, spal, spal24, morgnyl, serdcelit, serdceraz, vodal, voda, volosicm, volosi, volosivse, nogtiryk, nogtinog, vozdyx, vozdyxkg, pot, mochalit, sluni, nervi, smex, km)
if type == 'groupchat': send_msg(type, jid, nick, L('Send for you in private','%s/%s'%(jid,nick)))
send_msg('chat', jid, nick, msg)
except: send_msg(type, jid, nick, L('Smoke help about command!','%s/%s'%(jid,nick)))
def zalgo(type, jid, nick, text):
zalgo_threshold = 10
zalgo_chars = [unichr(i) for i in range(0x0300, 0x036F + 1)]
zalgo_chars.extend([u'\u0488', u'\u0489'])
zalgoized = []
for letter in text:
zalgoized.append(letter)
zalgo_num = random.randint(0, zalgo_threshold) + 1
for _ in range(zalgo_num):
zalgoized.append(random.choice(zalgo_chars))
msg = random.choice(zalgo_chars).join(zalgoized)
send_msg(type,jid,nick,msg)
def godville(type, jid, nick, text):
text = text.strip()
if ' ' in text:
mode, name = text.split(' ', 1)
else:
mode, name = 'last', text
if not mode in ['stat', 'extstat', 'last', 'inv', 'quest']:
mode, name = 'last', text
data = load_page('http://godville.net/gods/api/%s.json' % name.encode('utf-8'))
try:
data = json.loads(data)
if mode == 'last':
try:
msg = '%s: %s' % (data['name'], data['diary_last'])
except:
msg = L('Turn on extended API on game\'s settings','%s/%s'%(jid,nick))
elif mode in ['stat', 'extstat']:
msg = L('Name: %s\n','%s/%s'%(jid,nick)) % data['name']
msg += L('Gold: %s\n','%s/%s'%(jid,nick)) % data['gold_approx']
msg += L('Level: %s\n','%s/%s'%(jid,nick)) % data['level']
msg += L('Alignment: %s\n','%s/%s'%(jid,nick)) % data['alignment']
msg += L('Motto: %s','%s/%s'%(jid,nick)) % data['motto']
if data['clan']:
msg += L('\nClan: %s (%s)','%s/%s'%(jid,nick)) % (data['clan'], data['clan_position'])
if mode == 'extstat' and 'godpower' in data:
msg += L('\nHealth: %s/%s\n','%s/%s'%(jid,nick)) % (data['health'], data['max_health'])
msg += L('Bricks: %s\n','%s/%s'%(jid,nick)) % data['bricks_cnt']
msg += L('Godpower: %s%%','%s/%s'%(jid,nick)) % data['godpower']
elif mode == 'inv':
if data['inventory']:
msg = L('Inventory: %s','%s/%s'%(jid,nick)) % ', '.join(data['inventory'].keys())
else:
msg = L('Inventory: %s','%s/%s'%(jid,nick)) % L('Not found!','%s/%s'%(jid,nick))
elif mode == 'quest':
msg = '%s: %s' % (data['name'], data['quest'])
except:
msg = L('User not found','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(3, 'poem', poem, 1, 'Just funny poem'),
(3, 'oracle', oracle, 2, 'Prophecy oracle. Example: oracle your_answer?'),
(3, 'coin', coin, 2, 'Heads or tails'),
(3, 'poke', to_poke, 2, '"Poke" command\npoke nick - say a random phrase for nick\nControls command, available only for bot owner:\npoke show - show list of phrases\npoke add phrase - add phrase\npoke del phrase_number - remove phrase.'),
(3, 'life', life, 2, 'Info about your life. Example: life dd.mm.yy [hour:min:sec]'),
(3, 'zalgo', zalgo, 2, 'Zalgo translate'),
(3, 'godville', godville, 2, 'Information about hero from Godville.net.\ngodville [last|stat|extstat|inv|quest] username')]

101
plugins/gis.py Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def gweather_raw(type, jid, nick, text, fully):
def get_date(body):
tmp = get_tag_item(body,'FORECAST','day')+'.'+get_tag_item(body,'FORECAST','month')
ytmp = get_tag_item(body,'FORECAST','year')
if str(tuple(time.localtime())[0]) == ytmp: return tmp
return tmp+'.'+ytmp
def get_maxmin(body,tag,splitter):
tmax = get_tag_item(body,tag,'max')
tmin = get_tag_item(body,tag,'min')
if not fully: return str(int((int(tmax)+int(tmin))/2))
if tmax == tmin: return tmax
if (int(tmin)+int(tmax))/2 == 0: return '0'
return tmin + splitter + tmax
def get_themp(body): return get_maxmin(body,'TEMPERATURE','..')
def get_wind(body): return get_maxmin(body,'WIND','-')
def get_pressure(body): return get_maxmin(body,'PRESSURE','-')
def get_relwet(body): return get_maxmin(body,'RELWET','-')
tods = {'0':L('Night','%s/%s'%(jid,nick)),'1':L('Morning','%s/%s'%(jid,nick)),'2':L('Day','%s/%s'%(jid,nick)),'3':L('Evening','%s/%s'%(jid,nick))}
precipitation = {'4':L('rain','%s/%s'%(jid,nick)),'5':L('downpour','%s/%s'%(jid,nick)),'6':L('snow','%s/%s'%(jid,nick)),'7':L('snow','%s/%s'%(jid,nick)),
'8':L('storm','%s/%s'%(jid,nick)),'9':L('no data','%s/%s'%(jid,nick)),'10':L('no precipitation','%s/%s'%(jid,nick))}
cloudiness = {'0':L('clear','%s/%s'%(jid,nick)),'1':L('cloudy','%s/%s'%(jid,nick)),'2':L('Cloudy','%s/%s'%(jid,nick)),'3':L('overcast','%s/%s'%(jid,nick))}
winddir = {'0':L('N','%s/%s'%(jid,nick)),'1':L('NE','%s/%s'%(jid,nick)),'2':L('E','%s/%s'%(jid,nick)),'3':L('SE','%s/%s'%(jid,nick)),
'4':L('S','%s/%s'%(jid,nick)),'5':L('SW','%s/%s'%(jid,nick)),'6':L('W','%s/%s'%(jid,nick)),'7':L('NW','%s/%s'%(jid,nick))}
if len(text.strip()):
text = text.lower()
wzc = cur_execute_fetchall('select * from gis where code ilike %s or lcity ilike %s',(text,text))
if not wzc:
ttext = '%%%s%%' % text
wzc = cur_execute_fetchall('select * from gis where code ilike %s or lcity ilike %s',(ttext,ttext))
if not wzc and text.isdigit() and 4 <= len(text) <= 5: wzc = [(text,'','')]
if wzc:
if len(wzc) == 1:
text = wzc[0][0]
link = 'http://informer.gismeteo.ru/xml/%s.xml' % text
try: body, noerr = html_encode(load_page(link)), True
except Exception, SM:
try: body = str(SM)
except: body = unicode(SM)
noerr = None
if not body or body == '<?xml version="1.0" encoding="UTF-8"?>\n</xml>': body,noerr = L('Unexpected error','%s/%s'%(jid,nick)), None
if noerr:
if wzc[0][1]: ct = wzc[0][1]
else:
try: res = re.findall('<TOWN index=".*?" sname="(.*?)"',body)
except: res = ''
if res: ct = urllib2.unquote(res[0]).encode('cp1252').decode('cp1251')
else: ct = L('Unknown','%s/%s'%(jid,nick))
body = body.split('<FORE')[1:]
msg = L('Weather in %s:\nDate\t t%s\tWind\tClouds','%s/%s'%(jid,nick)) % (ct,u'°')
if fully: msg += L('\tPressure, mm. Hg. Art.\tHumidity %','%s/%s'%(jid,nick))
for tmp in body:
tmp2 = '<FORE' + tmp
msg += '\n' + tods[get_tag_item(tmp2,'FORECAST','tod')] + ' ' + get_date(tmp2) # дата + время суток
msg += '\t' + get_themp(tmp2) # температура
gwi = get_wind(tmp2) # ветер
if gwi == '0': msg += L('\tCalm','%s/%s'%(jid,nick))
else: msg += '\t' + gwi+' '+winddir[get_tag_item(tmp2,'WIND','direction')]
msg += '\t' + cloudiness[get_tag_item(tmp2,'PHENOMENA','cloudiness')] # облачность
msg += ', ' + precipitation[get_tag_item(tmp2,'PHENOMENA','precipitation')] # осадки
if fully: msg += '\t' + get_pressure(tmp2) + '\t' + get_relwet(tmp2) # давление, влажность
else: msg = L('Error! %s','%s/%s'%(jid,nick)) % body
else:
msg = L('Found:','%s/%s'%(jid,nick))
for tmp in wzc: msg += '\n'+tmp[0]+' - '+tmp[1]
else: msg = L('Not found.','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def gweather(type, jid, nick, text): gweather_raw(type, jid, nick, text, None)
def gweatherplus(type, jid, nick, text): gweather_raw(type, jid, nick, text, True)
global execute
execute = [(3, 'gis', gweather, 2, 'Weather forecast (short). Courtesy Gismeteo.Ru | http://www.gismeteo.ru'),
(3, 'gis+', gweatherplus, 2, 'Weather forecast (full). Courtesy Gismeteo.Ru | http://www.gismeteo.ru')]

139
plugins/google.py Normal file
View File

@@ -0,0 +1,139 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
google_last_res = {}
def replace_bold(t,b,e): return t.replace('<b>',b).replace('</b>',e)
def wiki_search(type, jid, nick, text):
if text not in ['next','']: text = L('%s site:en.wikipedia.org','%s/%s'%(jid,nick)) % text
google(type, jid, nick, text)
def xep_show(type, jid, nick,text):
ntext = 'xep '+text+' inurl:xmpp.org'
url = 'http://ajax.googleapis.com/ajax/services/search/web?'
search_results = html_encode(load_page(url, {'v': '1.0', 'q': ntext.encode("utf-8")}))
jsonl = json.loads(search_results)
try:
results = jsonl['responseData']['results']
title = results[0]['title']
content = results[0]['content']
noh_title = replace_bold(title,'','')
content = replace_bold(content,'','')
msg = '\n'.join((replacer(noh_title),replacer(content),results[0]['unescapedUrl']))
except: msg = L('xep \"%s\" not found!','%s/%s'%(jid,nick)) % text
send_msg(type, jid, nick, msg)
def google(type, jid, nick, text):
global google_last_res
results = ''
text = text.strip()
if text in ['next','']:
if google_last_res.has_key(jid) and google_last_res[jid].has_key(nick) and google_last_res[jid][nick]:
first = google_last_res[jid][nick][0]
google_last_res[jid][nick] = google_last_res[jid][nick][1:]
else: results = L('No results!','%s/%s'%(jid,nick))
else:
try:
url = 'http://ajax.googleapis.com/ajax/services/search/web?'
search_results = html_encode(load_page(url, {'v': '1.0', 'q': text.encode("utf-8")}))
jsonl = json.loads(search_results)
data = jsonl['responseData']['results']
first = data[0]
if google_last_res.has_key(jid): google_last_res[jid].update({nick: data[1:]})
else: google_last_res[jid] = {nick: data[1:]}
except: results = L('Expression \"%s\" not found!','%s/%s'%(jid,nick)) % text
if not results:
title = first['title']
content = first['content']
noh_title = replace_bold(title,u'«',u'»')
content = replace_bold(content,u'«',u'»')
url = urllib.unquote(first['unescapedUrl'].encode('utf8')).decode('utf8','ignore')
results = replacer(noh_title)+'\n'+replacer(content)+'\n'+url
send_msg(type, jid, nick, results)
def google_clear(room,jid,nick,type,arr):
if type == 'unavailable' and google_last_res.has_key(room) and google_last_res[room].has_key(nick): del google_last_res[room][nick]
def translate(type, jid, nick, text):
text = text.strip()
trlang = {'sq':L('Albanian','%s/%s'%(jid,nick)),'en':L('English','%s/%s'%(jid,nick)),'ar':L('Arabic','%s/%s'%(jid,nick)),'af':L('Afrikaans','%s/%s'%(jid,nick)),
'be':L('Belarusian','%s/%s'%(jid,nick)),'bg':L('Bulgarian','%s/%s'%(jid,nick)),'cy':L('Welsh','%s/%s'%(jid,nick)),
'hu':L('Hungarian','%s/%s'%(jid,nick)),'vi':L('Vietnamese','%s/%s'%(jid,nick)),'gl':L('Galician','%s/%s'%(jid,nick)),
'nl':L('Dutch','%s/%s'%(jid,nick)),'el':L('Greek','%s/%s'%(jid,nick)),'da':L('Danish','%s/%s'%(jid,nick)),'iw':L('Hebrew','%s/%s'%(jid,nick)),
'yi':L('Yiddish','%s/%s'%(jid,nick)),'id':L('Indonesian','%s/%s'%(jid,nick)),'ga':L('Irish','%s/%s'%(jid,nick)),'is':L('Icelandic','%s/%s'%(jid,nick)),
'es':L('Spanish','%s/%s'%(jid,nick)),'it':L('Italian','%s/%s'%(jid,nick)),'ca':L('Catalan','%s/%s'%(jid,nick)),'zh':L('Chinese','%s/%s'%(jid,nick)),
'ko':L('Korean','%s/%s'%(jid,nick)),'lv':L('Latvian','%s/%s'%(jid,nick)),'lt':L('Lithuanian','%s/%s'%(jid,nick)),
'mk':L('Macedonian','%s/%s'%(jid,nick)),'ms':L('Malay','%s/%s'%(jid,nick)),'mt':L('Maltese','%s/%s'%(jid,nick)),'de':L('German','%s/%s'%(jid,nick)),
'no':L('Norwegian','%s/%s'%(jid,nick)),'fa':L('Persian','%s/%s'%(jid,nick)),'pl':L('Polish','%s/%s'%(jid,nick)),'pt':L('Portuguese','%s/%s'%(jid,nick)),
'ro':L('Romanian','%s/%s'%(jid,nick)),'ru':L('Russian','%s/%s'%(jid,nick)),'sr':L('Serbian','%s/%s'%(jid,nick)),'sk':L('Slovak','%s/%s'%(jid,nick)),
'sl':L('Slovenian','%s/%s'%(jid,nick)),'sw':L('Swahili','%s/%s'%(jid,nick)),'tl':L('Tagalog','%s/%s'%(jid,nick)),'th':L('Thai','%s/%s'%(jid,nick)),
'tr':L('Turkish','%s/%s'%(jid,nick)),'uk':L('Ukrainian','%s/%s'%(jid,nick)),'fi':L('Finnish','%s/%s'%(jid,nick)),'fr':L('French','%s/%s'%(jid,nick)),
'hi':L('Hindi','%s/%s'%(jid,nick)),'hr':L('Croatian','%s/%s'%(jid,nick)),'cs':L('Czech','%s/%s'%(jid,nick)),'sv':L('Swedish','%s/%s'%(jid,nick)),
'et':L('Estonian','%s/%s'%(jid,nick)),'ja':L('Japanese','%s/%s'%(jid,nick)),'ht':L('Creole','%s/%s'%(jid,nick))}
if text.lower() == 'list': msg = L('Available languages for translate:','%s/%s'%(jid,nick)) + ' ' + ', '.join(sorted(trlang.keys()))
elif text[:5].lower() == 'info ':
text = text.lower().split(' ')
msg = ''
for tmp in text:
if tmp in trlang: msg += '%s - %s, ' % (tmp,trlang[tmp])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg[:-2]
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
elif text[:5].lower() == 'lang ' and text.count(' ')==1:
text = text.lower().split(' ')[1]
msg = ', '.join(['%s - %s' % (k,trlang[k]) for k in trlang.keys() if text in trlang[k].lower()])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
else:
if ' ' in text:
text = text.split(' ',2)
url = 'http://translate.google.ru/translate_a/t?'
if len(text)>1 and trlang.has_key(text[0].lower()):
if len(text)>2 and trlang.has_key(text[1].lower()): lfrom,lto,tr_text = text[0].lower(),text[1].lower(),text[2]
else: lfrom,lto,tr_text = '',text[0].lower(),' '.join(text[1:])
search_results = load_page(url, {'client':'x',\
'text':tr_text.encode("utf-8"),\
'hl':lfrom,\
'sl':lfrom,\
'tl':lto})
try: jsonl = json.loads(search_results)['sentences']
except ValueError: jsonl = None
try: src = trlang[json.loads(search_results)['src']].capitalize()
except: src = None
if jsonl:
msg = rss_replace(''.join(f['trans'] for f in jsonl))
if src and not lfrom: msg = L('%s [Source: %s]','%s/%s'%(jid,nick)) % (msg,src.strip())
else: msg = L('I can\'t translate it!','%s/%s'%(jid,nick))
else: msg = L('Incorrect language settings for translate. tr list - available languages.','%s/%s'%(jid,nick))
else: msg = L('Command\'s format: tr [from] to text','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute, presence_control
presence_control = [google_clear]
execute = [(3, 'tr', translate, 2, 'Translator.\ntr [from_language] to_language text - translate text\ntr list - list for available languages for translate\ntr info <reduction> - get info about language reduction\ntr lang <expression> - get languages by expression'),
(3, 'google', google, 2, 'Search in google'),
(3, 'xep', xep_show, 2, 'Search XEP'),
(3, 'wiki', wiki_search, 2, 'Search in en.wikipedia.org')]

123
plugins/googleplus.py Normal file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# translate: verb,noun,preposition,adverb,adjective,phrase,conjunction,abbreviation,Google URL Shortener/Unshortener,Google QR-code generator
def gcalc(type, jid, nick, text):
if not text.strip(): msg = L('What?','%s/%s'%(jid,nick))
else:
try:
data = load_page('http://www.google.ru/search?', {'q': '%s=' % text.replace('=','').strip().encode('utf-8'), 'hl': GT('youtube_default_lang')}).decode('utf-8', 'ignore')
msg = ' '.join([t.strip() for t in re.findall('<span class="cwclet" id="cwles">(.*?)</span> </div> </div>.*?<span class="cwcot" id="cwos">(.*?)</span> <script>',data)[0]])
msg = msg.replace('<sup>2</sup>',u'²').replace('<sup>3</sup>',u'³')
except:
try: msg = reduce_spaces_all(' '.join(re.findall('<div class="vk_gy vk_sh">(.*?)</div><div class="vk_ans vk_bk">(.*?)</div>',data,re.S)[0])).strip()
except: msg = L('Google Calculator results not found','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def define(type, jid, nick, text):
text = text.strip()
target, define_silent = '', False
if not text: msg = L('What?','%s/%s'%(jid,nick))
else:
if re.search('\A\d+?(-\d+?)? ', text): target, text = text.split(' ', 1)
data = load_page('http://www.google.com.ua/search?', {'hl': 'ru', 'q': text.encode('utf-8'), 'tbs': 'dfn:1'}).decode('utf-8')
result = re.findall('<li style="list-style:none">(.+?)</li></ul><div style="color:#551a8b"><cite><span class=bc><a href="/url\?url=(.+?)&amp', data)
if target:
try: n1 = n2 = int(target)
except: n1, n2 = map(int, target.split('-'))
if n1 + n2 == 0: define_silent, n1, n2 = True, 1, 1
if not result: msg = [L('I don\'t know!','%s/%s'%(jid,nick)), ''][define_silent]
else:
if target and target != '0':
msg = ''
if 0 < n1 <= n2 <= len(result):
for k in xrange(n1 - 1, n2): msg += '%s\n%s\n\n' % (result[k][0], urllib.unquote(result[k][1].replace('%25', '%').encode('utf8')).decode('utf8'))
else: msg = [L('I don\'t know!','%s/%s'%(jid,nick)), ''][define_silent]
else:
result = random.choice(result)
msg = result[0] + '\n' + urllib.unquote(result[1].replace('%25', '%').encode('utf8')).decode('utf8')
if '<' in msg and '>' in msg: msg = unhtml_hard(msg)
if msg: send_msg(type, jid, nick, msg)
def define_message(room, jid, nick, type, text):
s = get_config(room, 'parse_define')
if s != 'off':
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(room,'define')): return
troom = cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%room,))
if troom:
nowname = getResourse(troom[0])
text = re.sub('^%s[,:]\ ' % re.escape(nowname), '', text.strip())
what = re.search([u'^(?:(?:что такое)|(?:кто такой)|(?:кто такая)) ([^?]+?)\?$', u'(?:(?:что такое)|(?:кто такой)) ([^?]+?)\?'][s == 'partial'], text, re.I + re.U + re.S)
if what:
access_mode = get_level(room, nick)[0]
text = 'define 0 %s' % what.group(1)
com_parser(access_mode, nowname, type, room, nick, text, jid)
return True
def gdict(type, jid, nick, text):
text = reduce_spaces_all(text.encode('utf-8')).split(' ')
if 2 <= len(text) <= 3:
try: sl, tl, text = text
except: sl, tl, text = [''] + text
data = html_encode(load_page('http://translate.google.ru/translate_a/t?', {'client': 'x', 'text': text, 'hl': 'en', 'sl': sl, 'tl': tl}))
try:
data = json.loads(data)
if 'dict' in data: msg = '\n%s' % '\n'.join(['%s: %s' % (L(i['pos']).upper(), ', '.join(i['terms'])) for i in data['dict'] if i['pos']])
else: msg = L('I can\'t translate it!','%s/%s'%(jid,nick))
except: msg = L('Command execution error.','%s/%s'%(jid,nick))
else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def goo_gl_raw(text, is_qr):
url = text.strip().encode('utf-8')
if not re.findall('^http(s?)://',url[:10]) and not is_qr: url = 'http://' + url
if is_qr: regex = 'http://goo\.gl/[a-zA-Z0-9]+?\.qr\Z'
else: regex = 'http://goo\.gl/[a-zA-Z0-9]+?\Z'
if not url: msg = L('What?','%s/%s'%(jid,nick))
elif re.match(regex, url):
if is_qr: url = url[:-3]
f = get_opener(url)[0]
if L('Error! %s','%s/%s'%(jid,nick)) % '' in f: msg = f
else: msg = urllib.unquote(f.geturl().encode('utf8')).decode('utf8')
else:
data = load_page(urllib2.Request('http://goo.gl/api/url', 'url=%s' % urllib.quote(url)))
if L('Error! %s','%s/%s'%(jid,nick)) % '' in data: msg = data
else:
msg = json.loads(data)['short_url']
if is_qr: msg += '.qr'
return msg
def goo_gl_qr(type, jid, nick, text): send_msg(type, jid, nick, goo_gl_raw(text, True))
def goo_gl(type, jid, nick, text): send_msg(type, jid, nick, goo_gl_raw(text, False))
global execute, message_control
message_act_control = [define_message]
execute = [(3, 'gcalc', gcalc, 2, 'Google Calculator'),
(3, 'define', define, 2, 'Definition for a word or phrase.\ndefine word - random define of word or phrase\ndefine N word - N-th define of word or phrase\ndefine a-b word - from a to b defines of word or phrase'),
#(3, 'ggl', goo_gl, 2, 'Google URL Shortener/Unshortener'),
#(3, 'qr', goo_gl_qr, 2, 'Google QR-code generator'),
(3, 'gdict', gdict, 2, 'Google Dictionary\ngdict [from_language] to_language word')]

31
plugins/here.py Normal file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def muc_here(type, jid, nick):
users = non_case_sort([t[1] for t in megabase if t[0]==jid])
msg = L('I see %s participant(s): %s','%s/%s'%(jid,nick)) % (len(users), ', '.join(users))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'here', muc_here, 1, 'Current participants list')]

50
plugins/hideroom.py Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def hide_room(type, jid, nick, text):
if type == 'groupchat': msg = L('This command available only in private!','%s/%s'%(jid,nick))
else:
hmode = text.split(' ')[0]
try: hroom = text.split(' ')[1]
except: hroom = jid
if hmode == 'show':
hr = cur_execute_fetchall('select * from hiden_rooms;')
if len(hr): msg = '%s\n%s' % (L('Hidden conferences:','%s/%s'%(jid,nick)),'\n'.join([t[0] for t in hr]))
else: msg = L('No hidden conferences.','%s/%s'%(jid,nick))
elif hmode == 'add':
if not cur_execute_fetchone('select * from conference where room ilike %s;', ('%s/%%'%getRoom(hroom),)): msg = L('I am not in the %s','%s/%s'%(jid,nick)) % hroom
elif cur_execute_fetchone('select * from hiden_rooms where room=%s',(hroom,)): msg = L('I\'m already hide a %s','%s/%s'%(jid,nick)) % hroom
else:
cur_execute('insert into hiden_rooms values (%s)',(hroom,))
msg = L('%s has been hidden','%s/%s'%(jid,nick)) % hroom
elif hmode == 'del':
if hroom in hr:
cur_execute('delete from hiden_rooms where room=%s',(hroom,))
msg = L('%s will be shown','%s/%s'%(jid,nick)) % hroom
else: msg = L('I\'m not hide room %s','%s/%s'%(jid,nick)) % hroom
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(9, 'hide', hide_room, 2, 'Hide conference.\nhide [add|del|show] [room@conference.server.tld]')]

51
plugins/horo.py Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) ferym <ferym@jabbim.org.ru> #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# translate: aries,taurus,gemini,cancer,leo,virgo,libra,scorpio,sagittarius,capricorn,aquarius,pisces
horodb=['aries','taurus','gemini','cancer','leo','virgo','libra','scorpio','sagittarius','capricorn','aquarius','pisces']
def handler_horoscope(type, jid, nick, text):
param = text.strip().lower()
msg = L('What?','%s/%s'%(jid,nick))
if param:
if param == 'list': msg = ', '.join(['%s (%s)' % (L(t).capitalize(),t.capitalize()) for t in horodb])
if param == 'date':
horo_dates = ['21.03-19.04','20.04-20.05','21.05-20.06','21.06-22.07','23.07-22.08','23.08-22.09','23.09-22.10','23.10-21.11','22.11-21.12','22.12-19.01','20.01-18.02','19.02-20.03']
msg = L('List of dates:\n%s','%s/%s'%(jid,nick)) % '\n'.join([u'%s … %s' % (horo_dates[i],L(t).capitalize()) for i,t in enumerate(horodb)])
if type=='groupchat':
send_msg('chat', jid, nick, msg)
msg = L('Send for you in private','%s/%s'%(jid,nick))
if param in [L(t) for t in horodb] or param in horodb:
if param not in horodb: param = dict([[L(t),t] for t in horodb])[param]
body = html_encode(load_page('http://horo.mail.ru/prediction/%s/today' % param))
try: msg = unhtml_hard(re.findall('<div id="tm_today">(.+?)<div class="mb2">',body,re.S|re.I|re.U)[0].strip())
except: msg = L('Unknown error!','%s/%s'%(jid,nick))
if type=='groupchat':
send_msg('chat', jid, nick, msg)
msg = L('Send for you in private','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(3, 'horo', handler_horoscope, 2, 'Horoscope.\nhoro list - show all zodiacs.\nhoro date - show dates for zodiacs. | Author: ferym')]

60
plugins/idle.py Normal file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
idle_base = []
def idle(type, jid, nick, text):
global idle_base
if not len(text): text = nick
msg = L('I can\'t find %s','%s/%s'%(jid,nick)) % text
for tmp in idle_base:
if tmp[0] == jid and tmp[1] == text:
if text == nick: msg = L('Your last activity was %s ago','%s/%s'%(jid,nick)) % un_unix(int(time.time())-tmp[3],'%s/%s'%(jid,nick))
else: msg = L('%s\'s last ativity was %s ago','%s/%s'%(jid,nick)) % (text, un_unix(int(time.time())-tmp[3],'%s/%s'%(jid,nick)))
if tmp[2] == 'm': msg += ' ('+L('message','%s/%s'%(jid,nick))+')'
else: msg += ' ('+L('presence','%s/%s'%(jid,nick))+')'
break
send_msg(type, jid, nick, msg)
def append_to_idle(room,jid,nick,type,text):
global idle_base
for tmp in idle_base:
if tmp[0] == room and tmp[1] == nick:
idle_base.remove(tmp)
break
idle_base.append((room,nick,'m',int(time.time())))
def remove_from_idle(room,jid,nick,type,text):
global idle_base
for tmp in idle_base:
if tmp[0] == room and tmp[1] == nick:
idle_base.remove(tmp)
break
if type != 'unavailable': idle_base.append((room,nick,'p',int(time.time())))
global execute
message_control = [append_to_idle]
presence_control = [remove_from_idle]
execute = [(0, 'idle', idle, 2, 'Idle time')]

112
plugins/inlist.py Normal file
View File

@@ -0,0 +1,112 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def reban(type, jid, nick, text):
try: lim = int(text)
except:
send_msg(type, jid, nick, L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick)))
return
global banbase,iq_request
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':getRoom(jid)}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast'})])])
iq_request[iqid]=(time.time(),reban_async,[type, jid, nick, lim],xmpp.NS_MUC_ADMIN)
sender(i)
def reban_async(type, jid, nick, lim, iq_stanza):
isa = iq_stanza[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
_trusted = get_config(getRoom(jid),'trusted_servers').split()
_jids = [tmp.getAttr('jid') for tmp in iq_stanza[1][0].getTag('query',namespace=xmpp.NS_MUC_ADMIN).getTags('item')]
_srv_count = {}
for t in _jids:
if '@' in t:
_t = t.split('@',1)[1]
if _t not in _trusted: _srv_count[_t] = _srv_count[_t] + 1 if _srv_count.has_key(_t) else 1
_servers = [t for t in _jids if '@' not in t]
_new_servers = [t for t in _srv_count.keys() if _srv_count[t] >= lim and t not in _servers]
_need_remove = [t for t in _jids if '@' in t and t.split('@',1)[1] in _servers + _new_servers]
_new_servers.sort()
_limit = get_config_int(getRoom(jid),'make_stanza_jid_count')
nodes = []
for t in _new_servers:
reason = [xmpp.Node('reason',{},'Rebanned as dangerous! Found jids: %s' % _srv_count[t])]
nodes.append(xmpp.Node('item',{'affiliation':'outcast', 'jid':t},reason))
if len(nodes) >= _limit:
sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},nodes)]))
nodes = []
if nodes: sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},nodes)]))
nodes = []
for t in _need_remove:
nodes.append(xmpp.Node('item',{'affiliation':'none', 'jid':t},[]))
if len(nodes) >= _limit:
sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},nodes)]))
nodes = []
if nodes: sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},nodes)]))
msg = L('Unbaned jids: %s\nBanned servers: %s .. %s','%s/%s'%(jid,nick)) % (len(_need_remove), len(_new_servers), ', '.join(_new_servers))
send_msg(type, jid, nick, msg)
def inban(type, jid, nick, text): inlist_raw(type, jid, nick, text, 'outcast', L('Total banned: %s','%s/%s'%(jid,nick)))
def inowner(type, jid, nick, text): inlist_raw(type, jid, nick, text, 'owner', L('Total owners: %s','%s/%s'%(jid,nick)))
def inadmin(type, jid, nick, text): inlist_raw(type, jid, nick, text, 'admin', L('Total admins: %s','%s/%s'%(jid,nick)))
def inmember(type, jid, nick, text): inlist_raw(type, jid, nick, text, 'member', L('Total members: %s','%s/%s'%(jid,nick)))
def inlist_raw(type, jid, nick, text, affil, message):
global banbase,iq_request
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':getRoom(jid)}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':affil})])])
iq_request[iqid]=(time.time(),inlist_raw_async,[type, jid, nick, text, message],xmpp.NS_MUC_ADMIN)
sender(i)
def inlist_raw_async(type, jid, nick, text, message, iq_stanza):
isa = iq_stanza[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
bb = [[tmp.getAttr('jid'),['',tmp.getTagData('reason')][tmp.getTagData('reason') != None]] for tmp in iq_stanza[1][0].getTag('query',namespace=xmpp.NS_MUC_ADMIN).getTags('item')]
bb.sort()
msg = message % len(bb)
if text != '':
text = text.strip().split()
if len(text) == 1: text,nt = text[0], 0
elif text[0] == '!': text,nt = ' '.join(text[1:]), 1
elif text[0] == '=': text,nt = ' '.join(text[1:]), 2
else: text,nt = ' '.join(text[1:]), False
msg += ', '
mmsg, cnt = '', 1
for i in bb:
if [text.lower() in i[0].lower() or text.lower() in i[1].lower(), text.lower() not in i[0].lower(),text.lower() == i[0].lower() or text.lower() == i[1].lower()][nt]:
mmsg += '\n%s. %s' % (cnt,i[0])
if len(i[1]): mmsg += ' - %s' % i[1]
cnt += 1
if len(mmsg): msg += L('Found:','%s/%s'%(jid,nick)) + ' %s%s' % (mmsg.count('\n'),mmsg)
else: msg += L('no matches!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(7, 'inban', inban, 2, 'Search in outcast list of conference.'),
(7, 'inmember', inmember, 2, 'Search in members list of conference.'),
(7, 'inadmin', inadmin, 2, 'Search in admins list of conference.'),
(7, 'inowner', inowner, 2, 'Search in owners list of conference.'),
(8, 'reban', reban, 2, 'Cleen up outcast list. Replace different jids from same server by one server jid\nreban <count>')]

61
plugins/invite.py Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def call_body(type, jid, nick, text):
skip = 1
if len(text):
try:
reason = text.split('\n')[1]
text = text.split('\n')[0]
except: reason = None
fnd = cur_execute_fetchall('select jid from age where room=%s and (nick=%s or jid=%s) group by jid',(jid,text,text))
if len(fnd) == 1:
whojid = getRoom(unicode(fnd[0][0]))
is_found = 0
for tmp in megabase:
if tmp[0] == jid and getRoom(tmp[4]) == whojid:
is_found = 1
break
if is_found: msg = L('%s ishere!','%s/%s'%(jid,nick)) % text
else:
msg = L('Invited','%s/%s'%(jid,nick))
skip = 0
elif len(fnd) > 1: msg = L('I seen some peoples with this nick. Get more info!','%s/%s'%(jid,nick))
else: msg = L('I don\'n know %s','%s/%s'%(jid,nick)) % text
else: msg = L('What?','%s/%s'%(jid,nick))
if skip: send_msg(type, jid, nick, msg)
else:
inv_msg = L('%s invite you to %s','%s/%s'%(jid,nick)) % (nick, jid)
if reason: inv_msg += ' ' + L('because: %s','%s/%s'%(jid,nick)) % reason
send_msg('chat',whojid, '',inv_msg)
inv = xmpp.Message(jid)
inv.setTag('x', namespace=xmpp.NS_MUC_USER).addChild('invite', {'to':whojid})
sender(inv)
send_msg(type, jid, nick, msg)
global execute
execute = [(4, 'invite', call_body, 2, 'Invite to conference.\ninvite nick|jid\n[reason]')]

332
plugins/iq.py Normal file
View File

@@ -0,0 +1,332 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# translate: FN,NICKNAME,N.FAMILY,N.GIVEN,N.MIDDLE,ADR.LOCALITY,ADR.REGION,ADR.PCODE,ADR.CTRY,ADR.STREET,TEL.NUMBER,EMAIL.USERID,EMAIL,JABBERID,ROLE,BDAY,URL,DESC,ROLE,ORG.ORGNAME,ORG.ORGUNIT,GEO.LAT,GEO.LON,TITLE,PHOTO,uptime,seconds,users/registered,users,users/online,contacts/online,contacts,contacts/total,messages/in,messages,messages/out,memory-usage,KB,users/all-hosts/total,users/all-hosts/online,users/total
VCARD_LIMIT_LONG = 256
VCARD_LIMIT_SHORT = 128
iq_ping_minimal = GT('timeout')
def iq_iq_get(iq,id,room,acclvl,query,towh,al):
if iq.getTag(name='query', namespace=xmpp.NS_VERSION) and GT('iq_version_enable'):
pprint('*** iq:version from %s' % unicode(room),'magenta')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setQueryNS(namespace=xmpp.NS_VERSION)
i.getTag('query').setTagData(tag='name', val=botName)
i.getTag('query').setTagData(tag='version', val=botVersion)
i.getTag('query').setTagData(tag='os', val=botOs)
return i
elif iq.getTag(name='query', namespace=xmpp.NS_TIME) and GT('iq_time_enable'):
pprint('*** iq:time from %s' % unicode(room),'magenta')
t_utc,t_tz,t_display = nice_time(time.time(),room)
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setQueryNS(namespace=xmpp.NS_TIME)
i.getTag('query').setTagData(tag='utc', val=t_utc)
i.getTag('query').setTagData(tag='tz', val=t_tz)
i.getTag('query').setTagData(tag='display', val=t_display)
return i
elif iq.getTag(name='time', namespace=xmpp.NS_URN_TIME) and GT('iq_time_enable'):
pprint('*** iq:urn:time from %s' % unicode(room),'magenta')
if timeofset in [-12,-11,-10]: t_tz = '-%s:00' % timeofset
elif timeofset in range(-9,-1): t_tz = '-0%s:00' % timeofset
elif timeofset in range(0,9): t_tz = '+0%s:00' % timeofset
else: t_tz = '+%s:00' % timeofset
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setTag('time',namespace=xmpp.NS_URN_TIME)
i.getTag('time').setTagData(tag='tzo', val=t_tz)
i.getTag('time').setTagData(tag='utc', val=str(time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())))
return i
elif iq.getTag(name='ping', namespace=xmpp.NS_URN_PING) and GT('iq_ping_enable'):
pprint('*** iq:urn:ping from %s' % unicode(room),'magenta')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
return i
elif iq.getTag(name='query', namespace=xmpp.NS_LAST) and GT('iq_uptime_enable'):
pprint('*** iq:uptime from %s' % unicode(room),'magenta')
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setTag('query',namespace=xmpp.NS_LAST,attrs={'seconds':str(int(time.time())-starttime)})
i.setTagData('query','%s (%s) [%s]' % (Settings['message'],Settings['status'],Settings['priority']))
return i
return None
def get_who_iq(text,jid,nick):
if text == '': who = '%s/%s' % (getRoom(jid),nick)
else:
who = text
for mega1 in megabase:
if mega1[0] == jid and mega1[1] == text:
who = '%s/%s' % (getRoom(jid),text)
break
return who
def get_caps(room,nick):
try:
(id_node,id_ver,id_bmver) = capses['%s/%s' % (room,nick)].split('\n')
if id_bmver: msg = '%s %s (%s)' % (id_node,id_ver,id_bmver)
else: msg = '%s %s' % (id_node,id_ver)
except: msg = None
return msg
def noiq_caps(type, jid, nick, text):
text = [text,nick][text == '']
msg = get_caps(jid,text)
if not msg: msg = L('I can\'t get caps of %s','%s/%s'%(jid,nick)) % text
elif len(msg) == msg.count(' ')+msg.count('\n'): msg = L('%s has empty caps!','%s/%s'%(jid,nick)) % text
send_msg(type, jid, nick, msg)
def iq_vcard(type, jid, nick, text):
global iq_request
if '\n' in text: text,args = text.split('\n',1)
else: args = ''
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('vCard', {'xmlns': xmpp.NS_VCARD},[])])
iq_request[iqid]=(time.time(),vcard_async,[type, jid, nick, text, args],xmpp.NS_VCARD)
sender(i)
def vcard_async(type, jid, nick, text, args, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
try: vc,err = isa[1].getTag('vCard',namespace=xmpp.NS_VCARD),False
except: vc,err = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick)),True
if not vc or unicode(vc) == '<vCard xmlns="vcard-temp" />': msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),L('Empty!','%s/%s'%(jid,nick)))
elif err: msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),vc[:VCARD_LIMIT_LONG])
else:
data = []
for t in vc.getChildren():
if t.getChildren():
cm = []
for r in t.getChildren():
if r.getData(): cm.append(('%s.%s' % (t.getName(),r.getName()),unicode(r.getData())))
data += cm
elif t.getData(): data.append((t.getName(),t.getData()))
if data:
try:
photo_size = sys.getsizeof(get_value_from_array2(data,'PHOTO.BINVAL').decode('base64'))
photo_type = get_value_from_array2(data,'PHOTO.TYPE')
data_photo = L('type %s, %s','%s/%s'%(jid,nick)) % (photo_type,get_size_human(photo_size))
data = [t for t in list(data) if t[0] not in ['PHOTO.BINVAL','PHOTO.TYPE']]
data.append(('PHOTO',data_photo))
except: pass
args = args.lower()
if not args:
dd = get_array_from_array2(data,['NICKNAME','FN','BDAY','URL','PHOTO','DESC'])
if dd: msg = '%s\n%s' % (L('vCard:','%s/%s'%(jid,nick)),'\n'.join(['%s: %s' % ([L(t[0]),t[0].capitalize()][L(t[0])==t[0]],[u'%s…' % t[1][:VCARD_LIMIT_LONG].strip(),t[1].strip()][len(t[1])<VCARD_LIMIT_LONG]) for t in dd]))
else: msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),L('Not found!','%s/%s'%(jid,nick)))
elif args == 'all': msg = '%s\n%s' % (L('vCard:','%s/%s'%(jid,nick)),'\n'.join(['%s: %s' % ([L(t[0]),t[0].capitalize()][L(t[0])==t[0]],[u'%s…' % t[1][:VCARD_LIMIT_SHORT].strip(),t[1].strip()][len(t[1])<VCARD_LIMIT_SHORT]) for t in data]))
elif args == 'show':
dd = []
for t in data:
if t[0] not in dd: dd.append(t[0])
msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),', '.join([[t.capitalize(),'%s (%s)' % (t.capitalize(),L(t))][L(t)!=t] for t in dd]))
else:
args,dd = args.split('|'),[]
for t in args:
if ':' in t: val,loc = t.split(':',1)
else: val,loc = t,t.upper()
val = val.upper()
dv = get_array_from_array2(data,(val))
if dv: dd += [[loc,dv[0][1]]]
if dd: msg = '%s\n%s' % (L('vCard:','%s/%s'%(jid,nick)),'\n'.join(['%s: %s' % ([L(t[0]),t[0].capitalize()][L(t[0])==t[0]],[u'%s…' % t[1][:VCARD_LIMIT_LONG],t[1]][len(t[1])<VCARD_LIMIT_LONG]) for t in dd]))
else: msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),L('Not found!','%s/%s'%(jid,nick)))
else: msg = '%s %s' % (L('vCard:','%s/%s'%(jid,nick)),L('Empty!','%s/%s'%(jid,nick)))
send_msg(type, jid, nick, msg)
def iq_uptime(type, jid, nick, text):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_LAST},[])])
iq_request[iqid]=(time.time(),uptime_async,[type, jid, nick, text],xmpp.NS_LAST)
sender(i)
def uptime_async(type, jid, nick, text, is_answ):
isa = is_answ[1][0]
try:
msg = L('Uptime: %s','%s/%s'%(jid,nick)) % un_unix(int(get_tag_item(isa,'query','seconds')),'%s/%s'%(jid,nick))
up_stat = esc_min(get_tag(isa,'query'))
if len(up_stat): msg = '%s // %s' % (msg,up_stat)
except: msg = L('I can\'t do it','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def urn_ping(type, jid, nick, text):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('ping', {'xmlns': xmpp.NS_URN_PING},[])])
iq_request[iqid]=(time.time(),ping_async,[type, jid, nick, text],xmpp.NS_URN_PING)
sender(i)
def ping(type, jid, nick, text):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_VERSION},[])])
iq_request[iqid]=(time.time(),ping_async,[type, jid, nick, text],xmpp.NS_VERSION)
sender(i)
def ping_async(type, jid, nick, text, is_answ):
global iq_ping_minimal
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error' and isa[0] == 'remote-server-not-found': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
p_digits = GT('ping_digits')
original_ping = float(is_answ[0])
if iq_ping_minimal > original_ping: iq_ping_minimal = original_ping
fixed_ping = round(original_ping - iq_ping_minimal,p_digits)
if fixed_ping <= 0: fixed_ping = original_ping
f = '%'+'.0%sf' % p_digits
if text in ['',nick]: msg = L('Ping from you %s sec.','%s/%s'%(jid,nick)) % f % fixed_ping
else: msg = L('Ping from %s %s sec.','%s/%s'%(jid,nick)) % (text, f % fixed_ping)
send_msg(type, jid, nick, msg)
def iq_time(type, jid, nick, text):
iq_time_get(type, jid, nick, text, None)
def iq_time_raw(type, jid, nick, text):
iq_time_get(type, jid, nick, text, True)
def iq_time_get(type, jid, nick, text, mode):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_TIME},[])])
iq_request[iqid]=(time.time(),time_async,[type, jid, nick, text, mode],xmpp.NS_TIME)
sender(i)
def time_async(type, jid, nick, text, mode, is_answ):
isa = is_answ[1]
if len(isa) == 3:
msg = isa[0]
if mode: msg += ', Raw time: %s, TimeZone: %s' % (isa[1],isa[2])
else: msg = ' '.join(isa)
send_msg(type, jid, nick, msg)
def iq_utime(type, jid, nick, text):
iq_utime_get(type, jid, nick, text, None)
def iq_utime_raw(type, jid, nick, text):
iq_utime_get(type, jid, nick, text, True)
def iq_utime_get(type, jid, nick, text, mode):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('time', {'xmlns': xmpp.NS_URN_TIME},[])])
iq_request[iqid]=(time.time(),utime_async,[type, jid, nick, text, mode],xmpp.NS_URN_TIME)
sender(i)
def utime_async(type, jid, nick, text, mode, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
try:
ttup = isa[0].replace('T','-').replace('Z','').replace(':','-').split('-')+['0','0',str(tuple(time.localtime())[8])]
lt = time.localtime(time.mktime([int(tmp.split('.',1)[0]) for tmp in ttup])+(int(isa[1].split(':')[0])*60+int(isa[1].split(':')[1]))*60)
timeofset = float(isa[1].replace(':','.'))
if timeofset < 0: t_gmt = 'GMT%s' % int(timeofset)
else: t_gmt = 'GMT+%s' % int(timeofset)
if timeofset%1: t_gmt += ':%02d' % int((timeofset%1*60/100) * 100)
msg = '%02d:%02d:%02d, %02d.%s\'%s, %s, %s' % (lt[3],lt[4],lt[5],lt[2],L(wmonth[lt[1]-1],'%s/%s'%(jid,nick)),lt[0],L(wday[lt[6]],'%s/%s'%(jid,nick)),t_gmt)
if mode: msg = '%s | %s %s' % (msg,isa[0],isa[1])
except: msg = '%s %s' % (L('Unknown server answer!','%s/%s'%(jid,nick)),isa[0])
send_msg(type, jid, nick, msg)
def iq_version(type, jid, nick, text): iq_version_raw(type, jid, nick, text, False)
def iq_version_caps(type, jid, nick, text): iq_version_raw(type, jid, nick, text, True)
def iq_version_raw(type, jid, nick, text, with_caps):
global iq_request
who,iqid = get_who_iq(text,jid,nick),get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_VERSION},[])])
iq_request[iqid]=(time.time(),version_async,[type, jid, nick, text, with_caps],xmpp.NS_VERSION)
sender(i)
def version_async(type, jid, nick, text, with_caps, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else: msg = isa[0]
if with_caps:
caps = get_caps(jid,[text,nick][text == ''])
if caps: msg += ' || %s' % caps
send_msg(type, jid, nick, msg)
def iq_stats(type, jid, nick, text):
global iq_request
if text == '':
send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
return
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':text}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_STATS},[])])
iq_request[iqid]=(time.time(),stats_async_features,[type, jid, nick, text],xmpp.NS_STATS)
sender(i)
def stats_async_features(type, jid, nick, text, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error':
msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
else:
try: stats_list = [t.getAttr('name') for t in isa[1].getTag('query',namespace=xmpp.NS_STATS).getTags('stat')]
except: stats_list = []
if stats_list:
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':text}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_STATS},[xmpp.Node('stat', {'name':t},[]) for t in stats_list])])
iq_request[iqid]=(time.time(),stats_async,[type, jid, nick, text],xmpp.NS_STATS)
sender(i)
else: send_msg(type, jid, nick, L('Unavailable!','%s/%s'%(jid,nick)))
def stats_async(type, jid, nick, text, is_answ):
isa = is_answ[1]
if len(isa) >= 2 and isa[1] == 'error': msg = L('Error! %s','%s/%s'%(jid,nick)) % L(isa[0].capitalize().replace('-',' '),'%s/%s'%(jid,nick))
else:
try: stats_list = [[L(t.getAttr('name')),L(t.getAttr('value')),L(t.getAttr('units'))] for t in isa[1].getTag('query',namespace=xmpp.NS_STATS).getTags('stat')]
except: stats_list = []
if stats_list:
stats_list = ['%s: %s' % (t[0].capitalize(),t[1]) if t[2] in t[0] else '%s: %s %s' % (t[0].capitalize(),t[1],t[2]) for t in stats_list]
msg = L('Server statistic: %s\n%s','%s/%s'%(jid,nick)) % (text,'\n'.join(stats_list))
else: msg = L('Unavailable!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute, iq_hook
iq_hook = [[50,'get',iq_iq_get]]
execute = [(3, 'ver', iq_version, 2, 'Client version.', ['nick','jid','server']),
(3, 'ver+', iq_version_caps, 2, 'Client version with caps.', ['nick']),
(3, 'caps', noiq_caps, 2, 'Show caps node and version of client.', ['nick']),
(3, 'ping_old', ping, 2, 'Ping - reply time. You can ping nick in room, jid, server or transport.', ['nick','jid','server']),
(3, 'ping', urn_ping, 2, 'Ping - reply time. You can ping nick in room, jid, server or transport.', ['nick','jid','server']),
(3, 'time_old', iq_time, 2, 'Client side time.', ['nick','jid']),
(3, 'time', iq_utime, 2, 'Client side time.', ['nick','jid']),
(3, 'time_old_raw', iq_time_raw, 2, 'Client side time + raw time format.', ['nick','jid']),
(3, 'time_raw', iq_utime_raw, 2, 'Client side time + raw time format.', ['nick','jid']),
(3, 'stats', iq_stats, 2, 'Users server statistic.', ['nick','jid','server']),
(3, 'vcard_raw', iq_vcard, 2, 'vCard query. Recomends make command base alias for query needs info.\nvcard_raw [nick] - query generic info\nvcard_raw nick\nshow - show available fields\nvcard_raw nick\n[field:name|field:name] - show requested fields from vcard.', ['nick','jid','server']),
(3, 'uptime', iq_uptime, 2, 'Server or jid uptime.', ['nick','jid','server'])]

208
plugins/issue.py Normal file
View File

@@ -0,0 +1,208 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# id, room, jid, nick, level, tags, body, status, date, comment, accept_by, accept_date
# translate: new,pending,accepted,rejected,removed,done,Pending by,Accepted by,Rejected by,Removed by,Mark as done by
issue_status = ['new','pending','accepted','rejected','removed','done']
issue_status_show = ['','Pending by','Accepted by','Rejected by','Removed by','Mark as done by']
issue_new_id = 0
issue_pending_id = 1
issue_accept_id = 2
issue_reject_id = 3
issue_remove_id = 4
issue_done_id = 5
issue_number_format = '#%04d'
def issue(type, room, nick, text):
ttext = reduce_spaces_all(text)
subc = ttext.split()
acclvl,jid = get_level(room,nick)
if ttext.isdigit() or (ttext and ttext[0] == '#' and ttext[1:].isdigit()) or not subc or len(subc) == 1 or subc[0] == 'show' or (acclvl <= 3 and type == 'chat'): msg,type = issue_show(subc,room,type,nick)
elif subc[0] in ['del','delete','rm','remove']: msg = issue_remove(subc,acclvl,room,jid,nick)
elif subc[0] == 'pending': msg = issue_pending(subc,acclvl,room,jid,nick)
elif subc[0] == 'accept': msg = issue_accept(subc,acclvl,room,jid,nick)
elif subc[0] == 'reject': msg = issue_reject(subc,acclvl,room,jid,nick)
elif subc[0] == 'done': msg = issue_done(subc,acclvl,room,jid,nick)
else: msg = issue_new(subc,acclvl,room,jid,nick,text)
send_msg(type, room, nick, msg)
def issue_new(s,acclvl,room,jid,nick,text):
tags = []
for t in s:
if t[0] == '*' and len(t) > 1:
tags.append(t[1:])
text = text.replace(t,'',1)
else: break
s = s[len(tags):]
if not s: return L('No issue\'s body!','%s/%s'%(room,nick))
tags = ' '.join(tags)
body = text.strip()
try: id = cur_execute_fetchone('select count(*) from issues where room=%s',(room,))[0] + 1
except: id = 1
tbody = cur_execute_fetchall('select id from issues where room=%s and body ilike %s',(room,'%%%s%%' % body))
if tbody: return L('I know same issue(s): %s','%s/%s'%(room,nick)) % ', '.join(issue_number_format % t for t in zip(*tbody)[0])
stts = cur_execute('insert into issues values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)', (id, room, getRoom(jid), nick, acclvl, tags, body, issue_new_id, int(time.time()),'','',0))
if stts == True: return L('Added issue %s','%s/%s'%(room,nick)) % issue_number_format % id
else: return str(stts)
def issue_show(s,room,type,nick):
if len(s) > 1 and s[0] == 'show': s = s[1]
elif len(s) == 1 and s[0] == 'show': s = '%'
elif s: s = s[0]
else: s = '%'
if s.isdigit() or (s[0] == '#' and s[1:].isdigit()): s = s.replace('#','')
s_original = s
if s.isdigit(): iss = cur_execute_fetchall('select id,nick,tags,body,status,comment,accept_by,accept_date from issues where room=%s and id=%s order by id;',(room,int(s)))
elif s[0] == '*': iss = cur_execute_fetchall('select id,nick,tags,body,status,comment,accept_by,accept_date from issues where room=%s and tags ilike %s and status<%s order by id;',(room,'%%%s%%' % s[1:],issue_reject_id))
else:
if s != '%': s = '%%%s%%' % s
iss = cur_execute_fetchall('select id,nick,tags,body,status,comment,accept_by,accept_date from issues where room=%s and (tags ilike %s or body ilike %s or comment ilike %s or nick ilike %s) and status<%s order by id;',(room,s,s,s,s,issue_reject_id))
if iss:
tm = []
if len(iss) > 1 and type == 'groupchat':
send_msg(type, room, nick, L('Sent in private message','%s/%s'%(room,nick)))
type = 'chat'
for t in iss:
if t[2]: tmp = '%s (%s) *%s | %s\n%s' % (issue_number_format % t[0],L(issue_status[t[4]],'%s/%s'%(room,nick)),' *'.join(t[2].split()),L('Created by %s','%s/%s'%(room,nick)) % t[1],t[3])
else: tmp = '%s (%s) %s\n%s' % (issue_number_format % t[0],L(issue_status[t[4]],'%s/%s'%(room,nick)),L('Created by %s','%s/%s'%(room,nick)) % t[1],t[3])
if t[4]:
tmp = '%s\n%s %s [%s]' % (tmp,L(issue_status_show[t[4]],'%s/%s'%(room,nick)),t[6],disp_time(t[7],'%s/%s'%(room,nick)))
if t[5]: tmp += L(', by reason: %s','%s/%s'%(room,nick)) % t[5]
tm.append(tmp)
return L('Issue(s) list:\n%s','%s/%s'%(room,nick)) % '\n\n'.join(tm), type
elif s_original == '%': return L('Issues not found!','%s/%s'%(room,nick)), type
else: return L('Issues with match \'%s\' not found!','%s/%s'%(room,nick)) % s_original, type
def issue_remove(s,acclvl,room,jid,nick):
if len(s) > 1: id = s[1]
else: return L('Which issue need remove?','%s/%s'%(room,nick))
if id.isdigit() or id[0] == '#':
try: id = int(id.replace('#',''))
except: return L('You must use numeric issue id.','%s/%s'%(room,nick))
iss = cur_execute_fetchall('select jid,level,status from issues where room=%s and id=%s;',(room,id))
else: return L('You must use numeric issue id.','%s/%s'%(room,nick))
if iss:
if iss[0][2] != issue_remove_id:
if acclvl >= 7 or iss[0][0] == jid:
if len(s) > 2: cmt = ' '.join(s[2:])
else: cmt = ''
cur_execute('update issues set status=%s,accept_by=%s,accept_date=%s,comment=%s where room=%s and id=%s', (issue_remove_id,nick,int(time.time()),cmt,room,id))
return L('Issue %s removed!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('There is not Your issue or You have no rights to remove it.','%s/%s'%(room,nick))
else: return L('Issue %s was removed earlier!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('Issue %s not found!','%s/%s'%(room,nick)) % issue_number_format % id
def issue_accept(s,acclvl,room,jid,nick):
if len(s) > 1: id = s[1]
else: return L('Which issue need accept?','%s/%s'%(room,nick))
if id.isdigit() or id[0] == '#':
try: id = int(id.replace('#',''))
except: return L('You must use numeric issue id.','%s/%s'%(room,nick))
iss = cur_execute_fetchall('select jid,level,status,tags from issues where room=%s and id=%s;',(room,id))
else: return L('You must use numeric issue id.','%s/%s'%(room,nick))
if iss:
if acclvl >= 7 or iss[0][0] == jid or iss[0][1] <= acclvl:
if len(s) > 2:
tags = iss[0][3].split()
cnt = 2
for t in s[2:]:
if t[0] == '*' and len(t) > 1:
if t[1:] not in tags: tags.append(t[1:])
else: tags.remove(t[1:])
cnt += 1
else: break
s = s[cnt:]
tags = ' '.join(tags)
cmt = ' '.join(s)
else: cmt,tags = '',iss[0][3]
cur_execute('update issues set status=%s,accept_by=%s,accept_date=%s,comment=%s,tags=%s where room=%s and id=%s', (issue_accept_id,nick,int(time.time()),cmt,tags,room,id))
if iss[0][2] != issue_accept_id: return L('Issue %s accepted!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('Issue %s was accepted earlier!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('There is not Your issue or You have no rights to accept it.','%s/%s'%(room,nick))
else: return L('Issue %s not found!','%s/%s'%(room,nick)) % issue_number_format % id
def issue_reject(s,acclvl,room,jid,nick):
if len(s) > 1: id = s[1]
else: return L('Which issue need reject?','%s/%s'%(room,nick))
if id.isdigit() or id[0] == '#':
try: id = int(id.replace('#',''))
except: return L('You must use numeric issue id.','%s/%s'%(room,nick))
iss = cur_execute_fetchall('select jid,level,status from issues where room=%s and id=%s;',(room,id))
else: return L('You must use numeric issue id.','%s/%s'%(room,nick))
if iss:
if iss[0][2] != issue_reject_id:
if acclvl >= 7 or iss[0][0] == jid or iss[0][1] <= acclvl:
if len(s) > 2: cmt = ' '.join(s[2:])
else: cmt = ''
cur_execute('update issues set status=%s,accept_by=%s,accept_date=%s,comment=%s where room=%s and id=%s', (issue_reject_id,nick,int(time.time()),cmt,room,id))
return L('Issue %s rejected!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('There is not Your issue or You have no rights to reject it.','%s/%s'%(room,nick))
else: return L('Issue %s was rejected earlier!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('Issue %s not found!','%s/%s'%(room,nick)) % issue_number_format % id
def issue_pending(s,acclvl,room,jid,nick):
if len(s) > 1: id = s[1]
else: return L('Which issue is pending?','%s/%s'%(room,nick))
if id.isdigit() or id[0] == '#':
try: id = int(id.replace('#',''))
except: return L('You must use numeric issue id.','%s/%s'%(room,nick))
iss = cur_execute_fetchall('select jid,level,status from issues where room=%s and id=%s;',(room,id))
else: return L('You must use numeric issue id.','%s/%s'%(room,nick))
if iss:
if iss[0][2] != issue_reject_id:
if acclvl >= 7 or iss[0][0] == jid or iss[0][1] <= acclvl:
if len(s) > 2: cmt = ' '.join(s[2:])
else: cmt = ''
cur_execute('update issues set status=%s,accept_by=%s,accept_date=%s,comment=%s where room=%s and id=%s', (issue_pending_id,nick,int(time.time()),cmt,room,id))
return L('Issue %s is mark as pending!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('There is not Your issue or You have no rights to mark as pending.','%s/%s'%(room,nick))
else: return L('Issue %s was marked as pending earlier!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('Issue %s not found!','%s/%s'%(room,nick)) % issue_number_format % id
def issue_done(s,acclvl,room,jid,nick):
if len(s) > 1: id = s[1]
else: return L('Which issue is done?','%s/%s'%(room,nick))
if id.isdigit() or id[0] == '#':
try: id = int(id.replace('#',''))
except: return L('You must use numeric issue id.','%s/%s'%(room,nick))
iss = cur_execute_fetchall('select jid,level,status from issues where room=%s and id=%s;',(room,id))
else: return L('You must use numeric issue id.','%s/%s'%(room,nick))
if iss:
if iss[0][2] != issue_reject_id:
if acclvl >= 7 or iss[0][0] == jid or iss[0][1] <= acclvl:
if len(s) > 2: cmt = ' '.join(s[2:])
else: cmt = ''
cur_execute('update issues set status=%s,accept_by=%s,accept_date=%s,comment=%s where room=%s and id=%s', (issue_done_id,nick,int(time.time()),cmt,room,id))
return L('Issue %s marked as done!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('There is not Your issue or You have no rights to mark as done.','%s/%s'%(room,nick))
else: return L('Issue %s was marked as done earlier!','%s/%s'%(room,nick)) % issue_number_format % id
else: return L('Issue %s not found!','%s/%s'%(room,nick)) % issue_number_format % id
global execute
execute = [(3, 'issue', issue, 2, 'Issues\nissue [[[show|pending|accept|reject|delete|done] id] reason] - actions with issue\nissue *tag1 *tag2 some text - add issue `some text` with tags tag1 and tag2')]

64
plugins/istrue.py Normal file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def is_valid(type, jid, nick, text):
if text == '': text = nick
ru_lit, en_lit, caps_lit = 0, 0, 0
for tmp in text:
if re.match('[a-z]|[A-Z]',tmp): en_lit+=1
elif re.match(u'[а-яё]|[А-ЯЁ]',tmp): ru_lit+=1
if re.match(u'[A-Z]|[А-ЯЁ]',tmp): caps_lit+=1
lt = len(text)
if ru_lit<en_lit: idx, hl = float(ru_lit)/en_lit, 1
elif ru_lit>en_lit: idx, hl = float(en_lit)/ru_lit, 2
else: idx, hl = 0.5, None
if (ru_lit == lt or en_lit == lt) and float(caps_lit)/lt <= 0.5: msg = L('100% True-nick!','%s/%s'%(jid,nick))
elif ru_lit+en_lit == 0: msg = L('Nicks without letters isn\'t true!','%s/%s'%(jid,nick))
elif ru_lit+en_lit+text.count(' ')+text.count('.') == lt: msg = L('Valid of nick is - %s%s','%s/%s'%(jid,nick)) % (100-int(idx*100), '%!')
elif not ru_lit or not en_lit: msg = L('Normal nick, but left symbols in fireplace.','%s/%s'%(jid,nick))
else: msg = L('Valid of nick is - %s%s','%s/%s'%(jid,nick)) % (int(float(ru_lit+en_lit)/lt*100-int(idx*100)), '%!')
if float(caps_lit)/lt > 0.5: msg += ' ' + L('Many caps - %s%s','%s/%s'%(jid,nick)) % (int(float(caps_lit)/lt*100), '%!')
if ru_lit+en_lit:
msg += ' ' + L('Dominate letters:','%s/%s'%(jid,nick)) + ' '
if hl == 1: msg += L('Latin','%s/%s'%(jid,nick))
elif hl == 2: msg += L('Cyrillic','%s/%s'%(jid,nick))
else: msg += L('Equally','%s/%s'%(jid,nick))
def repl(t): return '[%s]' % t.group()
msg += ' - %s' % re.sub([u'([а-яё]+)','([a-z]+)'][hl==1],repl,text,flags=re.S|re.I|re.U)
send_msg(type, jid, nick, msg)
def is_true(type, jid, nick, text):
if text == '': msg = L('And?','%s/%s'%(jid,nick))
else:
idx = 0
for tmp in text: idx += ord(tmp)
msg = L('Expression is true for %s%s','%s/%s'%(jid,nick)) % (idx % 100, '%')
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'true', is_true, 2, 'Check truth of expession.'),
(3, 'valid', is_valid, 2, 'Check different languages symbols in nick.')]

35
plugins/jc.py Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def jc(type, jid, nick, text):
if not len(text): text = getName(jid)
try:
body = json.loads(html_encode(load_page('http://jc.jabber.ru/search.html?%s'.encode("utf-8") % (urllib.urlencode({'json':'1', 'search':text.encode("utf-8")})))))
if body['result']: msg = L('Found:','%s/%s'%(jid,nick)) + ''.join(['\n%s. %s [%s] %s' % ([t['raiting'],'-'][t['raiting']==''],t['description'],t['jid'],t['current']) for t in body['result']])
else: msg = L('Not found.','%s/%s'%(jid,nick))
except: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'jc', jc, 2, 'Show information about conference from jc.jabber.ru.\njc [address]')]

121
plugins/jidcatcher.py Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
JIDCATCHER_DEFAULT_LIMIT = 10
def info_search(type, jid, nick, text):
msg = L('What I must find?','%s/%s'%(jid,nick))
if text:
if '\n' in text:
text,lim = text.split('\n',1)
try:
lim = int(lim)
if lim < 100 or lim > 1: raise
except: lim = JIDCATCHER_DEFAULT_LIMIT
else: lim = JIDCATCHER_DEFAULT_LIMIT
cur_execute('delete from jid where server ilike %s',('<temporary>%',))
ttext = '%%%s%%' % text
tma = cur_execute_fetchall('select * from jid where login ilike %s or server ilike %s or resourse ilike %s order by login limit %s',(ttext,ttext,ttext,lim))
if tma: msg = '%s\n%s' % (L('Found:','%s/%s'%(jid,nick)),'\n'.join(['%s. %s@%s/%s' % tuple([tma.index(tt)+1]+list(tt)) for tt in tma]))
else: msg = L('\'%s\' not found!','%s/%s'%(jid,nick)) % text
send_msg(type, jid, nick, msg)
def info_res(type, jid, nick, text):
cur_execute('delete from jid where server ilike %s',('<temporary>%',))
if text.lower() == 'count':
tlen = cur_execute_fetchall('select count(*) from (select resourse,count(*) from jid group by resourse) tmp;')[0][0]
text,jidbase = '',''
else:
text1 = '%%%s%%' % text
tlen = cur_execute_fetchall('select count(*) from (select resourse,count(*) from jid where resourse ilike %s group by resourse) tmp;',(text1,))[0][0]
jidbase = cur_execute_fetchall('select resourse,count(*) from jid where resourse ilike %s group by resourse order by -count(*),resourse limit %s',(text1,JIDCATCHER_DEFAULT_LIMIT))
if not tlen: msg = L('\'%s\' not found!','%s/%s'%(jid,nick)) % text
else:
if text: msg = L('Found resources: %s','%s/%s'%(jid,nick)) % tlen
else: msg = L('Total resources: %s','%s/%s'%(jid,nick)) % tlen
if jidbase: msg += '\n%s' % '\n'.join(['%s. %s\t%s' % tuple([jidbase.index(jj)+1]+list(jj)) for jj in jidbase])
send_msg(type, jid, nick, msg)
def info_serv(type, jid, nick, text):
cur_execute('delete from jid where server ilike %s',('<temporary>%',))
if '\n' in text:
text,lim = text.split('\n',1)
try:
lim = int(lim)
if lim > 100 or lim < 1: raise
except: lim = JIDCATCHER_DEFAULT_LIMIT
else: lim = JIDCATCHER_DEFAULT_LIMIT
if text == 'count':
tlen = cur_execute_fetchone('select count(*) from (select server,count(*) from jid group by server) tmp;')[0]
text,jidbase = '',''
else:
text1 = '%%%s%%' % text
if base_type == 'pgsql': reqv = 'select * from (select row_number() over(order by -count(*)),server,count(*) from jid group by server order by -count(*),server) tmp where tmp.server ilike %s order by tmp.row_number;'
elif base_type == 'mysql': reqv = 'select * from (select @i:=@i+1 as itr,sr,cn from (select server as sr,count(*) as cn from jid group by server order by -count(*)) as t1,(select @i:=0) as t2) as t3 where sr like %s'
elif base_type == 'sqlite3':
# TODO: It's works not properly. Need fix record's numbers!
reqv = 'select row_number(),sr,cn from (select server as sr,count(*) as cn from jid group by server order by -cn) where sr like %s order by -cn'
jidbase = cur_execute_fetchall(reqv,(text1,))
tlen = len(jidbase)
jidbase = jidbase[:lim]
if not tlen: msg = L('\'%s\' not found!','%s/%s'%(jid,nick)) % text
else:
if text: msg = L('Found servers: %s','%s/%s'%(jid,nick)) % tlen
else: msg = L('Total servers: %s','%s/%s'%(jid,nick)) % tlen
if jidbase: msg = '%s\n%s' %(msg,'\n'.join(['%s. %s [%s]' % (int(jj[0]),jj[1],jj[2]) for jj in jidbase]))
send_msg(type, jid, nick, msg)
#room number date
def info_top(type, jid, nick, text):
if text: room = text
else: room = getRoom(jid)
cnf = cur_execute_fetchone('select count ,time from top where room=%s',(room,))
if cnf: msg = L('Max count of members: %s %s','%s/%s'%(jid,nick)) % (cnf[0], '(%s)' % disp_time(cnf[1],'%s/%s'%(jid,nick)))
else: msg = L('Statistic not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def jidcatcher_presence(room,jid,nick,type,text):
if jid != 'None' and not jid.startswith('<temporary>'):
tmp = (getName(jid),getServer(jid),getResourse(jid))
try:
tmpp = cur_execute_fetchone('select login from jid where login=%s and server=%s and resourse=%s',tmp)
if not tmpp: cur_execute('insert into jid values (%s,%s,%s)', tmp)
except: pass
cnt = len(['' for t in megabase if t[0]==room])
cnf = cur_execute_fetchone('select count from top where room=%s',(room,))
if cnf:
if cnt > cnf[0]: cur_execute('update top set count =%s, time=%s where room=%s;',(cnt,int(time.time()),room))
else: cur_execute('insert into top values (%s,%s,%s);',(room,cnt,int(time.time())))
global execute, presence_control
presence_control = [jidcatcher_presence]
execute = [(4, 'res', info_res, 2, 'Without parameters show top10 resources for all conferences, where bot is present.\nwith parameters - search in resources base\ncount - number of results.'),
(6, 'serv', info_serv, 2, 'Wihtout parameters show all servers freom where joined in rooms, where bot is present\nwith parameters - search on servers base\ncount - show number of results.'),
(9, 'search', info_search, 2, 'Search in internal jids base.'),
(2, 'top', info_top, 2, 'Conference\'s activity.')]

165
plugins/juick.py Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
JUICK_JID = 'juick@juick.com'
# Список последних сообщений:
JUICK_MESSAGES = 'http://api.juick.com/messages'
JUICK_MESSAGES_REQUEST = '%s?' % JUICK_MESSAGES
# Поиск по сообщениям: search=<запрос>
# Фильтрация по тегу: tag=<тег>
# Фильтрация по типу контента: media=all | media=photo | media=video
# Последние сообщения пользователя: user_id=<uid> | user_id=<uid>&tag=<тег>
# Для списков сообщений выводится одна «страница». Для вывода дополнительных «страниц»: параметры before_mid, page
# before_mid=<id последнего загруженного сообщения>&page=<page>
# Просмотр сообщения с комментариями
JUICK_THREAD = 'http://api.juick.com/thread?' # mid=<message ID>
# Получение UserID по нику:
JUICK_USERS = 'http://api.juick.com/users?' # uname=ugnich
# Популярные теги:
JUICK_TAGS = 'http://api.juick.com/tags'
# Все теги пользователя:
JUICK_TAGS_USER = '%s?' % JUICK_TAGS # user_id=<uid>
JUICK_URL = 'http://juick.com/%s'
def juick(type, jid, nick, text):
text = text.strip()
topt = text.split(' ',1)
topt[0] = topt[0].lower()
try: prm = topt[1].strip()
except: prm = ''
if topt[0] == 'msg' and prm: juick_msg(type, jid, nick, prm)
elif topt[0] == 'tags': juick_tags(type, jid, nick, prm)
elif topt[0] == 'search': juick_search(type, jid, nick, prm)
elif topt[0] == 'user': juick_user(type, jid, nick, prm)
else:
try: tmpt = re.findall('(^[^@]#?[0-9]+)',text)[0]
except: tmpt = ''
if tmpt: juick_msg(type, jid, nick, text)
elif text and text[0] == '@': juick_user(type, jid, nick, text)
else: send_msg(type, jid, nick, L('Smoke help about command!','%s/%s'%(jid,nick)))
def juick_user(type, jid, nick, text):
if text and text[0] == '@': text = text[1:]
try: result = json.loads(html_encode(load_page(JUICK_MESSAGES_REQUEST, {'user_id':str(json.loads(html_encode(load_page(JUICK_USERS, {'uname': text})).replace('\t',' '*8))[0]['uid'])})).replace('\t',' '*8))
except:
send_msg(type, jid, nick, L('User @%s not found!','%s/%s'%(jid,nick)) % text)
return
tp = []
for t in result[:GT('juick_user_post_limit')]:
tm = '#%s' % t['mid']
if t.has_key('tags'): tm = '%s *%s' % (tm, ' *'.join(t['tags']))
tm = '%s | %s' % (tm,replacer(t['body'][:GT('juick_user_post_size')].replace('\n',' \\ ')+['',u'…'][len(t['body']) > GT('juick_user_post_size')]))
if t.has_key('replies'): tm = '%s %s' % (tm, L('Replies: %s','%s/%s'%(jid,nick)) % t['replies'])
tp.append(tm)
msg = L('Found: %s','%s/%s'%(jid,nick)) % '%s\n%s' % (text,'\n'.join(tp))
send_msg(type, jid, nick, msg)
def juick_search(type, jid, nick, text):
result = json.loads(html_encode(load_page(JUICK_MESSAGES_REQUEST, {'search': text})).replace('\t',' '*8))
tp = []
for t in result[:GT('juick_user_post_limit')]:
tm = '#%s @%s: %s' % (t['mid'],replacer(t['user']['uname']),replacer(t['body'][:GT('juick_user_post_size')].replace('\n',' \\ ')+['',u'…'][len(t['body']) > GT('juick_user_post_size')]))
if t.has_key('replies'): tm = '%s | %s' % (tm, L('Replies: %s','%s/%s'%(jid,nick)) % t['replies'])
if t.has_key('tags'): tm = '%s | *%s' % (tm, ' *'.join(t['tags']))
tp.append(tm)
msg = L('Found: %s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join(tp)
send_msg(type, jid, nick, msg)
def juick_tags(type, jid, nick, text):
if text and text[0] == '@': text = text[1:]
try:
if text: hdr,url,params = L('Popular tags of @%s:','%s/%s'%(jid,nick)) % text,JUICK_TAGS_USER,{'user_id':str(json.loads(html_encode(load_page(JUICK_USERS, {'uname': text})).replace('\t',' '*8))[0]['uid'])}
else: hdr,url,params = L('Popular tags:','%s/%s'%(jid,nick)),JUICK_TAGS,{}
result = json.loads(html_encode(load_page(url,params)).replace('\t',' '*8))
tags = [((t['messages'],replacer(t['tag']))) for t in result]
tags.sort(reverse=True)
msg = '%s %s' % (hdr,', '.join(['%s [%s]' % (t[1],t[0]) for t in tags[:GT('juick_user_tags_limit')]]))
except:
if text: msg = L('User @%s not found!','%s/%s'%(jid,nick)) % text
else: msg = L('Unknown error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def juick_msg(type, jid, nick, text):
j_mid,j_rid = re.findall('#?([0-9]+)\/?([0-9]+)?',text)[0]
if j_rid:
try: j_rid = int(j_rid)
except: j_rid = 0
else: j_rid = 0
try: j_replies = int(text.split()[1])
except: j_replies = GT('juick_msg_answers_default')
try: result = json.loads(html_encode(load_page(JUICK_THREAD, {'mid': j_mid})).replace('\t',' '*8))
except:
send_msg(type, jid, nick, L('Message #%s is not found!','%s/%s'%(jid,nick)) % j_mid)
return
if j_rid:
found = False
for t in result:
if t.has_key('rid') and t['rid'] == j_rid:
result,found = t,True
break
if not found:
send_msg(type, jid, nick, L('Message #%s is not found!','%s/%s'%(jid,nick)) % '%s/%s' % (j_mid,j_rid))
return
else: result=result[0]
uname = replacer(result['user']['uname'])
try: tags = '*%s' % ' *'.join([replacer(t) for t in result['tags']])
except: tags = ''
body = replacer(result['body'])
timestamp = result['timestamp']
mid = str(result['mid'])
try: replies = L('Replies: %s','%s/%s'%(jid,nick)) % result['replies']
except: replies = 0
if result.has_key('video'):
media = result['video']
media = L('Attach: %s','%s/%s'%(jid,nick)) % media[media.keys()[0]]
elif result.has_key('photo'): media = L('Attach: %s','%s/%s'%(jid,nick)) % result['photo']['medium']
else: media = ''
try: replyto = result['replyto']
except: replyto = ''
try: mid2 = '%s#%s' % (mid,result['rid'])
except: mid2 = mid
if replyto:
if replies: msg = '@%s: %s\n%s\n#%s -> #%s/%s, %s, %s, %s' % (uname,tags,body,mid2.replace('#','/'),mid,replyto,timestamp,replies,JUICK_URL % mid2)
else: msg = '@%s: %s\n%s\n#%s -> #%s/%s, %s, %s' % (uname,tags,body,mid2.replace('#','/'),mid,replyto,timestamp,JUICK_URL % mid2)
else:
if replies: msg = '@%s: %s\n%s\n#%s, %s, %s, %s' % (uname,tags,body,mid2.replace('#','/'),timestamp,replies,JUICK_URL % mid2)
else: msg = '@%s: %s\n%s\n#%s, %s, %s' % (uname,tags,body,mid2.replace('#','/'),timestamp,JUICK_URL % mid2)
if media: msg = '%s\n%s' % (msg,media)
send_msg(type, jid, nick, msg)
def juick_post(type, jid, nick, text):
send_msg('chat', JUICK_JID, '', text)
time.sleep(1.2)
send_msg(type, jid, nick, L('Message posted to Juick.','%s/%s'%(jid,nick)))
global execute
execute = [(3, 'juick', juick, 2, 'Miniblogs http://juick.com\njuick [msg][#]post - show post\njuick tags [user] - show popular tags\njuick search [text] - search text\njuick [user] @username - show messages of user'),
(9, 'juick_post', juick_post, 2, 'Send message to blog at juick.com')]

271
plugins/karma.py Normal file
View File

@@ -0,0 +1,271 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
last_karma = {}
def karma(type, jid, nick, text):
arg = text.split(' ',1)
try: arg1 = arg[1]
except: arg1 = None
a0l = arg[0].lower()
karma_comm = {'show': [karma_show, (jid, nick, arg1)],
'top+': [karma_top, (jid, nick, arg1, None)],
'top-': [karma_top, (jid, nick, arg1, True)],
'set': [karma_set, (jid, nick, arg1)],
'clear': [karma_clear, (jid, nick, arg1)]}
if karma_comm.has_key(a0l): msg = karma_comm[a0l][0](*karma_comm[a0l][1])
else: msg = karma_show(jid, nick, text)
send_msg(type, jid, nick, msg)
def karma_top(jid, nick, text, order):
try: lim = int(text)
except: lim = GT('karma_show_default_limit')
if lim < 1: lim = 1
elif lim > GT('karma_show_max_limit'): lim = GT('karma_show_max_limit')
if order: stat = cur_execute_fetchall('select jid,karma from karma where room=%s order by karma',(jid,))
else: stat = cur_execute_fetchall('select jid,karma from karma where room=%s order by -karma',(jid,))
if stat == None: return L('In this room karma is not changed!','%s/%s'%(jid,nick))
msg, cnt = '', 1
for tmp in stat:
tmp2 = get_nick_by_jid(jid, tmp[0])
if tmp2:
msg += '\n%s. %s\t%s' % (cnt,tmp2,karma_val(int(tmp[1])))
cnt += 1
if cnt > lim: break
if len(msg): return L('Top karma: %s','%s/%s'%(jid,nick)) % msg
else: return L('Karma for members is present not changed!','%s/%s'%(jid,nick))
def karma_size_wrong(room):
k_size = int(config_prefs['karma_limit_size'][3])
put_config(jid,'karma_limit_size',k_size)
return k_size
def karma_get_limit(room,nick):
room = getRoom(room)
(acclvl, jid) = get_level(room,nick)
if acclvl >= 7: return -1,-1
k_log = cur_execute_fetchone('select log from karma_limits where room=%s and jid=%s',(room,getRoom(jid)))
k_size = get_config(room,'karma_limit_size')
if ''.join(re.findall('[-0-9, []]*', k_size)) != k_size: k_size = karma_size_wrong(room)
if len(json.loads(k_size)) != 2: k_size = karma_size_wrong(room)
k_size = json.loads(k_size)
k_limit = [k_size[0],k_size[1]][acclvl >= 4]
k_val = k_limit
if k_log:
k_log = json.loads(k_log[0])
for tmp in k_log:
if (time.time() - tmp) < 86400: k_val -= 1
k_log.sort()
else: k_log = [0]
return k_val, k_limit, k_log[0]
def karma_show(jid, nick, text):
if text == None or text == '' or text == nick: text, atext = nick, L('Your','%s/%s'%(jid,nick))
else: atext = text
karmajid = getRoom(get_level(jid,text)[1])
if karmajid == 'None': return L('I\'m not sure, but %s not is here.','%s/%s'%(jid,nick)) % atext
else:
lim_text = ''
if get_config(getRoom(jid),'karma_limit'):
k_val = karma_get_limit(jid,text)[0]
if k_val >= 0: lim_text = '. ' + L('Karma limit is %s','%s/%s'%(jid,nick)) % k_val
stat = cur_execute_fetchone('select karma from karma where room=%s and jid=%s',(jid,karmajid))
if stat == None: return L('%s have a clear karma','%s/%s'%(jid,nick)) % atext + lim_text
else: return L('%s karma is %s','%s/%s'%(jid,nick)) % (atext, karma_val(int(stat[0]))) + lim_text
def karma_set(jid, nick, text):
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(jid,'karma')): return
k_acc = get_level(jid,nick)[0]
try:
if '\n' in text: text,val = text.split('\n',1)
else: text,val = text.split(' ',1)
if k_acc >= 9:
val = int(val)
jid, karmajid = getRoom(jid), getRoom(get_level(jid,text)[1])
if karmajid == getRoom(selfjid): return
elif karmajid == 'None': return L('You can\'t change karma in outdoor conference!','%s/%s'%(jid,nick))
else:
cur_execute('delete from karma where room=%s and jid=%s',(jid,karmajid))
cur_execute('insert into karma values (%s,%s,%s)',(jid,karmajid,val))
val = karma_val(val)
return L('You changes %s\'s karma to %s','%s/%s'%(jid,nick)) % (text,val)
else: return L('You can\'t change karma!','%s/%s'%(jid,nick))
except: return L('incorrect digital parameter','%s/%s'%(jid,nick)).capitalize()
def karma_clear(jid, nick, text):
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(jid,'karma')): return
k_acc = get_level(jid,nick)[0]
if k_acc >= 9:
if '\n' in text: (param,text) = text.split('\n',1)
else: param = ''
jid, karmajid = getRoom(jid), getRoom(get_level(jid,text)[1])
if karmajid == getRoom(selfjid): return
elif karmajid == 'None': return L('You can\'t change karma in outdoor conference!','%s/%s'%(jid,nick))
else:
if param in ['','all','karma','limits']:
if param in ['','all','karma']: cur_execute('delete from karma where room=%s and jid=%s',(jid,karmajid))
if param in ['all','limits']: cur_execute('delete from karma_limits where room=%s and jid=%s',(jid,karmajid))
return L('You clear karma for %s','%s/%s'%(jid,nick)) % text
else: return L('Wrong arguments!','%s/%s'%(jid,nick))
else: return L('You can\'t change karma!','%s/%s'%(jid,nick))
def karma_get_access(room,jid):
stat = cur_execute_fetchone('select karma from karma where room=%s and jid=%s',(room,jid))
if stat == None: return None
if int(stat[0]) < GT('karma_limit'): return None
return True
def karma_val(val): return ['%+2d' % val,'0'][val==0]
def karma_correct(room):
def karma_correct_diff(vm,ac):
lim_up = [GT('karma_discret_lim_up')]
lim_dn = [GT('karma_discret_lim_dn')]
kd,rs = GT('karma_discret'),[]
def validate_mass(m):
for t in range(0,len(m)-1):
if abs(m[t]-m[t+1]) < kd or m[t] >= m[t+1]: return False
return True
def karma_blur_mass(vm):
vm = lim_dn + vm + lim_up
nm = []
for t in range(0,len(vm)-2): nm.append(int((vm[t]+vm[t+1]+vm[t+2])/3))
return nm
while not validate_mass(vm): vm = karma_blur_mass(vm)
for t in range(0,len(ac)): rs.append([vm[t],ac[t]])
return rs
tm,ac,vm,nm = config_group_karma[2],[],[],[]
for t in tm:
df = re.findall(r'karma_action_[0-9](.*)',t)
if df:
ac += df
tvm = get_config_int(room,t)
vm.append(tvm)
nm.append(t)
vm = karma_correct_diff(vm,ac)
for t in range(0,len(nm)): put_config(room,nm[t],str(vm[t][0]))
return vm
def karma_action_do(room,text,action):
nick = getResourse(cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%room,))[0])
action = action.replace('ban','outcast')
act = {'outcast':muc_affiliation,'none':muc_affiliation,'member':muc_affiliation,
'kick':muc_role,'participant':muc_role,'visitor':muc_role,'moderator':muc_role}
act[action]('chat',room,nick,'%s\n%s' % (text,get_config(room,'karma_action_reason')),action.replace('kick','none'),0)
def karma_change(room,jid,nick,type,text,value):
global last_karma
if type == 'chat': msg = L('You can\'t change karma in private!','%s/%s'%(room,nick))
else:
last_karma_text = last_karma.pop('%s/%s' % (room,jid), None)
if last_karma_text:
karma_text, karma_count = last_karma_text
last_karma['%s/%s' % (room,jid)] = (karma_text, karma_count + 1)
if karma_text == text and karma_count >= 2: return
else: last_karma['%s/%s' % (room,jid)] = (text, 1)
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(room,'karma')): return
if ': ' in text: (text,other) = text.split(': ',1)
elif ', ' in text: (text,other) = text.split(', ',1)
else: return
if len(other) > 2 and get_config(getRoom(room),'karma_hard'): return
k_acc = get_level(room,nick)[0]
if k_acc < 0: return
if k_acc >= 4 or karma_get_access(room,getRoom(jid)):
jid, karmajid = getRoom(jid), getRoom(get_level(room,text)[1])
if karmajid == getRoom(selfjid): return
elif karmajid == 'None': msg = L('You can\'t change karma in outdoor conference!','%s/%s'%(room,nick))
elif karmajid == jid: msg = L('You can\'t change own karma!','%s/%s'%(room,nick))
elif get_config(getRoom(jid),'karma_limit') and karma_get_limit(room,nick)[0] == 0: msg = L('Karma limit is %s','%s/%s'%(room,nick)) % L('over','%s/%s'%(room,nick)) + '. ' + L('Please wait: %s','%s/%s'%(room,nick)) % un_unix(int(86400-(time.time() - karma_get_limit(room,nick)[2])),'%s/%s'%(room,nick))
else:
stat = cur_execute_fetchone('select last from karma_commiters where room=%s and jid=%s and karmajid=%s',(room,jid,karmajid))
karma_valid, karma_time = None, int(time.time())
if stat == None: karma_valid = True
elif karma_time - int(stat[0]) >= GT('karma_timeout')[k_acc]: karma_valid = True
if karma_valid:
if k_acc < 7:
k_log = cur_execute_fetchone('select log from karma_limits where room=%s and jid=%s',(room,jid))
k_size = get_config(room,'karma_limit_size')
if ''.join(re.findall('[-0-9, []]*', k_size)) != k_size: k_size = karma_size_wrong(room)
if len(json.loads(k_size)) != 2: k_size = karma_size_wrong(room)
k_size = json.loads(k_size)
k_limit = [k_size[0],k_size[1]][k_acc >= 4]
k_val = k_limit
if k_log:
k_log = json.loads(k_log[0])
for tmp in k_log:
if time.time() - tmp < 86400: k_val -= 1
k_log = str([karma_time] + k_log[:k_limit-1])
cur_execute('update karma_limits set log=%s where room=%s and jid=%s',(k_log,room,jid))
else: cur_execute('insert into karma_limits values (%s,%s,%s)',(room,jid,'[%s]' % karma_time))
if stat: cur_execute('update karma_commiters set last=%s where room=%s and jid=%s and karmajid=%s',(karma_time,room,jid,karmajid))
else: cur_execute('insert into karma_commiters values (%s,%s,%s,%s)',(room,jid,karmajid,karma_time))
stat = cur_execute_fetchone('select karma from karma where room=%s and jid=%s',(room,karmajid))
if stat:
stat = stat[0]+value
cur_execute('delete from karma where room=%s and jid=%s',(room,karmajid))
else: stat = value
cur_execute('insert into karma values (%s,%s,%s)',(room,karmajid,stat))
msg = L('You changes %s\'s karma to %s. Next time to change across: %s','%s/%s'%(room,nick)) % (text,karma_val(stat),un_unix(GT('karma_timeout')[k_acc],'%s/%s'%(room,nick)))
pprint('karma change in %s for %s to %s' % (room,text,stat),'green')
am = None
if get_config(room,'karma_action'):
kmass = karma_correct(room)
for t in kmass:
if t[0] <= 0 and stat <= t[0]:
am = (room,text,t[1])
break
elif t[0] > 0 and stat >= t[0]: am = (room,text,t[1])
if am:
karma_action_do(*am)
pprint('karma action in %s for %s is %s' % am,'bright_green')
else: msg = L('Time from last change %s\'s karma is very small. Please wait %s','%s/%s'%(room,nick)) % (text,un_unix(int(stat[0])+GT('karma_timeout')[k_acc]-karma_time,'%s/%s'%(room,nick)))
if get_config(room,'karma_limit'):
k_val = karma_get_limit(room,nick)[0]
if k_val >= 0: msg += '. ' + L('Karma limit is %s','%s/%s'%(room,nick)) % [L('over','%s/%s'%(room,nick)), k_val][k_val > 0]
else: msg = L('You can\'t change karma!','%s/%s'%(room,nick))
send_msg(type, room, nick, msg)
def karma_check(room,jid,nick,type,text):
if getRoom(jid) == getRoom(selfjid): return
if len(unicode(text)) < 5: return
while len(text) and text[-1:] == ' ': text = text[:-1]
if text[-3:] == ' +1':
karma_change(room,jid,nick,type,text,1)
return True
elif text[-3:] == ' -1':
karma_change(room,jid,nick,type,text,-1)
return True
def karma_clear_log(room,jid,nick,type,arr):
global last_karma
if type == 'unavailable': last_karma.pop('%s/%s' % (room,jid), None)
global execute, message_control,presence_control
presence_control = [karma_clear_log]
message_act_control = [karma_check]
execute = [(3, 'karma', karma, 2, 'Karma.\nkarma [show] nick\nkarma top+|- [count]\nFor change karma: nick: +1\nnick: -1')]

52
plugins/kinopoisk.py Normal file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
kinopoisk_error_string = '<META HTTP-EQUIV="Pragma" CONTENT="no-cache">'
def kinopoisk(type, jid, nick, text):
text=text.strip()
if len(text) > 2:
query=urllib.quote(text.encode('cp1251'))
data = html_encode(load_page('http://m.kinopoisk.ru/search/'+query))
if kinopoisk_error_string in data: msg = unhtml_hard(re.findall(kinopoisk_error_regexp,data,re.I+re.U+re.S)[0])
else:
temp_urls = re.findall('<a href="http://m.kinopoisk.ru/movie/(\d+?)/">(.+?)</a>', data)
if temp_urls:
msg = L('Found:','%s/%s'%(jid,nick))
for n, t_u in enumerate(temp_urls):
rs = ''
if n < 3:
try:
r = load_page('http://www.kinopoisk.ru/rating/%s.xml' % t_u[0])
r = re.findall('>([\.\d]+?)<', r)
rs = ' (KP: %s / IMDB: %s)' % (r[0], r[1])
except:
pass
msg += '\nhttp://www.kinopoisk.ru/film/%s/ - %s%s' % (t_u[0], t_u[1], rs)
else: msg = L('Not found!','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(0, 'film', kinopoisk, 2, 'Search in www.kinopoisk.ru. Example:\nfilm film_name')]

47
plugins/known.py Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def known(type, jid, nick, text):
count = 10
if '\n' in text:
try:
t_count = text.split('\n')[1].strip().lower()
if t_count == 'all': count = 0
else: count = int(t_count)
except: pass
text = text.split('\n',1)[0]
if not text.strip(): text = nick
real_jid = cur_execute_fetchone('select jid from age where room=%s and (nick=%s or jid=%s) order by status,-time',(jid,text,text.lower()))
if real_jid:
if count: lst = cur_execute_fetchall('select nick from age where room=%s and jid=%s and nick!=%s order by status,-time limit %s',(jid,real_jid[0],text,count))
else: lst = cur_execute_fetchall('select nick from age where room=%s and jid=%s and nick!=%s order by status,-time',(jid,real_jid[0],text))
if lst: nicks = ', '.join([t[0] for t in lst])
else: nicks = text
if text == nick: msg = '%s %s' % (L('I know you as:','%s/%s'%(jid,nick)),nicks)
else: msg = '%s %s' % (L('I know %s as:','%s/%s'%(jid,nick)) % text,nicks)
else: msg = L('Not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'known', known, 2, 'Show user\'s nick changes.\nknown <nick>\n[count|all]')]

208
plugins/lastfm.py Normal file
View File

@@ -0,0 +1,208 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
global execute, lf_api, lfm_url
lfm_url = 'http://ws.audioscrobbler.com/2.0/'
def last_text_cnt(text,c):
text = reduce_spaces_all(text).split(' ')
try: cnt = int(text[1])
except: cnt = GT('lastfm_max_limit')
cnt += c
text = text[0]
return text,cnt
def last_check_ascii(type, jid, nick, text):
for tmp in text:
if tmp > '~' or tmp < ' ':
send_msg(type, jid, nick, L('Error!','%s/%s'%(jid,nick)))
return True
return None
def last_time_short(tm):
tm = time.localtime(tm)
tnow = time.localtime()
if tm[0] != tnow[0]: form = '%d.%m.%Y %H:%M'
elif tm[1]!=tnow[1] or tm[2]!=tnow[2]: form = '%d.%m %H:%M'
else: form = '%H:%M'
return str(time.strftime(form,tm))
def last_date_now(body):
if 'nowplaying=\"true\"' in body: return 'now'
else:
try: return last_time_short(int(get_subtag(get_tag_full(body,'date'),'uts')))
except: return 'Unknown'
def lastonetrack(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
ms = lf_api('user.getrecenttracks',text, '<track')
if len(ms): cnt = len(ms)
else: cnt = 0
if cnt >=2: msg = L('Last track %s: %s - %s %s','%s/%s'%(jid,nick)) % (text,get_tag(ms[1],'artist'),get_tag(ms[1],'name'),'['+last_date_now(ms[1])+']')
else: msg = L('Unavailable!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def lf_api(method, user, splitter):
user = reduce_spaces_all(user.lower().encode('utf-8').replace('\\x','%')).replace(' ','%20')
link = '%s?method=%s&user=%s&api_key=%s' % (lfm_url,method,user,GT('lfm_api'))
return rss_replace(html_encode(load_page(link))).split(splitter)
def lasttracks(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.getrecenttracks',text, '<track')
msg = L('Last tracks %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n[%s] %s - %s' % (last_date_now(a),get_tag(a,'artist'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def lastfriends(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
ms = lf_api('user.getfriends',text, '<user')
msg = L('Friends %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:]:
rn = get_tag(a,'realname')
if rn: msg += ' %s (%s),' % (get_tag(a,'name'),rn)
else: msg += ' %s,' % get_tag(a,'name')
msg = msg[:-1]
send_msg(type, jid, nick, msg)
def lastloved(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.getlovedtracks',text, '<track')
msg = L('Loved tracks %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n[%s] %s - %s' % (last_date_now(a),get_tag(a.split('<artist')[1],'name'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def lastneighbours(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.getneighbours',text, '<user')
msg = L('Neighbours %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n%s - %s' % (get_tag(a,'match'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def lastplaylist(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,2)
ms = lf_api('user.getplaylists',text, '<playlist')
msg = L('Playlists %s:','%s/%s'%(jid,nick)) % text
for a in ms[2:cnt]: msg += '\n[%s] %s (%s) - %s - %s' % (get_tag(a,'id'),get_tag(a,'title'),get_tag(a,'description'),get_tag(a,'size'),get_tag(a,'duration'))
send_msg(type, jid, nick, msg)
def topalbums(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.gettopalbums',text, '<album')
msg = L('Top albums %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n[%s] %s - %s' % (get_tag(a,'playcount'),get_tag(a.split('<artist')[1],'name'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def topartists(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.gettopartists',text, '<artist')
msg = L('Top artists %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n[%s] %s' % (get_tag(a,'playcount'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def toptags(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.gettoptags',text, '<tag')
msg = L('Top tags %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]: msg += '\n[%s] %s - %s' % (get_tag(a,'count'),get_tag(a,'name'),get_tag(a,'url'))
send_msg(type, jid, nick, msg)
def toptracks(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text,cnt = last_text_cnt(text,1)
ms = lf_api('user.gettoptracks',text, '<track')
if cnt > len(ms): cnt = len(ms)
msg = L('Top tracks %s:','%s/%s'%(jid,nick)) % text
for a in ms[1:cnt]:
b = a.split('<artist')
msg += '\n[%s] %s - %s' % (get_tag(a,'playcount'),get_tag(b[1],'name'),get_tag(a,'name'))
send_msg(type, jid, nick, msg)
def tasteometer(type, jid, nick, text):
if not text: text = nick
if last_check_ascii(type, jid, nick, text): return
text = reduce_spaces_all(text.lower().encode('utf-8').replace('\\x','%')).split(' ',1)
try: (user1,user2) = text
except:
send_msg(type, jid, nick, L('Need two users','%s/%s'%(jid,nick)))
return
link = '%s?method=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s&api_key=%s' % (lfm_url,user1,user2,GT('lfm_api'))
lfxml = html_encode(load_page(link))
scor = get_tag(lfxml,'score')
try: scor = float(scor)
except: scor = 0
if scor <= 0: msg = L('Tastes of %s and %s - soo different!','%s/%s'%(jid,nick)) % (user1,user2)
else:
msg,msg2 = L('Match tastes of %s and %s - %s','%s/%s'%(jid,nick)) % (user1,user2,str(int(scor*100))+'%'),''
lfxml = lfxml.split('<artist')
cnt = len(lfxml)
for a in lfxml[2:cnt]: msg2 += '%s, ' % get_tag(a,'name')
if len(msg2): msg += '\n%s' % L('Artists: %s','%s/%s'%(jid,nick)) % msg2[:-2]
send_msg(type, jid, nick, msg)
def no_api(type, jid, nick): send_msg(type, jid, nick, L('Not found LastFM api','%s/%s'%(jid,nick)))
exec_yes = [(3, 'lasttracks', lasttracks, 2, 'Last scrobled tracks'),
(3, 'last', lastonetrack, 2, 'Last scrobled track'),
(3, 'lastfriends', lastfriends, 2, 'Last friends'),
(3, 'lastloved', lastloved, 2, 'Last loved tracks'),
(3, 'lastneighbours', lastneighbours, 2, 'Last neighbours'),
(3, 'lastplaylist', lastplaylist, 2, 'Last playlist'),
(3, 'topalbums', topalbums, 2, 'Top albums'),
(3, 'topartists', topartists, 2, 'Top artists'),
(3, 'toptags', toptags, 2, 'Top tags'),
(3, 'toptracks', toptracks, 2, 'Top tracks'),
(3, 'tasteometer', tasteometer, 2, 'Music tastes')]
exec_no = [(3, 'lasttracks', no_api, 1, 'Not found LastFM api'),
(3, 'last', no_api, 1, 'Not found LastFM api'),
(3, 'lastfriends', no_api, 1, 'Not found LastFM api'),
(3, 'lastloved', no_api, 1, 'Not found LastFM api'),
(3, 'lastneighbours', no_api, 1, 'Not found LastFM api'),
(3, 'lastplaylist', no_api, 1, 'Not found LastFM api'),
(3, 'topalbums', no_api, 1, 'Not found LastFM api'),
(3, 'topartists', no_api, 1, 'Not found LastFM api'),
(3, 'toptags', no_api, 1, 'Not found LastFM api'),
(3, 'toptracks', no_api, 1, 'Not found LastFM api'),
(3, 'tasteometer', no_api, 1, 'Not found LastFM api')]
execute = [exec_no,exec_yes][len(GT('lfm_api')) >= 30]

243
plugins/logger.py Normal file
View File

@@ -0,0 +1,243 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# translate: chat_log_join,away_log_join,xa_log_join,dnd_log_join,online_log_join,chat_log_change,away_log_change,xa_log_change,dnd_log_change,online_log_change
smile_dictionary = {}
last_log_file = {}
last_log_presence = {}
log_header = ['','<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><link href="%s" rel="stylesheet" type="text/css" /><title>\n' % logs_css_path][GT('html_logs_enable')]
if not os.path.exists(log_folder % ''): os.mkdir(log_folder % '')
if not os.path.exists(public_log % ''): os.mkdir(public_log % '')
if not os.path.exists(system_log % '') and GT('syslogs_enable'): os.mkdir(system_log % '')
for smilepack in smiles_dirs_case:
smile_dictionary[smilepack] = {}
if smilepack[0] != '.':
data = readfile(os.path.join(sm_f,smilepack,smile_descriptor))
for icon in re.findall('<icon>((?:\s|.)+?)</icon>', data):
img = re.search('<object mime="image/.+?">(.+?)</object>', icon).group(1)
for pattern in re.findall('<text.*?>(.+?)</text>', icon): smile_dictionary[smilepack][pattern.replace('<','&lt;').replace('>','&gt;')] = img
def smile_replace(room, text):
global smile_dictionary
smilepack = smiles_dirs_case[smiles_dirs.index(get_config(getRoom(room),'smiles'))]
newtext = ' %s ' % text.replace('<br/>',' <br/> ').replace('&nbsp;', ' ')
for smile in sorted(smile_dictionary[smilepack], key = lambda x: len(x))[::-1]:
tmp_smile = ' %s ' % html_escape(smile.decode('utf-8')).replace('&amp;', '&')
while tmp_smile in newtext:
sm_tag = ' <img src="%s" alt="%s"> ' % ('../../../%s/%s/%s' % (smile_folder, smilepack, smile_dictionary[smilepack][smile]),smile.decode('utf-8'))
newtext = newtext.replace(tmp_smile, sm_tag)
return newtext.replace(' <br/>','<br/>').replace('<br/> ','<br/>')[1:-1]
def initial_log_users(room,ott):
txt = []
for tmp in megabase:
if tmp[0] == room: txt.append(tmp[1])
txt = non_case_sort(txt)
log_body = ['[%s] ' % ott,'<p><a id="%s" name="%s" href="#%s" class="time">%s</a> ' % (ott,ott,ott,ott)][GT('html_logs_enable')]
log_body += ['*** ','<span class="status">'][GT('html_logs_enable')]
log_body += L('Users: %s (%s)') % (', '.join(txt),len(txt))
log_body += '\n%s' % ['','</span></p>'][GT('html_logs_enable')]
return log_body
def append_message_to_log(room,jid,nick,type,text):
global public_log, system_log
lr = cur_execute_fetchone('select * from log_rooms where room=%s;',(room,))
if lr:
if GT('html_logs_enable'): text,jid,nick = html_escape(text).replace('\n','<br/>'), html_escape(jid), html_escape(nick)
if type == 'groupchat' and text != 'None':
if get_config(getRoom(room),'smiles') != 'off': ptext = smile_replace(room, text)
else: ptext = text
msg_logger(room,jid,nick,type,ptext,public_log)
if type == 'chat': nick = 'chat >>> %s' % nick
if GT('syslogs_enable'): msg_logger(room,jid,nick,type,text,system_log)
def write_log_with_end(curr_path,curr_file,log_body,log_he):
global last_log_file
if not os.path.isfile(curr_file):
fl = open(curr_file, 'a')
fl.write(log_he.encode('utf-8'))
fl.write(log_body.encode('utf-8'))
try:
ll = last_log_file[curr_path]
if os.path.isfile(ll):
ender = ['\n','</div></div><br/>%s</body></html>' % GT('html_logs_end_text')][GT('html_logs_enable')]
fle = open(ll, 'a')
fle.write(ender.encode('utf-8'))
fle.close()
except: pass
else:
fl = open(curr_file, 'a')
fl.write(log_body.encode('utf-8'))
fl.close()
last_log_file[curr_path] = curr_file
def msg_logger(room,jid,nick,type,text,logfile):
if GT('chatlogs_logs_gmt'): lt = tuple(time.gmtime())
else: lt = tuple(time.localtime())
curr_path = logfile % room
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_path = '%s/%s' % (curr_path,lt[0])
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_path = '%s/%02d' % (curr_path,lt[1])
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_file = ['%s/%02d.txt','%s/%02d.html'][GT('html_logs_enable')] % (curr_path,lt[2])
ott = onlytimeadd(lt)
log_body = ['[%s] ' % ott,'<p><a id="%s" name="%s" href="#%s" class="time">%s</a> ' % (ott,ott,ott,ott)][GT('html_logs_enable')]
if nick == '': log_body += ['*** %s\n','<span class="topic">%s</span></p>'][GT('html_logs_enable')] % text
else:
if text[:4] == '/me ': log_body += ['*%s %s\n','<span class="me">%s %s</span></p>\n'][GT('html_logs_enable')] % (nick,text[4:])
else:
if '<br/>' + '&nbsp;'*8 in text:
msg_type = '<span class="nick">%s:&nbsp;</span><span class="paste">%s</span></p>\n'
if not text.startswith('<br/>'): text = '<br/>%s' % text
text = text.replace('&nbsp;'*8,'<span style="padding: 0px 16px;">&nbsp;</span>')
elif '&nbsp;'*8 in text:
no_tab_text,cnt = [],0
for t in text.split('<br/>'):
if not '&nbsp;'*8 in t:
no_tab_text.append(t)
cnt += 1
else: break
text = '<br/>'.join(text.split('<br/>')[cnt:])
no_tab_text = '<br/>'.join(no_tab_text)
msg_type = '<span class="nick">%s:&nbsp;</span><span class="text">' + no_tab_text + '%s</span></p>\n'
text = '<table border="0" class="text" cellpadding="0" cellspacing="0"><tr><td>&nbsp;%s' % text
text = text.replace('&nbsp;'*8,'</td><td>&nbsp;')
text = '%s</tr></table>' % text
text = text.replace('<br/>','</td></tr><tr><td>&nbsp;')
else: msg_type = '<span class="nick">%s:&nbsp;</span><span class="text">%s</span></p>\n'
log_body += ['%s: %s\n',msg_type][GT('html_logs_enable')] % (nick,text)
lht = '%s - %02d/%02d/%02d' % (room,lt[0],lt[1],lt[2])
log_he = ['%s\t\thttp://isida-bot.com\n\n' % lht,log_header+lht+'</title></head><body><div class="main"><div class="top"><div class="heart"><a href="http://isida-bot.com">http://isida-bot.com</a></div><div class="conference">'+lht+'</div></div><div class="container">\n'][GT('html_logs_enable')]
try: log_he += initial_log_users(room,ott) + ['[%s] ' % ott,'<p><a id="%s" name="%s" href="#%s" class="time">%s</a> ' % (ott,ott,ott,ott)][GT('html_logs_enable')] + ['*** %s\n','<span class="topic">%s</span></p>'][GT('html_logs_enable')] % [topics[room],html_escape(topics[room]).replace('\n','<br/>')][GT('html_logs_enable')]
except: pass
write_log_with_end(logfile+room,curr_file,log_body,log_he)
def append_presence_to_log(room,jid,nick,type,mass):
global public_log, system_log
lr = cur_execute_fetchone('select * from log_rooms where room=%s;',(room,))
if lr:
# (text, role, affiliation, exit_type, exit_message, show, priority, not_found)
try: llp = [last_log_presence[room+jid+nick],None][type == 'unavailable']
except: llp = None
last_log_presence[room+jid+nick] = mass
if mass == llp: return
if GT('html_logs_enable'): jid,nick = html_escape(jid), html_escape(nick)
presence_logger(room,jid,nick,type,mass,0,public_log)
if GT('syslogs_enable'): presence_logger(room,jid,nick,type,mass,1,system_log)
def presence_logger(room,jid,nick,type,mass,mode,logfile):
role,affiliation = [mass[1],html_escape(mass[1])][GT('html_logs_enable')], [mass[2],html_escape(mass[2])][GT('html_logs_enable')]
if nick[:11] != '<temporary>' and role != 'None' and affiliation != 'None':
text,exit_type = [mass[0],html_escape(mass[0])][GT('html_logs_enable')],mass[3]
if GT('html_logs_enable') and text[:20] == '&lt;br&gt;&amp;nbsp;': text = ' %s' % text[20:]#text = correct_html(text)
try: em = mass[4].split('\r')[0]
except: em = mass[4]
exit_message,show = [em,html_escape(em)][GT('html_logs_enable')], [mass[5],html_escape(mass[5])][GT('html_logs_enable')]
priority,not_found = mass[6],mass[7]
if not_found == 1 and not GT('aff_role_logs_enable'): return
if not_found == 2 and not GT('status_logs_enable'): return
if GT('chatlogs_logs_gmt'): lt = tuple(time.gmtime())
else: lt = tuple(time.localtime())
curr_path = logfile % room
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_path = '%s/%s' % (curr_path,lt[0])
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_path = '%s/%02d' % (curr_path,lt[1])
if not os.path.exists(curr_path): os.mkdir(curr_path)
curr_file = ['%s/%02d.txt','%s/%02d.html'][GT('html_logs_enable')] % (curr_path,lt[2])
ott = onlytimeadd(lt)
log_body = ['[%s] ' % ott,'<p><a id="%s" name="%s" href="#%s" class="time">%s</a> ' % (ott,ott,ott,ott)][GT('html_logs_enable')]
if type == 'unavailable':
log_body += ['*** %s','<span class="unavailable">%s'][GT('html_logs_enable')] % nick
if mode and jid != 'None': log_body += ' (%s)' % jid
if len(exit_type): log_body += ' %s' % exit_type
else: log_body += ' %s' % L('leave')
if exit_message != '': log_body += ' (%s)' % exit_message
if mode and '\r' in mass[4]: log_body += ', %s %s' % (L('Client:'),mass[4].split('\r')[1])
log_body += '%s\n' % ['','</span></p>'][GT('html_logs_enable')]
else:
log_body += ['*** %s','<span class="status">%s'][GT('html_logs_enable')] % nick
if not_found == 0:
if mode and jid != 'None': log_body += ' (%s)' % jid
log_body += ' %s %s' % (L('join as'),L("%s/%s" % (role,affiliation)))
status_type = '%s_log_join'
elif not_found == 1:
log_body += ' %s %s' % (L('now is'),L("%s/%s" % (role,affiliation)))
if exit_message: log_body += ' (%s)' % exit_message
elif not_found == 2: status_type = '%s_log_change'
if not_found == 0 or not_found == 2:
status_mask = ' %s' if not_found else ', %s'
if show != 'None': log_body += status_mask % L(status_type % show).replace(status_type % '','')
else: log_body += status_mask % L(status_type % "online").replace(status_type % '','')
if priority != 'None': log_body += ' [%s]' % priority
else: log_body += ' [0]'
if text != 'None': log_body += ' (%s)' % text
log_body += '%s\n' % ['','</span></p>'][GT('html_logs_enable')]
lht = '%s - %02d/%02d/%02d' % (room,lt[0],lt[1],lt[2])
log_he = ['%s\t\thttp://isida-bot.com\n\n' % lht,log_header+lht+'</title></head><body><div class="main"><div class="top"><div class="heart"><a href="http://isida-bot.com">http://isida-bot.com</a></div><div class="conference">'+lht+'</div></div><div class="container">\n'][GT('html_logs_enable')]
try: log_he += initial_log_users(room,ott) + ['[%s] ' % ott,'<p><a id="%s" name="%s" href="#%s" class="time">%s</a> ' % (ott,ott,ott,ott)][GT('html_logs_enable')] + ['*** %s\n','<span class="topic">%s</span></p>'][GT('html_logs_enable')] % [topics[room],html_escape(topics[room]).replace('\n','<br/>')][GT('html_logs_enable')]
except: pass
write_log_with_end(logfile+room,curr_file,log_body,log_he)
global execute
message_control = [append_message_to_log]
presence_control = [append_presence_to_log]
def log_room(type, jid, nick, text):
if type == 'groupchat': msg = L('This command available only in private!','%s/%s'%(jid,nick))
else:
text = text.strip().lower().split(' ',1)
hmode = text[0]
try: hroom = text[1]
except: hroom = jid
if not hmode:
if cur_execute_fetchone('select * from log_rooms where room=%s;',(hroom,)): msg = L('Logs for %s enabled.','%s/%s'%(jid,nick)) % hroom
else: msg = L('Logs for %s disabled.','%s/%s'%(jid,nick)) % hroom
elif hmode == 'show':
lr = cur_execute_fetchall('select * from log_rooms;')
if lr: msg = '%s\n%s' % (L('Logged conferences:','%s/%s'%(jid,nick)),'\n'.join([t[0] for t in lr]))
else: msg = L('Logs are turned off in all conferences.','%s/%s'%(jid,nick))
elif hmode == 'add':
if not cur_execute_fetchall('select * from conference where room ilike %s;', ('%s/%%'%getRoom(hroom),)): msg = L('I am not in the %s','%s/%s'%(jid,nick)) % hroom
elif cur_execute_fetchone('select * from log_rooms where room=%s;',(hroom,)): msg = L('Logs for %s already enabled.','%s/%s'%(jid,nick)) % hroom
else:
cur_execute('insert into log_rooms values (%s);',(hroom,))
msg = L('Logs for %s enabled.','%s/%s'%(jid,nick)) % hroom
elif hmode == 'del':
if cur_execute_fetchone('select * from log_rooms where room=%s;',(hroom,)):
cur_execute('delete from log_rooms where room=%s;',(hroom,))
msg = L('Logs for %s disabled.','%s/%s'%(jid,nick)) % hroom
else: msg = L('Logs for %s not enabled.','%s/%s'%(jid,nick)) % hroom
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
execute = [(9, 'log', log_room, 2, 'Logging history conference.\nlog [add|del|show][ room@conference.server.tld]')]

1971
plugins/main.py Normal file

File diff suppressed because it is too large Load Diff

49
plugins/md5.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def md5body(type, jid, nick, text):
if len(text): msg = hashlib.md5(text.encode('utf-8')).hexdigest()
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def hashbody(type, jid, nick, text):
text = reduce_spaces_all(text)
if not len(text): text = nick
try: msg = hashes['%s/%s' % (jid,text)]
except: msg = L('Nick %s not found!','%s/%s'%(jid,nick)) % text
send_msg(type, jid, nick, msg)
def findhash(type, jid, nick, text):
text = reduce_spaces_all(text)
if text:
h = [t for t in hashes if hashes[t]==text]
if h: msg = L('Found: %s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join(h)
else: msg = L('Not found: %s','%s/%s'%(jid,nick)) % text
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'md5', md5body, 2, 'Calculate phrase md5 sum.'),
(4, 'hashbody', hashbody, 2, 'Show presence-hash of nick'),
(6, 'findhash', findhash, 2, 'Show room and nick by presence-hash')]

251
plugins/muc.py Normal file
View File

@@ -0,0 +1,251 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
visitors_list = {}
visitors_list_lock = False
# -------------- affiliation -----------------
def global_ban(type, jid, nick, text):
text = text.lower()
hroom = getRoom(jid)
al = get_level(jid,nick)[0]
if al == 9: af = 'owner'
else: af = get_affiliation(jid,nick)
if af != 'owner': msg = L('This command available only for conference owner!','%s/%s'%(jid,nick))
elif text == 'show' and al == 9:
ir = cur_execute_fetchone('select * from ignore_ban;')
if len(ir): msg = '%s\n%s' % (L('Global ban is off in:','%s/%s'%(jid,nick)),'\n'.join([t[0] for t in ir]))
else: msg = L('Global ban enable without limits!','%s/%s'%(jid,nick))
elif text == 'del' and af == 'owner':
if cur_execute_fetchone('select * from ignore_ban where room=%s' % (hroom,)): msg = L('Conference %s already deleted from global ban list!','%s/%s'%(jid,nick)) % hroom
else:
cur_execute('insert inro ignore_ban values (%s)' % (hroom,))
msg = L('Conference %s has been deleted from global ban list!','%s/%s'%(jid,nick)) % hroom
elif text == 'add' and af == 'owner':
if cur_execute_fetchone('select * from ignore_ban where room=%s' % (hroom,)):
cur_execute('delete from ignore_ban where room=%s' % (hroom,))
msg = L('Conference %s has been added from global ban list!','%s/%s'%(jid,nick)) % hroom
else: msg = L('Conference %s already exist in global ban list!','%s/%s'%(jid,nick)) % hroom
else:
if al == 9:
if cur_execute_fetchone('select * from ignore_ban where room=%s' % (hroom,)): msg = L('Your conference will be ignored for global ban!','%s/%s'%(jid,nick))
elif '@' not in text or '.' not in text: msg = L('I need jid!','%s/%s'%(jid,nick))
else:
reason = L('banned global by %s from %s','%s/%s'%(jid,nick)) % (nick, jid)
br = [t[0] for t in cur_execute_fetchall("select room from conference where split_part(room,'/',1) not in (select room from ignore_ban as igb);")]
for tmp in br:
i = xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':getRoom(tmp)}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':unicode(text)},[xmpp.Node('reason',{},reason)])])])
sender(i)
time.sleep(0.1)
msg = L('jid %s has been banned in %s conferences.','%s/%s'%(jid,nick)) % (text, len(br))
else: msg = L('Command temporary blocked!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def muc_tempo_ban(type, jid, nick, text):
text,mute = text.strip().split('\n'),False
if text:
cmd, par = text[0].lower().split(' ',1) if ' ' in text[0] else (text[0].lower().split(' ',1)[0],'')
if cmd == 'show':
if not par: par = '%'
tb = cur_execute_fetchall('select jid,time from tmp_ban where room=%s and jid ilike %s',(jid,par))
if tb: msg = L('Found: %s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join([['%s\t%s' % (ub[0],un_unix(ub[1]-int(time.time()),'%s/%s'%(jid,nick))),'%s\t< %s' % (ub[0],un_unix(GT('schedule_time'),'%s/%s'%(jid,nick)))][ub[1] < int(time.time())] for ub in tb])
else: msg = L('Not found.','%s/%s'%(jid,nick))
elif cmd == 'del':
if par:
tb = cur_execute_fetchall('select jid,time from tmp_ban where room=%s and jid ilike %s',(jid,par))
if tb:
msg = L('Removed: %s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join([['%s\t%s' % (ub[0],un_unix(ub[1]-int(time.time()),'%s/%s'%(jid,nick))),'%s\t< %s' % (ub[0],un_unix(GT('schedule_time'),'%s/%s'%(jid,nick)))][ub[1] < int(time.time())] for ub in tb])
for ub in tb: sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'none', 'jid':getRoom(unicode(ub[0]))},[])])]))
cur_execute('delete from tmp_ban where room=%s and jid ilike %s',(jid,par))
else: msg = L('Not found.','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
else:
try: ban_time = int(text[1][:-1]) * {'s':1, 'm':60, 'h':3600, 'd':86400}[text[1][-1].lower()]
except: ban_time = None
if ban_time:
reason = ' '.join(text[2:])
if not reason: reason = L('No reason!','%s/%s'%(jid,nick))
reason = L('ban on %s since %s because: %s','%s/%s'%(jid,nick)) % (un_unix(ban_time,'%s/%s'%(jid,nick)), timeadd(tuple(time.localtime())), reason)
who,msg = text[0],L('done','%s/%s'%(jid,nick))
try: whojid = getRoom([t[4] for t in megabase if t[0]==jid and t[1]==who][0])
except: whojid = None
if not whojid:
fnd = cur_execute_fetchall('select jid from age where room=%s and (nick=%s or jid=%s) group by jid',(jid,who,who))
if len(fnd) == 1: whojid = getRoom(fnd[0][0])
elif len(fnd) > 1: msg = L('I seen different people with this nick!','%s/%s'%(jid,nick))
else: msg,whojid = L('I don\'n know %s, and use as is!','%s/%s'%(jid,nick)) % who,who
if whojid:
sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':unicode(whojid)},[xmpp.Node('reason',{},reason)])])]))
was_banned = cur_execute_fetchone('select time from tmp_ban where room=%s and jid=%s;',(jid,whojid))
if was_banned:
cur_execute('delete from tmp_ban where room=%s and jid=%s;',(jid,whojid))
ban_tm = was_banned[0]-int(time.time())
if ban_tm > 0: ban_nm = L('old ban time is %s','%s/%s'%(jid,nick)) % un_unix(ban_tm,'%s/%s'%(jid,nick))
else: ban_nm = L('just passed!','%s/%s'%(jid,nick))
msg = L('Updated: %s','%s/%s'%(jid,nick)) % ban_nm
cur_execute('insert into tmp_ban values (%s,%s,%s)',(jid,whojid,ban_time+int(time.time())))
if who == nick: mute = True
else: msg = L('Time format error!','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
if not mute: send_msg(type, jid, nick, msg)
def muc_ban(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'outcast',0)
def muc_banjid(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'outcast',1)
def muc_none(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'none',0)
def muc_nonejid(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'none',1)
def muc_member(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'member',0)
def muc_memberjid(type, jid, nick,text): muc_affiliation(type, jid, nick, text, 'member',1)
def muc_affiliation(type, jid, nick, text, aff, is_jid):
nowname = get_xnick(jid)
xtype = get_xtype(jid)
if xtype == 'owner':
if is_start: return
else: send_msg(type, jid, nick, L('Command is locked!','%s/%s'%(jid,nick)))
elif len(text):
skip = None
if '\n' in text: who, reason = text.split('\n',1)[0], text.split('\n',1)[1]
else: who, reason = text, []
if reason: reason = [xmpp.Node('reason',{},reason)]
whojid = [unicode(get_level(jid,who)[1]),who][is_jid]
if whojid != 'None': sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':aff, 'jid':whojid},reason)])]))
else: send_msg(type, jid, nick, L('I don\'t know %s','%s/%s'%(jid,nick)) % who)
else: send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
def muc_ban_past(type, jid, nick,text): muc_affiliation_past(type, jid, nick, text, 'outcast')
def muc_none_past(type, jid, nick,text): muc_affiliation_past(type, jid, nick, text, 'none')
def muc_member_past(type, jid, nick,text): muc_affiliation_past(type, jid, nick, text, 'member')
def muc_affiliation_past(type, jid, nick, text, aff):
nowname = get_xnick(jid)
xtype = get_xtype(jid)
if xtype == 'owner':
if is_start: return
else: msg, text = L('Command is locked!','%s/%s'%(jid,nick)), ''
else: msg = L('What?','%s/%s'%(jid,nick))
if len(text):
skip = None
if '\n' in text: who, reason = text.split('\n',1)[0], text.split('\n',1)[1]
else: who, reason = text, []
if reason: reason = [xmpp.Node('reason',{},reason)]
fnd = cur_execute_fetchall('select jid from age where room=%s and (nick=%s or jid=%s) group by jid',(jid,who,who))
if len(fnd) == 1: msg, whojid = L('done','%s/%s'%(jid,nick)), getRoom(unicode(fnd[0][0]))
elif len(fnd) > 1:
whojid = getRoom(get_level(jid,who)[1])
if whojid != 'None': msg = L('done','%s/%s'%(jid,nick))
else: msg, skip = L('I seen some peoples with this nick. Get more info!','%s/%s'%(jid,nick)), True
else:
msg = L('I don\'n know %s, and use as is!','%s/%s'%(jid,nick)) % who
whojid = who
else: skip = True
if skip: send_msg(type, jid, nick, msg)
else:
i = xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':aff, 'jid':unicode(whojid)},reason)])])
sender(i)
send_msg(type, jid, nick, msg)
def muc_kick(type, jid, nick, text): muc_role(type, jid, nick, text, 'none',1)
def muc_participant(type, jid, nick, text): muc_role(type, jid, nick, text, 'participant',1)
def muc_visitor(type, jid, nick, text): muc_role(type, jid, nick, text, 'visitor',1)
def muc_moderator(type, jid, nick, text): muc_role(type, jid, nick, text, 'moderator',1)
def muc_role(type, jid, nick, text, role, unused):
nowname = get_xnick(jid)
xtype = get_xtype(jid)
if xtype == 'owner':
if is_start: return
else: send_msg(type, jid, nick, L('Command is locked!','%s/%s'%(jid,nick)))
elif len(text):
skip = None
if '\n' in text: who, reason = text.split('\n',1)[0], text.split('\n',1)[1]
else: who, reason = text, []
if reason: reason = [xmpp.Node('reason',{},reason)]
whojid = unicode(get_level(jid,who)[1])
if whojid != 'None': sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':jid}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'role':role, 'nick':who},reason)])]))
else: send_msg(type, jid, nick, L('I don\'t know %s','%s/%s'%(jid,nick)) % who)
else: send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
def check_unban():
tt = int(time.time())
ul = cur_execute_fetchall('select room,jid from tmp_ban where time<%s;',(tt,))
if ul:
for t in ul: sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':t[0]}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'none', 'jid':getRoom(unicode(t[1]))},[])])]))
cur_execute('delete from tmp_ban where time<%s;',(tt,))
def visitors_list_lock_wait():
while visitors_list_lock: time.sleep(0.05)
return True
def check_visitor():
global visitors_list, visitors_list_lock
visitors_list_lock = visitors_list_lock_wait()
ITT = int(time.time())
for t in visitors_list:
room = t.split('/')[0]
VISITOR_ACT = get_config(getRoom(room),'visitor_action')
if VISITOR_ACT != 'off' and ITT > visitors_list[t]:
reason = [xmpp.Node('reason',{},L('Too long was without voice!',t))]
if VISITOR_ACT == 'kick': sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':room}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'role':'none', 'nick':t.split('/',1)[1]},reason)])]))
else: sender(xmpp.Node('iq', {'id': get_id(), 'type': 'set', 'to':room}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':get_jid_by_nick(t.split('/',1))},reason)])]))
visitors_list_lock = False
def visitor_presence(room,jid,nick,type,mass):
global visitors_list, visitors_list_lock
if getRoom(jid) == getRoom(Settings['jid']): return
if type == 'error': return
elif type == 'unavailable':
visitors_list_lock = visitors_list_lock_wait()
try: visitors_list.pop('%s/%s' % (room,nick))
except: pass
visitors_list_lock = False
if mass[1] == 'visitor':
visitors_list_lock = visitors_list_lock_wait()
visitors_list['%s/%s' % (room,nick)] = int(time.time()) + get_config_int(getRoom(room),'visitor_action_time')
visitors_list_lock = False
global execute, timer, presence_control
timer = [check_unban,check_visitor]
presence_control = [visitor_presence]
execute = [(7, 'ban_past', muc_ban_past, 2, 'Ban user.'),
(7, 'ban', muc_ban, 2, 'Ban user.'),
(7, 'banjid', muc_banjid, 2, 'Ban user by jid.'),
(7, 'unban', muc_none, 2, 'Unban user.'),
(7, 'unbanjid', muc_nonejid, 2, 'Unban user by jid.'),
(7, 'tban', muc_tempo_ban, 2, 'Temporary ban.\ntban show|del [jid] - show/del temporary bans\ntban nick\ntimeD|H|M|S\nreason - ban nick for time because reason.'),
(7, 'none_past', muc_none_past, 2, 'Remove user affiliation.'),
(7, 'none', muc_none, 2, 'Remove user affiliation.'),
(7, 'nonejid', muc_nonejid, 2, 'Remove user affiliation.'),
(7, 'member_past', muc_member_past, 2, 'Get member affiliation.'),
(7, 'member', muc_member, 2, 'Get member affiliation.'),
(7, 'memberjid', muc_memberjid, 2, 'Get member affiliation.'),
(7, 'kick', muc_kick, 2, 'Kick user.'),
(7, 'participant', muc_participant, 2, 'Change role to participant.'),
(7, 'visitor', muc_visitor, 2, 'Revoke voice.'),
(7, 'moderator', muc_moderator, 2, 'Grant moderator.'),
(8, 'global_ban', global_ban, 2, 'Global ban. Available only for confernce owner.\nglobal_ban del - remove conference from banlist,\nglobal_ban add - add conference into banlist,\nglobal_ban <jid> - ban jid in all rooms, where bot is admin.')]

603
plugins/mucfilter.py Normal file
View File

@@ -0,0 +1,603 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
muc_filter_fast_join = {}
muc_filter_last_notify = 0
muc_filter_events = []
def muc_pprint(*param):
global muc_filter_events,muc_filter_last_notify
pprint(*param)
if GT('muc_filter_notify'):
_notify_count = GT('muc_filter_notify_count')
muc_filter_events = [time.time()] + muc_filter_events[:_notify_count-1]
if len(muc_filter_events) == _notify_count \
and muc_filter_events[0] - muc_filter_events[-1] < GT('muc_filter_notify_peroid') \
and muc_filter_last_notify + GT('muc_filter_notify_wait') < time.time():
pprint('*** MUC-Filter notify event!')
muc_filter_last_notify = time.time()
muc_filter_events = []
_jids = GT('muc_filter_notify_jids').split()
for t in _jids:
if t.strip(): send_msg('chat', t.strip(), '', 'MUC-Filter notify event!')
def muc_filter_set(iq,id,room,acclvl,query,towh,al):
msg_xmpp = iq.getTag('query', namespace=xmpp.NS_MUC_FILTER)
if msg_xmpp:
msg,mute,mute_type,mute_room = get_tag(unicode(msg_xmpp),'query'),None,'groupchat',room
jid = rss_replace(get_tag_item(msg,'message','from'))
nick = rss_replace(unicode(get_nick_by_jid_res(room,jid)))
rn = '%s/%s' % (room,nick)
mute_reason = L('Warning! Your message are blocked by policy of room!',rn)
if msg[:2] == '<m':
if '<body>' in msg and '</body>' in msg:
to_nick = getResourse(get_tag_item(msg,'message','to'))
tojid = rss_replace(getRoom(get_level(room,to_nick)[1]))
skip_owner = is_owner(jid)
gr = getRoom(room)
type = get_tag_item(msg,'message','type')
if type == 'chat' and not skip_owner:
tmp = cur_execute_fetchall('select * from muc_lock where room=%s and jid=%s', (room,tojid))
if tmp:
mute,mute_type,mute_room,mute_reason = True,'chat', '%s/%s' % (room,to_nick),L('Warning! This participant don\'t want to receive private messages!',rn)
muc_pprint('MUC-Filter pmlock: %s/%s [%s] > %s: %s' % (room,nick,jid,to_nick,get_tag(msg,'body')),'brown')
if skip_owner: pass
elif get_config(gr,'muc_filter') and not mute:
body = get_tag(msg,'body')
# Mute all private messages
if not mute and msg and type == 'chat' and get_config(gr,'muc_filter_mute_chat'):
muc_pprint('MUC-Filter lock private: %s/%s [%s] > %s: %s' % (room,nick,jid,to_nick,get_tag(msg,'body')),'brown')
try: cnt = mute_msg['%s|%s' % (gr,jid)]
except: cnt = 1
act = get_config(gr,'muc_filter_mute_repeat_action')
if act != 'off':
if cnt >= get_config_int(gr,'muc_filter_mute_repeat'):
muc_pprint('MUC-Filter mute repeat action (%s): %s %s [%s]' % (act,gr,jid,cnt),'brown')
msg = muc_filter_action(act,jid,room,L('Muted messages count overflow!',rn))
else: mute_msg['%s|%s' % (gr,jid)] = cnt + 1
mute,mute_type,mute_room,mute_reason = True,'chat', '%s/%s' % (room,to_nick),L('You couldn\'t send private messages! Don\'t repeat!',rn)
# Mute all public messages
if not mute and msg and type == 'groupchat' and get_config(gr,'muc_filter_mute_groupchat'):
muc_pprint('MUC-Filter lock public: %s/%s [%s] > %s' % (room,nick,jid,get_tag(msg,'body')),'brown')
try: cnt = mute_msg['%s|%s' % (gr,jid)]
except: cnt = 1
act = get_config(gr,'muc_filter_mute_repeat_action')
if act != 'off':
if cnt >= get_config_int(gr,'muc_filter_mute_repeat'):
muc_pprint('MUC-Filter mute repeat action (%s): %s %s [%s]' % (act,gr,jid,cnt),'brown')
msg = muc_filter_action(act,jid,room,L('Muted messages count overflow!',rn))
else: mute_msg['%s|%s' % (gr,jid)] = cnt + 1
mute,mute_reason = True,L('You couldn\'t send public messages! Don\'t repeat!',rn)
# Mute newbie
if not mute and msg and get_config(gr,'muc_filter_newbie'):
in_base = cur_execute_fetchall('select sum(sum) from (select sum(age) from age where jid=%s and room=%s union all select %s-time from age where jid=%s and room=%s and status=0) as sum_age;',(getRoom(jid),gr,int(time.time()),getRoom(jid),gr))
if not in_base: nmute = True
else:
newbie_time = get_config(gr,'muc_filter_newbie_time')
if newbie_time.isdigit(): newbie_time = int(newbie_time)
else: newbie_time = 60
if in_base[0][0] < newbie_time: nmute = True
else: nmute = False
if nmute:
try: cnt = newbie_msg['%s|%s' % (gr,jid)]
except: cnt = 1
muc_pprint('MUC-Filter mute newbie: %s %s [%s] %s' % (gr,jid,cnt,body),'brown')
act = get_config(gr,'muc_filter_newbie_repeat_action')
if act != 'off':
if cnt >= get_config_int(gr,'muc_filter_newbie_repeat'):
muc_pprint('MUC-Filter mute newbie repeat action (%s): %s %s [%s]' % (act,gr,jid,cnt),'brown')
msg = muc_filter_action(act,jid,room,L('Messages count overflow from newbie!',rn))
else: newbie_msg['%s|%s' % (gr,jid)] = cnt + 1
mute,mute_reason = True,L('Your messages are blocked %ssec. after first join! Please, wait quiet!',rn) % newbie_time
# New Line
if not mute and msg and get_config(gr,'muc_filter_newline_msg') != 'off':
act = get_config(gr,'muc_filter_newline_msg')
try:
nline_count = get_config_int(gr,'muc_filter_newline_msg_count')
if not 2 <= nline_count <= 50: raise
except:
nline_count = int(config_prefs['muc_filter_newline_msg_count'][3])
put_config(gr,'muc_filter_newline_msg_count',str(nline_count))
if body.count('\n') >= nline_count:
muc_pprint('MUC-Filter msg new line (%s): %s [%s] %s' % (act,jid,room,nick+'|'+body.replace('\n','[LF]')),'brown')
if act == 'replace':
body = body.replace('\n',' ')
msg = msg.replace(get_tag_full(msg,'body'),'<body>%s</body>' % body)
elif act == 'mute': mute,mute_reason = True,L('Blocked by content!',rn)
else: msg = muc_filter_action(act,jid,room,L('Blocked by content!',rn))
# Reduce spaces
if not mute and msg and get_config(gr,'muc_filter_reduce_spaces_msg') and ' ' in body:
muc_pprint('MUC-Filter msg reduce spaces: %s [%s] %s' % (jid,room,nick+'|'+body),'brown')
body = reduce_spaces_all(body)
msg = msg.replace(get_tag_full(msg,'body'),'<body>%s</body>' % body)
# AD-Block filter
need_raw = True
if not mute and msg and get_config(gr,'muc_filter_adblock') != 'off':
f = []
for reg in adblock_regexp:
tmp = re.findall(reg,body,re.S|re.I|re.U)
if tmp: f = f + tmp
if f:
act = get_config(gr,'muc_filter_adblock')
need_raw = False
muc_pprint('MUC-Filter msg adblock (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'replace':
for tmp in f: body = body.replace(tmp,[GT('censor_text')*len(tmp),GT('censor_text')][len(GT('censor_text'))>1])
msg = msg.replace(get_tag_full(msg,'body'),'<body>%s</body>' % body)
elif act == 'mute': mute,mute_reason = True,L('AD-Block!',rn)
else: msg = muc_filter_action(act,jid,room,L('AD-Block!',rn))
# Raw AD-Block filter
if not mute and msg and need_raw and get_config(gr,'muc_filter_adblock_raw') != 'off':
rawbody = match_for_raw(body,u'[a-zа-я0-9@.]*',gr)
if rawbody:
f = []
for reg in adblock_regexp:
tmp = re.findall(reg,rawbody,re.S|re.I|re.U)
if tmp: f = f + tmp
if f:
act = get_config(gr,'muc_filter_adblock_raw')
muc_pprint('MUC-Filter msg raw adblock (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'mute': mute,mute_reason = True,L('Raw AD-Block!',rn)
else: msg = muc_filter_action(act,jid,room,L('Raw AD-Block!',rn))
# Repeat message filter
if not mute and msg and get_config(gr,'muc_filter_repeat') != 'off':
grj = getRoom(jid)
try: lm = last_msg_base[grj]
except: lm = None
if lm:
rep_to = GT('muc_filter_repeat_time')
try: lmt = last_msg_time_base[grj]
except: lmt = 0
if rep_to+lmt > time.time():
action = False
if body == lm: action = True
elif lm in body:
try: muc_repeat[grj] += 1
except: muc_repeat[grj] = 1
if muc_repeat[grj] >= (GT('muc_filter_repeat_count')-1): action = True
else: muc_repeat[grj] = 0
if action:
act = get_config(gr,'muc_filter_repeat')
muc_pprint('MUC-Filter msg repeat (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'mute': mute,mute_reason = True,L('Repeat message block!',rn)
else: msg = muc_filter_action(act,jid,room,L('Repeat message block!',rn))
else: muc_repeat[grj] = 0
last_msg_base[grj] = body
last_msg_time_base[grj] = time.time()
# Match filter
if not mute and msg and get_config(gr,'muc_filter_match') != 'off' and len(body) >= GT('muc_filter_match_view'):
tbody,warn_match,warn_space = body.split(),0,0
for tmp in tbody:
cnt = 0
for tmp2 in tbody:
if tmp in tmp2: cnt += 1
if cnt > GT('muc_filter_match_count'): warn_match += 1
if not len(tmp): warn_space += 1
if warn_match > GT('muc_filter_match_warning_match') or warn_space > GT('muc_filter_match_warning_space') or '\n'*GT('muc_filter_match_warning_nn') in body:
act = get_config(gr,'muc_filter_match')
muc_pprint('MUC-Filter msg matcher (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'mute': mute,mute_reason = True,L('Match message block!',rn)
else: msg = muc_filter_action(act,jid,room,L('Match message block!',rn))
# Censor filter
need_raw = True
if not mute and msg and get_config(gr,'muc_filter_censor') != 'off' and esc_min2(body) != to_censore(esc_min2(body),gr):
act = get_config(gr,'muc_filter_censor')
need_raw = False
muc_pprint('MUC-Filter msg censor (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'replace': msg = msg.replace(get_tag_full(msg,'body'),'<body>%s</body>' % esc_max2(to_censore(esc_min2(body),gr)))
elif act == 'mute': mute,mute_reason = True,L('Blocked by censor!',rn)
else: msg = muc_filter_action(act,jid,room,L('Blocked by censor!',rn))
# Raw censor filter
if not mute and msg and need_raw and get_config(gr,'muc_filter_censor_raw') != 'off':
rawbody = match_for_raw(body,u'[a-zа-я0-9]*',gr)
if rawbody and rawbody != to_censore(rawbody,gr):
act = get_config(gr,'muc_filter_censor_raw')
muc_pprint('MUC-Filter msg raw censor (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'mute': mute,mute_reason = True,L('Blocked by raw censor!',rn)
else: msg = muc_filter_action(act,jid,room,L('Blocked by raw censor!',rn))
# Large message filter
if not mute and msg and get_config(gr,'muc_filter_large') != 'off' and len(body) > GT('muc_filter_large_message_size'):
act = get_config(gr,'muc_filter_large')
muc_pprint('MUC-Filter msg large message (%s): %s [%s] %s' % (act,jid,room,body),'brown')
if act == 'paste' or act == 'truncate':
url = paste_text(rss_replace(body),room,jid)
if act == 'truncate': body = u'%s[…] %s' % (body[:GT('muc_filter_large_message_size')],url)
else: body = L('Large message%s %s',rn) % (u'…',url)
msg = msg.replace(get_tag_full(msg,'body'),'<body>%s</body>' % body)
elif act == 'mute': mute,mute_reason = True,L('Large message block!',rn)
else: msg = muc_filter_action(act,jid,room,L('Large message block!',rn))
if mute: msg = unicode(xmpp.Message(to=jid,body=mute_reason,typ=mute_type,frm=mute_room))
else: msg = None
elif msg[:2] == '<p':
jid = rss_replace(get_tag_item(msg,'presence','from'))
gr = getRoom(room)
if server_hash_list.has_key('%s/%s' % (gr,getServer(jid))) or server_hash_list.has_key('%s/%s' % (gr,getRoom(jid))):
muc_pprint('MUC-Filter drop by previous ban: %s %s' % (room,jid),'brown')
return True
tojid = rss_replace(get_tag_item(msg,'presence','to'))
if is_owner(jid): pass
elif get_config(gr,'muc_filter') and not mute:
show = ['online',get_tag(msg,'show')][int('<show>' in msg and '</show>' in msg)]
if show not in ['chat','online','away','xa','dnd']: msg = msg.replace(get_tag_full(msg,'show'), '<show>online</show>')
status = ['',get_tag(msg,'status')][int('<status>' in msg and '</status>' in msg)]
nick = ['',tojid[tojid.find('/')+1:]]['/' in tojid]
newjoin = True
for tmp in megabase:
if tmp[0] == gr and tmp[4] == jid:
newjoin = False
break
# Drop presences without history
if not mute and newjoin and get_config(gr,'muc_filter_history'):
try: v = not sum([int(t) for t in msg_xmpp.getTag('presence').getTag('x',attrs={'xmlns':xmpp.NS_MUC}).getTag('history').getAttrs().values()])
except: v = False
if v:
muc_pprint('MUC-Filter history: %s/%s %s' % (gr,nick,jid),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by history request!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
if get_config(gr,'muc_filter_history_ban'):
muc_pprint('MUC-Filter history ban: %s/%s %s' % (gr,nick,jid),'brown')
sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':gr},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':jid},[xmpp.Node('reason',{},'Banned by empty history at %s' % timeadd(tuple(time.localtime())))])])]))
# Fast join filter
if not mute and newjoin and get_config(gr,'muc_filter_fast_join'):
_itt = int(time.time())
if muc_filter_fast_join.has_key(gr):
_cnt = get_config_int(gr,'muc_filter_fast_join_count')
_time = get_config_int(gr,'muc_filter_fast_join_time')
muc_filter_fast_join[gr] = [_itt] + muc_filter_fast_join[gr][:_cnt-1]
if len(muc_filter_fast_join[gr]) == _cnt and (muc_filter_fast_join[gr][0] - muc_filter_fast_join[gr][-1]) <= _time:
muc_pprint('MUC-Filter fast join: %s/%s %s' % (gr,nick,jid),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by fast join! Try again later!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
else: muc_filter_fast_join[gr] = [_itt]
# Validate items
if not mute and msg and get_config(gr,'muc_filter_validate_action') != 'off':
is_valid = True
validate_limit = get_config_int(gr,'muc_filter_validate_count')
validate_count = 0
id_node,id_ver,id_hash = 'empty','empty','empty'
if get_config(gr,'muc_filter_validate_nick'):
iv,vc = validate_nick(nick,validate_limit)
validate_count += vc
if validate_count > validate_limit or not iv: is_valid = False
if is_valid and get_config(gr,'muc_filter_validate_login'):
iv,vc = validate_nick(getName(jid),validate_limit)
validate_count += vc
if validate_count > validate_limit or not iv: is_valid = False
if is_valid and get_config(gr,'muc_filter_validate_resource'):
iv,vc = validate_nick(getResourse(jid),validate_limit)
validate_count += vc
if validate_count > validate_limit or not iv: is_valid = False
if is_valid:
msg_xmpp_tmp = msg_xmpp.getTag('presence')
caps_error = False
try: id_node = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")').decode('utf-8')
except: id_node,caps_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")'),True
try: id_ver = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")').decode('utf-8')
except: id_ver,caps_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")'),True
try: id_hash = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("hash")').decode('utf-8')
except: id_hash,caps_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("hash")'),True
if caps_error: writefile(slog_folder % 'bad_stanza_%s.txt' % int(time.time()),unicode(msg_xmpp).encode('utf-8'))
if get_config(gr,'muc_filter_validate_caps_node'):
iv,vc = validate_nick(id_node,validate_limit)
validate_count += vc
if validate_count > validate_limit or not iv: is_valid = False
if is_valid and get_config(gr,'muc_filter_validate_caps_version') and [len(id_ver),id_hash] in [[24,'md5'],[28,'sha-1']] and not id_ver.endswith('='):
iv,vc = validate_nick(id_ver,validate_limit)
validate_count += vc
if validate_count > validate_limit or not iv: is_valid = False
if not is_valid:
act = get_config(gr,'muc_filter_validate_action')
muc_pprint('MUC-Filter invalid items [%s]: %s/%s %s [%s] %s %s %s' % (act,gr,nick,jid,validate_count,id_node,id_ver,id_hash),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by validation!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
tmp_server = getServer(jid)
tmp2_server = '%s/%s' % (gr,tmp_server)
if act == 'ban' and not server_hash_list.has_key('%s/%s' % (gr,getRoom(jid))):
server_hash_list['%s/%s' % (gr,getRoom(jid))] = time.time()
sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':gr},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':jid},[xmpp.Node('reason',{},'Banned by invalid items at %s' % timeadd(tuple(time.localtime())))])])]))
elif act == 'ban server' and tmp_server not in get_config(gr,'muc_filter_validate_ban_server_exception').split() and not server_hash_list.has_key(tmp2_server):
server_hash_list[tmp2_server] = time.time()
sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':gr},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':tmp_server},[xmpp.Node('reason',{},'Banned by invalid items at %s' % timeadd(tuple(time.localtime())))])])]))
tmp_notify = get_config(gr,'muc_filter_validate_ban_server_notify_jid')
if len(tmp_notify):
for tmp in tmp_notify.split():
if len(tmp): send_msg('chat', tmp, '', L('Server %s was banned in %s',rn) % (tmp_server,gr))
# Lock by caps
if not mute and msg and get_config(gr,'muc_filter_caps_list') != 'off':
caps_error = False
if get_config(gr,'muc_filter_caps_list') == 'white': caps_list,caps_negate = 'muc_filter_caps_white',True
else: caps_list,caps_negate = 'muc_filter_caps_black',False
c_list = [t.strip() for t in get_config(gr,caps_list).split('\n') if t and not t.startswith('#')]
if c_list:
msg_xmpp_tmp = msg_xmpp.getTag('presence')
id_node,id_ver = 'error!','error!'
try: id_node = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")').decode('utf-8')
except: id_node,caps_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")'),True
try: id_ver = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")').decode('utf-8')
except: id_ver,caps_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")'),True
try:
id_bmver = msg_xmpp_tmp.getAttr('ver').decode('utf-8')
if id_bmver or id_bmver == '': id_bmver = '%s_' % id_bmver
else: id_bmver = ''
except: id_bmver = ''
c_caps = '%s %s %s' % (id_node,id_ver,id_bmver)
if caps_matcher(c_caps,c_list) ^ caps_negate:
muc_pprint('MUC-Filter caps node lock (%s): %s/%s %s %s' % (['black','white'][caps_negate],gr,nick,jid,c_caps),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by node lock!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
if caps_error: writefile(slog_folder % 'bad_stanza_%s.txt' % int(time.time()),unicode(msg_xmpp).encode('utf-8'))
# Hash lock
if not mute and msg and get_config(gr,'muc_filter_deny_hash'):
hashes_list = reduce_spaces_all(get_config(gr,'muc_filter_deny_hash_list').replace(',',' ').replace(';',' ').replace('|',' ')).split()
if hashes_list:
msg_xmpp_tmp = msg_xmpp.getTag('presence')
#id_node = id_ver = id_lang = id_photo = id_avatar = 'error!'
id_ver,id_lang,id_photo,id_avatar = 'error!','error!','error!','error!'
hash_error = False
#try: id_node = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")').decode('utf-8')
#except: id_node,hash_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")'),True
try: id_ver = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")').decode('utf-8')
except: id_ver,hash_error = get_eval_item(msg_xmpp_tmp,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")'),True
try:
id_bmver = msg_xmpp_tmp.getAttr('ver').decode('utf-8')
if id_bmver or id_bmver == '': id_bmver = '%s_' % id_bmver
else: id_bmver = ''
except: id_bmver = ''
try: id_lang = get_eval_item(msg_xmpp_tmp,'getAttr("xml:lang")').decode('utf-8')
except: id_lang,hash_error = get_eval_item(msg_xmpp_tmp,'getAttr("xml:lang")'),True
try: id_photo = get_eval_item(msg_xmpp_tmp,'getTag("x",namespace=xmpp.NS_VCARD_UPDATE).getTagData("photo")').decode('utf-8')
except: id_photo,hash_error = get_eval_item(msg_xmpp_tmp,'getTag("x",namespace=xmpp.NS_VCARD_UPDATE).getTagData("photo")'),True
try: id_avatar = get_eval_item(msg_xmpp_tmp,'getTag("x",namespace=xmpp.NS_AVATAR).getTagData("hash")').decode('utf-8')
except: id_avatar,hash_error = get_eval_item(msg_xmpp_tmp,'getTag("x",namespace=xmpp.NS_AVATAR).getTagData("hash")'),True
hash_body = '<'.join([unicode(tmp) for tmp in id_avatar,id_photo,id_ver,id_bmver,id_lang]) + '<<'
if hash_error:
writefile(slog_folder % 'bad_stanza_%s.txt' % int(time.time()),unicode(msg_xmpp).encode('utf-8'))
hash_body = parser(hash_body.decode('utf-8'))
current_hash = hashlib.md5(hash_body.encode('utf-8')).digest().encode('base64').replace('\n','')
hashes['%s/%s' % (gr,nick)] = current_hash
if current_hash in hashes_list:
muc_pprint('MUC-Filter hash lock: %s/%s %s %s' % (gr,nick,jid,current_hash),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by hash lock!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
tmp_server = getServer(jid)
tmp2_server = '%s/%s' % (gr,tmp_server)
if get_config(gr,'muc_filter_hash_ban_by_rejoin') and not server_hash.has_key(tmp2_server):
if user_hash.has_key('%s/%s' % (gr,getRoom(jid))):
user_hash.pop('%s/%s' % (gr,getRoom(jid)))
sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':gr},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':jid},[xmpp.Node('reason',{},'Banned by hash activity at %s' % timeadd(tuple(time.localtime())))])])]))
muc_pprint('MUC-Filter ban by hash lock: %s/%s' % (gr,nick),'brown')
else: user_hash['%s/%s' % (gr,getRoom(jid))] = time.time()
if get_config(gr,'muc_filter_hash_ban_server_by_rejoin'):
if tmp_server not in get_config(gr,'muc_filter_hash_ban_server_by_rejoin_exception').split():
tmp_rejoins = get_config_int(gr,'muc_filter_hash_ban_server_by_rejoin_rejoins')
if server_hash.has_key(tmp2_server): server_hash[tmp2_server] = [time.time()] + server_hash[tmp2_server][:tmp_rejoins-1]
else: server_hash[tmp2_server] = [time.time()]
tmp_times = server_hash[tmp2_server]
if len(tmp_times) == tmp_rejoins and tmp_times[0]-tmp_times[-1] <= get_config_int(gr,'muc_filter_hash_ban_server_by_rejoin_timeout') and not server_hash_list.has_key(tmp2_server):
server_hash_list[tmp2_server] = time.time()
sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':gr},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'affiliation':'outcast', 'jid':tmp_server},[xmpp.Node('reason',{},'Banned by hash activity at %s' % timeadd(tuple(time.localtime())))])])]))
muc_pprint('MUC-Filter server ban by hash lock: %s %s' % (gr,tmp_server),'brown')
tmp_notify = get_config(gr,'muc_filter_hash_ban_server_by_rejoin_notify_jid')
if len(tmp_notify):
for tmp in tmp_notify.split():
if len(tmp): send_msg('chat', tmp, '', L('Server %s was banned in %s',rn) % (tmp_server,gr))
else: pprint('User hash: %s %s/%s %s' % (current_hash,gr,nick,jid),'white')
# Blacklist
if not mute and msg and get_config(gr,'muc_filter_blacklist'):
bl_jid = get_config(gr,'muc_filter_blacklist_rules_jid')
try: re.compile(bl_jid)
except: bl_jid = None
bl_nick = get_config(gr,'muc_filter_blacklist_rules_nick')
try: re.compile(bl_nick)
except: bl_nick = None
is_bl = None
if bl_jid and re.findall(bl_jid,jid,re.S|re.I|re.U): is_bl = True
if not nick or (not is_bl and bl_nick and re.findall(bl_nick,nick,re.S|re.I|re.U)): is_bl = True
if is_bl:
muc_pprint('MUC-Filter blacklist: %s/%s %s' % (gr,nick,jid),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by blacklist!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
# Whitelist
if not mute and msg and get_config(gr,'muc_filter_whitelist') and newjoin:
in_base = cur_execute_fetchone('select jid from age where room=%s and jid=%s',(gr,getRoom(jid)))
if not in_base:
muc_pprint('MUC-Filter whitelist: %s/%s %s' % (gr,nick,jid),'brown')
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Deny by whitelist!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
# AD-Block filter
need_raw = True
if not mute and msg and get_config(gr,'muc_filter_adblock_prs') != 'off':
fs,fn = [],[]
for reg in adblock_regexp:
tmps = [None,re.findall(reg,status,re.S|re.I|re.U)][status != '']
tmpn = [None,re.findall(reg,nick,re.S|re.I|re.U)][nick != '']
if tmps: fs = fs + tmps
if tmpn: fn = fn + tmpn
if fs:
need_raw = False
act = get_config(gr,'muc_filter_adblock_prs')
muc_pprint('MUC-Filter adblock prs status (%s): %s [%s] %s' % (act,jid,room,status),'brown')
if act == 'replace':
for tmp in fs: status = status.replace(tmp,[GT('censor_text')*len(tmp),GT('censor_text')][len(GT('censor_text'))>1])
msg = msg.replace(get_tag_full(msg,'status'),'<status>%s</status>' % status)
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('AD-Block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('AD-Block!',rn))
if fn and msg:
need_raw = False
act = get_config(gr,'muc_filter_adblock_prs')
muc_pprint('MUC-Filter adblock prs nick (%s): %s [%s] %s' % (act,jid,room,nick),'brown')
if act == 'replace':
for tmp in fn: nick = nick.replace(tmp,[GT('censor_text')*len(tmp),GT('censor_text')][len(GT('censor_text'))>1])
msg = msg.replace(esc_max2(tojid),'%s/%s' % (tojid.split('/',1)[0],nick))
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('AD-Block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('AD-Block!',rn))
# Raw AD-Block filter
if not mute and msg and need_raw and get_config(gr,'muc_filter_adblock_prs_raw') != 'off':
rawstatus = match_for_raw(status,u'[a-zа-я0-9@.]*',gr)
rawnick = match_for_raw(nick,u'[a-zа-я0-9@.]*',gr)
fs,fn = [],[]
for reg in adblock_regexp:
tmps = [None,re.findall(reg,rawstatus,re.S|re.I|re.U)][status != '']
tmpn = [None,re.findall(reg,rawnick,re.S|re.I|re.U)][nick != '']
if tmps: fs = fs + tmps
if tmpn: fn = fn + tmpn
if rawstatus and fs:
act = get_config(gr,'muc_filter_adblock_prs_raw')
muc_pprint('MUC-Filter raw adblock prs status (%s): %s [%s] %s' % (act,jid,room,status),'brown')
if newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('AD-Block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Raw AD-Block!',rn))
if rawnick and fn and msg:
act = get_config(gr,'muc_filter_adblock_prs_raw')
muc_pprint('MUC-Filter raw adblock prs nick (%s): %s [%s] %s' % (act,jid,room,nick),'brown')
if newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('AD-Block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Raw AD-Block!',rn))
# New Line
if not mute and msg and get_config(gr,'muc_filter_newline') != 'off':
act = get_config(gr,'muc_filter_newline')
try:
nline_count = get_config_int(gr,'muc_filter_newline_count')
if not 2 <= nline_count <= 50: raise
except:
nline_count = int(config_prefs['muc_filter_newline_count'][3])
put_config(gr,'muc_filter_newline_count',str(nline_count))
if status.count('\n') >= nline_count:
muc_pprint('MUC-Filter prs new line (%s): %s [%s] %s' % (act,jid,room,nick+'|'+status.replace('\n','[CR]').replace('\r','[LF]')),'brown')
if act == 'replace':
status = reduce_spaces_all(status.replace('\n',' ').replace('\r',' '))
msg = msg.replace(get_tag_full(msg,'status'),'<status>%s</status>' % status)
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Blocked by content!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Blocked by content!',rn))
# Reduce spaces
if not mute and msg and get_config(gr,'muc_filter_reduce_spaces_prs') and (' ' in status or ' ' in nick):
muc_pprint('MUC-Filter prs reduce spaces: %s [%s] %s' % (jid,room,nick+'|'+status),'brown')
if len(status):
status = reduce_spaces_all(status)
msg = msg.replace(get_tag_full(msg,'status'),'<status>%s</status>' % status).replace(esc_max2(tojid),'%s/%s' % (tojid.split('/',1)[0],reduce_spaces_all(esc_max2(nick))))
else: msg = msg.replace(esc_max2(tojid),'%s/%s' % (tojid.split('/',1)[0],reduce_spaces_all(esc_max2(nick))))
# Censor filter
need_raw = True
if not mute and msg and get_config(gr,'muc_filter_censor_prs') != 'off' and '%s|%s' % (esc_min2(status),esc_min2(nick)) != to_censore('%s|%s' % (esc_min2(status),esc_min2(nick)),gr):
act = get_config(gr,'muc_filter_censor_prs')
need_raw = False
muc_pprint('MUC-Filter prs censor (%s): %s [%s] %s' % (act,jid,room,'%s|%s' % (status,nick)),'brown')
if act == 'replace':
if len(status):
status = esc_max2(to_censore(esc_min2(status),gr))
msg = msg.replace(get_tag_full(msg,'status'),'<status>%s</status>' % status).replace(esc_max2(tojid),'%s/%s' % (tojid.split('/',1)[0],to_censore(esc_max2(nick),gr)))
else: msg = msg.replace(esc_max2(tojid),'%s/%s' % (tojid.split('/',1)[0],to_censore(esc_max2(nick),gr)))
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Blocked by censor!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Blocked by censor!',rn))
# Raw censor filter
if not mute and msg and need_raw and get_config(gr,'muc_filter_censor_prs_raw') != 'off':
rawstatus = match_for_raw(status,u'[a-zа-я0-9]*',gr)
rawnick = match_for_raw(nick,u'[a-zа-я0-9]*',gr)
if (rawstatus or rawnick) and '%s|%s' % (rawstatus,rawnick) != to_censore('%s|%s' % (rawstatus,rawnick),gr):
act = get_config(gr,'muc_filter_censor_prs_raw')
muc_pprint('MUC-Filter prs raw censor (%s): %s [%s] %s' % (act,jid,room,nick+'|'+status),'brown')
if newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Blocked by censor!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Blocked by raw censor!',rn))
# Large status filter
if not mute and msg and get_config(gr,'muc_filter_large_status') != 'off' and len(esc_min2(status)) > GT('muc_filter_large_status_size'):
act = get_config(gr,'muc_filter_large_status')
muc_pprint('MUC-Filter large status (%s): %s [%s] %s' % (act,jid,room,status),'brown')
if act == 'truncate': msg = msg.replace(get_tag_full(msg,'status'),u'<status>%s…</status>' % esc_max2(esc_min2(status)[:GT('muc_filter_large_status_size')]))
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Large status block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Large status block!',rn))
# Large nick filter
if not mute and msg and get_config(gr,'muc_filter_large_nick') != 'off' and len(esc_min2(nick)) > GT('muc_filter_large_nick_size'):
act = get_config(gr,'muc_filter_large_nick')
if act == 'truncate': msg = msg.replace(esc_max2(tojid),u'%s/%s…' % (tojid.split('/',1)[0],esc_max2(esc_min2(nick)[:GT('muc_filter_large_nick_size')])))
elif newjoin: msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('Large nick block!',rn)])])])).replace('replace_it',get_tag(msg,'presence')),True
elif act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Large nick block!',rn))
# Rejoin filter
if not mute and msg and get_config(gr,'muc_filter_rejoin') and newjoin:
ttojid = '%s|%s' % (getRoom(tojid),getRoom(jid))
try: muc_rejoins[ttojid] = [muc_rejoins[ttojid],muc_rejoins[ttojid][1:]][len(muc_rejoins[ttojid])==GT('muc_filter_rejoin_count')] + [int(time.time())]
except: muc_rejoins[ttojid] = []
if len(muc_rejoins[ttojid]) == GT('muc_filter_rejoin_count'):
tmo = muc_rejoins[ttojid][GT('muc_filter_rejoin_count')-1] - muc_rejoins[ttojid][0]
if tmo < GT('muc_filter_rejoin_timeout'):
msg,mute = unicode(xmpp.Node('presence', {'from': tojid, 'type': 'error', 'to':jid}, payload = ['replace_it',xmpp.Node('error', {'type': 'auth','code':'403'}, payload=[xmpp.Node('forbidden',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[]),xmpp.Node('text',{'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'},[L('To many rejoins! Wait %s sec.',rn) % GT('muc_filter_rejoin_timeout')])])])).replace('replace_it',get_tag(msg,'presence')),True
muc_pprint('MUC-Filter rejoin: %s [%s] %s' % (jid,room,nick),'brown')
# Status filter
if not mute and msg and get_config(gr,'muc_filter_repeat_prs') != 'off' and not newjoin:
ttojid = '%s|%s' % (getRoom(tojid),getRoom(jid))
try: muc_statuses[ttojid] = [muc_statuses[ttojid],muc_statuses[ttojid][1:]][len(muc_statuses[ttojid])==GT('muc_filter_status_count')] + [int(time.time())]
except: muc_statuses[ttojid] = []
if len(muc_statuses[ttojid]) == GT('muc_filter_status_count'):
tmo = muc_statuses[ttojid][GT('muc_filter_status_count')-1] - muc_statuses[ttojid][0]
if tmo < GT('muc_filter_status_timeout'):
act = get_config(gr,'muc_filter_repeat_prs')
muc_pprint('MUC-Filter status (%s): %s [%s] %s' % (act,jid,room,nick),'brown')
if act == 'mute': msg,mute = None,True
else: msg = muc_filter_action(act,jid,room,L('Status-flood block!',rn))
if msg:
i=xmpp.Iq(to=room, typ='result')
i.setAttr(key='id', val=id)
i.setTag('query',namespace=xmpp.NS_MUC_FILTER).setTagData(tag='message', val='')
try: return unicode(i).replace('<message />',msg)
except: pass
return None
global iq_hook
iq_hook = [[200,'set',muc_filter_set]]

126
plugins/net.py Normal file
View File

@@ -0,0 +1,126 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def vendor_by_mac(type, jid, nick, text):
text = text.strip().replace('-','').replace(':','').replace(' ','')[:6].upper()
if text and len(text) == 6:
result = html_encode(load_page('http://standards.ieee.org/cgi-bin/ouisearch?%s' % text))
r = re.findall('\(hex\)(.*?)\n',result,re.S|re.I)
if 'Sorry!' in result and not r: msg = L('Not found!','%s/%s'%(jid,nick))
else: msg = r[0].strip().upper()
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def net_ping(type, jid, nick, text):
text = text.strip().lower().encode('idna')
if '.' in text and len(text) > 4 and re.match(r'[-0-9a-z.]+\Z', text, re.U+re.I): msg = deidna(shell_execute('ping -c4 %s' % text,'%s/%s'%(jid,nick)))
else: msg = L('Smoke help about command!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def get_tld(type, jid, nick, text):
if len(text) >= 2:
tld = readfile(tld_list).decode('utf-8')
tld = tld.split('\n')
msg = L('Not found!','%s/%s'%(jid,nick))
for tl in tld:
if tl.split('\t')[0].lower()==text.lower():
msg = '.'+tl.replace('\t',' - ',1).replace('\t','\n')
break
else: msg = L('What do you want to find?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def get_dns(type, jid, nick, text):
is_ip = None
if text.count('.') == 3:
is_ip = True
for ii in text:
if not nmbrs.count(ii):
is_ip = None
break
if is_ip:
try: msg = socket.gethostbyaddr(text)[0]
except: msg = L('I can\'t resolve it','%s/%s'%(jid,nick))
else:
try:
ans = socket.gethostbyname_ex(text.encode('idna'))[2]
msg = text+' - '
for an in ans: msg += an + ' | '
msg = msg[:-2]
except: msg = L('I can\'t resolve it','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def srv_nslookup(type, jid, nick, text):
srv_raw_check(type, jid, nick, 'nslookup '+text)
def srv_dig(type, jid, nick, text):
srv_raw_check(type, jid, nick, 'dig '+text)
def srv_host(type, jid, nick, text):
srv_raw_check(type, jid, nick, 'host '+text)
def srv_raw_check(type, jid, nick, text):
text = enidna_raw(text)
text = ''.join(re.findall(u'[-a-z0-9\.\_\?\#\=\@\%\ \+]+',text,re.S|re.I)[0])
send_msg(type, jid, nick, deidna(shell_execute(text,'%s/%s'%(jid,nick))))
def chkserver(type, jid, nick, text):
for a in ':;&/|\\\n\t\r': text = text.replace(a,' ')
t = re.findall(u'[-a-zа-я0-9._?#=@%]+',text,re.S|re.I|re.U)
if len(t) >= 2:
port = []
for a in t:
if a.isdigit(): port.append(a)
for a in port: t.remove(a)
if len(t)==1 and len(port)>=1:
t = t[0]
port.sort()
msg = shell_execute('nmap %s -p%s -P0 -T5' % (t.encode('idna'),','.join(port)),'%s/%s'%(jid,nick))
try: msg = '%s\n%s' % (t.encode('idna'),reduce_spaces_all(re.findall('SERVICE(.*)Nmap',msg,re.S|re.U)[0][1:-2]))
except:
try:
msg = ''
for a in port:
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
sock.connect((t.encode('idna'),int(a)))
s = L('on','%s/%s'%(jid,nick))
except: s = L('off','%s/%s'%(jid,nick))
msg += '\n%s %s' % (a,s)
sock.close()
msg = '%s%s' % (t,msg)
except: msg = '%s - %s' % (t,L('unknown','%s/%s'%(jid,nick)))
msg = L('Port status at %s','%s/%s'%(jid,nick)) % msg
else: msg = L('What?','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(6, 'nslookup', srv_nslookup, 2, 'Command nslookup'),
(6, 'host', srv_host, 2, 'Command host'),
(6, 'dig', srv_dig, 2, 'Command dig'),
(4, 'port', chkserver, 2, 'Check port activity\nport server port1 [port2 ...]'),
(4, 'net_ping', net_ping, 2, 'Net Ping.\nnet_ping ip|domain'),
(3, 'dns', get_dns, 2, 'DNS resolver.'),
(3, 'tld', get_tld, 2, 'Search domain zones TLD.'),
(3, 'mac', vendor_by_mac, 2, 'Show vendor of device by mac')]

37
plugins/oboobs.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def oboobs(type, jid, nick):
try: msg = 'http://media.oboobs.ru/%s' % json.loads(load_page('http://api.oboobs.ru/noise/1/'))[0]['preview']
except: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def obutts(type, jid, nick):
try: msg = 'http://media.obutts.ru/%s' % json.loads(load_page('http://api.obutts.ru/noise/1/'))[0]['preview']
except: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'oboobs', oboobs, 1, 'Show random picture from oboobs.ru'),
(3, 'obutts', obutts, 1, 'Show random picture from obutts.ru')]

37
plugins/paste.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def private_paste(type, jid, nick, text):
if type == 'groupchat': msg = L('This command available only in private!','%s/%s'%(jid,nick))
else: msg = paste_text(text,jid,get_level(jid,nick)[1])
send_msg(type, jid, nick, msg)
def public_paste(type, jid, nick, text):
if type == 'groupchat': msg = L('This command available only in private!','%s/%s'%(jid,nick))
else: msg,type,nick = L('%s pasted by %s','%s/%s'%(jid,nick)) % (paste_text(text,jid,get_level(jid,nick)[1]),nick),'groupchat',''
send_msg(type, jid, nick, msg)
global execute
execute = [(4, 'paste', public_paste, 2, 'Paste some text to server'),
(5, 'ppaste', private_paste, 2, 'Paste some text to server')]

129
plugins/phone.py Normal file
View File

@@ -0,0 +1,129 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
phone_short_format = '%s%s%s-%s%s-%s%s'
phone_ru_format = '+%s (%s%s%s) ' + phone_short_format
phone_ua_format = '+%s%s (%s%s%s) ' + phone_short_format
def phonecode(type, jid, nick, text):
if len(text):
def_info,country = L('Not found!','%s/%s'%(jid,nick)),L('Unknown','%s/%s'%(jid,nick))
if text[0] == '+': text = text[1:]
if text.isdigit():
if text[0] == '7':
if len(text) > 1 and text[1] == '9':
country = L('Russia, Mobile','%s/%s'%(jid,nick))
if len(text) >= 5:
dc, pn = text[1:4], text[4:]
if len(pn) < 7: pn = pn.ljust(7, '0')
elif len(pn) > 7: pn = pn[:7]
result = cur_execute_fetchall('select * from def_ru_mobile where def=%s and defbegin<=%s and defend>=%s', (dc,pn,pn))
if result:
def pfs(t): return phone_short_format % tuple('%07d' % t)
def_info = '\n'.join(['%s, %s (%s) %s..%s, %s ' % (res[0],res[1],res[2],pfs(res[3]),pfs(res[4]),res[5]) for res in result])
else: def_info = L('Too many results!','%s/%s'%(jid,nick))
else:
country = L('Russia','%s/%s'%(jid,nick))
if len(text) < 11: text = text.ljust(12, '2')
elif len(text) > 11: text = text[:11]
text = text[:7] + 'x'*4
pos = 7
while pos:
result = cur_execute_fetchall('select * from def_ru_stat where phone ilike %s', ('%s%%'%text,))
if result:
def_info = []
for res in result:
res = list(res)
while '' in res: res.remove('')
res[0] = phone_ru_format % tuple(res[0])
def_info += [', '.join(res)]
def_info = '\n'.join(def_info)
break
else:
text = list(text)
text[pos] = 'x'
text = ''.join(text)
pos -= 1
elif text[:3] == '380':
country = L('Ukraine','%s/%s'%(jid,nick))
if len(text) < 12: text = text.ljust(12, '2')
elif len(text) > 12: text = text[:12]
text = text[:8]+'x'*4
pos = 8
while pos > 2:
result = cur_execute_fetchall('select * from def_ua_stat where phone ilike %s', ('%s%%'%text,))
if result:
def_info = []
for res in result:
res = list(res)
while '' in res: res.remove('')
res[0] = phone_ua_format % tuple(res[0])
def_info += [', '.join(res)]
def_info = '\n'.join(def_info)
break
else:
text = list(text)
text[pos] = 'x'
text = ''.join(text)
pos -= 1
if country == L('Unknown','%s/%s'%(jid,nick)): result = def_info
elif def_info == L('Not found!','%s/%s'%(jid,nick)): result = L('Country: %s, Phone number not found','%s/%s'%(jid,nick)) % (country,)
else: result = L('Country: %s\n%s','%s/%s'%(jid,nick)) % (country,def_info)
else:
text = '%s%%'%text.lower().capitalize()
def_info = []
result = cur_execute_fetchall('select * from def_ru_stat where city ilike %s', (text,))
if result:
di = []
for res in result:
res = list(res)
while '' in res: res.remove('')
res[0] = phone_ru_format % tuple(res[0])
di += [', '.join(res)]
di = '\n'.join(di)
def_info += [L('Country: %s\n%s','%s/%s'%(jid,nick)) % (L('Russia','%s/%s'%(jid,nick)),di)]
result = cur_execute_fetchall('select * from def_ua_stat where city ilike %s', (text,))
if result:
di = []
for res in result:
res = list(res)
while '' in res: res.remove('')
res[0] = phone_ua_format % tuple(res[0])
di += [', '.join(res)]
di = '\n'.join(di)
def_info += [L('Country: %s\n%s','%s/%s'%(jid,nick)) % (L('Ukraine','%s/%s'%(jid,nick)),di)]
#result = cur_execute_fetchall('select * from def_ru_mobile where provider ilike %s or region ilike %s', (text,text))
#if result:
# di = []
# for res in result: di += ['%s, %s (%s) %s..%s, %s ' % res]
# di = '\n'.join(di)
# def_info += [L('Country: %s\n%s','%s/%s'%(jid,nick)) % (L('Russia, Mobile','%s/%s'%(jid,nick)),di)]
if def_info: result = '\n\n'.join(def_info)
else: result = L('Not found!','%s/%s'%(jid,nick))
msg = result
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'phone', phonecode, 2, 'Information about telephone city code, DEF code or search code for city.')]

86
plugins/psto.py Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
PSTO_JID = 'psto@psto.net/Psto'
PSTO_ERROR = '\nYou cannot read this psto.'
psto_msg_trunc = 64
psto_id = {}
def psto(type, jid, nick, text):
global psto_id
if not len(text) or len(text) == text.count(' '):
send_msg(type, jid, nick, L('What message do you want to find?','%s/%s'%(jid,nick)))
return
try:
psto_idn,psto_comm = re.findall('#?([a-z]{5,})\/?([0-9]*\-*[0-9]*)?',text)[0]
if psto_idn:
psto_id[psto_idn] = '%s\n%s\n%s\n%s' % (type,jid,nick,psto_comm)
send_msg('chat', PSTO_JID, '', '#%s+' % psto_idn)
else: send_msg(type, jid, nick, L('Smoke help about command!','%s/%s'%(jid,nick)))
except: send_msg(type, jid, nick, L('Smoke help about command!','%s/%s'%(jid,nick)))
def psto_catch(room,jid,nick,type,text):
global psto_id
if '%s/%s' % (room,nick) != PSTO_JID: return
if text == PSTO_ERROR:
(type,jid,nick,psto_comm) = psto_id.popitem()[1].split('\n')
send_msg(type, jid, nick, text[1:])
else:
try:
psto_idn, text = text.split(' ',1)[0][2:],text[1:]
(type,jid,nick,psto_comm) = psto_id.pop(psto_idn).split('\n')
splitter = re.findall('http\:\/\/[-a-z0-9]+?\.psto\.net\/%s' % psto_idn, text, re.S|re.I|re.U)[0]
while '\n\n' in text: text = text.replace('\n\n','\n')
while '\n ' in text: text = text.replace('\n ','\n')
if psto_comm:
new_text = text.split(splitter)[0][:-1]
comment = new_text.split('\n')[-1]
new_text = '\n'.join(new_text.split('\n')[:-1])
if len(new_text) > psto_msg_trunc: new_text = new_text[:psto_msg_trunc] + u'…'
new_text += '\n%s | %s' % (comment,splitter)
if '-' in psto_comm: psto_comm = psto_comm.split('-',1)
else: psto_comm = [psto_comm,psto_comm]
if not psto_comm[0]: psto_comm[0] = '1'
if not psto_comm[1]: psto_comm[1] = str(len(text.split(psto_idn)))
if len(psto_comm[0]) > 3: psto_comm[0] = psto_comm[0][:3]
if len(psto_comm[1]) > 3: psto_comm[1] = psto_comm[1][:3]
msg = ''
for tmp in range(int(psto_comm[0]),int(psto_comm[1])+1):
try: msg += u'• #%s/%s %s' % (psto_idn,tmp,text.split(splitter)[1].split('#%s/%s' % (psto_idn,tmp))[1].split('#%s/%s' % (psto_idn,tmp+1))[0].replace('\n',' ',1))
except: pass
new_text += '\n' + msg
else: new_text = text.split(splitter)[0][:-1] + ' ' + splitter
send_msg(type, jid, nick, new_text)
except: pass
def psto_post(type, jid, nick, text):
send_msg('chat', PSTO_JID, '', text)
time.sleep(1.2)
send_msg(type, jid, nick, L('Message posted to Psto.','%s/%s'%(jid,nick)))
global execute,message_control
message_control = [psto_catch]
execute = [(3, 'psto', psto, 2, 'Miniblogs http://psto.net\npsto [#]post[/[from_comment][-][to_comment]] - show post'),
(9, 'psto_post', psto_post, 2, 'Send message to blog at psto.net')]

78
plugins/quotes.py Normal file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
try: quotes_list = json.loads(readfile(data_folder % 'quotes.txt'),encoding='utf-8')
except:
quotes_list = {'bash':
{'title': u'bash.org.ru - Цитатник Рунета',
'random': ['http://bash.org.ru/random', '<div\ class="text">((?:.|\\s)+?)</div>'],
'number': ['http://bash.org.ru/quote/%s', '<div\ class="text">((?:.|\\s)+?)</div>']}}
def quote(type, jid, nick, text):
global quotes_list
tmp = text.strip().split()
if not tmp: tmp =[random.choice([q for q in quotes_list.keys() if quotes_list[q].has_key('random')])]
if len(tmp) == 1 and tmp[0] == 'list':
msg = (L('Quotes:\n','%s/%s'%(jid,nick)) + '\n'.join(['%s - %s (%s)' % (q, quotes_list[q]['title'],
', '.join(k for k in quotes_list[q].keys() if k != 'title').replace('random', L('rand','%s/%s'%(jid,nick))).replace('number', L('by number','%s/%s'%(jid,nick))).replace('search', L('search','%s/%s'%(jid,nick))))
for q in sorted(quotes_list.keys())]))
elif len(tmp) == 1 and quotes_list.has_key(tmp[0]) and quotes_list[tmp[0]].has_key('random'):
try:
url = quotes_list[tmp[0]]['random'][0]
body = html_encode(load_page(url))
message = re.search(unescape(quotes_list[tmp[0]]['random'][1]), body).group(1)
msg = unhtml(message)
except:
msg = L('Can\'t searching random quote!','%s/%s'%(jid,nick))
elif len(tmp) > 1 and quotes_list.has_key(tmp[0]) and quotes_list[tmp[0]].has_key('number') and re.match('\d+\Z', tmp[1]):
try:
url = quotes_list[tmp[0]]['number'][0] % tmp[1]
body = html_encode(load_page(url))
message = re.search(unescape(quotes_list[tmp[0]]['number'][1]), body).group(1)
msg = unhtml(message)
if not msg:
msg = L('Can\'t searching quote by number!','%s/%s'%(jid,nick))
except:
msg = L('Can\'t searching quote by number!','%s/%s'%(jid,nick))
elif len(tmp) > 1 and quotes_list.has_key(tmp[0]) and quotes_list[tmp[0]].has_key('search'):
try:
url = quotes_list[tmp[0]]['search'][0] % urllib.quote(tmp[1].encode(quotes_list[tmp[0]]['search'][2]))
body = html_encode(load_page(url))
message = re.search(unescape(quotes_list[tmp[0]]['search'][1]), body).group(1)
msg = unhtml(message)
except:
msg = L('Quote not found!','%s/%s'%(jid,nick))
else:
msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def ithap(type, jid, nick, text): quote(type, jid, nick, 'ithap %s' % text)
def afor(type, jid, nick): quote(type, jid, nick, 'afor')
global execute
execute = [(3, 'quote', quote, 2, 'Quote from Internet. Exaples:\nquote list - list of resources\nquote [<key> [number|text]]'),
(3, 'ithap', ithap, 2, 'Quote from ithappens.ru\nithap [number]'),
(3, 'afor', afor, 1, 'Show random aphorism from skio.ru')]

35
plugins/redirect.py Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def to_private(type, room, nick, text): raw_redirect('chat', room, nick, text)
def to_public(type, room, nick, text): raw_redirect('groupchat', room, nick, text)
def raw_redirect(type, room, nick, text):
access_mode,jid = get_level(room,nick)
com_parser(access_mode, get_xnick(room), type, room, nick, text, jid)
global execute
execute = [(3, 'private', to_private, 2, 'Redirect command output in private.'),
(3, 'public', to_public, 2, 'Redirect command output in groupchat.')]

46
plugins/say.py Normal file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def say(type, jid, nick, text):
text = random.choice(re.split(r'(?<!\\)\|', text)).replace('\\|', '|')
send_msg('groupchat', jid, '', to_censore(text,jid))
def psay(type, jid, nick, text):
try:
if '\n' in text: nnick,ntext = text.split('\n',1)
else: nnick,ntext = text.split(' ',1)
send_msg('chat', jid, nnick, to_censore(ntext,jid))
except: send_msg(type, jid, nick, L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick)))
def gsay(type, jid, nick, text):
for jjid in [t[0] for t in cur_execute_fetchall('select room from conference;')]: send_msg('groupchat', getRoom(jjid), '', text)
def set_topic(type, jid, nick, text):
sender(xmpp.Message(jid, subject=text, typ='groupchat'))
global execute
execute = [(6, 'say', say, 2, '"Say" command. Bot say in conference text after command. Example:\nsay text1[|text2[|text3[...]]]'),
(6, 'psay', psay, 2, '"Say" command. Bot say in private all text after command.\npsay <nick>\ntext'),
(9, 'gsay', gsay, 2, 'Global message in all conferences, where bot is present.'),
(7, 'topic', set_topic, 2, 'Set conference topic.')]

149
plugins/sayto.py Normal file
View File

@@ -0,0 +1,149 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
last_cleanup_sayto_base = 0
def sayto(type, jid, nick, text):
while len(text) and text[0] == '\n': text=text[1:]
while len(text) and (text[-1] == '\n' or text[-1] == ' '): text=text[:-1]
if text.split(' ')[0] == 'show':
try: text = text.split(' ',1)[1]
except: text = ''
ga = get_level(jid, nick)
if ga[0] != 9: msg = L('You access level is to low!','%s/%s'%(jid,nick))
else:
cm = cur_execute_fetchall('select * from sayto')
if len(cm):
msg = ''
for cc in cm:
zz = cc[0].split('\n')
tmsg = '\n' + cc[1] +'/'+ zz[0] +' ('+un_unix(time.time()-int(zz[1]),'%s/%s'%(jid,nick))+'|'+un_unix(GT('sayto_timeout')-(time.time()-int(zz[1])),'%s/%s'%(jid,nick))+') '+L('for','%s/%s'%(jid,nick))+' '+cc[2]+' - '+cc[3]
if len(text) and text.lower() in tmsg.lower(): msg += tmsg
elif not len(text): msg += tmsg
if len(msg): msg = L('Not transfered messages: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('Not found!','%s/%s'%(jid,nick))
if type == 'groupchat':
send_msg('chat', jid, nick, msg)
msg = L('Sent in private message','%s/%s'%(jid,nick))
else: msg = L('List is empty.','%s/%s'%(jid,nick))
elif ' ' in text or '\n' in text:
if '\n' in text: splitter = '\n'
else: splitter = ' '
to,what = text.split(splitter,1)[0],text.split(splitter,1)[1]
frm = '%s\n%s' % (nick,int(time.time()))
fnd = cur_execute_fetchall('select jid, status from age where room=%s and nick=%s group by jid, status',(jid,to))
if len(fnd) == 1:
if fnd[0][1]:
msg = L('I will convey your message.','%s/%s'%(jid,nick))
cur_execute('insert into sayto values (%s,%s,%s,%s)', (frm, jid, fnd[0][0], what))
else: msg = L('Or am I a fool or %s is here.','%s/%s'%(jid,nick)) % to
elif len(fnd) > 1:
off_count = 0
for tmp in fnd:
if tmp[1]:
cur_execute('insert into sayto values (%s,%s,%s,%s)', (frm, jid, tmp[0], what))
off_count += 1
if off_count: msg = L('I seen some people with this nick, and I can convey is incorrect. Coincidence: %s, and count convey messages: %s','%s/%s'%(jid,nick)) % (str(len(fnd)), str(off_count))
else: msg = L('All people with this nickname are here!','%s/%s'%(jid,nick))
else:
if '@' in to:
fnd = cur_execute_fetchall('select jid, status from age where room=%s and jid=%s group by jid,status',(jid,to))
if fnd:
off_count = 0
for tmp in fnd:
if tmp[1]:
cur_execute('insert into sayto values (%s,%s,%s,%s)', (frm, jid, tmp[0], what))
off_count += 1
if off_count: msg = L('I will convey your message.','%s/%s'%(jid,nick))
else: msg = L('This jid is here!','%s/%s'%(jid,nick))
else:
msg = L('I didn\'t seen user with jid %s, but if he join here I convey your message.','%s/%s'%(jid,nick)) % to
cur_execute('insert into sayto values (%s,%s,%s,%s)', (frm, jid, to, what))
else: msg = L('I didn\'t see user with nick %s. You can use jid.','%s/%s'%(jid,nick)) % to
else: msg = L('What convey to?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def say_memo(type, jid, nick, text):
while len(text) and text[0] == '\n': text=text[1:]
while len(text) and (text[-1] == '\n' or text[-1] == ' '): text=text[:-1]
gj = getRoom(get_level(jid, nick)[1])
if text.split(' ')[0] == 'show':
try: text = text.split(' ',1)[1]
except: text = ''
t = cur_execute_fetchall('select message,jid from sayto where room=%s and jid ilike %s', (jid,gj))
if t: msg = '\n%s' % '\n'.join([u'• %s' % tmp[0] for tmp in t])
else: msg = L('There is no memo for you!','%s/%s'%(jid,nick))
elif text:
cur_execute('insert into sayto values (%s,%s,%s,%s)', ('\n%s' % int(time.time()), jid, gj, text))
msg = L('I\'ll remember it to you.','%s/%s'%(jid,nick))
else: msg = L('What remember to you?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def sayto_presence(room,jid,nick,type,text):
global conn
if nick != '' and type != 'unavailable':
cm = cur_execute_fetchall('select * from sayto where room=%s and (jid=%s or jid=%s)',(room, getRoom(jid), nick))
if cm:
cur_execute('delete from sayto where room=%s and (jid=%s or jid=%s)',(room, getRoom(jid), nick))
for cc in cm:
if '\n' in cc[0]:
zz = cc[0].split('\n')
if zz[0]: msg = L('%s (%s ago) convey for you: %s','%s/%s'%(room,nick)) % (zz[0], un_unix(time.time()-int(zz[1]),'%s/%s'%(room,nick)), cc[3])
else: msg = L('You ask remember: %s','%s/%s'%(room,nick)) % cc[3]
else: msg = L('%s convey for you: %s','%s/%s'%(room,nick)) % (cc[3], cc[0])
send_msg('chat', room, nick, msg)
def cleanup_sayto_base():
global last_cleanup_sayto_base
ctime = int(time.time())
if ctime-last_cleanup_sayto_base > GT('sayto_cleanup_time'):
last_cleanup_sayto_base = ctime
cm = cur_execute_fetchall('select who, room, jid from sayto')
if len(cm):
for cc in cm:
if '\n' in cc[0]:
tim = int(cc[0].split('\n')[1])
if ctime-tim > GT('sayto_timeout'): cur_execute('delete from sayto where room=%s and jid=%s',(cc[1], cc[2]))
else: cur_execute('delete from sayto where room=%s and jid=%s',(cc[1], cc[2]))
def sayjid(type, jid, nick, text):
try:
text = text.split(' ',1)
if len(text) != 2: msg = L('Error!','%s/%s'%(jid,nick))
elif '@' not in text[0] and '@' not in text[0]: msg = L('Error!','%s/%s'%(jid,nick))
elif not len(text[1]): msg = L('Error!','%s/%s'%(jid,nick))
else:
send_msg(type, jid, nick, L('Sent','%s/%s'%(jid,nick)))
msg = L('%s from conference %s convey message for you: %s','%s/%s'%(jid,nick)) % (nick, jid, text[1])
type, nick, jid = 'chat', '', text[0]
except: msg = L('Error!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute, timer, presence_control
timer = [cleanup_sayto_base]
presence_control = [sayto_presence]
execute = [(3, 'sayto', sayto, 2, '"Say to" command.\nsayto jid|nick message - if jid or nick join in conference, bot send "message". Messages saves 14 days, after if message didn\'t be send this message remove.'),
(7, 'sayjid', sayjid, 2, 'Send message to jid\n sayjid jid message.'),
(3, 'memo', say_memo, 2, 'Send a message to yourself at next join')]

36
plugins/setnick.py Normal file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def set_nickname(type, jid, nick, text):
if get_affiliation(jid,nick) == 'owner' or get_level(jid,nick)[0] == 9:
msg = None
nickname = Settings['nickname']
text = '%s/%s' % (jid, text or nickname)
bot_join(type, jid, nick, text)
else:
msg = L('You can\'t do it!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(8, 'setnick', set_nickname, 2, 'Change bot nick. Available only for conference owner.')]

37
plugins/shell.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def shell(type, jid, nick, text):
sysshell(type, jid, nick, text, 1)
def shell_silent(type, jid, nick, text):
sysshell(type, jid, nick, text, 0)
def sysshell(type, jid, nick, text, mode):
msg = shell_execute(text,'%s/%s'%(jid,nick))
if mode: send_msg(type, jid, nick, msg)
global execute
if not GT('paranoia_mode'): execute = [(9, 'sh', shell, 2, 'Execute shell command.'),
(9, 'sh_silent', shell_silent, 2, 'Execute shell command without output result.')]

44
plugins/shortlink.py Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
SHORT_TINYURL = 'http://tinyurl.com/api-create.php?url=%s'
SHORT_CLCK = 'http://clck.ru/--?url=%s'
SHORT_QR = 'http://chart.apis.google.com/chart?cht=qr&chs=350x350&chld=M|2&chl=%s'
def shorter_raw(type, jid, nick, text, url):
text = text.strip()
if text: msg = load_page(url % enidna(text).decode('utf-8'))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def short_clck(type, jid, nick, text): shorter_raw(type, jid, nick, text, SHORT_CLCK)
def short_tinyurl(type, jid, nick, text): shorter_raw(type, jid, nick, text, SHORT_TINYURL)
def short_qr(type, jid, nick, text): shorter_raw(type, jid, nick, text, SHORT_TINYURL % SHORT_QR)
global execute
execute = [(3, 'clck', short_clck, 2, 'URL Shortener'),
(3, 'tinyurl', short_tinyurl, 2, 'URL Shortener'),
(3, 'qr', short_qr, 2, 'QR-code generator')]

61
plugins/shutdown.py Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def bot_shutdown(type, jid, nick, text, reason, xtype):
global game_over,bot_exit_type
StatusMessage = L('%s by command from %s','%s/%s'%(jid,nick)) % (reason, nick)
if text != '': StatusMessage += ', ' + L('reason: %s','%s/%s'%(jid,nick)) % text
send_presence_all(StatusMessage)
bot_exit_type, game_over = xtype, True
def bot_exit(type, jid, nick, text):
bot_shutdown(type, jid, nick, text, L('Shutdown','%s/%s'%(jid,nick)), 'exit')
def bot_restart(type, jid, nick, text):
bot_shutdown(type, jid, nick, text, L('Restart','%s/%s'%(jid,nick)), 'restart')
def bot_update(type, jid, nick, text):
bot_shutdown(type, jid, nick, text, L('Update','%s/%s'%(jid,nick)), 'update')
def bot_soft_update(type, jid, nick, text):
global plugins_reload
caps_and_send(xmpp.Presence(show='dnd', status=L('Soft update activated!','%s/%s'%(jid,nick)), priority=Settings['priority']))
plugins_reload = True
while not game_over and plugins_reload: time.sleep(1)
if GT('soft_update_resend_hash'):
pprint('*** Send new hash in to rooms','bright_green')
cnf = cur_execute_fetchall('select * from conference;')
for tocon in cnf:
if tocon[1]: pprint('->- %s | pass: %s' % tocon,'green')
else: pprint('->- %s' % tocon[0],'green')
zz = join(tocon)
if Settings['status'] == 'online': caps_and_send(xmpp.Presence(status=Settings['message'], priority=Settings['priority']))
else: caps_and_send(xmpp.Presence(show=Settings['status'], status=Settings['message'], priority=Settings['priority']))
send_msg(type, jid, nick, L('Soft update finished! Plugins loaded: %s. Commands: %s','%s/%s'%(jid,nick)) % (len(plugins)+1,len(comms)))
global execute
execute = [(9, 'quit', bot_exit, 2, 'Shutting down the bot. You can set reason.'),
(9, 'restart', bot_restart, 2, 'Restart the bot. You can set reason.'),
(9, 'update', bot_update, 2, 'Update from VCS. You can set reason.'),
(9, 'soft_update', bot_soft_update, 2, 'Soft update from VCS.')]

55
plugins/sokr.py Normal file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def sokr(type, jid, nick, text):
target = ''
text = text.strip()
if not text: msg = L('What?','%s/%s'%(jid,nick))
else:
if re.search('\A\d+?(-\d+?)? ', text): target, text = text.split(' ', 1)
if re.match('[a-zA-Z]+\Z', text):
data = load_page('http://www.abbreviations.com/%s' % text)
results = re.findall('<p class="desc">(.+?)</p>', data)
results = [i for k,i in enumerate(results) if results.index(i) == k]
else:
data = load_page("http://www.sokr.ru/search/?", {'abbr': text.encode('utf-8'), 'abbr_exact': '1'})
results = re.findall('em class="got_clear">.+?</em></a>.+?<p class="value">(.+?)</p>' , data, re.S)
cr = len(results)
if not results: msg = L('I don\'t know!','%s/%s'%(jid,nick))
else:
if not target:
if cr == 1: target = '1'
elif cr < 6: target = '1-%s' % cr
else: target = '1-5'
try: n1 = n2 = int(target)
except: n1, n2 = map(int, target.split('-'))
if 0 < n1 <= n2 <= cr:
msg = L('Total found %s matches. Result(s) %s:\n','%s/%s'%(jid,nick)) % (cr, target)
msg += '\n'.join(['%s. %s' % (i[0]+n1, i[1].replace('\n',' ')) for i in enumerate(results[n1-1: n2])]).decode('utf8')
msg = msg.replace('<br>', '').replace('\r','')
else: msg = L('I don\'t know!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'sokr', sokr, 2, 'Abbreviations.\nExamples: sokr abbr, sokr 6 abbr, sokr 3-7 abbr')]

42
plugins/sovm.py Normal file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def sovm(type, jid, nick, text):
text = text.lower().strip().replace('.',' ').split()
if text:
text = '.'.join(text)
znaki = getFile(data_folder % 'sovmestimosti.txt',{})
znak = znaki.get(text.encode('utf-8'),None)
if znak:
body = html_encode(load_page('http://astro-goroskop.ru/sovmestimosti/%s.html' % znak)).replace('\n',' ')
if '-' in znak: regexp = 'class="float_img" alt="(.*?)" />(.*?)<script'
else: regexp = 'class="float_img" alt="(.*?)" />(.*?)<br /><br />'
body = re.findall(regexp,body,re.S|re.I|re.U)
if body and len(body[0]) == 2: msg ='\n'.join(t.strip().replace('<br /> <br />','') for t in body[0])
else: msg = L('Error!','%s/%s'%(jid,nick))
else: msg = L('Sign not found!','%s/%s'%(jid,nick))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'sovm', sovm, 2, 'Reconcilability between zodiac signs')]

44
plugins/spellcheck.py Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def spell(type, jid, nick, text):
tmp = text.strip().split(' ', 1)
if tmp[0]:
langs = re.sub('-|:;', ',', tmp[0]).lower()
if len(tmp) == 2 and re.match('((uk)|(en)|(ru))(,((uk)|(en)|(ru)))*?$', langs): text = tmp[1].encode('utf-8')
else: text, langs = text.encode('utf-8'), ''
url = 'http://speller.yandex.net/services/spellservice.json/checkText?text=%s&lang=%s&options=7' % (urllib.quote_plus(text), langs)
j = json.loads(load_page(url),encoding='utf-8')
msg = text.decode('utf-8')
deltapos = 0
for err in j:
try:
msg = msg[:err['pos']+deltapos] + err['s'][0] + msg[err['len']+err['pos']+deltapos:]
deltapos += len(err['s'][0]) - err['len']
except: pass
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(0, 'spell', spell, 2, 'Spellchecker. Example: spell [uk|ru|en] sentence')]

115
plugins/spy.py Normal file
View File

@@ -0,0 +1,115 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
spy_stat_time = int(time.time()) # время последнего сканирования
#conf hrs usrs msgs action
def spy_add(text,rn):
if text == '': return L('what do you want to add?',rn)
text = text.lower()
sconf = text.split(' ')[0]
try: saction = text.split(' ',1)[1]
except: return L('not given tracking',rn)
for tmp in saction.split(' '):
if tmp[0] != 'u' and tmp[0] != 'm':
return L('is not specified criterion tracking',rn)
try: int(tmp[1:])
except: return L('incorrect digital parameter',rn)
if sconf not in [t[0] for t in cur_execute_fetchone('select room from conference;')]: return L('I am not in the %s ',rn) % sconf
if cur_execute_fetchone('select room from spy where room=%s;',(sconf,)):
msg = L('Updated: %s',rn) % text
cur_execute('delete from spy where room=%s;',(sconf,))
else: msg = L('Append: %s',rn) % text
cnt = len(['' for t in megabase if t[0]==tmp[0]])
cur_execute('insert into spy values (%s,%s,%s,%s,%s)',(sconf,int(time.time()),cnt,0,saction))
return msg
def spy_del(text,rn):
if text == '': return L('what do you want remove?',rn)
text = text.lower().split(' ')[0]
if cur_execute_fetchone('select room from spy where room=%s;',(text,)):
cur_execute('delete from spy where room=%s;',(text,))
return L('Removed: %s',rn) % text
else: return L('Not found: %s',rn) % text
def spy_show(rn):
sb = cur_execute_fetchall('select * from spy;')
if not sb: return L('List is empty.')
msg = L('Monitoring conferences:',rn)
msg += '\n%s' % '\n'.join(['%s %s (%s|u%s|m%s)' % (tmp[0],tmp[4],un_unix(int(time.time()-tmp[1]),rn),tmp[2],tmp[3]) for tmp in sb])
msg += L('\nNext scanning across %s',rn) % un_unix(int(GT('scan_time')-(time.time()-spy_stat_time)),rn)
return msg
def conf_spy(type, jid, nick,text):
text = text.strip().lower()
rn = '%s/%s'%(jid,nick)
msg = None
if text.startswith('add '): msg = spy_add(text[4:],rn)
elif text.startswith('del '): msg = spy_del(text[4:],rn)
elif text == 'show': msg = spy_show(rn)
if not msg: msg = L('Smoke help about command!',rn)
send_msg(type, jid, nick, msg)
def spy_message(room,jid,nick,type,text):
sb = cur_execute_fetchone('select message from spy where room=%s;',(room,))
if sb: cur_execute('update spy set message=message+1 where room=%s',(room,))
def get_spy_stat():
global spy_stat_time
if time.time()-spy_stat_time < GT('scan_time'): return None
spy_stat_time = time.time()
sb = cur_execute_fetchone('select room from spy;')
if sb:
for tmp in sb:
cnt = len(['' for t in megabase if t[0]==tmp[0]])
cur_execute('update spy set participant=(participant+%s)/2 where room=%s',(cnt,tmp[0]))
def spy_action():
try:
if cur_execute_fetchone('select count(*) from conference;')[0] == 1: raise
except: return None # Last conference
sb = cur_execute_fetchall('select * from spy where %s-time>%s;',(int(time.time()),GT('spy_action_time')))
for tmp in sb:
act = tmp[4].split(' ')
mist = None
for tmp2 in act:
if tmp2[0] == 'u' and int(tmp2[1:]) > tmp[2]: mist = tmp2
elif tmp2[0] == 'm' and int(tmp2[1:]) > tmp[3]: mist = tmp2
cur_execute('delete from spy where room=%s',(tmp[0],))
if mist:
if cur_execute_fetchall('select * from conference where room ilike %s;', ('%s/%%'%getRoom(tmp[0]),)):
cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(tmp[0]),))
leave(tmp[0], L('I leave your conference because low activity'))
pprint('*** Leave room: %s by spy activity!' % tmp[0],'red')
own = cur_execute_fetchall('select * from bot_owner;')
if own:
for tmpo in own: send_msg('chat', tmpo[0], '', L('I leave conference %s by condition spy plugin: %s') % (tmp[0], mist))
else: cur_execute('insert into spy values (%s,%s,%s,%s,%s)',(tmp[0],int(time.time()),tmp[2], 0,tmp[4]))
global execute, timer, message_control
timer = [get_spy_stat, spy_action]
message_control = [spy_message]
execute = [(9, 'spy', conf_spy, 2, 'Check conference activity\nspy add <conference>[ u<number>][ m<number>] - add conference to list. u - count users, m - count message per night. At default At least one condition - the bot will leave the conference\nspy del <conference> - remove conference from list\nspy show - show active monitoring.')]

79
plugins/steam.py Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
#http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=xxxx&steamids=76561198018559638
#http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=xxxx&steamid=76561198018559638&relationship=friend
steam_api_url = 'http://api.steampowered.com/ISteamUser/%s'
steam_summary = steam_api_url % 'GetPlayerSummaries/v0002/?'
steam_friends = steam_api_url % 'GetFriendList/v0001/?'
def time_str(t):
try: return time.strftime('%Y.%m.%d %H:%M',time.localtime(t))
except: return t
def steam(type, jid, nick, text):
text = text.strip().split()
need_id = len(text) > 1
text = text[0]
if text.isdigit():
STEAM_API = GT('steam_api_key')
if len(STEAM_API) == 32:
try:
data = load_page(steam_summary, {'key': STEAM_API, 'steamids': text})
data = json.loads(data)['response']['players']
if data:
data = data[0]
_PERSONANAME = data.get('personaname',L('Unknown','%s/%s'%(jid,nick)))
_REALNAME = data.get('realname',L('Unknown','%s/%s'%(jid,nick)))
_LOCCOUNTRYCODE = data.get('loccountrycode',L('Unknown','%s/%s'%(jid,nick)))
_TIMECREATED = data.get('timecreated',L('Hidden','%s/%s'%(jid,nick)))
_LASTLOGOFF = data.get('lastlogoff',L('Hidden','%s/%s'%(jid,nick)))
_PROFILEURL = data.get('profileurl',L('Unknown','%s/%s'%(jid,nick)))
data = load_page(steam_friends, {'key': STEAM_API, 'steamid': text, 'relationship': 'friend'})
if data.startswith(L('Error! %s')%''):
_FRIENDS = L('Hidden','%s/%s'%(jid,nick))
_LEN_FRIENDS = L('Unknown','%s/%s'%(jid,nick))
else:
data = json.loads(data)['friendslist']['friends']
_FRIENDS = ','.join(t['steamid'] for t in data)
data = load_page(steam_summary, {'key': STEAM_API, 'steamids': _FRIENDS})
data = json.loads(data)['response']['players']
_FRIENDS = [(t.get('personaname','-'),t['steamid']) for t in data]
_LEN_FRIENDS = len(_FRIENDS)
if need_id: _FRIENDS = ' | '.join('%s %s' % t for t in _FRIENDS)
else: _FRIENDS = ', '.join(t[0] for t in _FRIENDS)
msg = L('Nick: %s\nName: %s\nCountry: %s\nCreated: %s\nLast logoff: %s\nTotal friends: %s\nFriends: %s\nProfile: %s','%s/%s'%(jid,nick)) %\
(_PERSONANAME,_REALNAME,_LOCCOUNTRYCODE,time_str(_TIMECREATED),time_str(_LASTLOGOFF),_LEN_FRIENDS,_FRIENDS,_PROFILEURL)
if need_id and type == 'groupchat':
send_msg(type, jid, nick, L('Send for you in private','%s/%s'%(jid,nick)))
type = 'chat'
else: msg = L('Steam user not found!','%s/%s'%(jid,nick))
except: msg = L('Steam API is broken!','%s/%s'%(jid,nick))
else: msg = L('Steam API key is wrong!','%s/%s'%(jid,nick))
else: msg = L('Steam ID should be digital!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'steam', steam, 2, 'Show information about Steam profile')]

54
plugins/svn.py Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def svn_get(type, jid, nick,text):
if len(text):
if text[:7] !='http://' and text[:8] !='https://' and text[:6] !='svn://': text = 'http://%s' % text
count,revn = 1,0
if '-v' in text.split(): text,verb = reduce_spaces_all(text.replace('-v','')),True
else: verb = False
if ' ' in text:
text = text.split(' ')
url = text[0]
try: count = int(text[1])
except:
try:
if 'r' in text[1].lower(): revn = int(text[1][text[1].find('r')+1:])
except: revn = 0
else: url=text
if revn != 0: sh_exe = 'sh -c \"LANG=%s svn log %s -r%s\"' % (L('en_EN.UTF8','%s/%s'%(jid,nick)),url,revn)
else:
if count > 10: count = 10
sh_exe = 'sh -c \"LANG=%s svn log %s --limit %s\"' % (L('en_EN.UTF8','%s/%s'%(jid,nick)),url,count)
if verb: sh_exe = '%s -v\"' % sh_exe[:-1]
svn_log = shell_execute(sh_exe,'%s/%s'%(jid,nick)).replace('\n\n','\n')
while svn_log[-1] in ['-','\n']: svn_log = svn_log[:-1]
rpl = re.findall('-{10,}',svn_log)
if rpl: svn_log = svn_log.replace(rpl[0],'-'*3)
msg = 'SVN from %s\n%s' % (url,svn_log)
else: msg = L('Read user manual for commands...','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'svn', svn_get, 2, 'Show svn log.\nsvn [http://]url [limit] - show last revision(s) limit\nsvn [http://]url rXXX - show XXX revision')]

49
plugins/talkers.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def gtalkers(type, jid, nick, text):
if text:
ttext = '%%%s%%' % text
tma = cur_execute_fetchall('select * from talkers where (jid ilike %s or nick ilike %s or room ilike %s) order by -words limit %s',(ttext,ttext,ttext,10))
else: tma = cur_execute_fetchall('select * from talkers order by -words limit %s',(10,))
if tma:
msg = '%s\n' % L('Talkers:\nNick\t\tWords\tPhrases\tEffect\tConf.','%s/%s'%(jid,nick))
msg += '\n'.join(['%s. %s\t\t%s\t%s\t%s\t%s' % (cnd + 1, tt[2], tt[3], tt[4], round(tt[3]/float(tt[4]), 2),'%s@%s.%s' % (getName(tt[0]),'.'.join([tmp[0] for tmp in tt[0].split('@')[1].split('.')[:-1]]),tt[0].split('.')[-1])) for cnd, tt in enumerate(tma)])
else: msg = '%s %s' % (text, L('Not found!','%s/%s'%(jid,nick)))
send_msg(type, jid, nick, msg)
def talkers(type, jid, nick, text):
if text:
ttext = '%%%s%%' % text
tma = cur_execute_fetchall('select * from talkers where room=%s and (jid ilike %s or nick ilike %s) order by -words limit %s',(jid,ttext,ttext,10))
else: tma = cur_execute_fetchall('select * from talkers where room=%s order by -words limit %s',(jid,10))
if tma:
msg = '%s\n' % L('Talkers:\nNick\t\tWords\tPhrases\tEffect','%s/%s'%(jid,nick))
msg += '\n'.join(['%s. %s\t\t%s\t%s\t%s' % (cnd + 1, tt[2], tt[3], tt[4], round(tt[3]/float(tt[4]), 2)) for cnd, tt in enumerate(tma)])
else: msg = '%s %s' % (text, L('Not found!','%s/%s'%(jid,nick)))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'talkers', talkers, 2, 'Show local talkers'),
(4, 'gtalkers', gtalkers, 2, 'Show global talkers')]

28
plugins/test.py Normal file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def test(type, jid, nick): send_msg(type, jid, nick, L('Passed!','%s/%s'%(jid,nick)))
global execute
execute = [(0, 'test', test, 1, 'Check bot activity.')]

35
plugins/th.py Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def thread_info(type, jid, nick):
if thread_type:
tmas = [unicode(tmp).split('(',1)[1].split(')',1)[0] for tmp in threading.enumerate()]
tmas.sort()
msg = L('\nActive: %s\n%s','%s/%s'%(jid,nick)) % (threading.activeCount(),'\n'.join(tmas))
else: msg = ''
msg = L('Executed threads: %s | Error(s): %s','%s/%s'%(jid,nick)) % (th_cnt,thread_error_count) + msg
send_msg(type, jid, nick, msg)
global execute
execute = [(7, 'th', thread_info, 1, 'Threads statistic')]

117
plugins/todate.py Normal file
View File

@@ -0,0 +1,117 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def get_holiday(sdate):
''' Function get holiday from file plugins/date.txt and return title of
holiday if holiday found, else return empty unicode message. Input params
must be list of int
:[month, day]:'''
result = ''
date_base = readfile(date_file).decode('UTF').split('\n')
for ddate in date_base:
if ddate != '\n' or ddate != '':
ddate = ddate.split('-')
hdate = ddate[0]
if '.' in hdate:
hdate = map(int, hdate.split('.'))
hdate.reverse()
if hdate == sdate:
result += ddate[1].strip() + ', '
if len(result) > 2: result = result[:-2]
return result
def parse_date_string(string_date, spl='.'):
''' Parse date string and return list [year, month, day] '''
date_formats = ['%d'+spl+'%m', '%d'+spl+'%m'+spl+'%y',
'%d'+spl+'%m'+spl+'%Y', '%Y'+spl+'%m'+spl+'%d']
#output = list(time.localtime())[:3]
for format in date_formats:
try: output = list(time.strptime(string_date, format))[:3]
except: pass
return output
def to_date(type, jid, nick, text):
dmass = (L('days','%s/%s'%(jid,nick)), L('day','%s/%s'%(jid,nick)), L('Days','%s/%s'%(jid,nick)).lower(), L('Days','%s/%s'%(jid,nick)).lower(),
L('Days','%s/%s'%(jid,nick)).lower(), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)))
splitters = ('.', '-', ':', '/', ',', '\\')
if len(text):
try:
spl = [spl for spl in splitters if spl in text][0]
sdate = parse_date_string(text, spl)
if sdate[0] == 1900: sdate[0] = list(time.localtime())[0]
year = sdate.pop(0)
month, day = sdate
hday = get_holiday(sdate)
text = text.replace(spl, '.')
msg = ''
if len(hday) > 0: text = hday
days_remain = (datetime.date(year, month, day) - datetime.date.today()).days
if len(str(abs(days_remain))) > 1 and str(days_remain)[-2] == '1':
dmass = (L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),
L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),
L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)))
if days_remain < 0: msg += L('was %s %s ago','%s/%s'%(jid,nick)) % \
(str(abs(days_remain)), dmass[int(str(days_remain)[-1])])
elif days_remain == 0: msg += L('today','%s/%s'%(jid,nick))
else: msg += L('will be in %s %s','%s/%s'%(jid,nick)) % \
(str(abs(days_remain)), dmass[int(str(days_remain)[-1])])
msg = text + ' ' + msg
except: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def todate(type, jid, nick, text):
dmass = (L('days','%s/%s'%(jid,nick)), L('day','%s/%s'%(jid,nick)), L('Days','%s/%s'%(jid,nick)).lower(), L('Days','%s/%s'%(jid,nick)).lower(),
L('Days','%s/%s'%(jid,nick)).lower(), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)), L('days','%s/%s'%(jid,nick)))
splitters = ('.', '-', ':', '/', ',', '\\')
msg = ''
if len(text):
try:
if ' ' in text: ddate, msg = text.split(' ', 1)[0], text.split(' ', 1)[1]
else: ddate = text
spl = [spl for spl in splitters if spl in ddate][0]
if len(msg) == 0: msg = L('before the %s remained','%s/%s'%(jid,nick)) % ddate.replace(spl, '.')
sdate = parse_date_string(ddate, spl)
if sdate[0] == 1900: sdate[0] = list(time.localtime())[0]
year = sdate.pop(0)
month, day = sdate
days_remain = (datetime.date(year, month, day) - datetime.date.today()).days
if len(str(abs(days_remain))) > 1 and str(days_remain)[-2] == '1':
dmass = (L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),
L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)),
L('days','%s/%s'%(jid,nick)),L('days','%s/%s'%(jid,nick)))
if days_remain < 0: msg = L('Date has already in past!','%s/%s'%(jid,nick))
else: msg += ' %s %s' % (days_remain,dmass[int(str(days_remain)[-1])])
except: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'to_date', to_date, 2, 'Calculate count of days for requested date, if the date is holiday, that returned title of holiday.\nSupported date formats: dd.mm.yyyy, dd.mm, dd.mm.yy, yyyy.mm.dd\nSupported splitters: ,-.:/\\\ntodate 05.09\ntodate 5/9/2010'),
(3, 'todate', todate, 2, 'Calculate count of days for requested date.\nSupported date formats: dd.mm.yyyy, dd.mm, dd.mm.yy, yyyy.mm.dd\nSupported splitter: ,-.:/\\\ntodate 05.09 before New year remained\ntodate 5/9/2010 before New year remained')]

39
plugins/train.py Normal file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def train(type, jid, nick, text):
try:
from_to = map(lambda x: urllib.quote(x.encode('utf-8')), text.strip().split(' - '))
url = 'http://rasp.yandex.ru/search/train/?fromName=%s&toName=%s' % (from_to[0], from_to[1])
data = html_encode(load_page(url))
data = data.split('<div class="b-timetable__tripname">',3)[1]
res = re.findall(u'<a class="b-link" href="/thread/.+?><strong>(.+?)</strong> <span class="g-nowrap">(.+?)</span>.+?<span class="g-nowrap"></span>.*?<span class="g-nowrap">(.+?)</span></a>.+?<strong>(.+?)</strong>.+?<strong>(.+?)</strong>.+?<div class="b-timetable__pathtime">(.+?)</div>', data, re.S|re.I|re.U)
if res.count(res[0]) > 1: res = res[:res.index(res[0], 1)]
msg = '\n'.join(['%s\t%s-%s\t\t%s-%s\t(%s)' % _ for _ in res])
if not msg.strip() or 'b-pseudo-link js-transfers-trigger' in data: msg = L('What?','%s/%s'%(jid,nick))
except: msg = L('Command execution error.','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(3, 'train', train, 2, 'Train schedules by Yandex. Example: train city1 - city2')]

89
plugins/translate.py Normal file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def translate_ru(type, jid, nick, text):
text = text.strip()
trlang = {'en':['e',L('English','%s/%s'%(jid,nick))],'ru':['r',L('Russian','%s/%s'%(jid,nick))],'fr':['f',L('French','%s/%s'%(jid,nick))],
'es':['s',L('Spanish','%s/%s'%(jid,nick))],'it':['i',L('Italian','%s/%s'%(jid,nick))],'de':['g',L('German','%s/%s'%(jid,nick))],
'pt':['p',L('Portuguese','%s/%s'%(jid,nick))]}
trlang2 = {'e':'en','r':'ru','f':'fr','s':'es','i':'it','g':'de','p':'pt'}
if text.lower() == 'list': msg = L('Available languages for translate:','%s/%s'%(jid,nick)) + ' ' + ', '.join(sorted(trlang.keys()))
elif text[:5].lower() == 'info ':
text = text.lower().split(' ')
msg = ''
for tmp in text:
if tmp in trlang: msg += '%s - %s, ' % (tmp,trlang[tmp][1])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg[:-2]
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
elif text[:5].lower() == 'lang ' and text.count(' ')==1:
text = text.lower().split(' ')[1]
msg = ', '.join(['%s - %s' % (k,trlang[k][1]) for k in trlang.keys() if text in trlang[k][1].lower()])
if len(msg): msg = L('Available languages: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('I don\'t know this language','%s/%s'%(jid,nick))
else:
if ' ' in text:
text = text.split(' ',2)
url = 'http://m.translate.ru/services/MobileService.asmx/TranslateText4Touch?'
if len(text)>1 and trlang.has_key(text[0].lower()):
if len(text)>2 and trlang.has_key(text[1].lower()): lfrom,lto,tr_text = text[0].lower(),text[1].lower(),text[2]
else: lfrom,lto,tr_text = '',text[0].lower(),' '.join(text[1:])
if lfrom: lft = trlang[lfrom][0]
else: lft = 'a'
lft += trlang[lto][0]
search_results = load_page(url, {'intLang':lto,\
'text':tr_text.encode("utf-8"),\
'direction':lft,\
'template':'General'})
tr_xml = xmpp.simplexml.XML2Node(search_results)
isWord = tr_xml.getTagData('isWord') == 'true'
result = tr_xml.getTagData('result')
tr_direct = tr_xml.getTagData('ptsDirCode')
if isWord:
result = result.replace('&nbsp;<span class="ref_info"></span>,\n',',')
result = result.replace('<span class="ref_dictionary">\n','<span class="ref_dictionary">')
result = result.replace('<span class="ref_comment">\n','<span class="ref_comment">')
result = result.replace('</span>\n<span class="ref_info">','</span><span class="ref_info">')
result = result.replace('<li><span class="ref_result">\n','<li><span class="ref_result">, ')
for t in re.findall('(</div>\n.*?<div class="tr_pr">)',result,re.I+re.U+re.S): result = result.replace(t,'</div><div class="tr_pr">')
result = result.replace('<span class="ref_source">','||<span class="ref_source">')
for t in re.findall('(<a href=.*?</a>)',result,re.I+re.U+re.S): result = result.replace(t,'')
for t in re.findall('(<span id=.*?</span>)',result,re.I+re.U+re.S): result = result.replace(t,'')
result = result.replace('<br><span class="w_des">','<span class="w_des">')
result = result.replace('<b>\n','<b>')
msg = urllib.unquote(unhtml(result).encode('utf8')).decode('utf8', 'ignore')
msg = msg.replace('||','').replace(')\n(',') (').replace('\n, ',', ').replace(' ,',',').replace(',\n',', ')
else: msg = result
if not lfrom:
if '\n' in msg: symb = '\n'
else: symb = ' '
msg = L('%s%s[Source: %s]','%s/%s'%(jid,nick)) % (msg,symb,trlang[trlang2[tr_direct[0]]][1].strip())
else: msg = L('Incorrect language settings for translate. translate list - available languages.','%s/%s'%(jid,nick))
else: msg = L('Command\'s format: translate [from] to text','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'translate', translate_ru, 2, 'Translator from translate.ru\ntranslate [from_language] to_language text - translate text\ntranslate list - list for available languages for translate\ntranslate info <reduction> - get info about language reduction\ntranslate lang <expression> - get languages by expression')]

101
plugins/turn.py Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
turn_base = []
def turner_raw(text,jid,nick):
global turn_base
rtab = L('qwertyuiop[]asdfghjkl;\'zxcvbnm,.`QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>~','%s/%s'%(jid,nick))
ltab = L('QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>~qwertyuiop[]asdfghjkl;\'zxcvbnm,.`','%s/%s'%(jid,nick))
to_turn = text
if not text:
for tmp in turn_base:
if tmp[0] == jid and tmp[1] == nick:
turn_base.remove(tmp)
to_turn = tmp[2]
break
if to_turn:
if to_turn[:3] == '/me': msg, to_turn = '*%s' % nick, to_turn[3:]
elif ': ' in to_turn: msg, to_turn = '%s:' % to_turn.split(': ',1)[0], to_turn.split(': ',1)[1]
else: msg = ''
for tt in re.findall('\s+[^\s]*', ' ' + to_turn,re.I+re.U):
if re.findall('\s+(((svn|http[s]?|ftp)(://))|(magnet:\?))',tt,re.S|re.I|re.U): msg += tt
else: msg += ''.join([ltab[rtab.find(x)] if x in rtab else x for x in tt])
msg = msg.strip()
if get_config(getRoom(jid),'censor'): msg = to_censore(msg,jid)
return msg
else: return None
def turner(type, jid, nick, text):
if not text and type != 'groupchat':
send_msg(type, jid, nick, L('Not allowed in private!','%s/%s'%(jid,nick)))
return
to_turn = turner_raw(text,jid,nick)
if to_turn: send_msg(type, jid, [nick,''][type=='groupchat'], to_turn)
else: send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
def append_to_turner(room,jid,nick,type,text):
global turn_base
for tmp in turn_base:
if tmp[0] == room and tmp[1] == nick:
try: turn_base.remove(tmp)
except: pass
break
turn_base.append((room,nick,text))
def remove_from_turner(room,jid,nick,type,text):
global turn_base
if type == 'unavailable':
for tmp in turn_base:
if tmp[0] == room and tmp[1] == nick:
try: turn_base.remove(tmp)
except: pass
break
def autoturn(room,jid,nick,type,text):
if get_config(room,'autoturn') and type == 'groupchat':
if cur_execute_fetchone('select * from commonoff where room=%s and cmd=%s',(room,'turn')): return
nowname = get_xnick(room)
if nick == nowname: return
text = re.sub('^%s[,:]\ ' % re.escape(nowname), '', text.strip())
tmp = text.lower()
if ': ' in tmp: tmp = tmp.split(': ',1)[1]
count_two = 0
if not sum([int(ord(t)>127) for t in tmp]):
for tt in re.findall('\s+[^\s]*', ' ' + tmp):
if not re.findall('(svn|http[s]?|ftp)(://)',tt,re.S|re.U) and not re.findall(u'\s+[A-ZА-Я\d\']{2,}$',tt,re.U): count_two += sum([1 for k in two_en if k in tt])
if len(tmp.split()) < count_two - 1:
to_turn = turner_raw(text,room,nick)
if to_turn and to_turn != text:
pprint('Autoturn text: %s/%s [%s] %s > %s' % (room,nick,jid,text,to_turn),'dark_gray')
send_msg(type, room, '', to_turn)
return True
global execute, message_act_control
message_control = [append_to_turner]
presence_control = [remove_from_turner]
message_act_control = [autoturn]
execute = [(3, 'turn', turner, 2, 'Turn text from one layout to another.')]

108
plugins/watcher.py Normal file
View File

@@ -0,0 +1,108 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
watch_time = time.time()
watch_count = 0
watch_reset = True
watch_last_activity = {}
watch_activity = {}
def connect_watch():
global iq_request, watch_time, game_over, watch_count, bot_exit_type, watch_reset, plugins_reload
if GT('watcher_self_ping') and (time.time() - watch_time) > GT('watch_size'):
watch_time = time.time()
watch_count += 1
watch_reset = True
iqid = get_id()
i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':selfjid}, payload = [xmpp.Node('ping', {'xmlns': xmpp.NS_URN_PING},[])])
iq_request[iqid]=(time.time(),watcher_reset,['chat',god,'',''],xmpp.NS_URN_PING)
sender(i)
to = GT('timeout') - 10
if to <= 10: to = 600
while to > 0 and not game_over and not plugins_reload:
to -= 1
time.sleep(1)
if game_over or plugins_reload: return
if watch_reset:
pprint('Restart by watcher\'s timeout!','red')
bot_exit_type, game_over = 'restart', True
time.sleep(2)
def watch_room_activity():
if not GT('watcher_room_activity'): return
global watch_last_activity
to = int(time.time())-GT('watch_activity_timeout')
cnf = cur_execute_fetchall('select room from conference;')
if cnf:
for t in cnf:
tmp = t[0]
try: cw = watch_last_activity[getRoom(tmp)]
except: cw = to
if cw < to:
watch_last_activity[getRoom(tmp)] = int(time.time())
text = tmp
if '\n' in text: text,passwd = text.split('\n',2)
else: passwd = ''
zz = join(text, passwd)
while unicode(zz)[:3] == '409':
time.sleep(1)
text += '_'
zz = join(text, passwd)
time.sleep(1)
pprint('Low activity! Try rejoin into %s' % text,'white')
def watcher_reset(a,b,c,d,e):
global watch_reset
watch_reset = None
def c_watcher(type, jid, nick): send_msg(type, jid, nick, L('Timeout for ask: %s | Timeout for answer: %s | Last ask: %s | Total checks: %s','%s/%s'%(jid,nick)) % (GT('watch_size'),GT('timeout'),un_unix(int(time.time() - watch_time),'%s/%s'%(jid,nick)),watch_count))
def activity_watch(type, jid, nick):
rooms = cur_execute_fetchall("select split_part(room,'/',1) from conference;")
cnf = [[watch_activity[t],t] for t in watch_activity.keys()]
cnf.sort(reverse=1)
tt = int(time.time())
msg = '\n'.join(['%s - %s' % (t[1],un_unix(tt-t[0],'%s/%s'%(jid,nick))) for t in cnf])
rooms = ['%s - %s' % (t[0],L('Unknown','%s/%s'%(jid,nick))) for t in rooms if t[0] not in watch_activity.keys()]
if rooms: msg = '%s\n%s' % (msg,'\n'.join(rooms))
msg = L('Last activity in room(s):\n%s','%s/%s'%(jid,nick)) % msg
if type == 'groupchat':
send_msg('chat', jid, nick, msg)
msg = L('Send for you in private','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def connect_watch_uni(room,jid,nick,type,mass):
global watch_last_activity
if jid != 'None':
gr = getRoom(room)
watch_last_activity[gr] = int(time.time())
if jid != Settings['jid']: watch_activity[gr] = int(time.time())
global execute, timer
if GT('iq_version_enable'): timer = [connect_watch,watch_room_activity]
presence_control = [connect_watch_uni]
message_control = [connect_watch_uni]
execute = [(6,'watcher',c_watcher,1,'Connection activity control.'),
(9,'activity',activity_watch,1,'Show activity of conferences.')]

38
plugins/whowas.py Normal file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def whowas(type, jid, nick, text):
period = int(time.time()-86400)
text = '%%%s%%' % text if text else '%'
was_here = cur_execute_fetchall('select nick from age where room=%s\
and time>%s\
and status=1\
and (nick ilike %s or jid ilike %s)\
group by jid,nick order by nick;',(jid,period,text,text))
if was_here: msg = L('For a last day i see: %s','%s/%s'%(jid,nick)) % ', '.join([t[0] for t in was_here])
else:msg = L('All who i see for a last day now is here.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'whowas', whowas, 2, 'Show list of users for last day')]

281
plugins/wot.py Normal file
View File

@@ -0,0 +1,281 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) 2013 Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# RU
API_ADDR = 'http://api.worldoftanks.ru';
APP_ID = '171745d21f7f98fd8878771da1000a31';
clantags = re.compile('(\(.*?\))|(\[.*?\])')
def get_tanks_data():
data = urllib.urlopen('%s/2.0/encyclopedia/tanks/?application_id=%s&fields=level,name_i18n,name' % (API_ADDR, APP_ID))
d = json.load(data)
res = {}
for i in d['data']:
n18 = d['data'][i]['name_i18n'].rsplit(':', 1)[-1].replace('_', ' ')
n = d['data'][i]['name'].rsplit(':', 1)[-1].replace('_', ' ')
if n18[:2] == 'GB':
n18 = n18[5:]
if n[:2] == 'GB':
n = n[5:]
res[i] = {'name_i18n': n18, 'name': n, 'level': d['data'][i]['level']}
return res
try:
tanks_data = get_tanks_data()
except:
tanks_data = {}
def wot(type, jid, nick, text):
text = text.strip()
if not text:
tmp_text = clantags.sub('', nick).strip().split(' ', 1)[0]
if re.match('[\da-zA-Z_].*?', tmp_text):
text = tmp_text
if text:
text = text.split(' ', 1)
if len(text) == 1:
name, tank = text[0], ''
else:
name, tank = text[0], text[1].lower()
try:
data = load_page('%s/2.0/account/list/?application_id=%s&search=%s&fields=id&limit=1' % (API_ADDR, APP_ID, name))
v = json.loads(data)
player_id = str(v['data'][0]['id'])
data = load_page('%s/2.0/account/tanks/?application_id=%s&account_id=%s&fields=statistics,tank_id,mark_of_mastery' % (API_ADDR, APP_ID, player_id))
vdata = json.loads(data)
data = load_page('%s/2.0/account/info/?application_id=%s&account_id=%s&fields=clan,nickname,statistics' % (API_ADDR, APP_ID, player_id))
pdata = json.loads(data)
stat = pdata['data'][player_id]['statistics']
if pdata['data'][player_id]['clan']:
clan_id = str(pdata['data'][player_id]['clan']['clan_id'])
data = load_page('%s/2.0/clan/info//?application_id=%s&clan_id=%s&fields=abbreviation' % (API_ADDR, APP_ID, clan_id))
cdata = json.loads(data)
cname = cdata['data'][clan_id]['abbreviation']
except:
pdata = {'status': ''}
if pdata['status'] == 'ok' and pdata['data'][player_id]:
wotname = pdata['data'][player_id]['nickname'] + ('[%s]' % cname if pdata['data'][player_id]['clan'] else '')
if tank:
if len(tank) == 1:
msg = L('Use more characters in the name of the tank','%s/%s'%(jid,nick))
else:
try:
msg = '%s:' % wotname
tids = [tid for tid in tanks_data if tank in tanks_data[tid]['name'].lower() or tank in tanks_data[tid]['name_i18n'].lower()]
for t in vdata['data'][player_id]:
if str(t['tank_id']) in tids:
tank_win = t['statistics']['wins']
tank_battle = t['statistics']['battles']
mom = [L('none','%s/%s'%(jid,nick)), L('3 class','%s/%s'%(jid,nick)), L('2 class','%s/%s'%(jid,nick)), L('1 class','%s/%s'%(jid,nick)), L('master','%s/%s'%(jid,nick))][t['mark_of_mastery']]
if tank_battle:
msg += L('\n%s (%s/%s - %s%%), mastery: %s','%s/%s'%(jid,nick)) % (tanks_data[str(t['tank_id'])]['name_i18n'], tank_win, tank_battle, round(100.0*tank_win/tank_battle, 2), mom)
else:
msg += '\n%s (%s/%s)' % (tanks_data[str(t['tank_id'])]['name_i18n'], tank_win, tank_battle)
if not msg.count('\n'):
msg += L(' not founded tank','%s/%s'%(jid,nick))
except:
msg = L('Impossible to get tanks\' statistics','%s/%s'%(jid,nick))
else:
wins = stat['all']['wins']
battles = stat['all']['battles']
if not battles:
msg = '%s: %s/%s' % (wotname, wins, battles)
else:
try:
win_percent = round(100.0 * wins / battles, 2)
msg = '%s: %s/%s (%s%%)' % (wotname, wins, battles, win_percent)
np = int(win_percent) + 1
np_int = int((np * battles - 100 * wins) / (100 - np) + 1)
np05 = int(win_percent + 0.5) + 0.5
np_round = int((np05 * battles - 100 * wins) / (100 - np05) + 1)
msg += L('\nUp to %s%% win left: %s battles', '%s/%s'%(jid,nick)) % (np, np_int)
msg += L('\nUp to %s%% win left: %s battles', '%s/%s'%(jid,nick)) % (np05, np_round)
avg_exp = stat['all']['battle_avg_xp']
DAMAGE = stat['all']['damage_dealt'] / float(battles)
msg += L('\nAv. damage: %s','%s/%s'%(jid,nick)) % int(round(DAMAGE))
FRAGS = stat['all']['frags'] / float(battles)
msg += L('\nAv. destroyed: %s','%s/%s'%(jid,nick)) % round(FRAGS, 2)
SPOT = stat['all']['spotted'] / float(battles)
msg += L('\nAv. spotted: %s','%s/%s'%(jid,nick)) % round(SPOT, 2)
CAP = stat['all']['capture_points'] / float(battles)
msg += L('\nAv. captured points: %s','%s/%s'%(jid,nick)) % round(CAP, 2)
DEF = stat['all']['dropped_capture_points'] / float(battles)
msg += L('\nAv. defense points: %s','%s/%s'%(jid,nick)) % round(DEF, 2)
tanks = vdata['data'][player_id]
s = sum([t['statistics']['all']['battles'] * tanks_data[str(t['tank_id'])]['level'] for t in tanks])
TIER = s / float(battles)
WINRATE = wins / float(battles)
msg += L('\nAv. tank lvl: %s','%s/%s'%(jid,nick)) % round(TIER, 2)
er = DAMAGE * (10 / (TIER + 2)) * (0.23 + 2 * TIER / 100) + FRAGS * 250 + SPOT * 150 + math.log(CAP + 1) / math.log(1.732) * 150 + DEF * 150
if er < 420:
er_xvm = 0
else:
er_xvm = max(min(er*(er*(er*(er*(er*(4.5254e-17*er - 3.3131e-13) + 9.4164e-10) - 1.3227e-6) + 9.5664e-4) - 0.2598) + 13.23, 100), 0)
msg += L('\nEfficiency rating: %s (XVM: %s)','%s/%s'%(jid,nick)) % (int(round(er)), round(er_xvm, 1))
if er < 630:
msg += L(' - bad player','%s/%s'%(jid,nick))
elif er < 860:
msg += L(' - player below average','%s/%s'%(jid,nick))
elif er < 1140:
msg += L(' - average player','%s/%s'%(jid,nick))
elif er < 1460:
msg += L(' - good player','%s/%s'%(jid,nick))
elif er < 1735:
msg += L(' - great player','%s/%s'%(jid,nick))
elif er >= 1735:
msg += L(' - unicum','%s/%s'%(jid,nick))
wn6 = (1240 - 1040 / math.pow((min(TIER, 6)), 0.164)) * FRAGS + DAMAGE * 530 / (184 * math.exp(0.24 * TIER) + 130) + SPOT * 125 + min(DEF, 2.2) * 100 + ((185 / (0.17 + math.exp((WINRATE * 100 - 35) * -0.134))) - 500) * 0.45 + (6 - min(TIER, 6)) * (-60)
if wn6 > 2160:
wn6_xvm = 100
else:
wn6_xvm = max(min(wn6*(wn6*(wn6*(-1.268e-11*wn6 + 5.147e-8) - 6.418e-5) + 7.576e-2) - 7.25, 100), 0)
msg += L('\nWN6 rating: %s (XVM: %s)','%s/%s'%(jid,nick)) % (int(round(wn6)), round(wn6_xvm, 1))
if wn6 < 425:
msg += L(' - bad player','%s/%s'%(jid,nick))
elif wn6 < 795:
msg += L(' - player below average','%s/%s'%(jid,nick))
elif wn6 < 1175:
msg += L(' - average player','%s/%s'%(jid,nick))
elif wn6 < 1570:
msg += L(' - good player','%s/%s'%(jid,nick))
elif wn6 < 1885:
msg += L(' - great player','%s/%s'%(jid,nick))
elif wn6 >= 1885:
msg += L(' - unicum','%s/%s'%(jid,nick))
stat_rnd = lambda x: stat['all'][x] - stat['clan'][x] - stat['company'][x]
armor = math.log(stat_rnd('battles')) / 10 * (stat_rnd('xp')/float(stat_rnd('battles')) + stat_rnd('damage_dealt')/float(stat_rnd('battles')) * (stat_rnd('wins') * 2 + stat_rnd('frags') * 0.9 + (stat_rnd('spotted') + stat_rnd('capture_points') + stat_rnd('dropped_capture_points')) * 0.5)/float(stat_rnd('battles')))
msg += L('\nArmor-rating: %s','%s/%s'%(jid,nick)) % int(round(armor))
try:
data = load_page('http://armor.kiev.ua/wot/api.php?version=iSida3')
armor_limits = json.loads(data)
if armor > armor_limits['classRatings']['cv']:
msg += L(' - virtuoso','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['cm']:
msg += L(' - master tanker','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['c1']:
msg += L(' - tanker 1st class','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['c2']:
msg += L(' - tanker 2nd class','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['c3']:
msg += L(' - tanker 3rd class','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['d3']:
msg += L(' - deerhead 3rd class','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['d2']:
msg += L(' - deerhead 2nd class','%s/%s'%(jid,nick))
elif armor > armor_limits['classRatings']['d1']:
msg += L(' - deerhead 1st class','%s/%s'%(jid,nick))
else: #['dm']
msg += L(' - master deerhead','%s/%s'%(jid,nick))
except:
pass
except:
msg = L('Impossible to get statistics','%s/%s'%(jid,nick))
elif not pdata['status']:
msg = L('Query error','%s/%s'%(jid,nick))
else:
msg = L('Player not found','%s/%s'%(jid,nick))
else:
msg = L('What?','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
def wotclan(type, jid, nick, text):
text = text.strip().upper()
try:
data = load_page('%s/2.0/clan/list/?application_id=%s&search=%s' % (API_ADDR, APP_ID, text))
data = json.loads(data)
claninfo = [i for i in data['data'] if i['abbreviation'] == text]
if claninfo:
claninfo = claninfo[0]
clid = claninfo['clan_id']
owner = claninfo['owner_name']
created_at = claninfo['created_at']
abbrev = claninfo['abbreviation']
data = load_page('%s/2.0/clan/info/?application_id=%s&clan_id=%s' % (API_ADDR, APP_ID, clid))
data = json.loads(data)
claninfo2 = data['data'][str(clid)]
msg = L('Name: %s [%s]','%s/%s'%(jid,nick)) % (claninfo2['name'], abbrev)
msg += L('\nOwner: %s','%s/%s'%(jid,nick)) % owner
msg += L('\nCreated at: %s','%s/%s'%(jid,nick)) % time.ctime(created_at)
msg += L('\nCount of members: %s','%s/%s'%(jid,nick)) % claninfo2['members_count']
msg += L('\nMotto: %s','%s/%s'%(jid,nick)) % claninfo2['motto']
msg += '\n%s' % claninfo2['description']
else:
msg = L('Clan not found','%s/%s'%(jid,nick))
except:
msg = L('Impossible to get info','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
def wotoffers(type, jid, nick, text):
text = text.strip().split(' ', 1)
try:
url = 'http://jexp2.wotapi.ru/wotnews/get-news.php'
d = '?'
for opt in text:
if opt in ['active', 'all']:
url += '%sactivity=%s' % (d, opt)
d = '&'
if opt in ['real', 'prem', 'info']:
url += '%sdetailed=%s' % (d, opt)
d = '&'
msg = load_page(url).decode('utf-8')
except:
msg = L('Impossible to get info','%s/%s'%(jid,nick))
send_msg(type,jid,nick,msg)
global execute
execute = [(3, 'wot', wot, 2, 'World of Tanks - info about user. Usage: wot [nick [tank]]'),
(3, 'wotclan', wotclan, 2, 'World of Tanks - info about clan. Usage: wotclan clan'),
(3, 'wotoffers', wotoffers, 2, 'World of Tanks - info about offers. Usage: wotoffers [active|all] [real|prem|info]')]

166
plugins/wtf.py Normal file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def wtfall(type, jid, nick, text):
if text:
ww = cur_execute_fetchall('select * from wtf where (room=%s or room=%s or room=%s) and wtfword=%s order by -time',(jid,'global','import',text))
if ww: msg = L('I know that %s is %s','%s/%s'%(jid,nick)) % (text,'\n%s' % '\n\n'.join([L('from %s: %s','%s/%s'%(jid,nick)) % (t[3],t[5]) for t in ww]))
else: msg = L('I don\'t know!','%s/%s'%(jid,nick))
else: msg = L('What search?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def wtfsearch(type, jid, nick, text):
if text:
text = '%%%s%%' % text
ww = cur_execute_fetchall('select wtfword from wtf where (room=%s or room=%s or room=%s) and (room ilike %s or jid ilike %s or nick ilike %s or wtfword ilike %s or wtftext ilike %s)',(jid,'global','import',text,text,text,text,text))
if ww: msg = L('Some matches in definitions: %s','%s/%s'%(jid,nick)) % ', '.join(zip(*ww)[0])
else: msg = L('No matches.','%s/%s'%(jid,nick))
else: msg = L('What need to find?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def wtfrand(type, jid, nick):
ww = cur_execute_fetchall('select * from wtf where room=%s or room=%s or room=%s',(jid,'global','import'))
tlen = len(ww)
ww = ww[random.randint(0,tlen-1)]
msg = L('I know that %s is %s','%s/%s'%(jid,nick)) % (ww[4],ww[5])
send_msg(type, jid, nick, msg)
def wtfnames(type, jid, nick, text):
text = text.strip().lower()
if text == 'all': tmp = cur_execute_fetchall('select distinct wtfword from wtf where room=%s or room=%s or room=%s',(jid,'global','import'))
elif text in ['global','import']: tmp = cur_execute_fetchall('select distinct wtfword from wtf where room=%s',(text,))
else: tmp = cur_execute_fetchall('select distinct wtfword from wtf where room=%s',(jid,))
if tmp: msg = L('All I know is: %s','%s/%s'%(jid,nick)) % ', '.join(zip(*tmp)[0])
else: msg = L('No matches.','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def wtfcount(type, jid, nick):
tlen = cur_execute_fetchall('select count(*) from wtf')[0][0]
cnt = cur_execute_fetchall('select count(*) from wtf where room=%s',(jid,))[0][0]
glb = cur_execute_fetchall('select count(*) from wtf where room=%s',('global',))[0][0]
imp = cur_execute_fetchall('select count(*) from wtf where room=%s',('import',))[0][0]
msg = L('Locale definition: %s\nGlobal: %s\nImported: %s\nTotal: %s','%s/%s'%(jid,nick)) % (cnt,glb,imp,tlen)
send_msg(type, jid, nick, msg)
def wtf(type, jid, nick, text): wtf_get(0,type, jid, nick, text)
def wtff(type, jid, nick, text): wtf_get(1,type, jid, nick, text)
def wwtf(type, jid, nick, text): wtf_get(2,type, jid, nick, text)
def wtfp(type, jid, nick, text):
if '\n' in text:
text = text.split('\n')
tnick = text[1]
ttext = text[0]
is_found = 0
for mmb in megabase:
if mmb[0]==jid and mmb[1]==tnick:
is_found = 1
break
if is_found:
wtf_get(0,'chat', jid, tnick, ttext)
send_msg(type, jid, nick, L('Send to private %s','%s/%s'%(jid,nick)) % tnick)
else: send_msg(type, jid, nick, L('Nick %s not found!','%s/%s'%(jid,nick)) % tnick)
else: wtf_get(0,'chat', jid, nick, text)
def wtf_get(ff,type, jid, nick, text):
if text:
ww = cur_execute_fetchone('select * from wtf where (room=%s or room=%s or room=%s) and wtfword=%s order by -time',(jid,'global','import',text))
if ww:
msg = L('I know that %s is %s','%s/%s'%(jid,nick)) % (text,ww[5])
if ff == 1: msg += L('\nfrom: %s %s','%s/%s'%(jid,nick)) % (ww[3],'[%s]' % disp_time(ww[6],'%s/%s'%(jid,nick)))
elif ff == 2: msg = L('I know that %s was defined by %s %s %s','%s/%s'%(jid,nick)) % (text,ww[3],'(%s)' % ww[2],'[%s]' % disp_time(ww[6],'%s/%s'%(jid,nick)))
else: msg = L('I don\'t know!','%s/%s'%(jid,nick))
else: msg = L('What search?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def dfn(type, jid, nick, text):
text = text.strip()
if '=' in text and text[0] != '=':
al, realjid = get_level(jid,nick)
what, text = map(lambda x: x.strip(), text.split('=', 1))
matches = cur_execute_fetchall('select * from wtf where (room=%s or room=%s or room=%s) and wtfword=%s order by -time',(jid,'global','import',what))
if matches:
match_jid = None
grr = getRoom(realjid)
for t in matches:
if getRoom(t[2]) == grr:
match_jid = t[2]
break
if matches[0][1] == 'global': msg, text = L('This is global definition and not allowed to change!','%s/%s'%(jid,nick)), ''
elif text == '':
if match_jid:
msg = L('Definition removed!','%s/%s'%(jid,nick))
cur_execute('delete from wtf where wtfword=%s and room=%s and jid=%s',(what,jid,match_jid))
else: msg = L('This definition is not Your!','%s/%s'%(jid,nick))
else:
msg = L('Definition updated!','%s/%s'%(jid,nick))
if match_jid: cur_execute('delete from wtf where wtfword=%s and room=%s and jid=%s',(what,jid,match_jid))
elif text == '': msg = L('Nothing to remove!','%s/%s'%(jid,nick))
else: msg = L('Definition saved!','%s/%s'%(jid,nick))
idx = cur_execute_fetchall('select count(*) from wtf')[0][0]
if text != '': cur_execute('insert into wtf values (%s,%s,%s,%s,%s,%s,%s,%s)', (idx, jid, realjid, nick, what, text, int(time.time()),al))
else: msg = L('What need to remember?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def gdfn(type, jid, nick, text):
text = text.strip()
if '=' in text and text[0] != '=':
al, realjid = get_level(jid,nick)
what, text = map(lambda x: x.strip(), text.split('=', 1))
matches = cur_execute_fetchall('select * from wtf where (room=%s or room=%s or room=%s) and wtfword=%s order by lim,-time',(jid,'global','import',what))
if matches:
max = -1
for t in matches:
if t[7] >= max: max,match=t[7],t
if match[7] > al:
msg,text = L('Not enough rights!','%s/%s'%(jid,nick)),''
try: msg += ' ' + L(unlevltxt[unlevlnum[match[7]]],'%s/%s'%(jid,nick)) % L(unlevl[match[7]],'%s/%s'%(jid,nick))
except: pass
elif text == '':
msg = L('Definition removed!','%s/%s'%(jid,nick))
cur_execute('delete from wtf where wtfword=%s',(what,))
else:
msg = L('Definition updated!','%s/%s'%(jid,nick))
if getRoom(realjid) == getRoom(match[2]): cur_execute('delete from wtf where wtfword=%s and jid=%s',(what,match[2]))
elif text == '': msg = L('Nothing to remove!','%s/%s'%(jid,nick))
else: msg = L('Definition saved!','%s/%s'%(jid,nick))
idx = cur_execute_fetchall('select count(*) from wtf')[0][0]
if text != '': cur_execute('insert into wtf values (%s,%s,%s,%s,%s,%s,%s,%s)', (idx, 'global', realjid, nick, what, text, int(time.time()),al))
else: msg = L('What need to remember?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'wtfrand', wtfrand, 1, 'Random definition from base.'),
(3, 'wtfnames', wtfnames, 2, 'List of definitions in conference.\nwtfnames [all|global|import]'),
(3, 'wtfcount', wtfcount, 1, 'Definitions count.'),
(3, 'wtfsearch', wtfsearch, 2, 'Search in definitions base.'),
(3, 'wtfall', wtfall, 2, 'All definitions of word.'),
(9, 'wwtf', wwtf, 2, 'Information about definition commiter.'),
(3, 'wtff', wtff, 2, 'Show definition with nick and date.'),
(3, 'wtfp', wtfp, 2, 'Show definition in private.\nwtfp word\n[nick]'),
(0, 'wtf', wtf, 2, 'Show definition.'),
(3, 'dfn', dfn, 2, 'Set definition.\ndfn word=definition - remember definition as word\ndfn word= - remove definition word'),
(3, 'gdfn', gdfn, 2, 'Set global definition.\ngdfn word=definition - remember definition as word\ngdfn word= - remove definition word')]

223
plugins/www.py Normal file
View File

@@ -0,0 +1,223 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# Copyright (C) Vit@liy <vitaliy@root.ua> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
filename_chars_limit = 48
last_url_watch = ''
url_watch_ignore = ['pdf','sig','spl','class','ps','torrent','dvi','gz','pac','swf','tar','tgz','tar','zip','mp3','m3u','wma',\
'wax','ogg','wav','gif','jar','jpg','jpeg','png','xbm','xpm','xwd','css','asc','c','cpp','log','conf','text',\
'txt','dtd','xml','mpeg','mpg','mov','qt','avi','asf','asx','wmv','bz2','tbz','tar','so','dll','exe','bin',\
'img','usbimg','rar','deb','rpm','iso','ico','apk','patch','svg','7z','tcl']
def rss_search(type, jid, nick, text):
if text:
if not re.findall('^http(s?)://',text[:10]): text = 'http://%s' % text
text = enidna(text)
msg, result = get_opener(text)
if result:
msg = L('Bad url or rss/atom not found!','%s/%s'%(jid,nick))
page = remove_sub_space(html_encode(load_page(text)))
page = get_tag(page,'head')
l = []
while '<link' in page:
lnk = get_tag_full(page,'link')
page = page.replace(lnk,'')
l.append(lnk)
if l:
m = []
for t in l:
rss_type = get_subtag(t,'type')
if rss_type in ['application/rss+xml','application/atom+xml']:
if rss_type == 'application/rss+xml': rss_type = 'RSS'
else: rss_type = 'ATOM'
rss_title = get_subtag(t,'title')
rss_href = get_subtag(t,'href')
if rss_href == '/': rss_href = '/'.join(text.split('/',3)[:3]) + rss_href
m.append('[%s] %s - %s' % (rss_type,rss_href,rss_title))
if m:
m = '\n'.join(m)
msg = L('Found feed(s):%s%s','%s/%s'%(jid,nick)) % ([' ','\n']['\n' in m],unescape(m))
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def www_isdown(type, jid, nick, text):
text = text.strip().lower()
if text:
if not re.findall('^http(s?)://',text[:10]): text = 'http://%s' % text
_,result = get_opener(enidna(text))
if result: msg = L('It\'s just you. %s is up.','%s/%s'%(jid,nick)) % text
else: msg = L('It\'s not just you! %s looks down from here.','%s/%s'%(jid,nick)) % text
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def netheader(type, jid, nick, text):
if text:
try:
regex = text.split('\n')[0].replace('*','*?')
text = text.split('\n')[1]
except: regex = None
if not re.findall('^http(s?)://',text[:10]): text = 'http://%s' % text
body, result = get_opener(enidna(text))
if result:
k = body.headers.keys()
res = []
for t in k:
for tt in body.headers.getheaders(t): res.append('%s: %s' % (t,''.join([[r,'?'][r>'~'] for r in str(tt)])))
body = '%s\n%s' % (text,'\n'.join(res))
if regex:
try:
mt = re.findall(regex, body, re.S|re.I|re.U)
if mt != []: body = ''.join(mt[0])
else: body = L('RegExp not found!','%s/%s'%(jid,nick))
except: body = L('Error in RegExp!','%s/%s'%(jid,nick))
body = deidna(body)
else: body = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, body)
def netwww(type, jid, nick, text):
if text:
try:
regex = text.split('\n')[0].replace('*','*?')
tmp = regex.split(' ', 1)
if tmp[0].strip().isdigit():
n = int(tmp[0])
regex = tmp[1]
else:
n = 1
text = text.split('\n')[1]
except: regex = None
if not re.findall('^http(s?)://',text[:10]): text = 'http://%s' % text
text = enidna(text)
msg, result = get_opener(text)
if result:
page = remove_sub_space(html_encode(load_page(text)))
if regex:
try:
mt = re.findall(regex, page, re.S|re.I|re.U)
if mt != []:
if n:
msg = unhtml_hard('\n'.join([''.join(t) for t in mt[:n]]))
else:
msg = unhtml_hard('\n'.join([''.join(t) for t in mt]))
else: msg = L('RegExp not found!','%s/%s'%(jid,nick))
except: msg = L('Error in RegExp!','%s/%s'%(jid,nick))
else:
msg = urllib.unquote(unhtml_hard(page).encode('utf8')).decode('utf8', 'ignore')
if '<title' in page: msg = '%s\n%s' % (rss_replace(get_tag(page,'title')), msg)
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg[:msg_limit])
def get_content_title(link):
try:
ll = link.lower()
for t in url_watch_ignore:
if ll.endswith('.%s' % t): raise
link = enidna(link)
original_page = load_page_size(urllib2.Request(link),8192)
page = html_encode(original_page)
if '<title' in page: tag = 'title'
elif '<TITLE' in page: tag = 'TITLE'
else: raise
text = remove_sub_space(get_tag(page,tag).replace('\n',' ').replace('\r',' ').replace('\t',' '))
while ' ' in text: text = text.replace(' ',' ')
if text:
cnt = 0
for tmp in text: cnt += int(ord(tmp) in [1056,1057])
if cnt >= len(text)/3: text = remove_sub_space(html_encode(get_tag(original_page,tag)).replace('\n',' ').replace('\r',' ').replace('\t',' '))
except: text = ''
return text.strip()
def parse_url_in_message(room,jid,nick,type,text):
global last_url_watch
if type != 'groupchat' or text == 'None' or nick == '' or getRoom(jid) == getRoom(selfjid): return
if get_level(room,nick)[0] < 4: return
content_title = None
if get_config(getRoom(room),'store_users_url'):
rjid = getRoom(jid)
for t in text.split():
link = re.findall(r'(http[s]?://.*)',t)
if link:
link = link[0].split(' ')[0].split('"')[0].split('\'')[0]
if not cur_execute_fetchone('select * from url where room=%s and jid=%s and url=%s',(room,rjid,link)):
ttext = get_content_title(link)
if ttext:
ttext = to_censore(rss_del_html(rss_replace(ttext)),room)
content_title = [link,ttext]
else:
is_file,ttext = False,''
ll = link.lower()
for t in url_watch_ignore:
if ll.endswith('.%s' % t):
is_file = True
break
if is_file:
body, result = get_opener(enidna(link))
if result:
mt = float(body.headers.get('Content-Length',0))
if mt: ttext = L('Content length %s','%s/%s'%(jid,nick)) % get_size_human(mt)
else: ttext = ''
pprint('Store url: %s in %s/%s' % (link,room,nick),'white')
cur_execute('insert into url values (%s,%s,%s,%s,%s,%s);',(room,rjid,nick,int(time.time()),link,ttext))
was_shown = False
if get_config(getRoom(room),'url_title'):
try:
link = re.findall(r'(http[s]?://.*)',text)[0].split(' ')[0].split('"')[0].split('\'')[0]
if link and last_url_watch != link and pasteurl not in link:
if content_title and content_title[0] == link: ttext = content_title[1]
else: ttext = get_content_title(link)
if ttext:
pprint('Show url-title: %s in %s' % (link,room),'white')
was_shown = True
send_msg(type, room, '', L('Title: %s','%s/%s'%(jid,nick)) % to_censore(rss_del_html(rss_replace(ttext)),room))
last_url_watch = link
except: pass
if not was_shown and get_config(getRoom(room),'content_length'):
try:
link = re.findall(u'(http[s]?://[-0-9a-zа-я.]+\/[-a-zа-я0-9._?#=@%/]+\.[a-z0-9]{2,7})',text,re.I+re.U+re.S)[0]
if link and last_url_watch != link and pasteurl not in link:
is_file = False
ll = link.lower()
for t in url_watch_ignore:
if ll.endswith('.%s' % t):
is_file = True
break
if is_file:
last_url_watch = enidna(link)
body, result = get_opener(last_url_watch)
pprint('Show content length: %s in %s' % (link,room),'white')
if result:
mt = float(body.headers.get('Content-Length',0))
if mt:
link_end = urllib2.unquote(last_url_watch.rsplit('/',1)[-1]).decode('utf-8')
link_end = u'…%s%s' % (['/',''][len(link_end)>filename_chars_limit], link_end[-filename_chars_limit:])
send_msg(type, room, '', L('Length of %s is %s','%s/%s'%(jid,nick)) % (to_censore(link_end,room),get_size_human(mt)))
except: pass
global execute
message_act_control = [parse_url_in_message]
execute = [(3, 'www', netwww, 2, 'Show web page.\nwww [count (0 for all)] regexp\n[http://]url - page after regexp\nwww [http://]url - without html tags'),
(3, 'header', netheader, 2, 'Show net header'),
(3, 'isdown', www_isdown, 2, 'Check works site'),
(4, 'rss_search', rss_search, 2, 'Search RSS/ATOM feeds')]

130
plugins/wz.py Normal file
View File

@@ -0,0 +1,130 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def check_wz(text):
if not len(text): return True
for tm in text:
if ord(tm)<33 or ord(tm)>127: return True
return None
def get_weather(text):
wzc = cur_execute_fetchall('select code from wz where code ilike %s or city ilike %s or counry ilike %s',(text,text,text))
if not wzc: return 'Not Found'
if len(wzc) != 1: return 'Not Found'
return load_page('http://weather.noaa.gov/pub/data/observations/metar/decoded/%s.TXT' % wzc[0][0].upper())
def weather(type, jid, nick, text):
if check_wz(text): msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
else:
wzz = get_weather(text)
if 'Not Found' in wzz: msg = L('City not found!','%s/%s'%(jid,nick))
elif len(wzz.split('\n')) < 9: msg = L('Unexpected error','%s/%s'%(jid,nick))
else:
wzz = wzz.split('\n')
wzr = []
wzr.append(wzz[0]) # 0
wzr.append(wzz[1]) # 1
wzr.append(sfind(wzz,'Temperature')) # 2
wzr.append(sfind(wzz,'Wind')) # 3
wzr.append(sfind(wzz,'Relative')) # 4
wzr.append(sfind(wzz,'Sky')) # 5
wzr.append(sfind(wzz,'Weather')) # 6
wzr.append(sfind(wzz,'Visibility')) # 7
wzr.append(sfind(wzz,'Pressure')) # 8
if ')' in wzr[0]: msg = wzr[0][:wzr[0].find(')')+1]
else: msg = wzr[0]
msg += '\n'+ wzr[1]
wzz1 = wzr[2].find(':')+1 # Temperature
wzz2 = wzr[2].find('(',wzz1)
wzz3 = wzr[2].find(')',wzz2)
msg += '\n'+ wzr[2][:wzz1] + ' ' + wzr[2][wzz2+1:wzz3]
wzz1 = wzr[3].find('(')
wzz2 = wzr[3].find(')',wzz1)
wzz3 = wzr[3].find(':',wzz2)
msg += '\n'+ wzr[3][:wzz1-1] + wzr[3][wzz2+1:wzz3]
msg += '\n'+ wzr[4]
if len(wzr[5]): msg += ','+ wzr[5][wzr[5].find(':')+1:]
if len(wzr[6]): msg += ','+ wzr[6][wzr[6].find(':')+1:]
if not (len(wzr[5])+len(wzr[6])): msg += ', clear'
msg += '\n'+ wzr[7][:-2]
wzz1 = wzr[8].find('(')
wzz2 = wzr[8].find(':',wzz1)
wzz3 = wzr[8].find('(',wzz2)
msg += ', '+ wzr[8][:wzz1-1]+': '+wzr[8][wzz3+1:-1]
send_msg(type, jid, nick, msg)
def weather_short(type, jid, nick, text):
if check_wz(text): msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
else:
wzz = get_weather(text)
if 'Not Found' in wzz: msg = L('City not found!','%s/%s'%(jid,nick))
elif len(wzz.split('\n')) < 9: msg = L('Unexpected error','%s/%s'%(jid,nick))
else:
wzz = wzz.split('\n')
wzr = []
wzr.append(wzz[0]) # 0
wzr.append(sfind(wzz,'Temperature')) # 2
wzr.append(sfind(wzz,'Wind')) # 3
wzr.append(sfind(wzz,'Relative')) # 4
wzr.append(sfind(wzz,'Sky')) # 5
wzr.append(sfind(wzz,'Weather')) # 6
if ')' in wzr[0]: msg = wzr[0][:wzr[0].find(')')+1]
else: msg = wzr[0]
wzz1 = wzr[1].find(':')+1 # Temperature
wzz2 = wzr[1].find('(',wzz1)
wzz3 = wzr[1].find(')',wzz2)
msg += ' | '+ wzr[1][:wzz1] + ' ' + wzr[1][wzz2+1:wzz3]
wzz1 = wzr[2].find('(')
wzz2 = wzr[2].find(')',wzz1)
wzz3 = wzr[2].find(':',wzz2)
msg += ' | '+ wzr[2][:wzz1-1] + wzr[2][wzz2+1:wzz3]
msg += ' | '+ wzr[3]
if len(wzr[4]): msg += ','+ wzr[4][wzr[4].find(':')+1:]
if len(wzr[5]): msg += ','+ wzr[5][wzr[5].find(':')+1:]
if not (len(wzr[4])+len(wzr[5])): msg += ', clear'
send_msg(type, jid, nick, msg)
def weather_raw(type, jid, nick, text):
if check_wz(text): msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
else:
msg = get_weather(text)[:-1]
if 'Not Found' in msg: msg = L('City not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
def weather_search(type, jid, nick, text):
if len(text):
wzc = cur_execute_fetchall('select code,city,counry from wz where code ilike %s or city ilike %s or counry ilike %s',(text,text,text))
if not wzc: msg = msg = L('City not found!','%s/%s'%(jid,nick))
else:
msg = ''
for tmp in wzc: msg += '\n%s - %s (%s)' % tmp
msg = L('Found: %s','%s/%s'%(jid,nick)) % msg
else: msg = L('What?','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'wzz', weather_raw, 2, 'Weather by airport code. Full version.'),
(3, 'wzs', weather_short, 2, 'Weather by airport code. Short version.'),
(3, 'wz', weather, 2, 'Weather by airport code. Optimized version.'),
(3, 'wzsearch', weather_search, 2, 'Search weather by code, city, country.')]

49
plugins/youtube.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Plugin for iSida Jabber Bot #
# Copyright (C) diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
def youtube(type, jid, nick, text):
if '\n' in text:
try: lim = int(text.split('\n',1)[1])
except: lim = GT('youtube_default_videos')
if lim > GT('youtube_max_videos'): lim = GT('youtube_max_videos')
if lim < 1: lim = 1
text = text.split('\n',1)[0]
else: lim = GT('youtube_default_videos')
req = text.lower().encode("utf-8").replace(' ','+')
url = 'http://gdata.youtube.com/feeds/api/videos?q=%s&alt=json-in-script&callback=yt&max-results=%s&format=5'
res = json.loads(load_page(url % (req,lim)).split('yt(',1)[1][:-2])['feed']
if res.has_key('entry'):
msg = L('Found:','%s/%s'%(jid,nick))
for t in res['entry']:
y_title = t['title']['$t']
try: y_views = t['yt$statistics']['viewCount']
except: y_views = ''
y_link = t['media$group'][u'media$player'][0]['url'].split('?v=',1)[1].split('&')[0]
y_time = t['media$group'][u'media$thumbnail'][0]['time'].split('.',1)[0]
msg += unescape('\nhttp://youtu.be/%s - %s [%s] %s' % (y_link,y_title,y_time,y_views))
else: msg = L('Not found!','%s/%s'%(jid,nick))
send_msg(type, jid, nick, msg)
global execute
execute = [(3, 'youtube', youtube, 2, 'Search at YouTube')]