#!/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: random,smart,full,partial,on,off,kick,ban,replace,mute,visitor,truncate,paste,chat,online,away,xa,dnd,on start,on shutdown,by time,black,white,without highlight,all,ban server,Loading...,Mon,Tue,Wed,Thu,Fri,Sat,Sun,_Jan,_Feb,_Mar,_Apr,_May,_Jun,_Jul,_Aug,_Sep,_Oct,_Nov,_Dec,no limit,visitor/none,visitor/member,participant/none,participant/member,moderator/none,moderator/member,moderator/admin,moderator/owner,bot owner,You should be at least %s to do it.,You must be a %s to do it.,absent,Bad request,Conflict,Feature not implemented,Forbidden,Gone,Internal server error,Item not found,Jid malformed,Not acceptable,Not allowed,Not authorized,Payment required,Recipient unavailable,Redirect,Registration required,Remote server not found,Remote server timeout,Resource constraint,Service unavailable,Subscription required,Undefined condition,Unexpected request

rlmas_min = (('&','&amp;'),('\"','&quot;'),('\'','&apos;'),('<','&lt;'),('>','&gt;'))

rlmas = rlmas_min + (('~','&tilde;'),('\t','&nbsp;'*8))

lmass = (('\n','<br>'),('\n','<br />'),('\n','<br/>'),('\n','\n\r'),('','<![CDATA['),('',']]>'),
		('','&shy;'),('','&ensp;'),('','&emsp;'),('','&thinsp;'),('','&zwnj;'),('','&zwj;'))

rmass = (('&','&amp;'),('\"','&quot;'),('\'','&apos;'),('~','&tilde;'),(' ','&nbsp;'),
		('<','&lt;'),('>','&gt;'),(u'¡','&iexcl;'),(u'¢','&cent;'),(u'£','&pound;'),
		(u'¤','&curren;'),(u'¥','&yen;'),(u'¦','&brvbar;'),(u'§','&sect;'),(u'¨','&uml;'),(u'©','&copy;'),(u'ª','&ordf;'),
		(u'«','&laquo;'),(u'¬','&not;'),(u'®','&reg;'),(u'¯','&macr;'),(u'°','&deg;'),(u'±','&plusmn;'),
		(u'²','&sup2;'),(u'³','&sup3;'),(u'´','&acute;'),(u'µ','&micro;'),(u'¶','&para;'),(u'·','&middot;'),(u'¸','&cedil;'),
		(u'¹','&sup1;'),(u'º','&ordm;'),(u'»','&raquo;'),(u'¼','&frac14;'),(u'½','&frac12;'),(u'¾','&frac34;'),(u'¿','&iquest;'),
		(u'×','&times;'),(u'÷','&divide;'),(u'À','&Agrave;'),(u'Á','&Aacute;'),(u'Â','&Acirc;'),(u'Ã','&Atilde;'),(u'Ä','&Auml;'),
		(u'Å','&Aring;'),(u'Æ','&AElig;'),(u'Ç','&Ccedil;'),(u'È','&Egrave;'),(u'É','&Eacute;'),(u'Ê','&Ecirc;'),(u'Ë','&Euml;'),
		(u'Ì','&Igrave;'),(u'Í','&Iacute;'),(u'Î','&Icirc;'),(u'Ï','&Iuml;'),(u'Ð','&ETH;'),(u'Ñ','&Ntilde;'),(u'Ò','&Ograve;'),
		(u'Ó','&Oacute;'),(u'Ô','&Ocirc;'),(u'Õ','&Otilde;'),(u'Ö','&Ouml;'),(u'Ø','&Oslash;'),(u'Ù','&Ugrave;'),(u'Ú','&Uacute;'),
		(u'Û','&Ucirc;'),(u'Ü','&Uuml;'),(u'Ý','&Yacute;'),(u'Þ','&THORN;'),(u'ß','&szlig;'),(u'à','&agrave;'),(u'á','&aacute;'),
		(u'â','&acirc;'),(u'ã','&atilde;'),(u'ä','&auml;'),(u'å','&aring;'),(u'æ','&aelig;'),(u'ç','&ccedil;'),(u'è','&egrave;'),
		(u'é','&eacute;'),(u'ê','&ecirc;'),(u'ë','&euml;'),(u'ì','&igrave;'),(u'í','&iacute;'),(u'î','&icirc;'),(u'ï','&iuml;'),
		(u'ð','&eth;'),(u'ñ','&ntilde;'),(u'ò','&ograve;'),(u'ó','&oacute;'),(u'ô','&ocirc;'),(u'õ','&otilde;'),(u'ö','&ouml;'),
		(u'ø','&oslash;'),(u'ù','&ugrave;'),(u'ú','&uacute;'),(u'û','&ucirc;'),(u'ü','&uuml;'),(u'ý','&yacute;'),(u'þ','&thorn;'),
		(u'ÿ','&yuml;'),(u'∀','&forall;'),(u'∂','&part;'),(u'∃','&exists;'),(u'∅','&empty;'),(u'∇','&nabla;'),(u'∈','&isin;'),
		(u'∉','&notin;'),(u'∋','&ni;'),(u'∏','&prod;'),(u'∑','&sum;'),(u'−','&minus;'),(u'∗','&lowast;'),(u'√','&radic;'),
		(u'∝','&prop;'),(u'∞','&infin;'),(u'∠','&ang;'),(u'∧','&and;'),(u'∨','&or;'),(u'∩','&cap;'),(u'∪','&cup;'),
		(u'∫','&int;'),(u'∴','&there4;'),(u'∼','&sim;'),(u'≅','&cong;'),(u'≈','&asymp;'),(u'≠','&ne;'),(u'≡','&equiv;'),
		(u'≤','&le;'),(u'≥','&ge;'),(u'⊂','&sub;'),(u'⊃','&sup;'),(u'⊄','&nsub;'),(u'⊆','&sube;'),(u'⊇','&supe;'),
		(u'⊕','&oplus;'),(u'⊗','&otimes;'),(u'⊥','&perp;'),(u'⋅','&sdot;'),(u'Α','&Alpha;'),(u'Β','&Beta;'),(u'Γ','&Gamma;'),
		(u'Δ','&Delta;'),(u'Ε','&Epsilon;'),(u'Ζ','&Zeta;'),(u'Η','&Eta;'),(u'Θ','&Theta;'),(u'Ι','&Iota;'),(u'Κ','&Kappa;'),
		(u'Λ','&Lambda;'),(u'Μ','&Mu;'),(u'Ν','&Nu;'),(u'Ξ','&Xi;'),(u'Ο','&Omicron;'),(u'Π','&Pi;'),(u'Ρ','&Rho;'),
		(u'Σ','&Sigma;'),(u'Τ','&Tau;'),(u'Υ','&Upsilon;'),(u'Φ','&Phi;'),(u'Χ','&Chi;'),(u'Ψ','&Psi;'),(u'Ω','&Omega;'),
		(u'α','&alpha;'),(u'β','&beta;'),(u'γ','&gamma;'),(u'δ','&delta;'),(u'ε','&epsilon;'),(u'ζ','&zeta;'),(u'η','&eta;'),
		(u'θ','&theta;'),(u'ι','&iota;'),(u'κ','&kappa;'),(u'λ','&lambda;'),(u'μ','&mu;'),(u'ν','&nu;'),(u'ξ','&xi;'),
		(u'ο','&omicron;'),(u'π','&pi;'),(u'ρ','&rho;'),(u'ς','&sigmaf;'),(u'σ','&sigma;'),(u'τ','&tau;'),(u'υ','&upsilon;'),
		(u'φ','&phi;'),(u'χ','&chi;'),(u'ψ','&psi;'),(u'ω','&omega;'),(u'ϑ','&thetasym;'),(u'ϒ','&upsih;'),(u'ϖ','&piv;'),
		(u'Œ','&OElig;'),(u'œ','&oelig;'),(u'Š','&Scaron;'),(u'š','&scaron;'),(u'Ÿ','&Yuml;'),(u'ƒ','&fnof;'),(u'ˆ','&circ;'),
		(u'‎','&lrm;'),(u'‏','&rlm;'),(u'–','&ndash;'),(u'—','&mdash;'),(u'‘','&lsquo;'),(u'’','&rsquo;'),(u'‚','&sbquo;'),
		(u'“','&ldquo;'),(u'”','&rdquo;'),(u'„','&bdquo;'),(u'†','&dagger;'),(u'‡','&Dagger;'),(u'•','&bull;'),(u'…','&hellip;'),
		(u'‰','&permil;'),(u'′','&prime;'),(u'″','&Prime;'),(u'‹','&lsaquo;'),(u'›','&rsaquo;'),(u'‾','&oline;'),(u'€','&euro;'),
		(u'™','&trade;'),(u'←','&larr;'),(u'↑','&uarr;'),(u'→','&rarr;'),(u'↓','&darr;'),(u'↔','&harr;'),(u'↵','&crarr;'),
		(u'⌈','&lceil;'),(u'⌉','&rceil;'),(u'⌊','&lfloor;'),(u'⌋','&rfloor'),(u'◊','&loz;'),(u'♠','&spades;'),(u'♣','&clubs;'),
		(u'♥','&hearts;'),(u'♦','&diams;'))

levl = {'no|limit':0,'visitor|none':1,'visitor|member':2,'participant|none':3,'participant|member':4,
		'moderator|none':5,'moderator|member':6,'moderator|admin':7,'moderator|owner':8,'bot|owner':9}

unlevl = ['no limit','visitor/none','visitor/member','participant/none','participant/member',
		  'moderator/none','moderator/member','moderator/admin','moderator/owner','bot owner']

unlevltxt = ['You should be at least %s to do it.','You must be a %s to do it.']

unlevlnum = [0,0,0,0,0,0,0,0,0,1]

presence_error = {'401':L('Password required'),
				  '403':L('Forbidden'),
				  '407':L('Members-only')}

msg_status_codes = {'102':L('Room now shows unavailable members.'),
					'103':L('Room now does not show unavailable members.'),
					'104':L('Room\'s configuration changed.'),
					'171':L('Logs at server side are enabled.'),
					'172':L('Room now is non-anonymous.'),
					'173':L('Room now is semi-anonymous.'),
					'174':L('Room now is fully-anonymous.')}

wday = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
wmonth = ['_Jan','_Feb','_Mar','_Apr','_May','_Jun','_Jul','_Aug','_Sep','_Oct','_Nov','_Dec']

two_en = ['aa', 'aq', 'bc', 'bd', 'bf', 'bg', 'bh', 'bk', 'bn', 'bp', 'bq', 'bw', 'bx', 'bz', 'cb', 'cd', 'cf', 'cg', 'cj', \
		  'cm', 'cn', 'cp', 'cs', 'cv', 'cw', 'cx', 'cz', 'db', 'dc', 'dh', 'dj', 'dp', 'dq', 'dt', 'dx', 'dz', 'ej', 'fb', \
		  'fc', 'fd', 'fg', 'fh', 'fj', 'fk', 'fm', 'fn', 'fp', 'fq', 'fs', 'fv', 'fx', 'fz', 'gb', 'gc', 'gf', 'gj', 'gk', \
		  'gp', 'gq', 'gv', 'gw', 'gx', 'gz', 'hc', 'hg', 'hh', 'hj', 'hk', 'hp', 'hq', 'hs', 'hv', 'hx', 'hz', 'ih', 'ii', \
		  'ij', 'iq', 'iw', 'iy', 'jb', 'jc', 'jd', 'jf', 'jg', 'jh', 'jj', 'jk', 'jl', 'jm', 'jn', 'jq', 'jr', 'js', 'jt', \
		  'jv', 'jw', 'jx', 'jy', 'jz', 'kb', 'kc', 'kd', 'kj', 'kk', 'km', 'kp', 'kq', 'kr', 'ks', 'kt', 'kv', 'kx', 'kz', \
		  'lh', 'lj', 'ln', 'lq', 'lx', 'lz', 'mc', 'md', 'mg', 'mh', 'mj', 'mk', 'mq', 'mv', 'mw', 'mx', 'mz', 'nb', 'nr', \
		  'oq', 'pc', 'pf', 'pj', 'pk', 'pq', 'pv', 'px', 'pz', 'qa', 'qb', 'qc', 'qd', 'qe', 'qf', 'qg', 'qh', 'qi', 'qj', \
		  'qk', 'ql', 'qm', 'qn', 'qo', 'qp', 'qq', 'qr', 'qs', 'qt', 'qv', 'qw', 'qx', 'qy', 'qz', 'rj', 'rq', 'rx', 'rz', \
		  'sj', 'sv', 'sx', 'sz', 'tb', 'td', 'tg', 'tj', 'tk', 'tq', 'tv', 'tx', 'tz', 'uh', 'uj', 'uo', 'uq', 'uu', 'uv', \
		  'uw', 'ux', 'vb', 'vc', 'vd', 'vf', 'vg', 'vh', 'vj', 'vk', 'vl', 'vm', 'vn', 'vp', 'vq', 'vr', 'vs', 'vt', 'vu', \
		  'vv', 'vw', 'vx', 'vz', 'wb', 'wc', 'wg', 'wj', 'wm', 'wp', 'wq', 'wt', 'wu', 'wv', 'wx', 'wz', 'xb', 'xd', 'xg', \
		  'xj', 'xk', 'xl', 'xn', 'xo', 'xq', 'xr', 'xs', 'xu', 'xv', 'xw', 'xx', 'xz', 'yc', 'yd', 'yf', 'yg', 'yj', 'yk', \
		  'yn', 'yq', 'yu', 'yv', 'yx', 'yy', 'yz', 'zb', 'zc', 'zd', 'zf', 'zg', 'zh', 'zi', 'zj', 'zk', 'zm', 'zn', 'zp', \
		  'zq', 'zr', 'zs', 'zt', 'zu', 'zv', 'zw', 'zx']

def non_case_sort(arr):
	tmp = [[t.lower(),t] for t in arr]
	tmp.sort()
	return [t[1] for t in tmp]
		  
def get_size_human(mt):
	if mt < 1024: return '%sb' % int(mt)
	for t in ['Kb','Mb','Gb']:
		mt = mt / 1024.0
		if mt < 1024: break
	return '%.2f%s' % (mt,t)

def is_owner(jid): return cur_execute_fetchone('select * from bot_owner where jid=%s',(getRoom(jid),)) != None

def validate_nick(nick,count):
		nick = nick.lower()
		pairs = 0
		for t in re.findall('\s+[^\s]*', ' ' + nick):
			pairs += sum([t.count(k) for k in two_en])
		return pairs-len(nick.split()) < count, pairs

def get_xnick(jid):
	tmp = cur_execute_fetchone('select room from conference where room ilike %s',('%s/%%'%getRoom(jid),))
	if tmp: return getResourse(tmp[0])
	else: return Settings['nickname']

def get_xtype(jid):
	jid,xtype = getRoom(jid),'owner'
	nowname = get_xnick(jid)
	for base in megabase:
		if base[0].lower() == jid and base[1] == nowname:
			xtype = base[3]
			break
	return xtype

def clean_user_and_server_hash():
	global user_hash, server_hash, server_hash_list
	timing = {}
	for tmp in user_hash.keys():
		try:
			tm = user_hash[tmp]
			gr = getRoom(tmp)
			try: tmo = get_config_int(gr,'muc_filter_hash_ban_by_rejoin_timeout')
			except: tmo = 3600
			if timing.__contains__(gr): tmo = timing[gr]
			else: timing[gr] = tmo
			if time.time() > tm + tmo: user_hash.pop(tmp)
		except: pass
	for tmp in server_hash_list.keys():
		tm = server_hash_list[tmp]
		gr = getRoom(tmp)
		try: tmo = get_config_int(gr,'muc_filter_hash_ban_by_rejoin_timeout')
		except: tmo = 3600
		if timing.__contains__(gr): tmo = timing[gr]
		else: timing[gr] = tmo
		if time.time() > tm + tmo: server_hash_list.pop(tmp)
	for tmp in server_hash.keys():
		try:
			tm = server_hash[tmp][0]
			gr = getRoom(tmp)
			try: tmo = get_config_int(gr,'muc_filter_hash_ban_by_rejoin_timeout')
			except: tmo = 3600
			if timing.__contains__(gr): tmo = timing[gr]
			else: timing[gr] = tmo
			if time.time() > tm + tmo: server_hash.pop(tmp)
		except: pass

def ddos_info(type, room, nick, text):
	global ddos_ignore
	text = reduce_spaces_all(text.lower()).split()
	if text == []: text = ['']
	if text[0] in ['','show']:
		tmas = []
		for tmp in ddos_ignore.keys(): tmas.append('%s/%s [%s] %s' % (ddos_ignore[tmp][0],ddos_ignore[tmp][1],tmp,un_unix(ddos_ignore[tmp][2]-time.time(),'%s/%s'%(jid,nick))))
		if tmas: msg = L('Ignore list: %s','%s/%s'%(jid,nick)) % '; '.join(tmas)
		else: msg = L('List is empty.','%s/%s'%(jid,nick))
	elif text[0] in ['del','remove'] and len(text) > 1:
		if ddos_ignore.__contains__(text[1]):
			try:
				ddos_ignore.pop(text[1])
				msg = L('Removed: %s','%s/%s'%(jid,nick)) % text[1]
			except: msg = L('Not found: %s','%s/%s'%(jid,nick)) % text[1]
		else: msg = L('Not found: %s','%s/%s'%(jid,nick)) % text[1]
	else: msg = L('Error in parameters. Read the help about command.','%s/%s'%(jid,nick))
	send_msg(type, room, nick, msg)

def atempt_to_shutdown(critical):
	if not critical:
		pprint('Close age base','dark_gray')
		close_age()
	if thread_type:
		try: garbage_collector_timer.cancel()
		except: pass
	if base_type not in ['sqlite3','mysql']:
		conn.commit()
		conn.close()
	flush_stats()

def atempt_to_shutdown_with_reason(text,sleep_time,exit_type,critical):
	pprint(text,'red')
	send_presence_all(text)
	atempt_to_shutdown(critical)
	if sleep_time: time.sleep(sleep_time)
	sys.exit(exit_type)

def deidna(text):
	def repl(t): return t.group().lower().encode('ascii').decode('idna')
	return re.sub(r'(xn--[-0-9a-z_]*)',repl,text,flags=re.S|re.I|re.U)

def enidna(text):
	idn = re.findall(u'http[s]?://([-0-9a-zа-я._]*)',text,flags=re.S|re.I|re.U)
	if idn: text = text.replace(idn[0],idn[0].lower().encode('idna').decode('ascii'))
	return text

def enidna_raw(text):
	def repl(t): return t.group().lower().encode('idna').decode('ascii')
	return re.sub(u'([а-я][-0-9а-я_]*)',repl,text,flags=re.S|re.I|re.U)

def get_level(cjid, cnick):
	access_mode = -2
	jid = 'None'
	for base in megabase:
		if base[1] == cnick and base[0].lower()==cjid:
			jid = base[4]
			j_affl = base[3]
			if j_affl in ['admin','owner']: j_role = 'moderator'
			else: j_role = base[2]
			if '%s|%s' % (j_role,j_affl) in levl:
				access_mode = levl['%s|%s' % (j_role,j_affl)]
				break
	if cur_execute_fetchone('select pattern from bot_ignore where %s ilike pattern',(getRoom(jid.lower()),)): access_mode = -1
	rjid = getRoom(jid)
	if is_owner(rjid): access_mode = 9
	if jid == 'None' and is_owner(cjid): access_mode = 9
	return (access_mode, jid)

def show_syslogs(type, jid, nick, text):
	tmp = text.strip().split(' ', 1)
	lsz, txt = 10, ''
	if len(tmp) == 1:
		try: lsz = int(tmp[0])
		except: txt = tmp[0]
	elif len(tmp) == 2:
		try: lsz, txt = int(tmp[0]), tmp[1]
		except: txt = text
	lsz += 1
	lsz = 1 if lsz <= 0 else (last_logs_size if lsz > last_logs_size else lsz)
	msg = '\n'.join([tmp for tmp in last_logs_store if txt in tmp.lower() or txt in tmp][1:lsz][::-1])
	if msg:
		send_msg(type, jid, nick, L('Last syslogs:\n%s','%s/%s'%(jid,nick)) % msg)
	else:
		send_msg(type, jid, nick, L('Syslogs not found','%s/%s'%(jid,nick)))

def show_syslogs_search(type, jid, nick, text):
	if '\n' in text: text,value = text.lower().split('\n',1)
	else: text,value = text.lower(),''
	if not text.strip():
		send_msg(type, jid, nick, L('What?','%s/%s'%(jid,nick)))
		return
	if value:
		try: _ = re.compile(value)
		except:
			send_msg(type, jid, nick, L('Error in RegExp!','%s/%s'%(jid,nick)))
			return
	try: _ = re.compile(text)
	except:
		send_msg(type, jid, nick, L('Error in RegExp!','%s/%s'%(jid,nick)))
		return
	files = [t for t in os.listdir(slog_folder % '') if re.findall('^[0-9]{8}\.txt$',t)]
	files.sort()
	if not value: files = files[-1:]
	matches = []
	for t in files:
		if not value or (value and re.findall(value,t.split('.')[0])):
			m = [f for f in readfile(slog_folder % t).split('\n') if ' [9] syslogs_search' not in f and re.findall(text,f,re.S|re.I|re.U)]
			if m:
				if value: matches.append('*** %s%s%s%s-%s%s-%s%s ***' % tuple(t.split('.')[0]))
				matches += m
	if matches: msg = L('Last syslogs: %s','%s/%s'%(jid,nick)) % '\n%s' % '\n'.join(matches)
	else: msg = L('Not found!','%s/%s'%(jid,nick))
	if len(msg) > msg_limit*5-4: msg = u'[…]%s' % msg[-msg_limit*5+4:]
	send_msg(type, jid, nick, msg)

def set_locale(type, jid, nick, text):
	global CURRENT_LOCALE
	if len(text) >= 2:
		text = text.lower()
		lf = loc_folder % text
		if os.path.isfile(lf) or text == 'en':
			PT('bot_locale',text)
			msg = L('Locale set to: %s','%s/%s'%(jid,nick)) % text
			CURRENT_LOCALE = text
		else: msg = L('Locale not found!','%s/%s'%(jid,nick))
	else: msg = L('Current locale: %s','%s/%s'%(jid,nick)) % GT('bot_locale')
	send_msg(type, jid, nick, msg)

def shell_execute(*cmd):
	if len(cmd) == 2: rn = cmd[1]
	else: rn = ''
	cmd = cmd[0]
	if GT('paranoia_mode'): result = L('Command temporary blocked!',rn)
	else:
		tmp_file = '%s.tmp' % int(time.time())
		try:
			error_answ = os.system('%s > %s' % (cmd,tmp_file))
			if not error_answ:
				try: body = readfile(tmp_file)
				except: body = L('Command execution error.',rn)
				if len(body):
					enc = chardet.detect(body)['encoding']
					result = remove_sub_space(str(body,enc))
				else: result = L('ok')
			else: result = L('Command execution error.',rn)
		except Exception as SM:
			try: SM = str(SM)
			except: SM = str(SM)
			result = L('I can\'t execute it! Error: %s',rn) % SM
		try: os.remove(tmp_file)
		except: pass
	return result

def concat(list): return ''.join(list)

def get_affiliation(jid,nick):
	xtype = ''
	for base in megabase:
		if base[0].lower() == jid and base[1] == nick:
			xtype = base[3]
			break
	return xtype

def comm_on_off(type, jid, nick, text):
	text = text.strip().lower().split()
	if text:
		cmd = text[0]
		cmds = text[1:]
		if cmd == 'on':
			if not cmds: msg = L('What enable?','%s/%s'%(jid,nick))
			else:
				not_found,enabled,already = [],[],[]
				for t in cmds:
					if not [True for c in comms if c[1]==t]: not_found.append(t)
					elif cur_execute_fetchone('select cmd from commonoff where room=%s and cmd=%s;',(jid,t)):
						cur_execute('delete from commonoff where room=%s and cmd=%s;',(jid,t))
						enabled.append(t)
					else: already.append(t)
				msg = []
				if enabled: msg.append(L('Enabled commands: %s','%s/%s'%(jid,nick)) % ', '.join(enabled))
				if already: msg.append(L('Not disabled commands: %s','%s/%s'%(jid,nick)) % ', '.join(already))
				if not_found: msg.append(L('Commands not found: %s','%s/%s'%(jid,nick)) % ', '.join(not_found))
				msg = '\n'.join(msg)
		elif cmd == 'off':
			if not cmds: msg = L('What disable?','%s/%s'%(jid,nick))
			else:
				not_found,disabled,already = [],[],[]
				for t in cmds:
					if not [True for c in comms if c[1]==t]: not_found.append(t)
					elif cur_execute_fetchone('select cmd from commonoff where room=%s and cmd=%s;',(jid,t)): already.append(t)
					else:
						cur_execute('insert into commonoff values (%s,%s);',(jid,t))
						disabled.append(t)
				msg = []
				if disabled: msg.append(L('Disabled commands: %s','%s/%s'%(jid,nick)) % ', '.join(disabled))
				if already: msg.append(L('Commands disabled before: %s','%s/%s'%(jid,nick)) % ', '.join(already))
				if not_found: msg.append(L('Commands not found: %s','%s/%s'%(jid,nick)) % ', '.join(not_found))
				msg = '\n'.join(msg)
		else: msg = L('Unknown item!','%s/%s'%(jid,nick))
	else:
		cmd = cur_execute_fetchall('select cmd from commonoff where room=%s;',(jid,))
		if cmd: msg = L('Disabled commands: %s','%s/%s'%(jid,nick)) % ', '.join([t[0] for t in cmd])
		else: msg = L('Disabled commands not found!','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def reduce_spaces_all(text):
	text,t = text.strip(),''
	if len(text):
		for tmp in text:
			if tmp != ' ' or t[-1] != ' ': t += tmp
	return t

def status(type, jid, nick, text):
	if text == '': text = nick
	is_found = None
	for tmp in megabase:
		if tmp[0] == jid and tmp[1] == text:
			is_found = True
			break
	if is_found:
		realjid = getRoom(get_level(jid,text)[1])
		stat = cur_execute_fetchone('select message,status from age where jid=%s and room=%s and nick=%s',(realjid,jid,text))
		if stat:
			if stat[1]: msg = L('leave this room.','%s/%s'%(jid,nick))
			else:
				stat = stat[0].split('\n',4)
				if stat[3] != 'None': msg = stat[3]
				else: msg = 'online'
				if stat[4] != 'None': msg += ' ('+stat[4]+')'
				if stat[2] != 'None': msg += ' ['+stat[2]+'] '
				else: msg += ' [0] '
				if stat[0] != 'None' and stat[1] != 'None': msg += stat[0]+'/'+stat[1]
			if text != nick: msg = text + ' - '+msg
		else: msg = L('Not found!','%s/%s'%(jid,nick))
	else: msg = L('I can\'t see %s here...','%s/%s'%(jid,nick)) % text
	send_msg(type, jid, nick, msg)

def replacer(msg):
	def repl(t): return '%s\n' % re.findall('<div.*?>(.*?)</div>',t.group(0),re.S|re.I|re.U)[0]
	msg = rss_replace(msg)
	msg = re.sub(r'(<div.*?>).*?(</div>)',repl,msg,flags=re.S|re.I|re.U)
	for tmp in [['<br/>','\n'],['<br />','\n']]: msg = msg.replace(*tmp)
	msg = rss_del_html(msg)
	msg = rss_replace(msg)
	msg = rss_del_nn(msg)
	return msg.replace('...',u'…')

def vcs_info(type, jid, nick):
	if os.path.isfile(ul):
		try: msg = L('Last update:\n%s','%s/%s'%(jid,nick)) % readfile(ul).replace('\n\n','\n')
		except: msg = L('Error!','%s/%s'%(jid,nick))
	else: msg = L('File %s not found!','%s/%s'%(jid,nick)) % ul
	while msg[-1] in ['\n',' ']: msg = msg[:-1]
	if msg.count('\n') == 1: msg = msg.replace('\n',' ')
	send_msg(type, jid, nick, msg[:msg_limit])

def unhtml_raw(page,mode):
	for a in range(0,page.count('<style')):
		ttag = get_tag_full(page,'style')
		page = page.replace(ttag,'')

	for a in range(0,page.count('<script')):
		ttag = get_tag_full(page,'script')
		page = page.replace(ttag,'')

	page = rss_replace(page)
	if mode: page = replace_ltgt(page)
	else: page = rss_repl_html(page)
	page = rss_replace(page)
	page = rss_del_nn(page)
	page = page.replace('\n ','')
	return page

def unhtml(page): return unhtml_raw(page,None)

def unhtml_hard(page): return unhtml_raw(page,True)

def alias(type, jid, nick, text):
	text = text.strip()
	while '  ' in text: text = text.replace('  ',' ')
	mode = text.lower().split(' ',1)[0].strip(' ')
	try: cmd = text.split(' ',1)[1].split('=',1)[0].strip(' ')
	except: cmd = ''
	try: cbody = text.split(' ',1)[1].split('=',1)[1].strip(' ')
	except: cbody = ''
	msg = L('Mode %s not detected!','%s/%s'%(jid,nick)) % mode
	if mode in ['add','add_global']:
		am,amm = get_level(jid,nick)[0],-1
		tcmd = cbody.split(' ',1)[0].lower()
		for tmp in comms:
			if tmp[1] == tcmd:
				amm = tmp[0]
				break
		if amm < 0: msg = L('Command not found: %s','%s/%s'%(jid,nick)) % tcmd
		elif mode == 'add' and amm > am: msg = L('Not allowed create alias for: %s','%s/%s'%(jid,nick)) % tcmd
		elif mode == 'add_global' and am != 9: msg = L('Not allowed create global alias for: %s','%s/%s'%(jid,nick)) % tcmd
		else:
			gjid = jid if mode == 'add' else '*'
			fl = cur_execute_fetchone('select match from alias where room=%s and match =%s',(gjid,cmd))
			if fl:
				cur_execute('delete from alias where room=%s and match =%s',(gjid,cmd))
				msg = L('Updated:','%s/%s'%(jid,nick))
			else: msg = L('Added:','%s/%s'%(jid,nick))
			cur_execute('insert into alias values (%s,%s,%s)',(gjid,cmd,cbody))
			msg = '%s %s=%s' % (msg,cmd,cbody)
	if mode in ['del','del_global']:
		gjid = jid if mode == 'del' else '*'
		msg = L('Unable to remove %s','%s/%s'%(jid,nick)) % cmd
		fl = cur_execute_fetchone('select cmd from alias where room=%s and match =%s',(gjid,cmd))
		if fl:
			am,amm = get_level(jid,nick)[0],-1
			tcmd = fl[0].split(' ',1)[0].lower()
			for tmp in comms:
				if tmp[1] == tcmd:
					amm = tmp[0]
					break
			if mode == 'del' and amm > am: msg = L('Not allowed remove alias for: %s','%s/%s'%(jid,nick)) % tcmd
			elif mode == 'del_global' and am != 9: msg = L('Not allowed remove global alias for: %s','%s/%s'%(jid,nick)) % tcmd
			else:
				cur_execute('delete from alias where room=%s and match =%s',(gjid,cmd))
				msg = L('Removed: %s','%s/%s'%(jid,nick)) % cmd
	if mode=='show':
		if cmd == '':
			fl = cur_execute_fetchall('select match ,room from alias where room=%s or room=%s order by match ',(jid,'*'))
			if fl:
				aln = ', '.join([t[0] for t in fl if t[1] != '*'])
				alg = ', '.join([t[0] for t in fl if t[1] == '*'])
				if aln: msg = L('Aliases: %s','%s/%s'%(jid,nick)) % aln
				if alg:
					if aln: msg += '\n%s' % L('Global aliases: %s','%s/%s'%(jid,nick)) % alg
					else: msg = L('Global aliases: %s','%s/%s'%(jid,nick)) % alg
			else: msg = L('Aliases not found!','%s/%s'%(jid,nick))
		else:
			fl = cur_execute_fetchall('select match ,cmd,room from alias where (room=%s or room=%s) and match ilike %s order by match ',(jid,'*','%%%s%%'%cmd))
			if fl:
				aln = '\n'.join(['%s = %s' % (t[0],t[1]) for t in fl if t[2] != '*'])
				alg = '\n'.join(['%s = %s' % (t[0],t[1]) for t in fl if t[2] == '*'])
				if aln: msg = L('Aliases: %s','%s/%s'%(jid,nick)) % '\n%s' % aln
				if alg:
					if aln: msg += '\n%s' % L('Global aliases: %s','%s/%s'%(jid,nick)) % '\n%s' % alg
					else: msg = L('Global aliases: %s','%s/%s'%(jid,nick)) % '\n%s' % alg
			else: msg = L('Aliases not found!','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def un_unix(*val):
	if len(val) == 2: rn = val[1]
	else: rn = ''
	val = val[0]
	tt = list(map(lambda q,a: q-a, time.gmtime(val), time.gmtime(0)))[:6]
	ret = '%02d:%02d:%02d' % tuple(tt[3:6])
	if sum(tt[:3]):
		day_h,day_l = tt[2]//10%10,tt[2] % 10
		if day_h == 1: ret = L('%s days, %s',rn) % (tt[2],ret)
		else:
			if day_l in range(5,10): ret = L('%s days, %s',rn) % (tt[2],ret)
			elif day_l in range(2,5): ret = L('%s Days, %s',rn).lower() % (tt[2],ret)
			elif day_l == 1: ret = L('%s day, %s',rn) % (tt[2],ret)
	if sum(tt[:2]):
		if tt[1] in range(5,13): ret = L('%s months, %s',rn) % (tt[1],ret)
		elif tt[1] in range(2,5): ret = L('%s Months, %s',rn).lower() % (tt[1],ret)
		elif tt[1] == 1: ret = L('%s month, %s',rn) % (tt[1],ret)
	if tt[0]:
		ty = tt[0] % 100
		if ty >= 20: ty = ty % 10
		if ty in [0]+range(5,21): ret = L('%s years, %s',rn) % (tt[0],ret)
		elif ty in range(2,5): ret = L('%s Years, %s',rn).lower() % (tt[0],ret)
		else: ret = L('%s year, %s',rn) % (tt[0],ret)
	return ret

def close_age_null():
	cur_execute("delete from age where jid ilike '<temporary>%'")
	ccu = cur_execute_fetchall('select * from age where status=0 order by room')
	cur_execute('delete from age where status=0')
	for ab in ccu: cur_execute('insert into age values (%s,%s,%s,%s,%s,%s,%s,%s,%s)', (ab[0],ab[1],ab[2],ab[3],ab[4],1,ab[6],ab[7],ab[1].lower()))

def close_age():
	cur_execute('delete from age where jid ilike %s',('<temporary>%',))
	ccu = cur_execute_fetchall('select * from age where status=%s order by room',(0,))
	cur_execute('delete from age where status=%s', (0,))
	tt = int(time.time())
	for ab in ccu: cur_execute('insert into age values (%s,%s,%s,%s,%s,%s,%s,%s,%s)', (ab[0],ab[1],ab[2],tt,ab[4]+(tt-ab[3]),1,ab[6],ab[7],ab[1].lower()))

def sfind(mass,stri):
	for a in mass:
		if stri in a: return a
	return ''

def get_local_prefix(jid):
	lprefix = get_config(getRoom(jid),'prefix')
	if lprefix == None: return prefix
	return lprefix

def get_prefix(lprefix):
	if lprefix != '': return lprefix
	else: return 'absent'

def set_prefix(type, jid, nick, text):
	access_mode = get_level(jid,nick)[0]
	if access_mode >= 7:
		lprefix = get_config(getRoom(jid),'prefix')
		if text.lower() == 'none': lprefix = ''
		elif text.lower() == 'del': lprefix = prefix
		elif text != '': lprefix = text
		if lprefix == None: lprefix = prefix
		put_config(getRoom(jid),'prefix',lprefix)
		prf = L(get_prefix(lprefix),'%s/%s'%(jid,nick))
	else: prf = L(get_prefix(get_local_prefix(jid)),'%s/%s'%(jid,nick))
	send_msg(type, jid, nick, L('Command prefix: %s','%s/%s'%(jid,nick)) % prf)

def uptime(type, jid, nick): send_msg(type, jid, nick, L('Uptime: %s, Last session: %s','%s/%s'%(jid,nick)) % (un_unix(int(time.time()-starttime),'%s/%s'%(jid,nick)), un_unix(int(time.time())-sesstime,'%s/%s'%(jid,nick))))

def show_error(type, jid, nick, text):
	if text.lower() == 'clear': writefile(LOG_FILENAME,'')
	try: cmd = int(text)
	except: cmd = 1
	if os.path.isfile(LOG_FILENAME) and text.lower() != 'clear':
		log = readfile(LOG_FILENAME)
		log = log.split('ERROR:')
		lll = len(log)
		if cmd > lll: cmd = lll
		msg = L('Total Error(s): %s\n','%s/%s'%(jid,nick)) % (lll-1)
		if text != '':
			for aa in range(lll-cmd,lll): msg += log[aa]+'\n'
		else: msg += ' '
		msg = msg[:-2]
	else: msg = L('No Errors','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def get_nick_by_jid(room, jid):
	for tmp in megabase:
		if tmp[0] == room and getRoom(tmp[4]) == jid: return tmp[1]
	return None

def get_jid_by_nick(room, nick):
	for tmp in megabase:
		if tmp[0] == room and tmp[1] == nick: return getRoom(tmp[4])
	return ''

def get_nick_by_jid_res(room, jid):
	for tmp in megabase:
		if tmp[0] == room and tmp[4] == jid: return tmp[1]
	return None

def info_lang(type, jid, nick, text):
	if get_config(getRoom(jid),'set_default_locale') != 'off': msg = L('In current MUC used %s locale for all users.','%s/%s'%(jid,nick)) % get_config(getRoom(jid),'set_default_locale').upper()
	else:
		if not text: text = nick
		if users_locale.__contains__('%s/%s'%(jid,text)):
			cur_lang = users_locale['%s/%s'%(jid,text)]
			if locales.__contains__(cur_lang): msg = L('For %s i\'ll use locale: %s','%s/%s'%(jid,nick)) % (text,cur_lang.upper())
			else: msg = L('For %s detected unknown locale: %s. Used default locale: %s','%s/%s'%(jid,nick)) % (text,cur_lang.upper(),CURRENT_LOCALE.upper())
		else: msg = L('Locale for %s not found! Used default locale: %s','%s/%s'%(jid,nick)) % (text,CURRENT_LOCALE.upper())
	send_msg(type, jid, nick, msg)

def info_whois(type, jid, nick, text):
	if text != '': msg = raw_who(jid,nick,text)
	else: msg = L('What?','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def info_access(type, jid, nick):
	msg = raw_who(jid,nick,nick)
	send_msg(type, jid, nick, msg)

def raw_who(room,nick,text):
	access_mode = get_level(room,text)[0]
	if access_mode == -2: msg = L('Who do you need?','%s/%s'%(room,nick))
	else:
		realjid = get_level(room,text)[1]
		msg = L('Access level: %s','%s/%s'%(room,nick)) % access_mode
		msg += ', ' + [L('Ignored','%s/%s'%(room,nick)),L('Minimal','%s/%s'%(room,nick)),L('Visitor','%s/%s'%(room,nick)),L('Visitor and Member','%s/%s'%(room,nick)),L('Participant','%s/%s'%(room,nick)),L('Member','%s/%s'%(room,nick)), L('Moderator','%s/%s'%(room,nick)),L('Moderator and member','%s/%s'%(room,nick)),L('Admin','%s/%s'%(room,nick)),L('Owner','%s/%s'%(room,nick)),L('Bot\'s owner','%s/%s'%(room,nick))][access_mode+1]
		if realjid != 'None':
			msg = L('%s, jid detected','%s/%s'%(room,nick)) % msg
			if ddos_ignore.__contains__(getRoom(realjid)): msg = '%s, %s' % (msg,L('temporary ignored (%s)','%s/%s'%(room,nick)) % un_unix(ddos_ignore[getRoom(realjid)][2]-time.time(),'%s/%s'%(room,nick)))
	return msg

def info_comm(type, jid, nick):
	access_mode,tmp = get_level(jid,nick)[0],[]
	for i in comms:
		if access_mode >= i[0]: tmp.append((i[0],i[1]))
	tmp.sort()
	msg = ''
	for j in range(0,access_mode+1):
		cm = [t[1] for t in tmp if t[0] == j]
		if cm: msg += u'\n• %s … %s' % (j,', '.join(cm))
	msg = L('Total commands: %s | Prefix: %s | Your access level: %s | Available commands: %s%s','%s/%s'%(jid,nick)) % (len(comms), L(get_prefix(get_local_prefix(jid)),'%s/%s'%(jid,nick)), access_mode, len(tmp), msg)
	send_msg(type, jid, nick, msg)

def helpme(type, jid, nick, text):
	text = text.strip().lower()
	if text == 'about': msg = u'iSida Jabber Bot | © 2oo9-%s Disabler Production Lab. | http://isida.dsy.name' % str(time.localtime()[0]).replace('0','o')
	elif text in ['donation','donations']: msg = L('Send donation to: %sBest regards, %s','%s/%s'%(jid,nick)) % ('\nYandexMoney: 41001384336826\nWMZ: Z392970180590\nWMR: R378494692310\nWME: E164241657651\n','Disabler')
	elif text in [L('access','%s/%s'%(jid,nick)),'access']: msg = L('Bot has next access levels:\n-1 - ignored\n0 - minimal access\n1 - at least visitor and none\n2 - at least visitor and member\n3 - at least participant and none\n4 - at least participant and member\n5 - at least moderator and none\n6 - at least moderator and member\n7 - at least moderator and admin\n8 - at least moderator and owner\n9 - bot owner','%s/%s'%(jid,nick))
	elif len(text) > 1:
		tm,cm = [],[]
		for tmp in comms:
			if '\r' in tmp[4]: help_descr = L('Plugin %s. %s','%s/%s'%(jid,nick)) % (tmp[4].split('\r')[0],L(tmp[4].split('\r',1)[1],'%s/%s'%(jid,nick)))
			else: help_descr = L(tmp[4],'%s/%s'%(jid,nick))
			if tmp[1] == text:
				cm = (tmp[1],tmp[0],help_descr)
				break
			elif text in tmp[1].lower() or text in help_descr.lower(): tm.append((tmp[0], tmp[1], help_descr))
		if cm: msg = '%s. ' % cm[0].capitalize() + L('Access level: %s. %s','%s/%s'%(jid,nick)) % ('%s [%s]' % (cm[1],L(unlevl[int(cm[1])],'%s/%s'%(jid,nick))),cm[2])
		elif len(tm) == 1: msg = '%s. ' % tm[0][1].capitalize() + L('Access level: %s. %s','%s/%s'%(jid,nick)) % (tm[0][0],tm[0][2])
		elif not len(tm+cm): msg = L('"%s" not found','%s/%s'%(jid,nick)) % text
		else:
			tm.sort()
			msg = L('Prefix: %s, Available help for commands:\n','%s/%s'%(jid,nick)) % L(get_prefix(get_local_prefix(jid)),'%s/%s'%(jid,nick))
			for i in range(0,10):
				tmsg = []
				for tmp in tm:
					if tmp[0] == i and tmp[2] != '': tmsg.append(str(tmp[1]))
				if len(tmsg): msg += u'[%s]…%s\n' % (i,', '.join(tmsg))
	else: msg = L('%s Help for command: help command | Commands list: commands','%s/%s'%(jid,nick)) % (u'iSida Jabber Bot | http://isida.dsy.name | © 2oo9-'+str(time.localtime()[0]).replace('0','o')+' Disabler Production Lab. |')
	send_msg(type, jid, nick, msg)

def bot_rejoin(type, jid, nick, text):
	global lastserver, lastnick
	text=str(text)
	if not text: text = jid
	if '\n' in text: text, passwd = text.split('\n', 1)
	else: passwd = ''
	if '@' not in text: text = '%s@%s' % (text,lastserver)
	if '/' not in text: text = '%s/%s' % (text,lastnick)
	lastserver = getServer(text.lower())
	lastnick = getResourse(text)
	if cur_execute_fetchall('select * from conference where room ilike %s;', ('%s/%%'%getRoom(text),)):
		sm = L('Rejoin by %s','%s/%s'%(jid,nick)) % nick
		leave(text, sm)
		time.sleep(1)
		zz = join(text, passwd)
		while str(zz)[:3] == '409':
			time.sleep(1)
			text += '_'
			zz = join(text, passwd)
		time.sleep(1)
		if zz != None:
			try:
				send_msg(type, jid, nick, zz['CAPTCHA'])
				answered, Error = None, None
				while not answered 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
					time.sleep(1)
					for tmp in pres_answer:
						if tmp[0]==zz['ID']:
							Error = tmp[1]
							pres_answer.remove(tmp)
							answered = True
							break
				if Error: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % Error)
				else:
					cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
					cur_execute('insert into conference values (%s,%s)',(text,passwd))
			except: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % zz)
		else:
			cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
			cur_execute('insert into conference values (%s,%s)',(text,passwd))
	else: send_msg(type, jid, nick, L('I have never been in %s','%s/%s'%(jid,nick)) % getRoom(text))

def bot_join(type, jid, nick, text):
	global lastserver, lastnick, pres_answer
	text = str(text)
	if not text or ' ' in getRoom(text): send_msg(type, jid, nick, L('Wrong arguments!','%s/%s'%(jid,nick)))
	else:
		if '\n' in text: text, passwd = text.split('\n', 1)
		else: passwd = ''
		if '@' not in text: text = '%s@%s' % (text,lastserver)
		if '/' not in text: text = '%s/%s' % (text,lastnick)
		old_text = '%s\n%s' % (text, passwd) if passwd else text
		if cur_execute_fetchone('select * from blacklist where room=%s', (getRoom(text),)): send_msg(type, jid, nick, L('Denied!','%s/%s'%(jid,nick)))
		else:
			lastserver = getServer(text.lower())
			lastnick = getResourse(text)
			lroom = text.lower().split('/')[0]
			cnf = cur_execute_fetchall('select * from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
			if not cnf:
				zz = join(text, passwd)
				while str(zz)[:3] == '409':
					time.sleep(1)
					text += '_'
					zz = join(text, passwd)
				if zz != None:
					try:
						send_msg(type, jid, nick, zz['CAPTCHA'])
						answered, Error = None, None
						while not answered 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
							time.sleep(1)
							for tmp in pres_answer:
								if tmp[0]==zz['ID']:
									Error = tmp[1]
									pres_answer.remove(tmp)
									answered = True
									break
						if Error: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % Error)
						else:
							cur_execute('insert into conference values (%s,%s)',(text,passwd))
							send_msg(type, jid, nick, L('Joined to %s','%s/%s'%(jid,nick)) % text)
					except: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % zz)
				else:
					cur_execute('insert into conference values (%s,%s)',(text,passwd))
					send_msg(type, jid, nick, L('Joined to %s','%s/%s'%(jid,nick)) % text)
			elif cur_execute_fetchone('select * from conference where room=%s;', (text,)): send_msg(type, jid, nick, L('I\'m already in %s with nick %s','%s/%s'%(jid,nick)) % (lroom, lastnick))
			else:
				zz = join(text, passwd)
				while str(zz)[:3] == '409':
					time.sleep(0.1)
					text += '_'
					zz = join(text, passwd)
				if zz != None:
					try:
						send_msg(type, jid, nick, zz['CAPTCHA'])
						answered, Error = None, None
						while not answered 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
							time.sleep(1)
							for tmp in pres_answer:
								if tmp[0]==zz['ID']:
									Error = tmp[1]
									pres_answer.remove(tmp)
									answered = True
									break
						if Error: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % Error)
						else:
							cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
							cur_execute('insert into conference values (%s,%s)',(text,passwd))
							send_msg(type, jid, nick, L('Joined to %s','%s/%s'%(jid,nick)) % text)
					except: send_msg(type, jid, nick, L('Error! %s','%s/%s'%(jid,nick)) % zz)
				else:
					cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
					cur_execute('insert into conference values (%s,%s)',(text,passwd))
					#time.sleep(1)
					#send_msg(type, jid, nick, L('Changed nick in %s to %s','%s/%s'%(jid,nick)) % (lroom,getResourse(text)))

def bot_leave(type, jid, nick, text):
	global lastserver
	domain = getServer(Settings['jid'])
	cnf = cur_execute_fetchall('select * from conference;')
	if len(cnf) == 1: send_msg(type, jid, nick, L('I can\'t leave last room!','%s/%s'%(jid,nick)))
	else:
		if text == '': text = jid
		if '@' not in text: text = '%s@%s' % (text,lastserver)
		if '\n' in text: text, _ = text.split('\n', 1)
		lastserver = getServer(text)
		text=str(text)
		lroom = text
		if is_owner(jid): nick = getName(jid)
		cnf = cur_execute_fetchall('select * from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
		if cnf:
			cur_execute('delete from conference where room ilike %s;', ('%s/%%'%getRoom(text),))
			send_msg(type, jid, nick, L('Leave room %s','%s/%s'%(jid,nick)) % text)
			sm = L('Leave room by %s','%s/%s'%(jid,nick)) % nick
			leave(getRoom(text), sm)
			cur_execute('delete from hiden_rooms where room=%s',(getRoom(text),))
		else: send_msg(type, jid, nick, L('I have never been in %s','%s/%s'%(jid,nick)) % lroom)

def conf_limit(type, jid, nick, text):
	global msg_limit
	if text!='':
		try: msg_limit = int(text)
		except: msg_limit = default_msg_limit
	send_msg(type, jid, nick, L('Temporary message size limit %s','%s/%s'%(jid,nick)) % str(msg_limit))

def bot_plugin(type, jid, nick, text):
	global plname, plugins, execute, gtimer, gpresence, gmassage, giq_hook
	text = text.split()
	opt = text[0] if text else ''
	try: name = '%s.py' % text[1]
	except: name = ''
	msg = L('Wrong arguments!','%s/%s'%(jid,nick))
	pl_ignore = getFile(pliname,[])

	if opt == 'add' and os.path.isfile(pl_folder % name):
		if name in pl_ignore:
			pl_ignore.remove(name)
			writefile(pliname,str(pl_ignore))
		if name not in plugins: plugins.append(name)
		presence_control,message_control,message_act_control,iq_control,timer,execute,iq_hook = [],[],[],[],[],[],[]
		exec(open(pl_folder % name).read())
		tmsg = ''
		for cm in execute:
			tmsg += '%s[%s], ' % (cm[1],cm[0])
			comms.append((cm[0],cm[1],cm[2],cm[3],L('Plugin %s. %s','%s/%s'%(jid,nick)) % (name[:-3],cm[4])))
		msg = L('Loaded plugin: %s','%s/%s'%(jid,nick)) % name[:-3]
		if tmsg: msg += L('\nAdd commands: %s','%s/%s'%(jid,nick)) % tmsg[:-2]
		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()

	elif opt == 'del' and name in plugins:
		if name not in pl_ignore:
			pl_ignore.append(name)
			writefile(pliname,str(pl_ignore))
		plugins.remove(name)
		presence_control,message_control,message_act_control,iq_control,timer,execute,iq_hook = [],[],[],[],[],[],[]
		exec(open(pl_folder % name).read())
		tmsg = ''
		for cm in execute:
			tmsg += '%s[%s], ' % (cm[1],cm[0])
			for i in comms:
				if i[1] == cm[1]: comms.remove(i)
		msg = L('Unloaded plugin: %s','%s/%s'%(jid,nick)) % name[:-3]
		if tmsg: msg += L('\nDel commands: %s','%s/%s'%(jid,nick)) % tmsg[:-2]
		for tmr in timer: gtimer.remove(tmr)
		for tmp in presence_control: gpresence.remove(tmp)
		for tmp in message_control: gmessage.remove(tmp)
		for tmp in message_act_control: gactmessage.remove(tmp)
		for tmp in iq_hook: giq_hook.remove(tmp)
		giq_hook.sort()

	elif opt == 'local':
		a = os.listdir(pl_folder % '')
		b = []
		for c in a:
			if c[-3:] == '.py' and c[0] != '.' and c != 'main.py': b.append(c[:-3])
		b.sort()
		msg = L('Available plugins: %s','%s/%s'%(jid,nick)) % ', '.join(b)
		if len(pl_ignore):
			b = []
			for tmp in pl_ignore: b.append(tmp[:-3])
			msg += L('\nIgnored plugins: %s','%s/%s'%(jid,nick)) % ', '.join(b)

	elif opt == 'show':

		msg = L('Active plugins: %s','%s/%s'%(jid,nick)) % ', '.join([t[:-3] for t in plugins])
		msg[:-2]
		if len(pl_ignore):
			b = []
			for tmp in pl_ignore: b.append(tmp[:-3])
			msg += L('\nIgnored plugins: %s','%s/%s'%(jid,nick)) % ', '.join(b)

	plugins.sort()
	send_msg(type, jid, nick, msg)

def owner(type, jid, nick, text):
	global god
	text = text.lower().strip()
	do = text.split(' ',1)[0]
	try: nnick = text.split(' ',1)[1].lower()
	except:
		if do != 'show':
			send_msg(type, jid, nick, L('Wrong arguments!','%s/%s'%(jid,nick)))
			return
	if do == 'add':
		own = cur_execute_fetchone('select * from bot_owner where jid=%s',(nnick,))
		if not own:
			if '@' in nnick:
				j = xmpp.Presence(nnick, 'subscribed')
				j.setTag('c', namespace=xmpp.NS_CAPS, attrs={'node':capsNode,'ver':capsHash,'hash':'sha-1'})
				sender(j)
				j = xmpp.Presence(nnick, 'subscribe')
				j.setTag('c', namespace=xmpp.NS_CAPS, attrs={'node':capsNode,'ver':capsHash,'hash':'sha-1'})
				sender(j)
				msg = L('Append: %s','%s/%s'%(jid,nick)) % nnick
				cur_execute('insert into bot_owner values (%s)',(nnick,))
			else: msg = L('Wrong jid!','%s/%s'%(jid,nick))
		else: msg = L('%s is alredy in list!','%s/%s'%(jid,nick)) % nnick
	elif do == 'del':
		own = cur_execute_fetchone('select * from bot_owner where jid=%s',(nnick,))
		if own and nnick != god:
			cur_execute('delete from bot_owner where jid=%s',(nnick,))
			j = xmpp.Presence(nnick, 'unsubscribe')
			j.setTag('c', namespace=xmpp.NS_CAPS, attrs={'node':capsNode,'ver':capsHash,'hash':'sha-1'})
			sender(j)
			j = xmpp.Presence(nnick, 'unsubscribed')
			j.setTag('c', namespace=xmpp.NS_CAPS, attrs={'node':capsNode,'ver':capsHash,'hash':'sha-1'})
			sender(j)
			msg = L('Removed: %s','%s/%s'%(jid,nick)) % nnick
		else: msg = L('Not found!','%s/%s'%(jid,nick))
	elif do == 'show':
		own = cur_execute_fetchall('select * from bot_owner order by jid')
		msg = L('Bot owner(s): %s','%s/%s'%(jid,nick)) % ', '.join([t[0] for t in own])
	else: msg = L('Wrong arguments!','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def ignore(type, jid, nick, text):
	global god
	text = text.lower().strip()
	do = text.split(' ',1)[0]
	try: nnick = text.split(' ',1)[1].lower()
	except:
		if do != 'show':
			send_msg(type, jid, nick, L('Wrong arguments!','%s/%s'%(jid,nick)))
			return
	if do == 'add':
		ign = cur_execute_fetchone('select * from bot_ignore where pattern=%s;',(nnick,))
		if not ign:
			cur_execute('insert into bot_ignore values (%s)',(nnick,))
			msg = L('Append: %s','%s/%s'%(jid,nick)) % nnick
		else: msg = L('%s alredy in list!','%s/%s'%(jid,nick)) % nnick
	elif do == 'del':
		ign = cur_execute_fetchone('select * from bot_ignore where pattern=%s and pattern!=%s;',(nnick,god))
		if ign:
			cur_execute('delete from bot_ignore where pattern=%s',(nnick,))
			msg = L('Removed: %s','%s/%s'%(jid,nick)) % nnick
		else: msg = L('Not found!','%s/%s'%(jid,nick))
	elif do == 'show':
		ign = cur_execute_fetchall('select * from bot_ignore order by pattern;')
		if ign: msg = ', '.join([t[0] for t in ign])
		else: msg = L('Empty!','%s/%s'%(jid,nick))
		msg = L('Ignore list: %s','%s/%s'%(jid,nick)) % msg
	else: msg = L('Wrong arguments!','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def info_where(type, jid, nick):
	cnf = cur_execute_fetchall("select room from conference where split_part(room,'/',1) not in (select room from hiden_rooms as hrr);")
	len_cnf = cur_execute_fetchone('select count(*) from conference;')[0]
	hr_count = cur_execute_fetchone('select count(*) from hiden_rooms;')[0]
	msg = L('Active conference(s): %s','%s/%s'%(jid,nick)) % len_cnf
	wbase = []
	for jjid in cnf:
		cnt,rjid = 0,getRoom(jjid[0])
		for mega in megabase:
			if mega[0] == rjid: cnt += 1
		wbase.append((cnt, jjid[0]))
	wbase.sort(reverse=True)
	msg = '%s\n%s' % (msg,'\n'.join(['%s. %s [%s]' % (i[0]+1,i[1][1].split('\n')[0],i[1][0]) for i in enumerate(wbase)]))
	if hr_count: msg += L('\nHidden conference(s): %s','%s/%s'%(jid,nick)) % hr_count
	send_msg(type, jid, nick, msg)

def info_where_plus(type, jid, nick):
	cnf = cur_execute_fetchall("select room from conference where split_part(room,'/',1) not in (select room from hiden_rooms as hrr);")
	len_cnf = cur_execute_fetchone('select count(*) from conference;')[0]
	hr_count = cur_execute_fetchone('select count(*) from hiden_rooms;')[0]
	msg = L('Active conference(s): %s','%s/%s'%(jid,nick)) % len_cnf
	wbase = []
	for jjid in cnf:
		cnt,rjid,ra = 0,getRoom(jjid[0]),L('unknown','%s/%s'%(jid,nick))
		for mega in megabase:
			if mega[0] == rjid:
				cnt += 1
				if '%s/%s' % tuple(mega[0:2]) == jjid[0]: ra = L("%s/%s" % tuple(mega[2:4]))
		wbase.append((cnt, jjid[0], ra))
	wbase.sort(reverse=True)
	msg = '%s\n%s' % (msg,'\n'.join(['%s. %s (%s) [%s]' % (i[0]+1,i[1][1].split('\n')[0],i[1][2],i[1][0]) for i in enumerate(wbase)]))
	if hr_count: msg += L('\nHidden conference(s): %s','%s/%s'%(jid,nick)) % hr_count
	send_msg(type, jid, nick, msg)

def info(type, jid, nick):
	msg = L('Conference(s): %s (for more info use \'where\' command)\n','%s/%s'%(jid,nick)) % cur_execute_fetchone('select count(*) from conference;')[0]
	msg += L('Server: %s | Nick: %s\n','%s/%s'%(jid,nick)) % (lastserver,lastnick)
	msg += L('Message size limit: %s\n','%s/%s'%(jid,nick)) % msg_limit
	msg += L('Local time: %s\n','%s/%s'%(jid,nick)) % timeadd(tuple(time.localtime()))
	msg += L('Uptime: %s, Last session: %s','%s/%s'%(jid,nick)) % (un_unix(int(time.time()-starttime),'%s/%s'%(jid,nick)), un_unix(int(time.time())-sesstime,'%s/%s'%(jid,nick)))
	floods = get_config(getRoom(jid),'flood')
	censors = get_config(getRoom(jid),'censor')
	msg += L('\nFlood: %s | Censor: %s | Prefix: %s','%s/%s'%(jid,nick)) % (onoff(floods),onoff(censors),L(get_prefix(get_local_prefix(jid)),'%s/%s'%(jid,nick)))
	msg += L('\nExecuted threads: %s | Error(s): %s','%s/%s'%(jid,nick)) % (th_cnt,thread_error_count)
	msg += L('\nMessage in: %s | out: %s','%s/%s'%(jid,nick)) % (message_in,message_out)
	msg += L('\nPresence in: %s | out: %s','%s/%s'%(jid,nick)) % (presence_in,presence_out)
	msg += L('\nIq in: %s | out: %s','%s/%s'%(jid,nick)) % (iq_in,iq_out)
	msg += L('\nUnknown out: %s','%s/%s'%(jid,nick)) % unknown_out
	msg += L('\nCycles used: %s | unused: %s','%s/%s'%(jid,nick)) % (cycles_used,cycles_unused)
	if not GT('paranoia_mode'):
		try:
			memstat = tuple([get_size_human(int(t)*1024.0) for t in shell_execute('ps -o vsz,rss -p %s' % os.getpid(),'%s/%s'%(jid,nick)).split()[2:]])
			if not memstat or len(memstat) != 2: raise
		except: memstat = (L('Unknown','%s/%s'%(jid,nick)),L('Unknown','%s/%s'%(jid,nick)))
		msg += L('\nRAM for bot: %s (virtual), %s (real)','%s/%s'%(jid,nick)) % memstat
		if base_type == 'pgsql':
			try:
				memstat = tuple([get_size_human(int(t)*1024.0) for t in shell_execute('ps u -U postgres | grep "%s %s %s"' % (base_name,base_user,base_host)).split()[4:6]])
				if not memstat or len(memstat) != 2: raise
			except: memstat = (L('Unknown','%s/%s'%(jid,nick)),L('Unknown','%s/%s'%(jid,nick)))
			msg += L('\nRAM for database: %s (virtual), %s (real)','%s/%s'%(jid,nick)) % memstat
		elif base_type == 'mysql':
			# TODO: add detect ram usage for mysql base!
			memstat = (L('Unknown','%s/%s'%(jid,nick)),L('Unknown','%s/%s'%(jid,nick)))
			msg += L('\nRAM for database: %s (virtual), %s (real)','%s/%s'%(jid,nick)) % memstat
		elif base_type == 'sqlite3': msg += L('\nDatabase size: %s','%s/%s'%(jid,nick)) % get_size_human(os.path.getsize(sqlite_base))
	send_msg(type, jid, nick, msg)

def info_base(type, jid, nick):
	msg = L('What need find?','%s/%s'%(jid,nick))
	if nick != '':
		msg = ''
		fl = 1
		for base in megabase:
			if base[1] == (nick) and base[0].lower() == jid:
				msg = L('I see you as %s/%s','%s/%s'%(jid,nick)) % (base[2],base[3])
				break
	send_msg(type, jid, nick, msg)

def real_search_owner(type, jid, nick, text):
	if text:
		msg = L('Found:','%s/%s'%(jid,nick))
		fl = 1
		for mega1 in megabase:
			if mega1[2] != 'None' and mega1[3] != 'None':
				for mega2 in mega1:
					if text.lower() in mega2.lower():
						msg += '\n%s - %s/%s' % (mega1[1],mega1[2],mega1[3])
						if mega1[4] != 'None': msg += ' (%s)' % mega1[4]
						msg += ' %s' % mega1[0]
						fl = 0
						break
		if fl: msg = L('\'%s\' not found!','%s/%s'%(jid,nick)) % text
	else: msg = L('What need find?','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def real_search(type, jid, nick, text):
	if text:
		msg = L('Found:','%s/%s'%(jid,nick))
		fl = 1
		for mega1 in megabase:
			if mega1[2] != 'None' and mega1[3] != 'None':
				for mega2 in mega1:
					if text.lower() in mega2.lower():
						msg += u'\n%s - %s/%s %s' % (mega1[1],mega1[2],mega1[3],mega1[0])
						fl = 0
						break
		if fl: msg = L('\'%s\' not found!','%s/%s'%(jid,nick)) % text
	else: msg = L('What do you need to find?','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def unescape(text):
	def fixup(m):
		text = m.group(0)
		if text[:2] == '&#':
			try:
				if text[:3] == '&#x': return chr(int(text[3:-1], 16))
				else: return chr(int(text[2:-1]))
			except ValueError: pass
		else:
			try: text = chr(html.entities.html5[text[1:-1]])
			except KeyError: pass
		return text
	return re.sub('&#?\w+;', fixup, text)

def html_escape(text):
	def link(text): return '<a href="%s">%s</a>' % (text.group(0),text.group(0))
	#def email(text): return '<a href="mailto:%s">%s</a>' % (text.group(0),text.group(0))
	def brnbsp(text): return '<br/>' + '&nbsp;' * len(text.group(0))
	def nbsp(text): return '&nbsp;' * len(text.group(0))
	for tmp in (('&','&amp;'),('<','&lt;'),('>','&gt;'),('~','&tilde;'),('\t','&nbsp;'*8)): text = text.replace(tmp[0],tmp[1])
	text = re.sub(u'^(\ +)',nbsp,text)
	text = re.sub(u'http[s]?://[-a-zA-Z0-9а-яА-Я._/?&#=;@%:()+]+',link,text)
	#text = re.sub(u'[-a-zA-Z._0-9?:а-яА-Я]+@[-a-zA-Z._0-9а-яА-Я/?:]+',email,text)
	text = text.replace('\n','<br/>')
	text = re.sub('<br/>\ +',brnbsp,text)
	#for tmp in (('\"','&quot;'),('\'','&apos;')): text = text.replace(tmp[0],tmp[1])
	return text

def esc_max2(ms):
	for tmp in rlmas_min: ms = ms.replace(tmp[0],tmp[1])
	return ms

def esc_min2(ms):
	for tmp in rlmas_min: ms = ms.replace(tmp[1],tmp[0])
	return ms

def esc_min(ms):
	for tmp in rmass: ms = ms.replace(tmp[1],tmp[0])
	return ms

def rss_replace(ms):
	for tmp in lmass: ms = ms.replace(tmp[1],tmp[0])
	return unescape(esc_min(ms))

def rss_repl_del_html(ms,item):
	DS,SP,T = '<%s>','/%s',re.findall('<(.*?)>', ms, re.S)
	if len(T):
		for tmp in T:
			if (tmp[:3] == '!--' and tmp[-2:] == '--') or tmp[-1:] == '/':
				pattern = DS % tmp
				pos = ms.find(pattern)
				ms = ms[:pos] + item + ms[pos+len(pattern):]
	T = re.findall('<(.*?)>', ms, re.S)
	if len(T):
		for tmp in range(0,len(T)-1):
			pos = None
			TT = T[tmp].split(' ')[0]
			if TT and TT[0] != '/':
				try: pos = T.index(SP % TT,tmp)
				except: pass
				if pos:
					pat1,pat2 = DS % T[tmp],DS % T[pos]
					pos1 = ms.find(pat1)
					pos2 = ms.find(pat2,pos1)
					ms = ms[:pos1] + item + ms[pos1+len(pat1):pos2] + item + ms[pos2+len(pat2):]
	for tmp in ('hr','br','li','ul','img','dt','dd','p'):
		T = re.findall('<%s.*?>' % tmp, ms, re.S)
		for tmp1 in T: ms = ms.replace(tmp1,item,1)
	return ms

def rss_repl_html(ms): return rss_repl_del_html(ms,' ')

def rss_del_html(ms): return rss_repl_del_html(ms,'')

def remove_replace_ltgt(text,item):
	T = re.findall('<.*?>', text, re.S)
	for tmp in T: text = text.replace(tmp,item,1)
	return text

def replace_ltgt(text): return remove_replace_ltgt(text,' ')

def rss_del_nn(ms):
	ms = ms.replace('\r',' ').replace('\t',' ')
	while '\n ' in ms: ms = ms.replace('\n ','\n')
	while len(ms) and (ms[0] == '\n' or ms[0] == ' '): ms = ms[1:]
	while '\n\n' in ms: ms = ms.replace('\n\n','\n')
	while '  ' in ms: ms = ms.replace('  ',' ')
	while u'\n\n•' in ms: ms = ms.replace(u'\n\n•',u'\n•')
	while u'• \n' in ms: ms = ms.replace(u'• \n',u'• ')
	return ms.strip()

def html_encode(body):
	encidx = re.findall('encoding=["\'&]*(.*?)["\'& ]{1}',body[:1024])
	if encidx: enc = encidx[0]
	else:
		encidx = re.findall('charset=["\'&]*(.*?)["\'& ]{1}',body[:1024])
		if encidx: enc = encidx[0]
		else: enc = chardet.detect(body)['encoding']
	if body == None: body = ''
	if enc == None or enc == '' or enc.lower() == 'unicode': enc = 'utf-8'
	if enc == 'ISO-8859-2':
		tx,splitter = '','|'
		while splitter in body: splitter += '|'
		tbody = body.replace('</','<'+splitter+'/').split(splitter)
		cntr = 0
		for tmp in tbody:
			try:
				enc = chardet.detect(tmp)['encoding']
				if enc == None or enc == '' or enc.lower() == 'unicode': enc = 'utf-8'
				tx += str(tmp,enc)
			except:
				ttext = ''
				for tmp2 in tmp:
					if (tmp2<='~'): ttext+=tmp2
					else: ttext+='?'
				tx += ttext
			cntr += 1
		return tx
	else:
		try: return smart_encode(body,enc)
		except: return L('Encoding error!')

def rss_flush(jid,link,break_point):
	tstop = cur_execute_fetchone('select hash from feed where room=%s and url=%s',(jid,link))
	if tstop: tstop = tstop[0] if base_type == 'pgsql' else eval(tstop[0])
	else: tstop = []
	if not break_point: break_point = tstop
	cur_execute('update feed set time=%s, hash=%s where room=%s and url=%s',(int(time.time()),break_point if base_type == 'pgsql' else str(break_point),jid,link))
	return tstop

def smart_concat(text):
	#while ' \n' in text: text = text.replace(' \n','\n')
	#while '\n ' in text: text = text.replace('\n ','\n')
	text = [' ']+text.split('\n')
	tmp = 1
	while tmp < len(text):
		if not (' ' in text[tmp] or '/' in text[tmp] or '.' in text[tmp] or '\\' in text[tmp]): text = text[:tmp-1]+[text[tmp-1]+' '+text[tmp]]+text[tmp+1:]
		else: tmp += 1
	return '\n'.join(text)

def rss(type, jid, nick, text):
	msg = 'rss show|add|del|clear|new|get'
	nosend = None
	text = text.split(' ')
	tl = len(text)
	if tl < 5: text.append('!')
	mode = text[0].lower() # show | add | del | clear | new | get
	if mode == 'add' and tl < 4: msg,mode = 'rss add [http://]url timeH|M [full|body|head][-url]',''
	elif mode == 'del' and tl < 2: msg,mode = 'rss del [http://]url',''
	elif mode == 'new' and tl < 4: msg,mode = 'rss new [http://]url max_feed_humber [full|body|head][-url]',''
	elif mode == 'get' and tl < 4: msg,mode = 'rss get [http://]url max_feed_humber [full|body|head][-url]',''
	if mode == 'clear':
		if get_level(jid,nick)[0] == 9 and tl > 1: tjid = text[1]
		else: tjid = jid
		msg = L('All RSS was cleared!','%s/%s'%(jid,nick))
		cur_execute('delete from feed where room=%s',(tjid,))
	elif mode == 'all':
		feedbase = cur_execute_fetchall('select * from feed;')
		msg = L('No RSS found!','%s/%s'%(jid,nick))
		if feedbase:
			msg = L('All schedule feeds:','%s/%s'%(jid,nick))
			for rs in feedbase:
				msg += '\n%s\t%s (%s) %s' % (getName(rs[4]),rs[0],rs[1],rs[2])
				try: msg += ' - %s' % disp_time(rs[3],'%s/%s'%(jid,nick))
				except: msg += ' - Unknown'
	elif mode == 'show':
		feedbase = cur_execute_fetchall('select * from feed where room=%s;',(jid,))
		msg = L('No RSS found!','%s/%s'%(jid,nick))
		if feedbase:
			msg = ''
			for rs in feedbase:
				msg += '\n%s (%s) %s' % tuple(rs[0:3])
				try: msg += ' - %s' % disp_time(rs[3],'%s/%s'%(jid,nick))
				except: msg += ' - Unknown'
			if len(msg): msg = L('Schedule feeds for %s:%s','%s/%s'%(jid,nick)) % (jid,msg)
			else: msg = L('Schedule feeds for %s not found!','%s/%s'%(jid,nick)) % jid
	elif mode == 'add':
		mdd = ['full','body','head']
		if text[3].split('-')[0] not in mdd:
			send_msg(type, jid, nick, L('Mode %s not detected!','%s/%s'%(jid,nick)) % text[3])
			return
		link = text[1]
		if not re.findall('^http(s?)://',link[:10]): link = 'http://%s' % link
		cur_execute('delete from feed where room=%s and url=%s;',(jid,link))
		timetype = text[2][-1:].lower()
		if not timetype in ('h','m'): timetype = 'h'
		try: ofset = int(text[2][:-1])
		except: ofset = 4
		if timetype == 'm' and ofset < GT('rss_min_time_limit'): timetype = '%sm' % GT('rss_min_time_limit')
		else: timetype = str(ofset)+timetype
		cur_execute('insert into feed values (%s,%s,%s,%s,%s,%s,%s);',(link, timetype, text[3], int(time.time()), getRoom(jid),[] if base_type == 'pgsql' else '[]',''))
		msg = L('Add feed to schedule: %s (%s) %s','%s/%s'%(jid,nick)) % (link,timetype,text[3])
		rss(type, jid, nick, 'get %s 1 %s' % (link,text[3]))
	elif mode == 'del':
		link = text[1]
		if not re.findall('^http(s?)://',link[:10]): link = 'http://%s' % link
		msg = L('Can\'t find in schedule: %s','%s/%s'%(jid,nick)) % link
		fdb = cur_execute_fetchall('select * from feed where room=%s and url=%s;',(jid,link))
		if fdb:
			cur_execute('delete from feed where room=%s and url=%s;',(jid,link))
			msg = L('Delete feed from schedule: %s','%s/%s'%(jid,nick)) % link
	elif mode in ['new','get']:
		link = text[1]
		if not re.findall('^http(s?)://',link[:10]): link = 'http://%s' % link
		if cur_execute_fetchone('select * from feed where room=%s and url=%s;',(jid,link)):			
			body, result = get_opener(enidna(link))
			modified,need_update_feed = '',True
			if result:
				modified = body.headers.get('last-modified',None)
				if not modified: modified = get_tag(load_page_size(link, 1024),'updated')
			if modified:
				changed = cur_execute_fetchone('select changed from feed where room=%s and url=%s;',(jid,link))[0]
				if modified == changed: need_update_feed = False
				else: cur_execute('update feed set changed=%s where room=%s and url=%s',(modified,jid,link))
			is_rss_aton = 0
			if need_update_feed:
				try:
					req = urllib2.Request(link.encode('utf-8'))
					req.add_header('User-Agent',GT('user_agent'))
					feed = urllib2.urlopen(url=req,timeout=GT('rss_get_timeout')).read(GT('size_overflow'))
				except: feed = L('Unable to access server!','%s/%s'%(jid,nick))
				fc = feed[:256]
				if '<?xml version=' in fc:
					if '<feed' in fc:
						is_rss_aton = 2
						t_feed = feed.split('<title>')
						feed = t_feed[0]
						for tmp in t_feed[1:]:
							tm = tmp.split('</title>',1)
							if ord(tm[0][-1]) == 208: tm[0] = tm[0][:-1] + '...'
							feed += '<title>%s</title>%s' % tuple(tm)
					elif '<rss' in fc or '<rdf' in fc: is_rss_aton = 1
					feed = html_encode(feed)
					feed = re.sub('(<span.*?>.*?</span>)','',feed)
					feed = re.sub('(<div.*?>)','',feed)
					feed = re.sub('(</div>)','',feed)
			else: feed = L('New feeds not found!','%s/%s'%(jid,nick))
			if is_rss_aton and feed != L('Encoding error!','%s/%s'%(jid,nick)) and feed != L('Unable to access server!','%s/%s'%(jid,nick)):
				if is_rss_aton == 1:
					if '<item>' in feed: fd = feed.split('<item>')
					else: fd = feed.split('<item ')
					feed = [fd[0]]
					for tmp in fd[1:]: feed.append(tmp.split('</item>')[0])
				else:
					if '<entry>' in feed: fd = feed.split('<entry>')
					else: fd = feed.split('<entry ')
					feed = [fd[0]]
					for tmp in fd[1:]: feed.append(tmp.split('</entry>')[0])
				if len(text) > 2 and text[2].isdigit(): lng = int(text[2])
				else: lng = len(feed)-1
				if len(feed)-1 <= lng: lng = len(feed)-1
				if lng > GT('rss_max_feed_limit'): lng = GT('rss_max_feed_limit')
				elif len < 1: lng = 1
				if len(text) > 3: submode = text[3]
				else: submode = 'full'
				msg = L('Feeds for','%s/%s'%(jid,nick))+' '
				if 'url' in submode.split('-'): submode,urlmode = submode.split('-')[0],True
				else:
					urlmode = None
					msg += link+' '
				msg += get_tag(feed[0],'title')
				try:
					break_point = []
					for tmp in feed[1:GT('rss_max_feed_limit')+1]:
						ttitle = get_tag(tmp,'title').replace('&lt;br&gt;','\n')
						break_point.append(hashlib.md5(ttitle.encode('utf-8')).hexdigest())
					tstop = rss_flush(jid,link,break_point)
					t_msg, new_count = [], 0
					for mmsg in feed[1:GT('rss_max_feed_limit')+1]:
						ttitle = get_tag(mmsg,'title').replace('&lt;br&gt;','\n')
						if mode == 'get' or not (hashlib.md5(ttitle.encode('utf-8')).hexdigest() in tstop):
							if is_rss_aton == 1: tbody,turl = get_tag(mmsg,'description').replace('&lt;br&gt;','\n'),get_tag(mmsg,'link')
							else:
								tbody = get_tag(mmsg,'content').replace('&lt;br&gt;','\n')
								try:
									tu1 = mmsg.find('href=\"',mmsg.index('<link'))+6
									tu2 = mmsg.find('\"',tu1)
									turl = mmsg[tu1:tu2].replace('&lt;br&gt;','\n')
								except: turl = 'URL %s' % L('Not found!','%s/%s'%(jid,nick))
							tsubj,tmsg,tlink = '','',''
							if submode == 'full': tsubj,tmsg = replacer(ttitle),replacer(tbody.replace('<li>',u'\n♦ ').replace('</li>',''))
							elif submode == 'body': tmsg = replacer(tbody.replace('<li>',u'\n♦ ').replace('</li>',''))
							elif submode == 'head': tsubj = replacer(ttitle)
							else: return
							if urlmode: tlink = urllib.parse.unquote(turl.encode('utf8')).decode('utf8','ignore')
							t_msg.append((tsubj.replace('\n','; '),smart_concat(tmsg),tlink))
							new_count += 1
							if new_count >= lng: break
					if new_count:
						t_msg.reverse()
						tmp = ''
						for tm in t_msg: tmp += '!'.join(tm)
						if len(tmp+msg)+len(t_msg)*12 >= msg_limit:
							over = 100 * msg_limit / (len(tmp+msg)+len(t_msg)*12.0) # overflow in persent
							tt_msg = []
							for tm in t_msg:
								tsubj,tmsg,tlink = tm
								cut = int(len(tsubj+tmsg+tlink)/100*over)
								if cut < len(tlink): tsubj,tmsg,tlink = u'%s[…]' % tsubj[:cut],'',''
								elif cut < len(tsubj+tlink): tsubj,tmsg = u'%s[…]' % tsubj[:cut-len(tlink)],''
								else: tmsg = u'%s[…]' % tmsg[:cut-len(tlink+tsubj)]
								tt_msg.append((tsubj,tmsg,tlink))
							t_msg = tt_msg
						tmp = ''
						for tm in t_msg:
							if submode == 'full': tmp += u'\n• %s\n%s' % tm[0:2]
							elif submode == 'body': tmp += u'\n• %s' % tm[1]
							elif submode == 'head': tmp += u'\n• %s' % tm[0]
							if len(tm[2]): tmp += '\n'+tm[2]
						msg = unhtml(msg+tmp)
					elif mode == 'new':
						if text[4] == 'silent': nosend = True
						else: msg = L('New feeds not found!','%s/%s'%(jid,nick))
				except Exception as SM:
					rss_flush(jid,link,None)
					if text[4] == 'silent': nosend = True
					else: msg = L('Error! %s','%s/%s'%(jid,nick)) % SM
			else:
				rss_flush(jid,link,None)
				if text[4] == 'silent': nosend = True
				else:
					if need_update_feed:
						if feed in [L('Encoding error!','%s/%s'%(jid,nick)),L('Unable to access server!','%s/%s'%(jid,nick))]: title = feed
						else: title = html_encode(get_tag(feed,'title'))
						msg = L('Bad url or rss/atom not found at %s - %s','%s/%s'%(jid,nick)) % (link,title)
					else: msg = feed
		else: msg = L('Not found!','%s/%s'%(jid,nick))
	if not nosend: send_msg(type, jid, nick, msg)

def configure(type, jid, nick, text):
	text = text.lower().replace('\n',' ').replace('\r',' ').replace('\t',' ')
	while '  ' in text: text = text.replace('  ',' ')
	text = text.split(' ',1)
	to_conf = text[0]
	param = text[1] if len(text) == 2 else ''
	if to_conf in ['show','item','items','it','sh']:
		if param in ['status','info','st']:
			tmp = sorted(config_prefs.keys())
			msg = ''
			for t in tmp: msg += '\n[%s] - ' % t + L(config_prefs[t][0],'%s/%s'%(jid,nick)) % onoff(get_config(getRoom(jid),t))
			msg = L('Current status: %s','%s/%s'%(jid,nick)) % msg
		elif param in config_prefs: msg = L(config_prefs[param][0],'%s/%s'%(jid,nick)) % onoff(get_config(getRoom(jid),param))
		else:
			tmp = sorted(config_prefs.keys())
			msg = L('Available items: %s','%s/%s'%(jid,nick)) % ', '.join(tmp)
	elif to_conf == 'help' or not to_conf:
		if param in config_prefs: msg = L(config_prefs[param][1],'%s/%s'%(jid,nick))
		elif not param:
			tmp = sorted(config_prefs.keys())
			msg = L('Available items: %s','%s/%s'%(jid,nick)) % ', '.join(tmp)
		else:
			tmp = sorted(config_prefs.keys())
			tmp = [cp for cp in cps if param in cp]
			if tmp:
				msg = L('Available items: %s','%s/%s'%(jid,nick)) % ', '.join(tmp)
			else:
				msg = L('Help for %s not found!','%s/%s'%(jid,nick)) % param
	elif to_conf in config_prefs:
		if param.lower() in ['show','item','items','it','sh']:
			msg = ''
			if config_prefs[to_conf][2]:
				for tmp in config_prefs[to_conf][2]: msg += ['%s (%s), ' % (onoff_no_tr(tmp),onoff(tmp)),'%s, ' % onoff_no_tr(tmp)][onoff_no_tr(tmp) == onoff(tmp)]
			else: msg += L('text field','%s/%s'%(jid,nick)) + '  '
			msg = L('Available items: %s','%s/%s'%(jid,nick)) % msg[:-2]
		elif param == '': msg = L(config_prefs[to_conf][0],'%s/%s'%(jid,nick)) % onoff(get_config(getRoom(jid),to_conf))
		else:
			if not config_prefs[to_conf][2]: ssta = param
			else:
				ssta = get_config(getRoom(jid),to_conf)
				if (param.lower() in [L('on','%s/%s'%(jid,nick)),'on','true']) and not param in config_prefs[to_conf][2]: param = True
				elif (param.lower() in [L('off','%s/%s'%(jid,nick)),'off','false','none']) and not param in config_prefs[to_conf][2]: param = False
				else: param = param.lower()
				if param in config_prefs[to_conf][2]: ssta = param
				else: ssta = ''
			if len(str(ssta)):
				put_config(getRoom(jid),to_conf,ssta)
				msg = L(config_prefs[to_conf][0],'%s/%s'%(jid,nick)) % onoff(ssta)
			else: msg = L('Unknown item!','%s/%s'%(jid,nick))
	else: msg = L('Unknown item!','%s/%s'%(jid,nick))
	send_msg(type, jid, nick, msg)

def muc_filter_lock(type, jid, nick, text):
	realjid = getRoom(get_level(jid,nick)[1])
	tmp = cur_execute_fetchall('select * from muc_lock where room=%s and jid=%s', (jid,realjid))
	if text in ['on','off']:
		if tmp: cur_execute('delete from muc_lock where room=%s and jid=%s', (jid,realjid))
		if text == 'on':
			cur_execute('insert into muc_lock values (%s,%s)', (jid, realjid))
			st = L('on','%s/%s'%(jid,nick))
		else: st = L('off','%s/%s'%(jid,nick))
	elif tmp: st = L('on','%s/%s'%(jid,nick))
	else: st = L('off','%s/%s'%(jid,nick))
	msg = L('Ignore messages from unaffiliated participants in private - %s','%s/%s'%(jid,nick)) % st
	send_msg(type, jid, nick, msg)

def get_opener(page_name, parameters=None):
	socket.setdefaulttimeout(GT('rss_get_timeout'))
	try:
		proxy_support = urllib2.ProxyHandler({'http' : 'http://%(user)s:%(password)s@%(host)s:%(port)d' % http_proxy})
		opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)
		urllib2.install_opener(opener)
	except: opener = urllib2.build_opener(urllib2.HTTPHandler)
	opener.addheaders = [('User-agent', GT('user_agent'))]
	if parameters: page_name += urllib.parse.urlencode(parameters)
	try: data, result = opener.open(page_name), True
	except Exception as SM:
		try: SM = str(SM)
		except: SM = str(SM)
		data, result = L('Error! %s') % SM.replace('>','').replace('<','').capitalize(), False
	return data, result

def load_page_size(page_name, page_size, parameters=None):
	data, result = get_opener(page_name, parameters)
	if result: return data.read(page_size)
	else: return data

def load_page(page_name, parameters=None):
	data, result = get_opener(page_name, parameters)
	if result: return data.read(GT('size_overflow'))
	else: return data

config_prefs = {'url_title': ['Url title is %s', 'Automatic show title of urls in conference', [True,False], False],
				'content_length': ['Content length %s', 'Automatic show lenght of content in conference', [True,False], False],
				'censor': ['Censor is %s', 'Censor', [True,False], False],
				#'censor_message': ['Censor message is %s', 'Censor message', None, censor_text],
				'censor_warning': ['Censor warning is %s', 'Warning for moderators and higher' ,[True,False], False],
				'censor_action_member': ['Censor action for member is %s', 'Censor action for member', ['off','visitor','kick','ban'], 'off'],
				'censor_action_non_member': ['Censor action for non member is %s', 'Censor action for non member', ['off','visitor','kick','ban'], 'off'],
				'censor_custom': ['Custom censor is %s', 'Custom censor', [True,False], False],
				'censor_custom_rules': ['Custom rules for censor is %s', 'Custom rules for censor', None, '\n'],
				'parse_define': ['Parse define is %s', 'Automatic parse definition via google', ['off','full','partial'], 'off'],
				'clear_answer':['Clear notification by %s','Clear notification by presence or message', ['presence','message'],'presence'],
				'smiles':['Smiles in logs is %s', 'Smiles in logs', ['off'] + smiles_dirs, 'off'],
				'autoturn': ['Autoturn layout of text is %s', 'Turn text from one layout to another.', [True,False], False],
				'make_stanza_jid_count':['Jid\'s per stanza for affiliations in backup is %s','Count of jid\'s per stanza for affiliations change in backup',None,'100'],
				'acl_multiaction': ['ACL multiaction is %s', 'Execute more than one action per pass in ACL.', [True,False], False],
				'paste_xhtml_images': ['Paste xhtml images %s', 'Detect and paste xhtml images in messages', [True,False], True],
				#'use_default_locale': ['Use default locale %s', 'Ignore locale settings and use default bot locale', [True,False], False],
				'set_default_locale': ['Set default locale %s', 'Ignore users locale and use one locale for all users in room', ['off','en'] + [tmp[:-4] for tmp in os.listdir(loc_folder[:-6]) if tmp[-4:]=='.txt'], 'off'],
				'store_users_url': ['Store Users URL %s', 'Store Users URL', [True,False], True],
				'trusted_servers': ['Trusted servers %s', 'Servers list marked as trusted. They are excluded from any actions with servers', None, ''],
				'visitor_action': ['Action for visitors is %s', 'Action for visitors', ['off','kick','ban'], 'off'],
				'visitor_action_time': ['Time for visitors action %s', 'Time for visitors action', None, '1800'],
				'ai': ['AI is %s', 'AI parser for messages', [True,False], True],

				# MUC-Filter messages

				'muc_filter': ['Muc filter is %s', 'Message filter for participants', [True,False], False],
				'muc_filter_mute_chat': ['Mute all private messages %s', 'Mute all private messages', [True,False], False],
				'muc_filter_mute_groupchat': ['Mute all public messages %s', 'Mute all public messages', [True,False], False],
				'muc_filter_mute_repeat': ['Count of messages for action %s', 'Count of messages for action', None, '3'],
				'muc_filter_mute_repeat_action': ['Action for messages overflow %s', 'Action for messages overflow', ['off','kick','ban'], 'off'],
				'muc_filter_newbie': ['Mute newbie %s', 'Mute all messages from newbie', [True,False], False],
				'muc_filter_newbie_repeat': ['Count of messages for newbie %s', 'Count of messages for newbie for action', None, '3'],
				'muc_filter_newbie_repeat_action': ['Action for messages overflow for newbie %s', 'Action for messages overflow for newbie', ['off','kick','ban'], 'off'],
				'muc_filter_newbie_time': ['Mute newbie time %s', 'Time of mute all messages from newbie', None, '60'],
				'muc_filter_adblock': ['Adblock muc filter is %s', 'Adblock filter', ['off','visitor','kick','ban','replace','mute'], 'off'],
				'muc_filter_repeat': ['Repeat muc filter is %s', 'Repeat same messages filter', ['off','visitor','kick','ban','mute'], 'off'],
				'muc_filter_match': ['Match muc filter is %s', 'Repeat text in message filter', ['off','visitor','kick','ban','mute'], 'off'],
				'muc_filter_large': ['Large muc filter is %s', 'Large message filter', ['off','visitor','kick','ban','paste','truncate','mute'], 'off'],
				'muc_filter_censor': ['Censor muc filter is %s', 'Censor filter', ['off','visitor','kick','ban','replace','mute'], 'off'],
				'muc_filter_adblock_raw': ['Raw adblock muc filter is %s', 'Raw adblock filter', ['off','visitor','kick','ban','mute'], 'off'],
				'muc_filter_censor_raw': ['Raw censor muc filter is %s', 'Raw censor filter', ['off','visitor','kick','ban','mute'], 'off'],
				'muc_filter_raw_percent': ['Persent of short words for raw actions is %s', 'Persent of short words for raw actions', None, '40'],
				'muc_filter_reduce_spaces_msg': ['Reduce spaces in message %s', 'Reduce duplicates of spaces in message', [True,False], False],

				# MUC-Filter presence

				'muc_filter_history': ['Block joins without history %s', 'Block joins without history', [True,False], True],
				'muc_filter_history_ban': ['Ban joins without history %s', 'Additional ban joins without history', [True,False], True],
				'muc_filter_adblock_prs': ['Adblock muc filter for presence is %s', 'Adblock filter for presence', ['off','kick','ban','replace','mute'], 'off'],
				'muc_filter_rejoin': ['Repeat join muc filter is %s', 'Repeat join muc filter', [True,False], False],
				'muc_filter_whitelist': ['Whitelist is %s', 'Whitelist via muc filter', [True,False], False],
				'muc_filter_blacklist': ['Blacklist is %s', 'Blacklist via muc filter', [True,False], False],
				'muc_filter_blacklist_rules_jid': ['Blacklist rules for jid\'s %s', 'Jid\'s rules for blacklist via muc filter.', None, ''],
				'muc_filter_blacklist_rules_nick': ['Blacklist rules for nick\'s %s', 'Nick\'s rules for blacklist via muc filter.', None, ''],
				'muc_filter_newline': ['New line in presence muc filter is %s', 'New line muc filter', ['off','kick','ban','mute','replace'], 'off'],
				'muc_filter_newline_count': ['New line count in presence muc filter is %s', 'Count of new line muc filter', None, '2'],
				'muc_filter_newline_msg': ['New line in message muc filter is %s', 'New line muc filter', ['off','kick','ban','mute','replace'], 'off'],
				'muc_filter_newline_msg_count': ['New line count in message muc filter is %s', 'Count of new line muc filter', None, '2'],
				'muc_filter_repeat_prs': ['Repeat presence muc filter is %s', 'Repeat presence muc filter', ['off','kick','ban','mute'], 'off'],
				'muc_filter_large_nick': ['Large nick muc filter is %s', 'Large nick muc filter', ['off','visitor','kick','ban','truncate','mute'], 'off'],
				'muc_filter_large_status': ['Large status muc filter is %s', 'Large status muc filter', ['off','visitor','kick','ban','truncate','mute'], 'off'],
				'muc_filter_censor_prs': ['Censor muc filter for presence is %s', 'Censor muc filter for presence', ['off','kick','ban','replace','mute'], 'off'],
				'muc_filter_deny_hash': ['Deny by hash %s', 'Lock joins via hash', [True,False], False],
				'muc_filter_deny_hash_list': ['Deny hashes list %s', 'Hashes list for lock joins', None, ''],
				'muc_filter_hash': ['Hash. Check activity %s', 'Actions by hash activity', [True,False], False],
				'muc_filter_hash_ban_by_rejoin': ['Hash. Ban if hash activity %s', 'Actions for ban by hash activity', [True,False], True],
				'muc_filter_hash_ban_by_rejoin_timeout': ['Hash. Timeout for clean hash activity %s', 'Time period for clean hash activity', None, '600'],
				'muc_filter_hash_ban_server_by_rejoin': ['Hash. Ban server by hash activity %s', 'Ban server by hash activity', [True,False], True],
				'muc_filter_hash_ban_server_by_rejoin_exception': ['Hash. Exception for ban servers %s', 'Exception for ban servers', None, ''],
				'muc_filter_hash_ban_server_by_rejoin_notify_jid': ['Hash. Jid\'s for servers ban notify %s', 'Jid\'s for servers ban notify', None, ''],
				'muc_filter_hash_ban_server_by_rejoin_rejoins': ['Hash. Count of rejoins from server for ban %s', 'Count of rejoins from server for ban', None, '5'],
				'muc_filter_hash_ban_server_by_rejoin_timeout': ['Hash. Timeout of rejoins from server for ban %s', 'Timeout of rejoins from server for ban', None, '60'],
				'muc_filter_hash_time': ['Hash. Time for events %s', 'Time period for events', None, '20'],
				'muc_filter_hash_events': ['Hash. Events count %s', 'Events count per time period', None, '10'],
				'muc_filter_hash_action': ['Hash. Action type %s', 'Type of action', ['whitelist','lock by hash'], 'whitelist'],
				'muc_filter_hash_action_time': ['Hash. Time to disable action %s', 'Time to disable action', None, '1800'],
				'muc_filter_hash_action_current': ['Hash. Action for already joined %s', 'Action for already joined', ['off','kick','ban'], 'off'],
				'muc_filter_censor_prs_raw': ['Raw censor muc filter for presence is %s', 'Raw censor muc filter for presence', ['off','kick','ban','mute'], 'off'],
				'muc_filter_adblock_prs_raw': ['Raw adblock muc filter for presence is %s', 'Raw adblock filter for presence', ['off','kick','ban','mute'], 'off'],
				'muc_filter_reduce_spaces_prs': ['Reduce spaces in presence %s', 'Reduce duplicates of spaces in presence', [True,False], False],
				#'muc_filter_caps': ['Limitation by caps %s', 'Limitation to join by caps', [True,False], False],
				'muc_filter_caps_list': ['Type of list %s', 'Type of list for caps', ['off','black','white'], 'off'],
				'muc_filter_caps_white': ['Whitelist %s', 'Whitelist for caps', None, '\n'],
				'muc_filter_caps_black': ['Blacklist %s', 'Blacklist for caps', None, '\n'],
				#'muc_filter_caps_smart': ['Smart lists %s', 'Smart lists for caps', [True,False], False],
				#'muc_filter_caps_white_smart': ['Smart whitelist %s', 'Smart whitelist for caps', None, '\n'],
				#'muc_filter_caps_black_smart': ['Smart blacklist %s', 'Smart blacklist for caps', None, '\n'],
				'muc_filter_validate_action': ['Action for invalid items %s', 'Action for invalid items', ['off','ban','ban server'], 'ban'],
				'muc_filter_validate_nick': ['Validate nick %s', 'Validate nick', [True,False], True],
				'muc_filter_validate_login': ['Validate login %s', 'Validate login', [True,False], True],
				'muc_filter_validate_resource': ['Validate resource %s', 'Validate resource', [True,False], True],
				'muc_filter_validate_caps_node': ['Validate caps node %s', 'Validate caps node', [True,False], True],
				'muc_filter_validate_caps_version': ['Validate caps version %s', 'Validate caps version', [True,False], True],
				'muc_filter_validate_count': ['Count of invalid items %s', 'Count of invalid items for action', None, '4'],
				'muc_filter_validate_ban_server_exception': ['Exception for ban servers %s', 'Exception for ban servers', None, ''],
				'muc_filter_validate_ban_server_notify_jid': ['Jid\'s for servers ban notify %s', 'Jid\'s for servers ban notify', None, ''],
				'muc_filter_fast_join': ['Lock fast joins %s', 'Lock fast joins', [True,False], True],
				'muc_filter_fast_join_count': ['Count of fast joins %s', 'Count of fast joins', None, '3'],
				'muc_filter_fast_join_time': ['Time for count of fast joins %s', 'Time for count of fast joins', None, '5'],

				# Bomb

				'bomb': ['Bomb. Allow take a bomb %s', 'Allow take a bomb in current conference', [True,False], True],
				'bomb_fault': ['Bomb. Allow random unexplosive bombs %s', 'Allow some times take unexplosive bombs', [True,False], True],
				'bomb_fault_persent': ['Bomb. Persent of fault bombs %s', 'Persent of fault bombs', None, '25'],
				'bomb_random': ['Bomb. Allow bot take a bomb to random user %s', 'Allow bot take a bomb to random user', [True,False], False],
				'bomb_random_active': ['Bomb. Allow random bombs only in active room %s', 'Allow random bombs only in active room', [True,False], True],
				'bomb_random_active_timer': ['Bomb. Time for detect room as unactive %s', 'Time for detect room as unactive', None, '1200'],
				'bomb_random_timer': ['Bomb. Time between random bombs %s', 'Time between random bombs', None, '1800'],
				'bomb_random_timer_persent': ['Bomb. Persent of mistakes for time between random bombs %s', 'Persent of mistakes for time between random bombs', None, '25'],
				'bomb_random_timer_skip_persent': ['Bomb. Persent of skiped random bombs %s', 'Persent of mistakes skiped random bombs', None, '25'],
				'bomb_timer': ['Bomb. Timer is %s', 'Time to deactivate a bomb', None, '45'],
				'bomb_wire': ['Bomb. Wire count is %s', 'Wire count for bomb', None, '4'],
				'bomb_action': ['Bomb. Action for bomb explode %s', 'Type of action for bomb explode', ['off','kick'], 'kick'],
				'bomb_action_level': ['Bomb. Don\'t use action when access level lower than or equal %s', 'Ignore bomb action depends from access level', ['4','5','6','7','8','9'], '4'],
				'bomb_reason': ['Bomb. Reason %s', 'Reason for bomb explode', None, 'KA-BO-OM!!!111'],
				'bomb_idle': ['Bomb. Idle for unable get the bomb %s', 'Idle for unable get the bomb', None, '900'],

				# Karma actions

				'karma_action': ['Karma. Actions for karma change is %s', 'Allow change role/affiliation by karma change', [True,False], False],
				'karma_action_reason': ['Karma. Reason for actions by karma change is %s', 'Reason for change role/affiliation by karma change', None, 'by karma change!'],
				'karma_action_1ban': ['Karma. Ban when karma is lower than %s', 'Ban when karma is lower than defined value', None, '-50'],
				'karma_action_2kick': ['Karma. Kick when karma is lower than %s', 'Kick when karma is lower than defined value', None, '-20'],
				'karma_action_3visitor': ['Karma. Revoke voice when karma is lower than %s', 'Revoke voice when karma is lower than defined value', None, '-10'],
				'karma_action_4none': ['Karma. None affiliation when karma is lower than %s', 'Revoke affiliation when karma is lower than defined value', None, '-5'],
				'karma_action_5participant': ['Karma. Participant affiliation when karma is higher than %s', 'Give a participant affiliation when karma is higher than defined value', None, '5'],
				'karma_action_6member': ['Karma. Member affiliation when karma is higher than %s', 'Give a member affiliation when karma is higher than defined value', None, '20'],
				'karma_action_7moderator': ['Karma. Moderator role when karma is higher than %s', 'Give a moderator role when karma is higher than defined value', None, '50'],
				'karma_hard': ['Hard rule for karma is %s', 'Not allow any symbols between nick and karma digit' ,[True,False], False],
				'karma_limit': ['Limits for karma change is %s', 'Limitation of karma\'s change. Depends of access level' ,[True,False], True],
				'karma_limit_size': ['Value of limits for karma change %s', 'Value of limitation of karma\'s change. Depends of access level' ,None, '[3,5]'],

				# Flood
				'flood': ['Flood is %s', 'Autoanswer', ['off','random','smart'], 'off'],
				'autoflood': ['Autoflood is %s', 'Autoflood', [True,False], False],
				'floodcount': ['Number of message for autoflood\'s start: %s', 'Number of message for autoflood\'s start', None, '3'],
				'floodtime': ['Time period for autoflood\'s start: %s', 'Time period for autoflood\'s start', None, '1800'],
				'autophrases': ['Autophrases is %s', 'Autophrases', ['off','without highlight','all'], 'off'],
				'autophrasestime': ['Time period for autophrases is %s', 'Time period for autophrases', None, '7200'],
				'floodrepeat': ['Repeat phrase after match %s', 'Repeat phrase after match same messages', ['off','2','3','4','5','6','7','8','9','10'], '3']

				}

config_group_other = ['Other settings','#room-other',
				['ai','url_title','parse_define','clear_answer','smiles','autoturn','make_stanza_jid_count','content_length','acl_multiaction',
				'paste_xhtml_images','set_default_locale','store_users_url','trusted_servers','visitor_action','visitor_action_time'],None]

config_group_censor = ['Censor settings','#room-censor',
				['censor','censor_warning','censor_action_member','censor_action_non_member',
				'censor_custom','censor_custom_rules'],None]

config_group_mucfilter = ['General Muc-filter settings','#room-mucfilter',
				['muc_filter','muc_filter_mute_chat','muc_filter_mute_groupchat','muc_filter_mute_repeat','muc_filter_mute_repeat_action'],None]

config_group_mucfilter_newbie = ['Muc-filter settings for newbie','#room-mucfilter-newbie',
				['muc_filter_newbie','muc_filter_newbie_time','muc_filter_newbie_repeat','muc_filter_newbie_repeat_action'],None]

config_group_mucfilter_hash = ['Muc-filter settings for hash','#room-mucfilter-hash',
				['muc_filter_hash','muc_filter_hash_time','muc_filter_hash_events','muc_filter_hash_action','muc_filter_hash_action_time',
				'muc_filter_hash_action_current','muc_filter_deny_hash','muc_filter_deny_hash_list','muc_filter_hash_ban_server_by_rejoin',
				'muc_filter_hash_ban_server_by_rejoin_exception','muc_filter_hash_ban_server_by_rejoin_notify_jid',
				'muc_filter_hash_ban_server_by_rejoin_rejoins','muc_filter_hash_ban_server_by_rejoin_timeout','muc_filter_hash_ban_by_rejoin',
				'muc_filter_hash_ban_by_rejoin_timeout'],None]

config_group_mucfilter_content = ['Muc-filter settings by content','#room-mucfilter-content',
				['muc_filter_newline','muc_filter_newline_count','muc_filter_newline_msg_count','muc_filter_newline_msg',
				'muc_filter_large','muc_filter_repeat','muc_filter_match','muc_filter_reduce_spaces_msg','muc_filter_reduce_spaces_prs',
				'muc_filter_rejoin','muc_filter_repeat_prs','muc_filter_large_nick','muc_filter_large_status','muc_filter_history',
				'muc_filter_history_ban'],None]

config_group_mucfilter_raw = ['Muc-filter settings for raw-actions','#room-mucfilter-raw',
				['muc_filter_adblock_raw','muc_filter_adblock_prs_raw',
				'muc_filter_censor_raw','muc_filter_censor_prs_raw','muc_filter_raw_percent'],None]

config_group_mucfilter_censor = ['Muc-filter settings for censor/ad-block','#room-mucfilter-censor',
				['muc_filter_adblock_prs','muc_filter_adblock','muc_filter_censor','muc_filter_censor_prs'],None]

config_group_mucfilter_lists = ['Muc-filter settings for while/black lists','#room-mucfilter-lists',
				['muc_filter_whitelist','muc_filter_blacklist','muc_filter_blacklist_rules_jid','muc_filter_blacklist_rules_nick'],None]

config_group_mucfilter_caps = ['Muc-filter settings for while/black lists by caps','#room-mucfilter-caps-lists',
				['muc_filter_caps_list','muc_filter_caps_white',
				#'muc_filter_caps','muc_filter_caps_smart','muc_filter_caps_white_smart','muc_filter_caps_black_smart',
				'muc_filter_caps_black'],None]

config_group_mucfilter_validate = ['Muc-filter settings for validate items','#room-mucfilter-validate',
				['muc_filter_validate_nick','muc_filter_validate_login','muc_filter_validate_resource',
				'muc_filter_validate_caps_node','muc_filter_validate_caps_version','muc_filter_validate_count',
				'muc_filter_validate_action','muc_filter_validate_ban_server_exception','muc_filter_validate_ban_server_notify_jid'],None]

config_group_mucfilter_fast_action = ['Muc-filter settings for fast action','#room-mucfilter-fast-action',
				['muc_filter_fast_join','muc_filter_fast_join_count','muc_filter_fast_join_time'],None]

config_group_bomb = ['Settings for bomb-joke','#room-bombjoke',
				['bomb','bomb_fault','bomb_fault_persent','bomb_random','bomb_random_timer',
				'bomb_timer','bomb_wire','bomb_action','bomb_action_level','bomb_reason','bomb_random_active',
				'bomb_random_active_timer','bomb_random_timer_persent',
				'bomb_random_timer_skip_persent','bomb_idle'],None]

config_group_karma = ['Actions for karma change','#room-karma-action',
				['karma_action','karma_action_1ban','karma_action_2kick','karma_action_3visitor',
				'karma_action_4none','karma_action_5participant','karma_action_6member','karma_action_7moderator','karma_hard',
				'karma_limit','karma_limit_size'],None]

config_group_flood = ['Flood settings','#room-flood',
				['flood','autoflood','floodcount','floodtime','autophrases','autophrasestime','floodrepeat'],None]

config_groups = [config_group_mucfilter,config_group_mucfilter_newbie,config_group_mucfilter_hash,config_group_mucfilter_content,
				config_group_mucfilter_raw,config_group_mucfilter_censor,config_group_mucfilter_lists,config_group_mucfilter_caps,
				config_group_mucfilter_validate,config_group_mucfilter_fast_action,config_group_other,config_group_bomb,
				config_group_karma,config_group_censor,config_group_flood]

# type:
# b - binary (true\false)
# i - integer
# f - float
# tXX - text[:XX]
# mXX - multiline text[:XX]
# lXX - len(list) == XX
# d - droplist
# XXe - execute latest field by eval

owner_prefs = {'syslogs_enable': ['Logger. Enable system logs','b',True],
				'movement_logs_enable':['Logger. Enable logins and logouts logging','b',True],
				'status_logs_enable':['Logger. Enable status change logging','b',True],
				'aff_role_logs_enable':['Logger. Enable role and affiliation logging','b',True],
				'html_logs_enable':['Logger. Html logs. Otherwize in text','b',True],
				'chatlogs_logs_gmt':['Logger. Use GMT time in MUC logs','b',False],
				'html_logs_end_text':['Logger. Additional text for logs','m512',''],
				'karma_limit':['Karma. Minimal karma for allow krama change for participants','i',5],
				'karma_show_default_limit':['Karma. Default length of list karma top+/-','i',10],
				'karma_show_max_limit':['Karma. Maximal length of list karma top+/-','i',20],
				'watch_size':['Watcher. Frequency of requests in watcher','i',900],
				'user_agent':['Www. User-agent for web queries','m256','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11'],
				'size_overflow':['Www. Limit of page in bytes for www command','i',262144],
				'youtube_max_videos':['Youtube. Maximal links number','i',10],
				'youtube_default_videos':['Youtube. Default links number','i',3],
				'youtube_max_page_size':['Youtube. Page size limit','i',131072],
				'youtube_default_lang':['Youtube. Default language','t2','ru'],
				'age_default_limit':['Age. Default number of users for age commands','i',10],
				'age_max_limit':['Age. Maximal number of users for age commands','i',100],
				'anek_private_limit':['Anek. Anekdote size for private send','i',500],
				'troll_default_limit':['Troll. Default message number for troll command','i',10],
				'troll_max_limit':['Troll. Maximal message number for troll command','i',100],
				'troll_sleep_time':['Troll. Delay between messages for troll command','f',0.05],
				'backup_sleep_time':['Backup. Requests delay for backup command','f',0.1],
				'calendar_default_splitter':['Calendar. Default splitter for calendar','t10','_'],
				'clear_delay':['Clear. Delay between massages in clear command','f',1.3],
				'clear_default_count':['Clear. Default message number for clear command','i',20],
				'clear_max_count':['Clear. Maximal message number for clear command','i',100],
				'ping_digits':['Iq. Number after point in ping','i',3],
				'lfm_api':['LastFM. Api for lastfm plugin','t64','no api'],
				'lastfm_max_limit':['LastFM. Number of answers for lastfm plugin','i',10],
				'reboot_time':['Kernel. Restart timeout for error at bot initial (no connection, auth error)','i',180],
				'timeout':['Iq. Timeout for iq queries','i',600],
				'schedule_time':['Kernel. Schedule time','i',10],
				'sayto_timeout':['Sayto. Age of message in sayto before delete it from base with undelivered','i',1209600],
				'sayto_cleanup_time':['Sayto. Timeout for sayto base cleanup','i',86400],
				'scan_time':['Spy. Time for spy scan','i',1800],
				'spy_action_time':['Spy. Time for reaction on spy scan','i',86400],
				'rss_max_feed_limit':['Rss. Maximum rss count','i',10],
				'rss_min_time_limit':['Rss. Minimal time for rss check in minutes','i',10],
				'rss_get_timeout':['Rss. Timeout for rss request from server in seconds','i',15],
				'whereis_time_dec':['Whereis. Frequency for answer check for whereis command','f',0.5],
				'watcher_room_activity':['Watcher. Try rejoin in rooms with low activity','b',True],
				'watcher_self_ping':['Watcher. Allow self ping','b',True],
				'disco_max_limit':['Disco. Maximus andwers count for disco command','i',10],
				'juick_user_post_limit':['Juick. Number of posts','i',10],
				'juick_user_post_size':['Juick. Number of symbols in post','i',50],
				'juick_msg_answers_default':['Juick. Number of answers','i',10],
				'juick_user_tags_limit':['Juick. Number of tags','i',10],
				'iq_time_enable':['Iq. Allow answer to time request','b',True],
				'iq_uptime_enable':['Iq. Allow answer to uptime request','b',True],
				'iq_version_enable':['Iq. Allow answer to version request','b',True],
				'iq_disco_enable':['Iq. Allow answer to service discovery','b',True],
				'iq_ping_enable':['Iq. Allow answer to ping','b',True],
				'iq_show_rooms_disco':['Iq. Show bot rooms in service discovery','b',True],
				'paranoia_mode':['Kernel. Paranoic mode. Disable all execute possibles on bot','b',False],
				'show_loading_by_status':['Kernel. Bot status. Show different status for bot loading','b',True],
				'show_loading_by_status_show':['Kernel. Bot status. Status while loading','d','dnd',['chat','online','away','xa','dnd']],
				'show_loading_by_status_message':['Kernel. Bot status. Message while loading','t256','Loading...'],
				'show_loading_by_status_percent':['Kernel. Bot status. Show percent of loading','b',True],
				'show_loading_by_status_room':['Kernel. Bot status. Show join to room while loading','b',True],
				'kick_ban_notify':['Kernel. Notify when bot is kicked or banned','b',True],
				'kick_ban_notify_jid':['Kernel. Notify jid for bot kick or ban','t1024',''],
				'watch_activity_timeout':['Watcher. Timeout for no actions in room for rejoin','i',1800],
				'muc_filter_large_message_size':['Muc-filter. Message size for filter','i',512],
				'muc_filter_match_count':['Muc-filter. A kind words count','i',3],
				'muc_filter_match_warning_match':['Muc-filter. Number of kind parts in message','i',3],
				'muc_filter_match_warning_space':['Muc-filter. Number of empty parts in message','i',5],
				'muc_filter_match_view':['Muc-filter. Message limit','i',512],
				'muc_filter_match_warning_nn':['Muc-filter. Number of empty new lines','i',3],
				'muc_filter_rejoin_count':['Muc-filter. Number of reconnects for monitoring','i',3],
				'muc_filter_rejoin_timeout':['Muc-filter. Time for reconnect count','i',120],
				'muc_filter_status_count':['Muc-filter. Number of precences per time','i',3],
				'muc_filter_status_timeout':['Muc-filter. Time between presences','i',600],
				'muc_filter_large_status_size':['Muc-filter. Maximux status-message size','i',50],
				'muc_filter_large_nick_size':['Muc-filter. Maximum nick size','i',20],
				'muc_filter_repeat_count':['Muc-filter. Repeat count','i',3],
				'muc_filter_repeat_time': ['Muc-filter. Timeout for repeat message', 'i', 3600],
				'muc_filter_notify': ['Muc-filter. Notify about abnormal activity', 'b', False],
				'muc_filter_notify_jids': ['Muc-filter. Jid\'s for notify', 't1024', ''],
				'muc_filter_notify_peroid': ['Muc-filter. Time peroid for notify', 'i', 10],
				'muc_filter_notify_count': ['Muc-filter. Count of events for notify', 'i', 5],
				'muc_filter_notify_wait': ['Muc-filter. Time between notifies', 'i', 300],
				'html_paste_enable':['Paste. Paste as html. Otherwize as text','b',True],
				'yandex_api_key':['City. Yandex.Map API-key','t128','no api'],
				'bing_api_key':['Bing. Translator API-key','t128','no api'],
				'steam_api_key':['Steam. API-key','t128','no api'],
				'censor_text':['Kernel. Text for hide censore','t32','[censored]'],
				'ddos_limit':['Kernel. Time of ignore for anti-ddos','l10','[1800,1800,1800,1800,1800,600,300,150,60,0]'],
				'ddos_diff':['Kernel. Anti-ddos time delay between messages','l10','[30,30,30,30,20,20,15,10,5,0]'],
				'ddos_iq_requests':['Kernel. Iq anti-ddos. Requests number','i',30],
				'ddos_iq_limit':['Kernel. Iq anti-ddos. Time limits for requests','i',10],
				'amsg_limit_size':['Msgtoadmin. Size limit for msgtoadmin','i',1024],
				'amsg_limit':['Msgtoadmin. Time limit for next message for msgtoadmin','l10','[86400,86400,86400,86400,86400,86400,43200,3600,1800,60]'],
				'karma_timeout':['Karma. Time for karma change from access level','l10','[86400,86400,86400,86400,86400,86400,43200,3600,1800,5]'],
				'karma_discret':['Karma. Difference between two action in karma','i',5],
				'karma_discret_lim_up':['Karma. Upper value of karma for control action','i',100],
				'karma_discret_lim_dn':['Karma. Lower value of karma for control action','i',-100],
				'disco_exclude':['Disco. Exclude from disco by regexps','m256e',u'([؀-ݭ)\n(ﭐ-ﻼ])\n(syria|arab)','disco_exclude_update()'],
				'exclude_messages':['Kernel. Exclude symbols from bot\'s messages','m256e',u'([؀-ۿ])\n([ݐ-ݿ])\n([ﭐ-﷿])\n([ﹰ-﻿])','message_exclude_update()'],
				'1st_april_joke':['Kernel. 1st April joke','b',True],
				'soft_update_resend_hash':['Kernel. Send new hash into rooms after soft update','b',False],
				'notepad':['Notepad','m4096',''],
				'wot_region':['Region of API Server', 'd', 'RU', ['RU','EU','COM','SEA','KR']],
				'wot_appid':['World of Tanks. Application ID','t64','demo'],
				'wot_delay':['World of Tanks. Time of delay','i',2],
				'wot_retries':['World of Tanks. Count of retries','i',2]
				}

owner_group_mucfilter = ['Muc-filter settings','#owner-mucfilter',
				['muc_filter_large_message_size','muc_filter_match_count','muc_filter_match_warning_match',
				'muc_filter_match_warning_space','muc_filter_match_view','muc_filter_match_warning_nn',
				'muc_filter_rejoin_count','muc_filter_rejoin_timeout','muc_filter_status_count',
				'muc_filter_status_timeout','muc_filter_large_status_size','muc_filter_large_nick_size',
				'muc_filter_repeat_count','muc_filter_repeat_time','muc_filter_notify','muc_filter_notify_jids',
				'muc_filter_notify_peroid','muc_filter_notify_count','muc_filter_notify_wait']]

owner_group_iq = ['Iq requests settings','#owner-iq',
				['iq_time_enable','iq_uptime_enable','iq_version_enable','iq_disco_enable',
				'iq_ping_enable','ping_digits','timeout','iq_show_rooms_disco']]

owner_group_juick = ['Juick settings','#owner-juick',
				['juick_user_post_limit','juick_user_post_size','juick_msg_answers_default','juick_user_tags_limit']]

owner_group_logs = ['Logs settings','#owner-logs',
				['syslogs_enable','status_logs_enable','aff_role_logs_enable','movement_logs_enable','html_logs_enable','html_logs_end_text','chatlogs_logs_gmt']]

owner_group_youtube = ['Youtube settings','#owner-youtube',
				['youtube_max_videos','youtube_default_videos','youtube_max_page_size','youtube_default_lang']]

owner_group_other = ['Other settings','#owner-other',
				['anek_private_limit','backup_sleep_time','calendar_default_splitter',
				'disco_max_limit','disco_exclude','html_paste_enable']]

owner_group_api = ['API settings','#owner-api',
				['yandex_api_key','bing_api_key','steam_api_key','lfm_api','wot_appid']]

owner_group_karma = ['Karma settings','#owner-karma',
				['karma_limit','karma_show_default_limit','karma_show_max_limit','karma_timeout','karma_discret','karma_discret_lim_up','karma_discret_lim_dn']]

owner_group_www = ['WWW settings','#owner-www',
				['size_overflow','user_agent']]

owner_group_troll = ['Antitroll settings','#owner-troll',
				['troll_default_limit','troll_max_limit','troll_sleep_time']]

owner_group_kernel = ['Kernel settings','#owner-kernel',
				['censor_text','ddos_limit','ddos_diff','paranoia_mode','reboot_time','schedule_time',
				'show_loading_by_status','show_loading_by_status_show','show_loading_by_status_message',
				'show_loading_by_status_percent','kick_ban_notify','kick_ban_notify_jid',
				'ddos_iq_requests','ddos_iq_limit','exclude_messages','1st_april_joke','soft_update_resend_hash']]

owner_group_lastfm = ['LastFM settings','#owner-lastfm',
				['lfm_api','lastfm_max_limit']]

owner_group_whereis = ['Whereis settings','#owner-whereis',
				['whereis_time_dec']]

owner_group_watcher = ['Watcher settings','#owner-watcher',
				['watch_size','watcher_room_activity','watch_activity_timeout','watcher_self_ping']]

owner_group_clear = ['Clear settings','#owner-clear',
				['clear_delay','clear_default_count','clear_max_count']]

owner_group_rss = ['RSS settings','#owner-rss',
				['rss_max_feed_limit','rss_min_time_limit','rss_get_timeout']]

owner_group_amsg = ['Message for admin settings','#owner-amsg',
				['amsg_limit_size','amsg_limit']]

owner_group_age = ['Age settings','#owner-age',
				['age_default_limit','age_max_limit']]

owner_group_sayto = ['Sayto settings','#owner-sayto',
				['sayto_timeout','sayto_cleanup_time']]

owner_group_spy = ['Spy settings','#owner-spy',
				['scan_time','spy_action_time']]

owner_group_notepad = ['Notepad','#owner-notepad',
				['notepad']]

owner_group_wot = ['World of Tanks settings','#owner-wot',
				['wot_region','wot_appid', 'wot_delay', 'wot_retries']]

owner_groups = [owner_group_amsg,owner_group_rss,owner_group_clear,
				owner_group_kernel,owner_group_lastfm,owner_group_whereis,
				owner_group_watcher,owner_group_troll,owner_group_www,
				owner_group_karma,owner_group_sayto,owner_group_age,
				owner_group_mucfilter,owner_group_iq,owner_group_juick,
				owner_group_logs,owner_group_youtube,owner_group_other,
				owner_group_api,owner_group_notepad,owner_group_wot]

comms = [
	 (0, 'help', helpme, 2, 'Help system. Helps without commands: about, donation, access'),
	 (9, 'join', bot_join, 2, 'Join conference.\njoin room[@conference.server.ru[/nick]]\n[password]'),
	 (9, 'leave', bot_leave, 2, 'Leave conference.\nleave room[@conference.server.ru[/nick]]'),
	 (9, 'rejoin', bot_rejoin, 2, 'Rejoin conference.\nrejoin room[@conference.server.ru[/nick]]\n[password]'),
	 (9, 'bot_owner', owner, 2, 'Bot owners list.\nbot_owner show\nbot_owner add|del jid'),
	 (9, 'bot_ignore', ignore, 2, 'Black list.\nbot_ignore show\nbot_ignore add|del jid'),
	 (9, 'syslogs', show_syslogs, 2, 'Show bot\'s syslogs.\nsyslogs [number of records] [text]'),
	 (9, 'syslogs_search', show_syslogs_search, 2, 'Search in bot\'s syslogs.\nsyslogs_search <regexp>\n[date regexp]'),
	 (6, 'where', info_where, 1, 'Show conferences.'),
	 (6, 'where+', info_where_plus, 1, 'Show conferences.'),
	 (0, 'inbase', info_base, 1, 'Your identification in global base.'),
	 (9, 'look', real_search, 2, 'Search user in conferences where the bot is.'),
	 (9, 'glook', real_search_owner, 2, 'Search user in conferences where the bot is. Also show jid\'s'),
	 (7, 'rss', rss, 2, 'News:\nrss show - show current.\nrss add url time mode - add news.\nrss del url - remove news.\nrss get url feeds mode - get current news.\nrss new url feeds mode - get unread news only.\nrss clear - clear all news in current conference.\nrss all - show all news in all conferences.\n\nurl - url of rss/atom chanel. can set without http://\ntime - update time. number + time identificator. h - hour, m - minute. allowed only one identificator.\nfeeds - number of messages to receive. 10 max.\nmode - receive mode. full - full news, head - only headers, body - only bodies.\nwith -url to be show url of news.'),
	 (7, 'alias', alias, 2, 'Aliases.\nalias add|add_global new=old\nalias del|del_global|show text'),
	 (0, 'commands', info_comm, 1, 'Show commands list.'),
	 (8, 'comm', comm_on_off, 2, 'Enable/Disable commands.\ncomm - show disable commands\ncomm on command - enable command\ncomm off command1[ command2 command3 ...] - disable one or more command'),
	 (0, 'bot_uptime', uptime, 1, 'Show bot uptime.'),
	 (6, 'info', info, 1, 'Misc information about bot.'),
	 (3, 'new', vcs_info, 1, 'Last VCS update log'),
	 (9, 'limit', conf_limit, 2, 'Set temporary message limit.'),
	 (9, 'plugin', bot_plugin, 2, 'Plugin system.\nplugin show|local\nplugin add|del name'),
	 (9, 'error', show_error, 2, 'Show error(s).\nerror [number|clear]'),
	 (0, 'whoami', info_access, 1, 'Your identification.'),
	 (0, 'whois', info_whois, 2, 'Identification.'),
	 (0, 'lang', info_lang, 2, 'Show language for user.'),
	 (0, 'status', status, 2, 'Show status.'),
	 (3, 'prefix', set_prefix, 2, 'Set command prefix. Use \'none\' for disable prefix'),
	 (9, 'set_locale', set_locale, 2, 'Change bot localization.\nset_locale en|%s' % '|'.join([tmp[:-4] for tmp in os.listdir(loc_folder[:-6]) if tmp[-4:]=='.txt'])),
	 (7, 'config', configure, 2, 'Conference configure.\nconfig [show[ status]|help][ item]'),
	 (4, 'pmlock', muc_filter_lock, 2, 'Deny recieve messages from unaffiliated participants in private'),
	 (9, 'ddos', ddos_info, 2, 'Temporary ignore with ddos detect.\nddos [show|del jid]')]
