#!/usr/bin/python # -*- coding: utf-8 -*- # --------------------------------------------------------------------------- # # # # iSida Jabber Bot # # Copyright (C) diSabler # # # # 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 . # # # # --------------------------------------------------------------------------- # from __future__ import with_statement import calendar import crontab import datetime import gc import json import hashlib import htmlentitydefs import httplib import logging import operator import os import math import random import re import socket import string import sys import time import urllib import urllib2 import chardet import xmpp global execute, prefix, comms, hashlib, trace def sqlite3_split_part(txt, spltr, cnt): if txt: return (txt.split(spltr) + [''] * (cnt-1))[cnt-1] else: return txt sqlite3_row_number_last_x = 0 def sqlite3_row_number(): global sqlite3_row_number_last_x sqlite3_row_number_last_x += 1 return sqlite3_row_number_last_x def cur_execute_sqlite3(*params): conn = sqlite3.connect(sqlite_base) if 'split_part' in list(params)[0]: conn.create_function('split_part', 3, sqlite3_split_part) if 'row_number' in list(params)[0]: global sqlite3_row_number_last_x sqlite3_row_number_last_x = 0 conn.create_function('row_number', 0, sqlite3_row_number) cur = conn.cursor() par = True try: params = list(params) params[0] = params[0].replace('%s','?').replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ') params = tuple(params) cur.execute(*params) prm = params[0].split()[0].lower() if prm in ['update','insert','delete','create','drop','alter']: conn.commit() except Exception, par: par = None conn.rollback() if halt_on_exception: raise conn.commit() conn.close() return par def cur_execute_mysql(*params): conn = mysqldb.connect(database=base_name, user=base_user, host=base_host, password=base_pass, port=base_port) cur = conn.cursor() par = True try: params = list(params) params[0] = params[0].replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ').replace('split_part(','substring_index(') params = tuple(params) cur.execute(*params) prm = params[0].split()[0].lower() if prm in ['update','insert','delete','create','drop','alter']: conn.commit() except Exception, par: par = None conn.rollback() if halt_on_exception: raise conn.commit() conn.close() return par def cur_execute(*params): if base_type == 'sqlite3': return cur_execute_sqlite3(*params) elif base_type == 'mysql': return cur_execute_mysql(*params) global conn cur = conn.cursor() if base_type == 'pgsql': psycopg2.extensions.register_type(psycopg2.extensions.UNICODE, cur) par = True try: cur.execute(*params) prm = params[0].split()[0].lower() if prm in ['update','insert','delete','create','drop','alter']: conn.commit() except Exception, par: if database_debug: try: par = str(par) except: par = unicode(par) pprint(par,'red') else: par = None conn.rollback() if halt_on_exception: raise cur.close() return par def cur_execute_fetchone_sqlite3(*params): conn = sqlite3.connect(sqlite_base) if 'split_part' in list(params)[0]: conn.create_function('split_part', 3, sqlite3_split_part) if 'row_number' in list(params)[0]: global sqlite3_row_number_last_x sqlite3_row_number_last_x = 0 conn.create_function('row_number', 0, sqlite3_row_number) try: cur = conn.cursor() except: return None par = None try: params = list(params) params[0] = params[0].replace('%s','?').replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ') params = tuple(params) cur.execute(*params) try: par = cur.fetchone() except Exception, par: par = None if halt_on_exception: raise except Exception, par: par = None conn.rollback() conn.close() return par def cur_execute_fetchone_mysql(*params): conn = mysqldb.connect(database=base_name, user=base_user, host=base_host, password=base_pass, port=base_port) try: cur = conn.cursor() except: return None par = None try: params = list(params) params[0] = params[0].replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ').replace('split_part(','substring_index(') params = tuple(params) cur.execute(*params) try: par = cur.fetchone() except Exception, par: par = None if halt_on_exception: raise except Exception, par: par = None conn.rollback() conn.close() return par def cur_execute_fetchone(*params): if base_type == 'sqlite3': return cur_execute_fetchone_sqlite3(*params) elif base_type == 'mysql': return cur_execute_fetchone_mysql(*params) global conn try: cur = conn.cursor() except: return None if base_type == 'pgsql': psycopg2.extensions.register_type(psycopg2.extensions.UNICODE, cur) par = None try: cur.execute(*params) try: par = cur.fetchone() except Exception, par: if database_debug: try: par = str(par) except: par = unicode(par) else: par = None if halt_on_exception: raise except Exception, par: if database_debug: try: par = str(par) except: par = unicode(par) pprint(par,'red') if halt_on_exception: raise else: par = None conn.rollback() cur.close() return par def cur_execute_fetchall_sqlite3(*params): conn = sqlite3.connect(sqlite_base) if 'split_part' in list(params)[0]: conn.create_function('split_part', 3, sqlite3_split_part) if 'row_number' in list(params)[0]: global sqlite3_row_number_last_x sqlite3_row_number_last_x = 0 conn.create_function('row_number', 0, sqlite3_row_number) try: cur = conn.cursor() except: return None par = None try: params = list(params) params[0] = params[0].replace('%s','?').replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ') params = tuple(params) cur.execute(*params) try: par = cur.fetchall() except Exception, par: par = None if halt_on_exception: raise except Exception, par: par = None conn.rollback() if halt_on_exception: raise conn.close() return par def cur_execute_fetchall_mysql(*params): conn = mysqldb.connect(database=base_name, user=base_user, host=base_host, password=base_pass, port=base_port) try: cur = conn.cursor() except: return None par = None try: params = list(params) params[0] = params[0].replace(' ilike ',' like ').replace(' update ',' `update` ').replace(' repeat ',' `repeat` ').replace(' option ',' `option` ').replace(' count ',' `count` ').replace(' match ',' `match` ').replace('split_part(','substring_index(') params = tuple(params) cur.execute(*params) try: par = cur.fetchall() except Exception, par: par = None if halt_on_exception: raise except Exception, par: par = None conn.rollback() if halt_on_exception: raise conn.close() return par def cur_execute_fetchall(*params): if base_type == 'sqlite3': return cur_execute_fetchall_sqlite3(*params) elif base_type == 'mysql': return cur_execute_fetchall_mysql(*params) global conn try: cur = conn.cursor() except: return None if base_type == 'pgsql': psycopg2.extensions.register_type(psycopg2.extensions.UNICODE, cur) par = None try: cur.execute(*params) try: par = cur.fetchall() except Exception, par: if database_debug: try: par = str(par) except: par = unicode(par) else: par = None if halt_on_exception: raise except Exception, par: if database_debug: try: par = str(par) except: par = unicode(par) pprint(par,'red') else: par = None conn.rollback() if halt_on_exception: raise cur.close() return par def get_color(c): color = os.environ.has_key('TERM') colors = {'clear':'[0m','blue':'[34m','red':'[31m','magenta':'[35m','green':'[32m','cyan':'[36m','brown':'[33m','light_gray':'[37m','black':'[30m','bright_blue':'[34;1m','bright_red':'[31;1m','purple':'[35;1m','bright_green':'[32;1m','bright_cyan':'[36;1m','yellow':'[33;1m','dark_gray':'[30;1m','white':'[37;1m'} return ['','\x1b%s' % colors[c]][color] def get_color_win32(c): colors = {'clear':7,'blue':1,'red':4,'magenta':5,'green':2,'cyan':3,'brown':6,'light_gray':7,'black':0,'bright_blue':9,'bright_red':12,'purple':13,'bright_green':10,'bright_cyan':11,'yellow':14,'dark_gray':8,'white':15} return colors[c] def thr(func,param,name): global th_cnt, thread_error_count, sema th_cnt += 1 try: if thread_type: with sema: tmp_th = KThread(group=None,target=log_execute,name='%s_%s' % (th_cnt,name),args=(func,param)) tmp_th.start() else: thread.start_new_thread(log_execute,(func,param)) except SystemExit: pass except Exception, SM: try: SM = str(SM) except: SM = unicode(SM) if 'thread' in SM.lower(): thread_error_count += 1 else: logging.exception(' [%s] %s' % (timeadd(tuple(time.localtime())),unicode(func))) if thread_type: try: tmp_th.kill() except: pass if halt_on_exception: raise def log_execute(proc, params): try: proc(*params) except SystemExit: pass except: logging.exception(' [%s] %s' % (timeadd(tuple(time.localtime())),unicode(proc))) def sender(item): global message_out, presence_out, iq_out, unknown_out, last_stanza, messages_log last_stanza = unicode(item) if last_stanza[:2] == '(.*?)' % (tag,tag),body,re.S) if T: return T[0] else: return '' def get_tag_full(body,tag): T = re.findall('(<%s[^>]*?>|)' % (tag,tag),body,re.S) if T and len(T)==1: return T[0] elif len(T) >= 2 and T[0][1:len(tag)+1] == T[1][-len(tag)-1:-1]: T1 = re.findall('(%s.*?%s)' % (re.escape(T[0]),re.escape(T[1])),body,re.S) if T1: return T1[0] else: return '' elif len(T): return T[0] else: return '' def get_tag_item(body,tag,item): body = get_tag_full(body,tag) return get_subtag(body,item) def parser(t): try: return ''.join([['?',l][l<='~'] for l in unicode(t)]) except: fp = file(slog_folder % 'critical_exception_%s.txt' % int(time.time()), 'wb') fp.write(t) fp.close() def remove_sub_space(t): return ''.join([['?',l][l>=' ' or l in '\t\r\n'] for l in unicode(t)]) def smart_encode(text,enc): tx,splitter = '','|' while splitter in text: splitter += '|' ttext = text.replace(' 1: if is_win32: win_color = get_color_win32(text[1]) else: c,wc = get_color(text[1]),get_color('clear') elif is_win32: win_color = get_color_win32('clear') text = text[0] lt = tuple(time.localtime()) zz = '%s[%s]%s %s%s' % (wc,onlytimeadd(lt),c,text,wc) last_logs_store = ['[%s] %s' % (onlytimeadd(lt),text)] + last_logs_store[:last_logs_size] if debug_console: if is_win32 and win_color: ctypes.windll.Kernel32.SetConsoleTextAttribute(win_console_color, get_color_win32('clear')) print zz.split(' ',1)[0], ctypes.windll.Kernel32.SetConsoleTextAttribute(win_console_color, win_color) try: print zz.split(' ',1)[1] except: print parser(zz.split(' ',1)[1]) ctypes.windll.Kernel32.SetConsoleTextAttribute(win_console_color, get_color_win32('clear')) else: try: print zz except: print parser(zz) if CommandsLog: fname = slog_folder % '%02d%02d%02d.txt' % (lt[0],lt[1],lt[2]) fbody = '%s|%s\n' % (onlytimeadd(lt),text.replace('\n','\r')) fl = open(fname, 'a') fl.write(fbody.encode('utf-8')) fl.close() def send_presence_all(sm): pr=xmpp.Presence(typ='unavailable') pr.setStatus(sm) sender(pr) time.sleep(2) def errorHandler(text): draw_warning(text) sys.exit('exit') def get_joke(text): def joke_blond(text): def blond_text(text): b = '' cnt = random.randint(0,1) for tmp in text: if cnt: b += tmp.upper() else: b += tmp.lower() cnt = not cnt return b text = text.split(' ') new_text = [] for t in text: if t == '/me' or [True for s in ['http://','https://','ftp://','svn://','xmpp:','git://'] if t.startswith(s)]: new_text.append(t) else: new_text.append(blond_text(t)) return ' '.join(new_text) def joke_upyachka(text): upch = [u'пыщь!!!111адын',u'ололололо!!11',u'ГОЛАКТЕКО ОПАСНОСТЕ!!11',u'ТЕЛОИД!!',u'ЖАЖА1!',u'ОНОТОЛЕЙ!!!!!',u'ПОТС ЗОХВАЧЕН11!!!', u'ПыЩЩЩЩЩЩЩЩЩь!!!!!!!1111',u'ПыЩЩЩЩЩЩЩЩЩь11111адинадин1адин'] return '%s %s' % (text.strip(),random.choice(upch)) def no_joke(text): return text jokes = [joke_blond,no_joke,joke_upyachka] return random.choice(jokes)(text) def msg_validator(t): return ''.join([[l,'?'][l<' ' and l not in '\n\t\r' or l>u'\uff00'] for l in unicode(t)]) def message_exclude_update(): global messages_excl excl = GT('exclude_messages').replace('\r','').replace('\t','').split('\n') messages_excl = [] for c in excl: if '#' not in c and len(c): messages_excl.append(c) def message_validate(item): if messages_excl: for c in messages_excl: cn = re.findall(c,' %s ' % item,re.S|re.I|re.U) for tmp in cn: item = item.replace(tmp,[GT('censor_text')*len(tmp),GT('censor_text')][len(GT('censor_text'))>1]) return item def send_msg(mtype, mjid, mnick, mmessage): global between_msg_last,time_limit if mmessage: mmessage = message_validate(mmessage) mnick = message_validate(mnick) # 1st april joke :) if time.localtime()[1:3] == (4,1) and GT('1st_april_joke'): mmessage = get_joke(mmessage) no_send = True if len(mmessage) > msg_limit: cnt = 0 maxcnt = int(len(mmessage)/msg_limit) + 1 mmsg = mmessage while len(mmsg) > msg_limit and not game_over: tmsg = u'[%s/%s] %s[…]' % (cnt+1,maxcnt,mmsg[:msg_limit]) cnt += 1 sender(xmpp.Message('%s/%s' % (mjid,mnick), tmsg, 'chat')) mmsg = mmsg[msg_limit:] time.sleep(time_limit) tmsg = '[%s/%s] %s' % (cnt+1,maxcnt,mmsg) sender(xmpp.Message('%s/%s' % (mjid,mnick), tmsg, 'chat')) if mtype == 'chat': no_send = None else: mmessage = mmessage[:msg_limit] + u'[…]' if no_send: if mtype == 'groupchat' and mnick != '': mmessage = '%s: %s' % (mnick,mmessage) else: mjid += '/' + mnick while mmessage[-1:] in ['\n','\t','\r',' ']: mmessage = mmessage[:-1] mmessage = msg_validator(mmessage) if len(mmessage): sender(xmpp.Message(mjid, mmessage, mtype)) def os_version_disco(): iSys = sys.platform iOs = os.name isidaPyVer = sys.version.split()[0] if iOs == 'posix': osInfo = os.uname() isidaOs = osInfo[0] isidaOsVer = '%s-%s/PYv%s' % (osInfo[2].split('-',1)[0],osInfo[4],isidaPyVer) elif iSys == 'win32': def get_registry_value(key, subkey, value): import _winreg key = getattr(_winreg, key) handle = _winreg.OpenKey(key, subkey) (value, type) = _winreg.QueryValueEx(handle, value) return value def get(key): return get_registry_value("HKEY_LOCAL_MACHINE", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",key) osInfo = get("ProductName") buildInfo = get("CurrentBuildNumber") try: spInfo = get("CSDVersion") isidaOs = osInfo isidaOsVer = 'SP:%s/BLD:%s/PYv%s' % (spInfo,buildInfo,isidaPyVer) except: isidaOs = 'Windows' isidaOsVer = '%s/BLD:%s/PYv%s' % (osInfo.replace('Windows','').strip(),buildInfo,isidaPyVer) else: isidaOs = isidaOsVer = 'unknown' return isidaOs, isidaOsVer def os_version(): iSys = sys.platform iOs = os.name isidaPyVer = '%s [%s]' % (sys.version.split(' (')[0],sys.version.split(')')[0].split(', ')[1]) if iOs == 'posix': osInfo = os.uname() isidaOs = '%s %s-%s / Python %s' % (osInfo[0],osInfo[2],osInfo[4],isidaPyVer) elif iSys == 'win32': def get_registry_value(key, subkey, value): import _winreg key = getattr(_winreg, key) handle = _winreg.OpenKey(key, subkey) (value, type) = _winreg.QueryValueEx(handle, value) return value def get(key): return get_registry_value("HKEY_LOCAL_MACHINE", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",key) osInfo = ' '.join(get("ProductName").split()[:3]) buildInfo = get("CurrentBuildNumber") try: spInfo = get("CSDVersion") isidaOs = '%s %s [%s] / Python %s' % (osInfo,spInfo,buildInfo,isidaPyVer) except: isidaOs = '%s [%s] / Python %s' % (osInfo,buildInfo,isidaPyVer) else: isidaOs = 'unknown' return isidaOs def caps_and_send(tmp): tmp.setTag('x', namespace=xmpp.NS_VCARD_UPDATE) tmp.getTag('x', namespace=xmpp.NS_VCARD_UPDATE).setTagData('photo',photo_hash) tmp.setTag('c', namespace=xmpp.NS_CAPS, attrs={'node':capsNode,'ver':capsHash,'hash':'sha-1'}) sender(tmp) def join(conference,passwd): global pres_answer,cycles_used,cycles_unused,current_join id = get_id() current_join[conference] = id if Settings['status'] == 'online': j = xmpp.Node('presence', {'id': id, 'to': conference}, payload = [xmpp.Node('status', {},[Settings['message']]),\ xmpp.Node('priority', {},[Settings['priority']])]) else: j = xmpp.Node('presence', {'id': id, 'to': conference}, payload = [xmpp.Node('show', {},[Settings['status']]),\ xmpp.Node('status', {},[Settings['message']]),\ xmpp.Node('priority', {},[Settings['priority']])]) j.setTag('x', namespace=xmpp.NS_MUC).addChild('history', {'maxchars':'0', 'maxstanzas':'0'}) j.getTag('x').setTagData('password', passwd) caps_and_send(j) answered, Error, join_timeout = None, None, 3 if is_start: join_timeout_delay = 0.3 else: join_timeout_delay = 1 while not answered and join_timeout >= 0 and not game_over: if is_start: cyc = cl.Process(1) if str(cyc) == 'None': cycles_unused += 1 elif int(str(cyc)): cycles_used += 1 else: cycles_unused += 1 else: time.sleep(join_timeout_delay) join_timeout -= join_timeout_delay for tmp in pres_answer: if tmp[0]==id: Error = tmp[1] pres_answer.remove(tmp) answered = True break if current_join.has_key(conference) and current_join[conference] != id: break if current_join.has_key(conference): if current_join[conference] != id: Error = {'CAPTCHA':current_join[conference],'ID':id} current_join.pop(conference) return Error def leave(conference, sm): j = xmpp.Presence(conference, 'unavailable', status=sm) sender(j) def muc_filter_action(act,jid,room,reason): if act in ['visitor','kick']: nick = get_nick_by_jid(room,getRoom(jid)) if nick and act=='visitor': sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':room},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'role':'visitor', 'nick':nick},[xmpp.Node('reason',{},reason)])])])) elif nick and 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':nick},[xmpp.Node('reason',{},reason)])])])) elif not nick and act=='visitor': sender(xmpp.Node('iq',{'id': get_id(), 'type': 'set', 'to':room},payload = [xmpp.Node('query', {'xmlns': xmpp.NS_MUC_ADMIN},[xmpp.Node('item',{'role':'visitor', 'jid':jid},[xmpp.Node('reason',{},reason)])])])) elif not nick and 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', 'jid':jid},[xmpp.Node('reason',{},reason)])])])) elif act=='ban': 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':jid},[xmpp.Node('reason',{},reason)])])])) return None def paste_text(text,room,jid): return paste_text_raw(text,room,jid,True) def paste_text_muc(text,room,jid): return paste_text_raw(text,room,jid,False) def paste_text_raw(text,room,jid,need_replace): nick = get_nick_by_jid_res(room,jid) _html_paste = GT('html_paste_enable') if _html_paste: if need_replace: text = html_escape(text).replace(' ',' ') else: text = html_escape(text) nick = html_escape(nick) paste_header = ['','\n' % paste_css_path][_html_paste] url = '%s%s' % (str(hex(int(time.time()*100)))[2:-1],['.txt','.html'][_html_paste]) lt = tuple(time.localtime()) ott = onlytimeadd(tuple(time.localtime())) paste_body = ['%s','<p><span class="paste">%s</span></p>\n'][_html_paste] % (text) lht = '%s [%s] - %02d/%02d/%02d %02d:%02d:%02d' % (nick,room,lt[0],lt[1],lt[2],lt[3],lt[4],lt[5]) paste_he = ['%s\t\thttp://isida.dsy.name\n\n' % lht,'%s%s
\n' % (paste_header,lht,lht)][_html_paste] fl = open(pastepath+url, 'a') fl.write(paste_he.encode('utf-8')) fl.write(paste_body.encode('utf-8')) paste_ender = ['','
'][_html_paste] fl.write(paste_ender.encode('utf-8')) fl.close() return pasteurl+url def disp_time(*t): if len(t) == 2: rn = t[1] else: rn = '' t = t[0] lt=tuple(time.localtime(t)) return '%02d:%02d:%02d, %02d.%s\'%s, %s' % (lt[3],lt[4],lt[5],lt[2],L(wmonth[lt[1]-1],rn).replace('_',''),lt[0],L(wday[lt[6]],rn)) def nice_time(*ttim): if len(ttim) == 2: rn = ttim[1] else: rn = '' ttim = ttim[0] gt=tuple(time.gmtime(ttim)) lt=tuple(time.localtime(ttim)) timeofset = (datetime.datetime(*lt[:6])-datetime.datetime(*gt[:6])).seconds / 3600.0 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) t_utc='%s%02d%02dT%02d:%02d:%02d' % gt[:6] t_display = '%02d:%02d:%02d, %02d.%s\'%s, %s, ' % (lt[3],lt[4],lt[5],lt[2],L(wmonth[lt[1]-1],rn).replace('_',''),lt[0],L(wday[lt[6]],rn)) #t_tz = time.tzname[time.localtime()[8]] #enc = chardet.detect(t_tz)['encoding'] #if t_tz == None: body = '' #if enc == None or enc == '' or enc.lower() == 'unicode': enc = 'utf-8' #t_tz = unicode(t_tz,enc) #t_display += '%s, %s' % (t_tz,t_gmt) #return t_utc,t_tz,t_display t_display += t_gmt return t_utc,t_gmt,t_display def get_eval_item(mess,string): try: result = eval('mess.%s' % string) if result: return result.encode('utf-8') except: pass return '' def match_for_raw(original,regexp,gr): orig_drop = orig_reg = re.findall(regexp, original.replace('\n',' '), re.S|re.I|re.U) while '' in orig_drop: orig_drop.remove('') orig_join = ''.join(orig_reg) if orig_join: #orig_split = original.split() #match_percent = 100.0 / len(original) * len(orig_join) #match_percent = 100.0 / len(orig_drop) * len(orig_split) match_percent = 100.0 / len(orig_drop) * sum([len(tmp) <= 2 for tmp in orig_drop]) raw_percent = get_config(gr,'muc_filter_raw_percent') if raw_percent.isdigit(): raw_percent = int(raw_percent) else: raw_percent = int(config_prefs['muc_filter_raw_percent'][3]) return ['',orig_join][match_percent >= raw_percent] else: return '' def caps_matcher(c_caps,c_list): result = False for t in c_list: r = int(t[0] == '*')*2+int(t[-1] == '*') if r == 3 and t[1:-1].lower() in c_caps.lower(): return True elif r == 2 and c_caps.endswith(t[1:]): return True elif r == 1 and c_caps.startswith(t[:-1]): return True elif c_caps == t: return True return result def iqCB(sess,iq): global timeofset, iq_in, iq_request, last_msg_base, last_msg_time_base, ddos_ignore, ddos_iq, user_hash, server_hash, server_hash_list global disco_excl, message_excl, users_locale iq_in += 1 id = iq.getID() if id == None: return None room = unicode(iq.getFrom()) if cur_execute_fetchone('select * from bot_owner where jid=%s',(getRoom(room),)): towh = selfjid else: towh = '%s/%s' % (getRoom(room),get_nick_by_jid_res(getRoom(room), selfjid)) query = iq.getTag('query') was_request = id in iq_request al,tjid = get_level(getRoom(room),getResourse(room)) acclvl = al >= 7 and GT('iq_disco_enable') nnj,tjid = False,getRoom(tjid) if room == selfjid: nnj = True else: for tmp in megabase: if '%s/%s' % tuple(tmp[0:2]) == room: nnj = True break c_lang = iq.getAttr('xml:lang') if c_lang: users_locale[room] = c_lang[:2].replace('uk','ua') if getServer(Settings['jid']) == room: nnj = True if iq.getType()=='error' and was_request: try: er_name = get_tag(unicode(iq),'error').replace('<','').split()[0] except: er_name = 'Unknown error!' iq_async(id,time.time(),er_name,'error') elif iq.getType()=='result' and was_request: try: nspace = query.getNamespace() except: nspace = 'None' if nspace == xmpp.NS_MUC_ADMIN: iq_async(id,nspace,time.time(),iq) elif nspace == xmpp.NS_MUC_OWNER: iq_async(id,nspace,time.time(),iq) elif nspace == xmpp.NS_VERSION: ver_client = unicode(query.getTagData(tag='name')) ver_version = unicode(query.getTagData(tag='version')) ver_os = unicode(query.getTagData(tag='os')) t = cur_execute_fetchone('select jid from versions where room=%s and jid=%s and client=%s and version=%s and os=%s',(getRoom(room),tjid,ver_client,ver_version,ver_os)) if not t: cur_execute('insert into versions values (%s,%s,%s,%s,%s,%s)',(getRoom(room),tjid,ver_client,ver_version,ver_os,int(time.time()))) iq_async(id,nspace,time.time(),'%s %s // %s' % (ver_client,ver_version,ver_os)) elif nspace == xmpp.NS_TIME: iq_async(id,nspace,time.time(),query.getTagData(tag='display'),query.getTagData(tag='utc'),query.getTagData(tag='tz')) elif iq.getTag('time',namespace=xmpp.NS_URN_TIME): iq_async(id,xmpp.NS_URN_TIME,time.time(),iq.getTag('time').getTagData(tag='utc'),iq.getTag('time').getTagData(tag='tzo')) elif iq.getTag('vCard',namespace=xmpp.NS_VCARD): iq_async(id,xmpp.NS_VCARD,time.time(),unicode(iq),iq) else: iq_async(id,nspace,time.time(),unicode(iq),iq) elif iq.getType()=='get' and nnj and not ddos_ignore.has_key(tjid): iq_ddos_requests,iq_ddos_limit = GT('ddos_iq_requests'),GT('ddos_iq_limit') nick = getResourse(room) qry = unicode(iq.getTag(name='query')) if ddos_iq.has_key(tjid): time_tuple = [time.time()] + ddos_iq[tjid][:iq_ddos_requests-1] else: time_tuple = [time.time()] ddos_iq[tjid] = time_tuple if len(time_tuple) == iq_ddos_requests and (time_tuple[0]-time_tuple[-1]) < iq_ddos_limit: ddos_ignore[tjid] = [getRoom(room),nick,time.time()+GT('ddos_limit')[al]] pprint('!!! IQ-DDOS Detect: %s %s [%s] %s' % (al, room, tjid, qry),'bright_red') return for t in [tmp[2] for tmp in giq_hook if tmp[1] == 'get']: to_send = t(iq,id,room,acclvl,query,towh,al) if to_send: if to_send != True: sender(to_send) raise xmpp.NodeProcessed elif iq.getType()=='set': for t in [tmp[2] for tmp in giq_hook if tmp[1] == 'set']: to_send = t(iq,id,room,acclvl,query,towh,al) if to_send: if to_send != True: sender(to_send) raise xmpp.NodeProcessed def iq_async_clean(): global iq_reques while not game_over: to = GT('timeout') while to > 0 and not game_over: to -= 1 time.sleep(1) if len(iq_request): for tmp in iq_request.keys(): if iq_request[tmp][0] + GT('timeout') < time.time(): iq_request.pop(tmp) break def presence_async_clean(): global pres_answer while not game_over: to = GT('timeout') while to > 0 and not game_over: to -= 1 time.sleep(1) if len(pres_answer): tm = [] for tmp in pres_answer: if tmp[2] + GT('timeout') > time.time(): tm.append(tmp) pres_answer = tm def iq_async(*answ): global iq_request req = iq_request.pop(answ[0]) try: er_code = answ[3] except: er_code = None if er_code == 'error': is_answ = (answ[1]-req[0],(answ[2],'error')) elif req[3] == xmpp.NS_URN_PING or req[3] == answ[1]: is_answ = (answ[2]-req[0],answ[3:]) elif req[3] == xmpp.NS_VCARD and answ[1] == 'None': answ[4].setTag('vCard',namespace=xmpp.NS_VCARD) is_answ = (answ[2]-req[0],answ[3:]) else: pprint('!!! Got a fake iq answer. Request: %s. Answer: %s. Raw: %s' % (req[3],answ[1],answ[3]),'red') is_answ = (answ[2]-req[0],('%s %s' % (L('Error!'),L('Got a fake iq answer!')),)) req[2].append(is_answ) thr(req[1],(tuple(req[2])),'iq_async_%s' % answ[0]) def remove_ignore(): global ddos_ignore while not game_over: if len(ddos_ignore): tt = time.time() for tmp in ddos_ignore.keys(): if tt > ddos_ignore[tmp][2]: try: ddos_ignore.pop(tmp) pprint('!!! DDOS: Jid %s is removed from ignore!' % tmp,'red') except: pprint('!!! DDOS: Unable find jid %s in ignore list. Perhaps it\'s removed by bot\'s owner!' % tmp,'red') time.sleep(10) def com_parser(access_mode, nowname, type, room, nick, text, jid): global last_command, ddos_ignore jjid = getRoom(jid) if ddos_ignore.has_key(jjid): return if last_command[1:7] == [nowname, type, room, nick, text, jid] and time.time() < last_command[7]+GT('ddos_diff')[access_mode]: ddos_ignore[jjid] = [room,nick,time.time()+GT('ddos_limit')[access_mode]] pprint('!!! DDOS Detect: %s %s/%s %s %s' % (access_mode, room, nick, jid, text),'bright_red') send_msg(type, room, nick, L('Warning! Exceeded the limit of sending the same commands. You to ignore for %s.','%s/%s'%(room,nick)) % un_unix(GT('ddos_limit')[access_mode],'%s/%s'%(room,nick))) return None no_comm = True cof = cur_execute_fetchall('select * from commonoff;')#!!! for parse in comms: if access_mode >= parse[0] and nick != nowname: not_offed = True if access_mode != 9 or ignore_owner: for co in cof: if co[0]==room and co[1]==text.lower()[:len(co[1])]: not_offed = None break p1l = parse[1].lower() if not_offed and (text.lower() == p1l or text[:len(parse[1])+1].lower() in ['%s '%p1l,'%s\n'%p1l]): pprint('%s %s/%s [%s] %s' % (jid,room,nick,access_mode,text),'bright_cyan') no_comm = None if not parse[3]: thr(parse[2],(type, room, nick, parse[4:]),parse[1]) elif parse[3] == 1: thr(parse[2],(type, room, nick),parse[1]) elif parse[3] == 2: thr(parse[2],(type, room, nick, text[len(parse[1])+1:]),parse[1]) last_command = [access_mode, nowname, type, room, nick, text, jid, time.time()] break return no_comm def messageCB(sess,mess): global lfrom, lto, lastserver, lastnick, comms, message_in, no_comm, last_hash, current_join message_in += 1 type=unicode(mess.getType()) room=unicode(mess.getFrom().getStripped()) allow_execute = True if getRoom(Settings['jid']) == getRoom(room): allow_execute = False msg = 'Warning! Self-message detected!' pprint('!!! %s Stanza:\n%s' % (msg,unicode(mess))) own = cur_execute_fetchall('select * from bot_owner;') if own: for ajid in own: send_msg('chat', ajid[0], '', msg) text=unicode(mess.getBody()) id = mess.getID() try: was_send = messages_log.pop(id) except: was_send = None if was_send and type == 'error' and mess.getTag('error',attrs={'code':'500','type':'wait'}): time.sleep(time_limit) sender(was_send) return if current_join and room in [getRoom(t) for t in current_join.keys()]: try: tt = {} for t in mess.getTag('captcha',attrs={'xmlns':'urn:xmpp:captcha'}).getTag('x',attrs={'xmlns':'jabber:x:data'}).getTags('field'): tt[t.getAttrs()['var']] = t.getTagData('value') if current_join[tt['from']] == tt['sid']: pprint('*** Captcha: %s' % text) current_join[tt['from']] = text else: current_join.pop(tt['from']) except: for t in current_join.keys(): if room == getRoom(t): current_join.pop(t) break try: code = mess.getTag('x',namespace=xmpp.NS_MUC_USER).getTagAttr('status','code') if code in msg_status_codes: append_message_to_log(room,'','',type,msg_status_codes[code]) return except: pass if (text == 'None' or text == '') and not mess.getSubject(): return if mess.getTimestamp() != None: return nick=mess.getFrom().getResource() if nick != None: nick = unicode(nick) towh=unicode(mess.getTo().getStripped()) lprefix = get_local_prefix(room) ft = back_text = text rn = '%s/%s' % (room,nick) access_mode,jid = get_level(room,nick) if not allow_execute: access_mode = -1 nowname = get_xnick(room) if '@' not in jid and (jid == 'None' or jid.startswith('j2j.')) and is_owner(room): access_mode = 9 if type == 'groupchat' and nick != '' and access_mode >= 0 and jid not in ['None',Settings['jid']]: talk_count(room,jid,nick,text) if nick != '' and nick != None and nick != nowname and len(text)>1 and text != 'None' and text != to_censore(text,room) and access_mode >= 0 and get_config(getRoom(room),'censor'): cens_text = L('Censored!',rn) lvl = get_level(room,nick)[0] if lvl >= 5 and get_config(getRoom(room),'censor_warning'): send_msg(type,room,nick,cens_text) elif lvl == 4 and get_config(getRoom(room),'censor_action_member') != 'off': act = get_config(getRoom(room),'censor_action_member') muc_filter_action(act,jid,room,cens_text) elif lvl < 4 and get_config(getRoom(room),'censor_action_non_member') != 'off': act = get_config(getRoom(room),'censor_action_non_member') muc_filter_action(act,jid,room,cens_text) no_comm = True if text != 'None' and text and access_mode >= 0 and not mess.getSubject(): no_comm = True is_par = False if text.startswith('%s: ' % nowname) or text.startswith('%s, ' % nowname): text = text[len(nowname)+2:] is_par = True btext = text if text.startswith(lprefix): text = text[len(lprefix):] is_par = True if type == 'chat': is_par = True if is_par: no_comm = com_parser(access_mode, nowname, type, room, nick, text, jid) if no_comm: btl = btext.lower() if base_type == 'mysql': alias = cur_execute_fetchone("select match ,cmd from alias where (room=%s or room=%s) and ( match =%s or %s like concat( match ,' %%')) order by room desc",(room,'*',btl,btl)) else: alias = cur_execute_fetchone("select match ,cmd from alias where (room=%s or room=%s) and ( match =%s or %s ilike match ||' %%') order by room desc",(room,'*',btl,btl)) if alias: pprint('%s %s/%s [%s|alias] %s' % (jid,room,nick,access_mode,text),'bright_cyan') argz = btext[len(alias[0])+1:] if not argz: ppr = alias[1].replace('%*', '').replace('%{reduce}*', '').replace('%{reduceall}*', '').replace('%{unused}*', '') ppr = re.sub('\%\{nick2jid\}[0-9\*]','',ppr,flags=re.S|re.I|re.U) cpar = re.findall('%([0-9]+)', ppr, re.S) if len(cpar): for tmp in cpar: try: ppr = ppr.replace('%'+tmp,'') except: pass else: if '%' not in alias[1]: ppr = '%s %%*' % alias[1] else: ppr = alias[1] ppr = ppr.replace('%*', argz).replace('%{reduce}*', argz.strip()).replace('%{reduceall}*', reduce_spaces_all(argz)) argz = argz.split() argzbk = list(argz) n2j = re.findall('\%\{nick2jid\}([0-9])',ppr,flags=re.S|re.I|re.U) if n2j: for t in n2j: it = int(t) try: curr_nick = get_jid_by_nick(room, argz[it]) except: curr_nick = '' ppr = re.sub('\%%\{nick2jid\}%s' % t,curr_nick,ppr,flags=re.S|re.I|re.U) argzbk = argzbk[:it]+argzbk[it+1:] n2j = re.findall('\%\{nick2jid\}(\*)',ppr,flags=re.S|re.I|re.U) if n2j: curr_nick = get_jid_by_nick(room, ' '.join(argz)) ppr = re.sub('\%\{nick2jid\}[0-9\*]',curr_nick,ppr,flags=re.S|re.I|re.U) argz = [] if '%' in ppr: cpar = re.findall('%([0-9]+)', ppr, re.S) if cpar: for tmp in cpar: try: it = int(tmp) ppr = ppr.replace('%'+tmp,argz[it]) argzbk = argzbk[:it]+argzbk[it+1:] except: pass ppr = ppr.replace('%{unused}*',' '.join(argzbk)) if len(ppr) == ppr.count(' '): ppr = '' no_comm = com_parser(access_mode, nowname, type, room, nick, ppr, jid) thr(msg_afterwork,(mess,room,jid,nick,type,back_text,no_comm,access_mode,nowname),'msg_afterwork') def msg_afterwork(mess,room,jid,nick,type,back_text,no_comm,access_mode,nowname): global topics not_alowed_flood = False subj = unicode(mess.getSubject()) text = back_text if subj != 'None': if '\n' in subj: subj = '\n%s' % subj subj = L('*** Topic: %s','%s/%s'%(room,nick)) % subj if len(text) and text != 'None': subj = text.replace(': ',':\n',1) if '\n' in text else text topics[room],nick = subj,'' text = subj not_alowed_flood, no_comm = True, False # Fetch and store xhtml images! if type == 'groupchat' and get_config(room,'paste_xhtml_images'): try: raw_data = mess.getTag('html',attrs={'xmlns':'http://jabber.org/protocol/xhtml-im'}).getTag('body').getTagAttr('img','src') ext = re.findall('^data:image/(.*?);',raw_data[:32])[0] def unproc(t): return chr(int(t.group(0)[1:],16)) img = re.sub('%[0-9A-F]{2}', unproc, raw_data.split('base64,',1)[1]).decode('base64') filename = '%s.%s' % (hex(int(time.time()))[2:],ext) fp = file(pastepath + filename, 'wb') fp.write(img) fp.close() send_msg(type, room, '', L('Fetched xhtml image: %s%s','%s/%s'%(room,nick)) % (pasteurl,filename)) pprint('*** Fetched xhtml image from %s/%s [%s], size %s, file %s' % (room,nick,jid,len(img),pastepath + filename),'cyan') except: pass for tmp in gmessage: not_alowed_flood = tmp(room,jid,nick,type,text) or not_alowed_flood if no_comm: for tmp in gactmessage: not_alowed_flood = not_alowed_flood or tmp(room,jid,nick,type,text) if not not_alowed_flood and no_comm and text not in ['None','',' '] and not mess.getSubject(): if room != selfjid: is_flood = get_config(getRoom(room),'flood') not in ['off',False] else: is_flood = None if selfjid != jid and access_mode >= 0 and (back_text[:len(nowname)+2] == nowname+': ' or back_text[:len(nowname)+2] == nowname+', ' or type == 'chat') and is_flood: pprint('Send msg human: %s/%s [%s] <<< %s' % (room,nick,type,text),'dark_gray') if len(back_text) > 128: send_msg_human(type, room, nick, L('Too many letters!','%s/%s'%(room,nick)), 'msg_human') else: if back_text[:len(nowname)] == nowname: back_text = back_text[len(nowname)+2:] try: text = getAnswer(type, room, nick, back_text) if text: send_msg_human(type, room, nick, text, 'msg_human') except: pass def send_msg_human(type, room, nick, text, th): if nick: rn = '%s/%s' % (room,nick) else: rn = room pprint('Send msg human: %s [%s] >>> %s' % (rn,type,text),'dark_gray') thr(send_msg_hmn,(type, room, nick, text),th) def send_msg_hmn(type, room, nick, text): time.sleep(len(text)/4.0+random.randint(0,3)) send_msg(type, room, nick, text) def to_censore(text,room): ccn = [] custom_replace = {} if get_config(getRoom(room),'censor_custom'): custom_censor = get_config(getRoom(room),'censor_custom_rules').replace('\r','').replace('\t','').split('\n') for c in custom_censor: if c.count('#') <= 1: cc=c.split('#',1) else: cc=c.split('#') if cc[-1] == cc[-2] == '': cc = ['#'.join(cc[:-2]),'#'] else: cc = ['#'.join(cc[:-1]),cc[-1]] if cc[0]: try: _ = re.compile(cc[0],re.S|re.I|re.U) ccn.append(cc[0]) if len(cc) > 1: custom_replace[cc[0]] = reduce_spaces_all(cc[1]) except: pass wca = None def_replacer = GT('censor_text') for c in censor+ccn: cn = re.findall(c,' %s ' % text,re.S|re.I|re.U) for tmp in cn: t = ''.join(tmp) try: replacer = custom_replace[c] except: replacer = def_replacer text,wca = text.replace(t,[replacer*len(t),replacer][len(replacer)>1]),True if wca: text = text.strip(' ') return text def check_hash_actions(): global hash_actions_list if hash_actions_list: for tmp in hash_actions_list.keys(): if time.time() > hash_actions_list[tmp][1]: hal = hash_actions_list.pop(tmp) if hal[0] == L('whitelist'): put_config(tmp,'muc_filter_whitelist',False) elif hal[0] == L('lock by hash'): hashes_list = reduce_spaces_all(get_config(tmp,'muc_filter_deny_hash_list').replace(',',' ').replace(';',' ').replace('|',' ')).split() if hal[2] in hashes_list: hashes_list.remove(hal[2]) put_config(tmp,'muc_filter_deny_hash_list',' '.join(hashes_list)) if not hashes_list: put_config(tmp,'muc_filter_deny_hash',False) pprint('Removed hash action %s in %s' % (hal[0],tmp),'cyan') def presenceCB(sess,mess): global megabase, pres_answer, cu_age, presence_in, hashes, last_hash, users_locale presence_in += 1 room=unicode(mess.getFrom().getStripped()) nick=unicode(mess.getFrom().getResource()) text=unicode(mess.getStatus()) type=unicode(mess.getType()) affiliation=unicode(mess.getAffiliation()) role=unicode(mess.getRole()) jid=unicode(mess.getJid()) mss = unicode(mess) bad_presence = mss.count(' 1 and mss.count(' affiliation=\"') > 1 and mss.count(' role=\"') > 1 priority=unicode(mess.getPriority()) show=unicode(mess.getShow()) reason=unicode(mess.getReason()) status=unicode(mess.getStatusCode()) try: chg_nick = [None,esc_max2(mess.getTag('x',namespace=xmpp.NS_MUC_USER).getTagAttr('item','nick'))][status == '303'] except: chg_nick = None actor=unicode(mess.getActor()) to=unicode(mess.getTo()) id = mess.getID() tt = int(time.time()) if type=='error': try: error_code = mess.getTagAttr('error','code') except: error_code = None try: error_type = mess.getTagAttr('error','type') except: error_type = None try: error_text = mess.getTag('error').getTagData(tag='text') if not error_text: raise except: try: error_text = get_tag(unicode(mess.getTag('error')),'error') except: error_text = L('Unknown error!') if not error_text and presence_error.has_key(error_code): error_text = presence_error[error_code] if error_code: if error_type: error_msg = '%s [%s]' % (error_code,error_type) else: error_msg = error_code if error_text: error_msg = '%s - %s' % (error_msg,error_text) else: if error_type: error_msg = '%s [%s]' % (error_type.capitalize(),error_text) else: error_msg = error_text pres_answer.append((id,error_msg,tt)) return elif id != None: pres_answer.append((id,None,tt)) if jid == 'None': jid = get_level(room,nick)[1] # Get Caps if '%s|%s' % (role,affiliation) in levl: id_ver = id_lang = id_photo = id_avatar = 'error!' hash_error = False try: id_node = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")').decode('utf-8') except: id_node,hash_error = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("node")'),True try: id_ver = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")').decode('utf-8') except: id_ver,hash_error = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ver")'),True try: id_hash = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("hash")').decode('utf-8') except: id_hash,hash_error = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("hash")'),True try: id_ext = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ext")').decode('utf-8') except: id_ext,hash_error = get_eval_item(mess,'getTag("c",namespace=xmpp.NS_CAPS).getAttr("ext")'),True try: id_bmver = mess.getAttr('ver').decode('utf-8') if id_bmver or id_bmver == '': id_bmver = '%s_' % id_bmver else: id_bmver = '' except: id_bmver = '' if id_ext and id_hash: id_hash = '%s|%s' % (id_hash,id_ext) elif id_ext: id_hash = id_ext if id_hash: capses['%s/%s' % (room,nick)] = '%s\n%s [%s]\n%s' % (id_node,id_ver,id_hash,id_bmver) else: capses['%s/%s' % (room,nick)] = '%s\n%s\n%s' % (id_node,id_ver,id_bmver) # Hash control if '%s|%s' % (role,affiliation) in levl and levl['%s|%s' % (role,affiliation)] <= 3: try: id_lang = get_eval_item(mess,'getAttr("xml:lang")').decode('utf-8') except: id_lang,hash_error = get_eval_item(mess,'getAttr("xml:lang")'),True try: id_photo = get_eval_item(mess,'getTag("x",namespace=xmpp.NS_VCARD_UPDATE).getTagData("photo")').decode('utf-8') except: id_photo,hash_error = get_eval_item(mess,'getTag("x",namespace=xmpp.NS_VCARD_UPDATE).getTagData("photo")'),True try: id_avatar = get_eval_item(mess,'getTag("x",namespace=xmpp.NS_AVATAR).getTagData("hash")').decode('utf-8') except: id_avatar,hash_error = get_eval_item(mess,'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(mess).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' % (room,nick)] = current_hash if type != 'unavailable' and not get_config(room,'muc_filter_whitelist') and get_config(room,'muc_filter_hash'): try: lh = last_hash[room] except: lh = [current_hash,[]] try: hash_ev = get_config_int(room,'muc_filter_hash_events') if not 3 <= hash_ev <= 1000: raise except: hash_ev = config_prefs['muc_filter_hash_events'][3] put_config(room,'muc_filter_hash_events',hash_ev) try: hash_tm = get_config_int(room,'muc_filter_hash_time') if not 3 <= hash_tm <= 1000: raise except: hash_tm = config_prefs['muc_filter_hash_time'][3] put_config(room,'muc_filter_hash_time',hash_tm) if current_hash == lh[0]: if lh[1]: lh[1] = [time.time()] + lh[1][:hash_ev-1] else: lh[1] = [time.time()] lh[0] = current_hash else: lh = [current_hash,[]] if lh[1] and len(lh[1]) == hash_ev and lh[1][0]-lh[1][-1] <= hash_tm: pprint('Hash high action: %s %s/%s' % (current_hash,room,nick),'red') h_action = get_config(room,'muc_filter_hash_action') try: h_action_time = get_config_int(room,'muc_filter_hash_action_time') if not 3 <= h_action_time <= 86400: raise except: h_action_time = config_prefs['muc_filter_hash_action_time'][3] put_config(room,'muc_filter_hash_action_time',h_action_time) hash_actions_list[room] = [h_action,h_action_time+time.time(),current_hash] if h_action == L('whitelist'): put_config(room,'muc_filter_whitelist',True) elif h_action == L('lock by hash'): put_config(room,'muc_filter_deny_hash',True) hashes_list = reduce_spaces_all(get_config(room,'muc_filter_deny_hash_list').replace(',',' ').replace(';',' ').replace('|',' ')).split() if not current_hash in hashes_list: hashes_list.append(current_hash) put_config(room,'muc_filter_deny_hash_list',' '.join(hashes_list)) h_action_current = get_config(room,'muc_filter_hash_action_current') if h_action_current != L('off'): pprint('MUC-Filter initial flush by hash: %s %s' % (room,jid),'brown') muc_filter_action(h_action_current,jid,room,L('Deny by hash lock!')) for tmp in hashes.keys(): tmp_room,tmp_nick = tmp.split('/',1) if tmp_room == room and hashes[tmp] == current_hash: tmp_access,tmp_jid = get_level(room,tmp_nick) if tmp_access <= 3 and tmp_jid != 'None': 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(tmp_jid),room,int(time.time()),getRoom(tmp_jid),room)) if not in_base: nmute = True else: newbie_time = get_config(room,'muc_filter_newbie_time') if newbie_time.isdigit(): newbie_time = int(newbie_time) else: newbie_time = 60 if in_base[0] < newbie_time: nmute = True else: nmute = False if nmute: pprint('MUC-Filter flush by hash: %s %s' % (room,tmp_jid),'brown') muc_filter_action(h_action_current,tmp_jid,room,L('Deny by hash lock!')) lh = [current_hash,[]] last_hash[room] = lh if bad_presence: send_msg('groupchat', room, '', L('/me detect bad stanza from %s') % nick) nowname = get_xnick(room.lower()) not_found,exit_type,exit_message = 0,'','' if type=='unavailable': try: users_locale.pop('%s/%s' % (room,nick)) except: pass if status=='307': exit_type,exit_message = L('kicked'),reason elif status=='321': exit_type,exit_message = L('kicked'),L('revoke member affiliation in members-only room') elif status=='301': exit_type,exit_message = L('banned'),reason elif status=='303': exit_type,exit_message = L('change nick to %s') % chg_nick,'' else: exit_type,exit_message = L('leave'),text if exit_message == 'None': exit_message = '' try: exit_message += '\r' + acl_ver_tmp['%s/%s' % (room,nick)] except: pass if nick != '': for mmb in megabase: if mmb[0]==room and mmb[1]==nick: megabase.remove(mmb) break if to == selfjid and status in ['307','301'] and cur_execute_fetchone('select room from conference where room=%s',('%s/%s' % (room,nick),)): cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(room),)) pprint('*** bot was %s %s %s' % (['banned in','kicked from'][status=='307'],room,exit_message),'red') if GT('kick_ban_notify'): ntf_list = GT('kick_ban_notify_jid').replace(',',' ').replace('|',' ').replace(';',' ') while ' ' in ntf_list: ntf_list = ntf_list.replace(' ',' ') ntf_list = ntf_list.split() if len(ntf_list): ntf_msg = [L('banned in'),L('kicked from')][status == '307'] ntf_msg = L('Bot was %s %s with reason: %s') % (ntf_msg,room,exit_message) for tmp in ntf_list: send_msg('chat', tmp, '', ntf_msg) else: if reason: exit_message = reason c_lang = mess.getAttr('xml:lang') if c_lang and nick: users_locale['%s/%s' % (room,nick)] = c_lang[:2].replace('uk','ua') if nick != '': for mmb in megabase: if mmb[0]==room and mmb[1]==nick: megabase.remove(mmb) megabase.append([room, nick, role, affiliation, jid]) if role != mmb[2] or affiliation != mmb[3]: not_found = 1 else: not_found = 2 break if not not_found: megabase.append([room, nick, role, affiliation, jid]) if jid == 'None': jid, jid2 = '%s' % nick, 'None' else: jid2, jid = jid, getRoom(jid.lower()) for tmp in gpresence: thr(tmp,(room,jid2,nick,type,(text, role, affiliation, exit_type, exit_message, show, priority, not_found, chg_nick)),'presence_afterwork') al = get_level(getRoom(room),nick)[0] if type == 'subscribe': if al == 9: caps_and_send(xmpp.Presence(room, 'subscribed')) caps_and_send(xmpp.Presence(room, 'subscribe')) pprint('Subscribtion accepted %s' % room,'light_gray') else: caps_and_send(xmpp.Presence(room, 'unsubscribed')) pprint('Subscribtion rejected %s' % room,'red') elif type == 'unsubscribed': if al == 9: caps_and_send(xmpp.Presence(room, 'unsubscribe')) caps_and_send(xmpp.Presence(room, 'unsubscribed')) pprint('Unsubscribtion accepted %s' % room,'light_gray') else: pprint('Unsubscribtion rejected %s' % room,'red') if reason in ['','None',None] and nick != '' and (nick != 'None' or (text != 'None' and len(text)>1)) and nick != nowname and al >= 0 and get_config(getRoom(room),'censor'): nt = '%s %s' % (nick,text) if nt != to_censore(nt,room): cens_text = L('Censored!','%s/%s'%(room,nick)) if al >= 5 and get_config(getRoom(room),'censor_warning'): send_msg('groupchat',room,nick,cens_text) elif al == 4 and get_config(getRoom(room),'censor_action_member') != 'off': act = get_config(getRoom(room),'censor_action_member') muc_filter_action(act,jid2,getRoom(room),cens_text) elif al < 4 and get_config(getRoom(room),'censor_action_non_member') != 'off': act = get_config(getRoom(room),'censor_action_non_member') muc_filter_action(act,jid2,getRoom(room),cens_text) ab = cur_execute_fetchone('select * from age where room=%s and jid=%s and nick=%s',(room, jid, nick)) ttext = '%s\n%s\n%s\n%s\n%s' % (role,affiliation,priority,show,text) if ab: if type=='unavailable': cur_execute('update age set time=%s, age=%s, status=%s, type=%s, message=%s where room=%s and jid=%s and nick=%s', (tt,ab[4]+(tt-ab[3]),1,exit_type,exit_message,room, jid, nick)) else: if ab[5]: cur_execute('update age set time=%s, status=%s, message=%s where room=%s and jid=%s and nick=%s', (tt,0,ttext,room, jid, nick)) else: cur_execute('update age set status=%s, message=%s where room=%s and jid=%s and nick=%s', (0,ttext,room, jid, nick)) else: cur_execute('insert into age values (%s,%s,%s,%s,%s,%s,%s,%s,%s)', (room,nick,jid,tt,0,0,'',ttext,nick.lower())) if not cur_execute_fetchone('select time from first_join where room=%s and jid=%s;',(room,jid)): cur_execute('insert into first_join values (%s,%s,%s);', (room,jid,tt)) def onoff_no_tr(msg): if msg in [None,False,0,'0']: return 'off' elif msg in [True,1,'1']: return 'on' else: return msg def onoff(*msg): if len(msg) == 1: return L(onoff_no_tr(msg[0])) else: return L(onoff_no_tr(msg[0]),msg[1]) def getName(jid): jid = unicode(jid) if jid == 'None': return jid if '@' not in jid: return '' return jid[:jid.find('@')].lower() def getServer(jid): jid = unicode(jid) if '/' not in jid: jid += '/' if jid == 'None': return jid return jid[jid.find('@')+1:jid.find('/')].lower() def getResourse(jid): jid = unicode(jid) if jid == 'None': return jid try: return jid.split('/')[1] except: return '' def getRoom(jid): jid = unicode(jid) if jid == 'None': return jid if '@' in jid: return '%s@%s' % (getName(jid),getServer(jid)) else: return getServer(jid) def now_schedule(): while not game_over: to = GT('schedule_time') while to > 0 and not game_over: time.sleep(2) to -= 2 if not game_over: for tmp in gtimer: if not game_over: thr(tmp,(),('time_thread_%s' % tmp).split(' ',2)[1]) def check_rss(): global rss_processed if rss_processed: return l_hl = int(time.time()) feedbase = cur_execute_fetchall('select * from feed order by time;') if feedbase: for fd in feedbase: ltime = fd[1] timetype = ltime[-1:].lower() if not timetype in ('h','m'): timetype = 'h' try: ofset = int(ltime[:-1]) except: ofset = 4 if timetype == 'h': ofset *= 3600 elif timetype == 'm': ofset *= 60 try: ll_hl = int(fd[3]) except: ll_hl = 0 in_room = cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%fd[4],)) if ofset < 600: ofset = 600 if in_room and ll_hl + ofset <= l_hl: rss_processed = True pprint('check rss: %s in %s' % (fd[0],fd[4]),'green') rss('groupchat', fd[4], 'RSS', 'new %s 10 %s silent' % (fd[0],fd[2])) break rss_processed = False def talk_count(room,jid,nick,text): jid = getRoom(jid) ab = cur_execute_fetchone('select * from talkers where room=%s and jid=%s',(room,jid)) wtext = len(reduce_spaces_all(text).split(' ')) if ab: cur_execute('update talkers set nick=%s, words=%s, frases=%s where room=%s and jid=%s', (nick,ab[3]+wtext,ab[4]+1,room,jid)) else: cur_execute('insert into talkers values (%s,%s,%s,%s,%s)', (room, jid, nick, wtext, 1)) def flush_stats(): pprint('Executed threads: %s | Error(s): %s' % (th_cnt,thread_error_count),'bright_blue') pprint('Message in %s | out %s' % (message_in,message_out),'bright_blue') pprint('Presence in %s | out %s' % (presence_in,presence_out),'bright_blue') pprint('Iq in %s | out %s' % (iq_in,iq_out),'bright_blue') pprint('Unknown out %s' % unknown_out,'bright_blue') pprint('Cycles used %s | unused %s' % (cycles_used,cycles_unused),'bright_blue') if is_win32: ctypes.windll.Kernel32.SetConsoleTextAttribute(win_console_color, get_color_win32('clear')) def disconnecter(): global bot_exit_type, game_over pprint('--- Restart by disconnect handler! ---','bright_blue') pprint('--- Last stanza ---','bright_blue') pprint(last_stanza,'bright_blue') pprint('-'*19,'blue') game_over, bot_exit_type = True, 'restart' time.sleep(2) def get_L_(jid): if jid: _CL = get_config(getRoom(jid),'set_default_locale') if _CL != 'off' and locales.has_key(_CL): return _CL try: loc = users_locale[jid] if locales.has_key(loc): return loc else: return CURRENT_LOCALE except: return CURRENT_LOCALE def L(*par): if len(par) == 2: text,jid = par else: text,jid = par[0],'' if not len(text): return text loc = get_L_(jid) try: return locales[loc][text] except: return text def get_id(): global id_count id_count += 1 return 'request_%s' % id_count def draw_warning(wt): wt = '!!! Warning! %s !!!' % wt pprint('!'*len(wt),'bright_red') pprint(wt,'bright_red') pprint('!'*len(wt),'bright_red') def get_bot_version(): if os.path.isfile(ver_file): bvers = readfile(ver_file).decode('utf-8').replace('\n','').replace('\r','').replace('\t','').replace(' ','') bV = '%s.%s-%s' % (botVersionDef,bvers,base_type) if bvers[:-1] == 'M': draw_warning('Launched bot\'s modification!') else: bV = '%s-%s' % (botVersionDef, base_type) return bV def update_locale(): global CURRENT_LOCALE locales = {} llist = ['en'] + [tmp[:-4] for tmp in os.listdir(loc_folder[:-6]) if tmp[-4:]=='.txt'] CL = cur_execute_fetchone('select value from config_owner where option = %s', ('bot_locale',)) if CL: CURRENT_LOCALE = CL[0] for t in llist: locales[t] = {} lf = loc_folder % t if os.path.isfile(lf): lf = readfile(lf).decode('UTF').replace('\r','').split('\n') for c in lf: if ('#' not in c[:3]) and len(c) and '\t' in c: locales[t][c.split('\t',1)[0].replace('\\n','\n').replace('\\t','\t')] = c.split('\t',1)[1].replace('\\n','\n').replace('\\t','\t') return locales,CURRENT_LOCALE def init_hash(): id_category = 'client' id_type = 'bot' id_lang = CURRENT_LOCALE id_name = 'iSida' capsHash = '%s<' % '/'.join([t.replace('/','//') for t in [id_category,id_type,id_lang,id_name]]) bot_features.sort() capsHash += ''.join(['%s<' % t for t in bot_features]) capsHash += '%s<' % xmpp.NS_SOFTWAREINFO tmp = ['%s<%s' % (t,bot_softwareinfo[t]) for t in bot_softwareinfo.keys()] tmp.sort() capsHash += ''.join(['%s<' % t for t in tmp]) capsHash = hashlib.sha1(capsHash.encode('utf-8')).digest().encode('base64').replace('\n','') return id_category,id_type,id_lang,id_name,capsHash def get_repo(): dirs = os.listdir('.')+os.listdir('../') if '.svn' in dirs: return 'svn' elif '.git' in dirs: return 'git' else: return 'unknown' def get_value_from_array2(a,v): for t in a: if t[0] == v: return t[1] return None def get_array_from_array2(a1,a2): a_res = [] for t in a1: if t[0] in a2: a_res.append(t) return a_res def self_vcard(): global iq_request iqid = get_id() i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to':getRoom(selfjid)}, payload = [xmpp.Node('vCard', {'xmlns': xmpp.NS_VCARD},[])]) iq_request[iqid]=(time.time(),self_vcard_async,[],xmpp.NS_VCARD) sender(i) def self_vcard_async(is_answ): global photo_hash try: vc = is_answ[1][1].getTag('vCard',namespace=xmpp.NS_VCARD) except: return if not vc or unicode(vc) == '': return 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_data = get_value_from_array2(data,'PHOTO.BINVAL').decode('base64') photo_hash = hashlib.sha1(photo_data).hexdigest() PT('photo_hash',photo_hash) except: pass # --------------------- Иницилизация переменных ---------------------- nmbrs = ['0','1','2','3','4','5','6','7','8','9','.'] ul = slog_folder % 'update.log' # лог последнего обновление halt_on_exception = False # остановка на ошибках debug_xmpppy = False # отладка xmpppy debug_console = False # отладка действий бота CommandsLog = None # логгирование команд prefix = '_' # префикс комманд msg_limit = 1000 # лимит размера сообщений botName = 'iSida' # название бота botVersionDef = u'4.0' # версия бота disco_config_node = 'http://isida.dsy.name/config' pres_answer = [] # результаты посылки презенсов iq_request = {} # iq запросы th_cnt = 0 # счётчик тредов thread_error_count = 0 # счётчик ошибок тредов bot_exit_type = None # причина завершения бота last_stream = [] # очередь станз к отправке last_command = [] # последняя исполненная ботом команда messages_log = {} # лог отправленных сообщений thread_type = True # тип тредов time_limit = 0.5 # максимальная задержка между посылкой станз с одинаковым типом в groupchat time_nolimit = 0.1 # задержка между посылкой станз с разными типами message_in,message_out = 0,0 # статистика сообщений iq_in,iq_out = 0,0 # статистика iq запросов presence_in,presence_out = 0,0 # статистика презенсов unknown_out = 0 # статистика ошибочных отправок cycles_used,cycles_unused = 0,0 # статистика циклов id_count = 0 # номер запроса megabase = [] # главная временная база с полной информацией из презенсов ignore_owner = None # исполнять отключенные команды для владельца бота configname = 'settings/config.py' # конфиг бота topics = {} # временное хранение топиков last_msg_base = {} # последние сообщения last_msg_time_base = {} # время между последними сообщениями последние сообщения no_comm = True muc_rejoins = {} muc_statuses = {} muc_repeat = {} last_stanza = '' # последняя станза, посланная ботом ENABLE_TLS = True # принудительное отключение TLS ENABLE_SASL = True # включение SASL base_timeout = 20 # таймаут на доступ ко всем базам between_msg_last = {} # время последнего сообщения last_sender_activity = time.time() # время последней отправки hashes = {} # хеши презенсов capses = {} # капсы клиентов last_hash = {} # хеш последнего события hash_actions_list = {} # список действий на хеш-события smile_folder = '.smiles' # папка со смайлами в чатлогах smile_descriptor = 'icondef.xml' # дескриптор смайлов last_logs_store = [] # последние записи в логах last_logs_size = 20 # максимальное количество последних записей в логах ddos_ignore = {} # данные при подозрении на ddos ddos_iq = {} CURRENT_LOCALE = 'en' user_hash = {} server_hash = {} server_hash_list = {} newbie_msg = {} mute_msg = {} messages_excl = [] rss_processed = False database_debug = False current_join = {} default_censor_set = 1 # номер набора правил для цензора users_locale = {} base_type = 'pgsql' # тип базы: pgsql, mysql, sqlite3 base_name = 'isidabot' # название базы base_user = 'isidabot' # пользователь базы base_host = 'localhost' # хост базы base_port = '5432' # порт для подключения base_charset = 'utf8' # кодировка bot_features = [xmpp.NS_DISCO_INFO,xmpp.NS_DISCO_ITEMS,xmpp.NS_COMMANDS,disco_config_node,xmpp.NS_PING,xmpp.NS_URN_TIME,xmpp.NS_X_OOB,xmpp.NS_MUC_FILTER, xmpp.NS_VERSION,xmpp.NS_TIME,xmpp.NS_MUC,xmpp.NS_LAST,xmpp.NS_DATA,xmpp.NS_MUC_ROOMS] gc.enable() gt=tuple(time.gmtime()) lt=tuple(time.localtime()) if lt[0:3] == gt[0:3]: timeofset = int(lt[3])-int(gt[3]) elif lt[0:3] > gt[0:3]: timeofset = int(lt[3])-int(gt[3]) + 24 else: timeofset = int(gt[3])-int(lt[3]) + 24 is_win32 = sys.platform == 'win32' if is_win32: import ctypes ctypes.windll.Kernel32.GetStdHandle.restype = ctypes.c_ulong win_console_color = ctypes.windll.Kernel32.GetStdHandle(ctypes.c_ulong(0xfffffff5)) if os.path.isfile(configname): execfile(configname) else: errorHandler('%s is missed.' % configname) if base_type == 'pgsql': import psycopg2 import psycopg2.extensions elif base_type == 'mysql': import mysql.connector as mysqldb elif base_type == 'sqlite3': import sqlite3 else: errorHandler('Unknown database backend!') if base_type in ['mysql','sqlite3']: class psycopg2(): def InterfaceError(): return None if thread_type: import threading sema = threading.BoundedSemaphore(value=30) #try: threading.stack_size(65536) #except ValueError: pass class KThread(threading.Thread): def __init__(self, *args, **keywords): threading.Thread.__init__(self, *args, **keywords) self.killed = False def start(self): self.__run_backup = self.run self.run = self.__run threading.Thread.start(self) def __run(self): sys.settrace(self.globaltrace) self.__run_backup() self.run = self.__run_backup def globaltrace(self, frame, why, arg): if why == 'call': return self.localtrace else: return None def localtrace(self, frame, why, arg): if self.killed: if why == 'line': raise SystemExit() return self.localtrace def kill(self): self.killed = True def garbage_collector(): gc.collect() garbage_collector_timer = threading.Timer(3600,garbage_collector) garbage_collector_timer.start() garbage_collector() else: import thread botVersion = get_bot_version() try: tmp = botOs except: botOs = os_version() tmp_os,tmp_ver = os_version_disco() bot_softwareinfo = {'software':botName,'software_version':'%s-%s-%s' % (botVersionDef,get_repo().replace('unknown','none'),base_type),'os':tmp_os,'os_version':tmp_ver} sm_f = os.path.join(public_log % smile_folder) if os.path.isdir(sm_f): smiles_dirs_case = [sd for sd in os.listdir(sm_f) if sd[0] != '.' and os.path.isfile(os.path.join(sm_f,sd,smile_descriptor))] smiles_dirs = [sd.lower() for sd in smiles_dirs_case] else: smiles_dirs, smiles_dirs_case = [], [] logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,) # включение логгирования capsNode = 'http://v4.isida.dsy.name' god = SuperAdmin.lower() pprint('-'*50,'blue') if os.path.basename(sys.argv[0]) != 'isida.py': errorHandler('Ugly launch detect! Read wiki!') if base_type == 'pgsql': conn = psycopg2.connect(database=base_name, user=base_user, host=base_host, password=base_pass, port=base_port) elif base_type == 'mysql': pass elif base_type == 'sqlite3': pass else: errorHandler('Can\'t connect to `%s` base type!' % base_type) own = cur_execute_fetchall('select * from bot_owner;') if not own: cur_execute('insert into bot_owner values (%s)',(SuperAdmin.lower(),)) pprint('*** Loading localization','white') locales,CURRENT_LOCALE = update_locale() pprint('*** Init caps hash','white') id_category,id_type,id_lang,id_name,capsHash = init_hash() pl_folder = 'plugins/%s' gpresence = [] gmessage = [] gactmessage = [] giq_hook = [] pprint('*** Loading Main plugin','white') execfile(pl_folder % 'main.py') pprint('*** Loading AI plugin','white') execfile(pl_folder % 'ai.py') GTIMER_DEF = [check_rss,check_hash_actions,clean_user_and_server_hash] pliname = data_folder % 'ignored.txt' gtimer = list(GTIMER_DEF) pprint('*** Loading other plugins','white') pl,pl_ignore,plugins = os.listdir(pl_folder % ''),getFile(pliname,[]),[] for tmp in pl: if tmp.endswith('.py') and not tmp.startswith('.') and tmp not in ['main.py','ai.py']: plugins.append(tmp) plugins.sort() for pl in plugins: if pl in pl_ignore: pprint('Ignore plugin: %s' % pl,'red') else: presence_control,message_control,message_act_control,iq_control,timer,execute,iq_hook = [],[],[],[],[],[],[] pprint('Append plugin: %s' % pl,'cyan') execfile(pl_folder % pl) for cm in execute: comms.append((cm[0],cm[1],cm[2],cm[3],'%s\r%s' % (pl[:-3],cm[4]))+cm[5:]) for tmr in timer: gtimer.append(tmr) for tmp in presence_control: gpresence.append(tmp) for tmp in message_control: gmessage.append(tmp) for tmp in message_act_control: gactmessage.append(tmp) for tmp in iq_hook: giq_hook.append(tmp) giq_hook.sort() if os.path.isfile(starttime_file): try: starttime = int(readfile(starttime_file)) except: starttime = readfile(starttime_file) else: starttime = int(time.time()) sesstime = int(time.time()) cu_age = [] close_age_null() try: confbase = cur_execute_fetchall('select * from conference;') if confbase: confbase.sort() else: raise except: c_room,c_passwd = '%s/%s' % (defaultConf.lower(),Settings['nickname']),'' confbase = [(c_room,c_passwd)] cur_execute('insert into conference (room,passwd) values (%s,%s);',(c_room,c_passwd)) censor = [] if os.path.isfile(cens): cf = readfile(cens).decode('UTF').replace('\r','').split('# censor ')[default_censor_set].split('\n') for c in cf: if '#' not in c and len(c): censor.append(c) if os.path.isfile(custom_cens): cf = readfile(cens).decode('UTF').replace('\r','').split('\n') for c in cf: if '#' not in c and len(c): censor.append(c) pprint('*'*50,'blue') pprint('*** Name: %s' % botName,'yellow') pprint('*** Version: %s' % botVersion,'yellow') pprint('*** OS: %s ' % botOs,'yellow') pprint('*'*50,'blue') pprint('*** (c) 2oo9-%s Disabler Production Lab.' % str(time.localtime()[0]).replace('0','o'),'bright_cyan') if float(sys.version[:3]) < 2.7: errorHandler('Required Python >= 2.7') lastnick = Settings['nickname'] jid = xmpp.JID(Settings['jid']) if getResourse(jid) in ['None','']: jid = xmpp.JID(Settings['jid'].split('/')[0]+'/my owner is stupid and can not complete the configuration') selfjid = jid pprint('JID: %s' % unicode(jid),'light_gray') message_exclude_update() photo_hash = GT('photo_hash') if not photo_hash: photo_hash = '' try: try: Server = (':'.join(server.split(':')[:-1]),server.split(':')[-1]) Port = int(Server[1]) pprint('Trying to connect to %s' % server,'yellow') except: Server,Port = None,5222 if debug_xmpppy: cl = xmpp.Client(jid.getDomain(),Port,ENABLE_TLS=ENABLE_TLS) else: cl = xmpp.Client(jid.getDomain(),Port,debug=[],ENABLE_TLS=ENABLE_TLS) try: Proxy = proxy pprint('Using proxy %s' % Proxy['host'],'green') except NameError: Proxy = None try: Secure = secure pprint('Tryins secured connection','cyan') except NameError: Secure = None con_stat = cl.connect(Server,Proxy,Secure,ENABLE_TLS=ENABLE_TLS) if con_stat: pprint('Connected as %s' % con_stat.upper(),'yellow') else: raise except: pprint('No connection. Restart in %s sec.' % GT('reboot_time'),'red') time.sleep(GT('reboot_time')) sys.exit('restart') auth_type = cl.auth(jid.getNode(), Settings['password'], jid.getResource(),sasl=ENABLE_SASL) if auth_type: pprint('Authenticated via %s' % auth_type.upper(),'yellow') else: pprint('Authentication error!','red') sys.exit('exit') pprint('Registration Handlers','yellow') cl.RegisterHandler('message',messageCB) cl.RegisterHandler('iq',iqCB) cl.RegisterHandler('presence',presenceCB) cl.RegisterDisconnectHandler(disconnecter) cl.UnregisterDisconnectHandler(cl.DisconnectHandler) if GT('show_loading_by_status'): if GT('show_loading_by_status_show') == 'online': caps_and_send(xmpp.Presence(status=GT('show_loading_by_status_message'), priority=Settings['priority'])) else: caps_and_send(xmpp.Presence(show=GT('show_loading_by_status_show'), status=GT('show_loading_by_status_message'), priority=Settings['priority'])) else: 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'])) pprint('Update self vcard','yellow') self_vcard() time.sleep(1) pprint('Wait conference','yellow') time.sleep(0.5) game_over = None thr(remove_ignore,(),'ddos_remove') cb = [] is_start = True lastserver = getServer(confbase[-1][0].lower()) join_percent, join_pers_add = 0, 100.0/len(confbase) for tocon in confbase: if tocon[1]: pprint('->- %s | pass: %s' % tocon,'green') else: pprint('->- %s' % tocon[0],'green') if GT('show_loading_by_status_percent'): join_percent += join_pers_add join_status = '%s %s%%' % (GT('show_loading_by_status_message'),int(join_percent)) if GT('show_loading_by_status'): if GT('show_loading_by_status_room'): join_status = '%s [%s]' % (join_status,tocon[0]) if GT('show_loading_by_status_show') == 'online': caps_and_send(xmpp.Presence(status=join_status, priority=Settings['priority'])) else: caps_and_send(xmpp.Presence(show=GT('show_loading_by_status_show'), status=join_status, priority=Settings['priority'])) baseArg = unicode(tocon[0]) if '/' not in baseArg: baseArg += '/%s' % unicode(Settings['nickname']) zz = join(baseArg, tocon[1]) while unicode(zz)[:3] == '409' and not game_over: time.sleep(1) baseArg += '_' zz = join(baseArg, tocon[1]) if zz: pprint('-!- Error "%s" while join in to %s' % (zz,baseArg),'red') if GT('show_loading_by_status'): if GT('show_loading_by_status_room'): join_status = L('Error while join in to %s - %s') % (tocon[0],zz) if GT('show_loading_by_status_show') == 'online': caps_and_send(xmpp.Presence(status=join_status, priority=Settings['priority'])) else: caps_and_send(xmpp.Presence(show=GT('show_loading_by_status_show'), status=join_status, priority=Settings['priority'])) else: pprint('-<- %s' % baseArg,'bright_green') if game_over: break is_start = plugins_reload = None pprint('Joined','white') thr(now_schedule,(),'schedule') thr(iq_async_clean,(),'async_iq_clean') thr(presence_async_clean,(),'async_presence_clean') try: thr(bomb_random,(),'bomb_random') except: pass if GT('show_loading_by_status'): 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'])) while 1: try: while not game_over: cyc = cl.Process(1) if str(cyc) == 'None': cycles_unused += 1 elif int(str(cyc)): cycles_used += 1 else: cycles_unused += 1 if plugins_reload: from isida import update as isida_update isida_update(get_repo()) botVersion = get_bot_version() bot_softwareinfo['software_version'] = botVersion pprint('*** Reload localization','white') locales,CURRENT_LOCALE = update_locale() pprint('*** Reinit caps hash','white') self_vcard() id_category,id_type,id_lang,id_name,capsHash = init_hash() gtimer,gpresence,gmessage,gactmessage,giq_hook = list(GTIMER_DEF),[],[],[],[] pprint('*** Reload Main plugin','white') execfile(pl_folder % 'main.py') pprint('*** Reload AI plugin','white') execfile(pl_folder % 'ai.py') pprint('*** Reload other plugins','white') pl,pl_ignore,plugins = os.listdir(pl_folder % ''),getFile(pliname,[]),[] for tmp in pl: if tmp.endswith('.py') and not tmp.startswith('.') and tmp not in ['main.py','ai.py']: plugins.append(tmp) plugins.sort() for pl in plugins: if pl in pl_ignore: pprint('Ignore plugin: %s' % pl,'red') else: presence_control,message_control,message_act_control,iq_control,timer,execute,iq_hook = [],[],[],[],[],[],[] pprint('Append plugin: %s' % pl,'cyan') execfile(pl_folder % pl) for cm in execute: comms.append((cm[0],cm[1],cm[2],cm[3],'%s\r%s' % (pl[:-3],cm[4]))+cm[5:]) for tmr in timer: gtimer.append(tmr) for tmp in presence_control: gpresence.append(tmp) for tmp in message_control: gmessage.append(tmp) for tmp in message_act_control: gactmessage.append(tmp) for tmp in iq_hook: giq_hook.append(tmp) giq_hook.sort() pprint('*** Soft update finished! Plugins loaded: %s. Commands: %s' % (len(plugins)+1,len(comms)),'white') plugins_reload = None atempt_to_shutdown(False) sys.exit(bot_exit_type) except KeyboardInterrupt: atempt_to_shutdown_with_reason(L('Shutdown by CTRL+C...'),0,'exit',False) except xmpp.SystemShutdown: atempt_to_shutdown_with_reason(L('System Shutdown. Trying to restart in %s sec.') % GT('reboot_time'),GT('reboot_time'),'restart',False) except psycopg2.InterfaceError: atempt_to_shutdown_with_reason(L('Interface error! Trying to restart in %s sec.') % int(GT('reboot_time')/4),int(GT('reboot_time')/4),'restart',False) except Exception, SM: try: SM = str(SM) except: SM = unicode(SM) pprint('*** Error *** %s ***' % SM,'red') logging.exception(' [%s] ' % timeadd(tuple(time.localtime()))) if 'parsing finished' in SM.lower() or 'database is locked' in SM.lower(): atempt_to_shutdown_with_reason(L('Critical error! Trying to restart in %s sec.') % int(GT('reboot_time')/4),GT('reboot_time')/4,'restart',True) if halt_on_exception: raise # The end is near!