From 96bd6ca7689c4d8427386ad368441a9f06110693 Mon Sep 17 00:00:00 2001 From: Vladislav Ivanov Date: Sun, 9 Oct 2016 20:16:18 +0300 Subject: [PATCH] Release cleanups. --- .gitignore | 3 +- conf/blacklist.cfg | 26 -------- conf/c2b.cfg | 15 ----- conf/chat_modules.cfg | 15 ----- conf/config.cfg | 18 ------ conf/df.cfg | 32 ---------- conf/goodgame.cfg | 11 ---- conf/levels.cfg | 10 --- conf/logger.cfg | 10 --- conf/mentions.cfg | 12 ---- conf/messaging.cfg | 19 ------ conf/sc2tv.cfg | 11 ---- conf/twitch.cfg | 13 ---- conf/webchat.cfg | 17 ----- http/czt/img/levels/{default => }/0.png | Bin http/czt/img/levels/{default => }/1.png | Bin http/czt/img/levels/10.png | Bin 0 -> 299 bytes http/czt/img/levels/11.png | Bin 0 -> 415 bytes http/czt/img/levels/12.png | Bin 0 -> 370 bytes http/czt/img/levels/13.png | Bin 0 -> 374 bytes http/czt/img/levels/14.png | Bin 0 -> 786 bytes http/czt/img/levels/15.png | Bin 0 -> 1204 bytes http/czt/img/levels/16.png | Bin 0 -> 1356 bytes http/czt/img/levels/17.png | Bin 0 -> 15449 bytes http/czt/img/levels/18.png | Bin 0 -> 15395 bytes http/czt/img/levels/19.png | Bin 0 -> 572 bytes http/czt/img/levels/{default => }/2.png | Bin http/czt/img/levels/20.png | Bin 0 -> 422 bytes http/czt/img/levels/21.png | Bin 0 -> 407 bytes http/czt/img/levels/22.png | Bin 0 -> 467 bytes http/czt/img/levels/23.png | Bin 0 -> 555 bytes http/czt/img/levels/24.png | Bin 0 -> 467 bytes http/czt/img/levels/25.png | Bin 0 -> 809 bytes http/czt/img/levels/26.png | Bin 0 -> 1360 bytes http/czt/img/levels/27.png | Bin 0 -> 1335 bytes http/czt/img/levels/28.png | Bin 0 -> 560 bytes http/czt/img/levels/29.png | Bin 0 -> 589 bytes http/czt/img/levels/{default => }/3.png | Bin http/czt/img/levels/30.png | Bin 0 -> 1166 bytes http/czt/img/levels/31.png | Bin 0 -> 1166 bytes http/czt/img/levels/32.png | Bin 0 -> 1166 bytes http/czt/img/levels/33.png | Bin 0 -> 1166 bytes http/czt/img/levels/34.png | Bin 0 -> 1166 bytes http/czt/img/levels/35.png | Bin 0 -> 1166 bytes http/czt/img/levels/36.png | Bin 0 -> 1166 bytes http/czt/img/levels/37.png | Bin 0 -> 1166 bytes http/czt/img/levels/38.png | Bin 0 -> 1166 bytes http/czt/img/levels/39.png | Bin 0 -> 1166 bytes http/czt/img/levels/{default => }/4.png | Bin http/czt/img/levels/40.png | Bin 0 -> 1166 bytes http/czt/img/levels/41.png | Bin 0 -> 1166 bytes http/czt/img/levels/42.png | Bin 0 -> 1166 bytes http/czt/img/levels/43.png | Bin 0 -> 1166 bytes http/czt/img/levels/5.png | Bin 0 -> 504 bytes http/czt/img/levels/6.png | Bin 0 -> 482 bytes http/czt/img/levels/7.png | Bin 0 -> 613 bytes http/czt/img/levels/8.png | Bin 0 -> 777 bytes http/czt/img/levels/9.png | Bin 0 -> 657 bytes http/czt/img/levels/cube.png | Bin 0 -> 3139 bytes {conf => http/czt}/levels.xml | 0 main.py | 67 +++++++++++++------- messaging.py | 22 +++++-- modules/chats/goodgame.py | 50 ++++++++------- modules/chats/sc2tv.py | 80 ++++++++++++------------ modules/chats/twitch.py | 53 +++++++++------- modules/messaging/levels.py | 24 ++----- modules/messaging/webchat.py | 22 +------ translations/en/goodgame.key | 6 +- translations/en/main.key | 3 + translations/en/sc2tv.key | 6 +- translations/en/twitch.key | 8 +-- translations/en/webchat.key | 2 - translations/ru/goodgame.key | 6 +- translations/ru/main.key | 3 + translations/ru/sc2tv.key | 6 +- translations/ru/twitch.key | 8 +-- translations/ru/webchat.key | 2 - 77 files changed, 195 insertions(+), 385 deletions(-) delete mode 100644 conf/blacklist.cfg delete mode 100644 conf/c2b.cfg delete mode 100644 conf/chat_modules.cfg delete mode 100644 conf/config.cfg delete mode 100644 conf/df.cfg delete mode 100644 conf/goodgame.cfg delete mode 100644 conf/levels.cfg delete mode 100644 conf/logger.cfg delete mode 100644 conf/mentions.cfg delete mode 100644 conf/messaging.cfg delete mode 100644 conf/sc2tv.cfg delete mode 100644 conf/twitch.cfg delete mode 100644 conf/webchat.cfg rename http/czt/img/levels/{default => }/0.png (100%) rename http/czt/img/levels/{default => }/1.png (100%) create mode 100644 http/czt/img/levels/10.png create mode 100644 http/czt/img/levels/11.png create mode 100644 http/czt/img/levels/12.png create mode 100644 http/czt/img/levels/13.png create mode 100644 http/czt/img/levels/14.png create mode 100644 http/czt/img/levels/15.png create mode 100644 http/czt/img/levels/16.png create mode 100644 http/czt/img/levels/17.png create mode 100644 http/czt/img/levels/18.png create mode 100644 http/czt/img/levels/19.png rename http/czt/img/levels/{default => }/2.png (100%) create mode 100644 http/czt/img/levels/20.png create mode 100644 http/czt/img/levels/21.png create mode 100644 http/czt/img/levels/22.png create mode 100644 http/czt/img/levels/23.png create mode 100644 http/czt/img/levels/24.png create mode 100644 http/czt/img/levels/25.png create mode 100644 http/czt/img/levels/26.png create mode 100644 http/czt/img/levels/27.png create mode 100644 http/czt/img/levels/28.png create mode 100644 http/czt/img/levels/29.png rename http/czt/img/levels/{default => }/3.png (100%) create mode 100644 http/czt/img/levels/30.png create mode 100644 http/czt/img/levels/31.png create mode 100644 http/czt/img/levels/32.png create mode 100644 http/czt/img/levels/33.png create mode 100644 http/czt/img/levels/34.png create mode 100644 http/czt/img/levels/35.png create mode 100644 http/czt/img/levels/36.png create mode 100644 http/czt/img/levels/37.png create mode 100644 http/czt/img/levels/38.png create mode 100644 http/czt/img/levels/39.png rename http/czt/img/levels/{default => }/4.png (100%) create mode 100644 http/czt/img/levels/40.png create mode 100644 http/czt/img/levels/41.png create mode 100644 http/czt/img/levels/42.png create mode 100644 http/czt/img/levels/43.png create mode 100644 http/czt/img/levels/5.png create mode 100644 http/czt/img/levels/6.png create mode 100644 http/czt/img/levels/7.png create mode 100644 http/czt/img/levels/8.png create mode 100644 http/czt/img/levels/9.png create mode 100644 http/czt/img/levels/cube.png rename {conf => http/czt}/levels.xml (100%) diff --git a/.gitignore b/.gitignore index 45b4278..f774a56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ *.pyc .idea/* /logs -/conf/levels.db* +levels.db* /build /dist /libs +/conf *.spec *.log diff --git a/conf/blacklist.cfg b/conf/blacklist.cfg deleted file mode 100644 index 25a7b58..0000000 --- a/conf/blacklist.cfg +++ /dev/null @@ -1,26 +0,0 @@ -[gui_information] -category = messaging -id = 30 - -[main] -message = Пытаеться что-то сказать, но у него лалка во рту - -[users__gui] -for = users_hide, users_block -view = list -addable = true - -[users_hide] - -[users_block] -announce - -[words__gui] -for = words_hide, words_block -addable = true -view = list - -[words_hide] - -[words_block] - diff --git a/conf/c2b.cfg b/conf/c2b.cfg deleted file mode 100644 index 8386b77..0000000 --- a/conf/c2b.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[gui_information] -category = messaging -id = 10 - -[config__gui] -for = config -view = list_dual -addable = true - -[config] -sc2tv = funstream, адольф -gnomoria = игра, которую нельзя называть -гномория = игра, которая не нужна -czt = lalka - diff --git a/conf/chat_modules.cfg b/conf/chat_modules.cfg deleted file mode 100644 index 5ab8adb..0000000 --- a/conf/chat_modules.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[gui_information] -category = main - -[chats] -goodgame -sc2tv -twitch - -[chats__gui] -for = chats -view = choose_multiple -check_type = files -check = modules/chats -file_extension = False - diff --git a/conf/config.cfg b/conf/config.cfg deleted file mode 100644 index 3bf341c..0000000 --- a/conf/config.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[gui_information] -category = main - -[language__gui] -check = translations -check_type = folder -for = language -view = choose_single - -[gui] -on_top = True -gui = True -show_hidden = True -reload - -[language] -en - diff --git a/conf/df.cfg b/conf/df.cfg deleted file mode 100644 index c1c7f83..0000000 --- a/conf/df.cfg +++ /dev/null @@ -1,32 +0,0 @@ -[gui_information] -category = messaging - -[grep] -symbol = # -file = logs/df.txt - -[prof__gui] -for = prof -view = list_dual -addable = true - -[prof] -archer = ([Лл]учник|[Aa]rcher) -carpenter = ([Пп]лотник|[Cc]arpenter|[Ll]umberjack) -child = ([Дд]итя|[Cc]hild) -clothemaker = ([Шш]ве[яй]|[Cc]lothemaker) -craftsdwarf = ([Кк]рафтер|[Cc]raft(er|sdwarf)) -engraver = ([Шш]лифов(щик|альщик)|[Ee]ngraver]) -farmer = ([Фф]ермер|[Пп]овар|[Бб]ухлодел|[Ff]armer|[Bb]rewer|[Cc]ook) -fisher = ([Рр]ыбак|[Ff]isher) -hunter = ([Оо]хотник|[Hh]unter) -jeweler = ([Юю]велир|[Сс]аша|[Jj]eweler) -mason = ([Кк]аменьщик|[Мм]асон|[Mm]ason) -mechanic = ([Мм]еханик|[Mm]echanic) -medic = ([Мм]едик|[Дд]октор|[Вв]рач|[Кк]оновал|[Хх]ирург|[Mm]edic|[Dd]octor) -miner = ([Шш]ахтер|[Кк]опатель|[Mm]iner) -noble = ([Мм]удак|[Бб]лагородный|[Дд]ворянин|[Нн]обл|[Nn]oble) -smith = ([Кк]узнец|[Ss]mith) -warrior = ([Вв]оин|[Вв]а(р)?риор|[Ww]arrior) -nothing = ([Нн]икто|[Nn]othing|\w*) - diff --git a/conf/goodgame.cfg b/conf/goodgame.cfg deleted file mode 100644 index 1e0ab5b..0000000 --- a/conf/goodgame.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[gui_information] -category = chat - -[config__gui] -for = config -hidden = socket - -[config] -socket = ws://chat.goodgame.ru:8081/chat/websocket -channel_name = CzT - diff --git a/conf/levels.cfg b/conf/levels.cfg deleted file mode 100644 index 97f401d..0000000 --- a/conf/levels.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[gui_information] -category = messaging - -[config] -experience = random -exp_for_level = 50 -file = conf/levels.xml -db = levels.db -message = {0} засунули в соковыжималку, выжали, и он теперь {1} - diff --git a/conf/logger.cfg b/conf/logger.cfg deleted file mode 100644 index cb51e89..0000000 --- a/conf/logger.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[gui_information] -category = messaging -id = 20 - -[config] -logging = true -rotation = daily -file_format = %Y-%m-%d -message_date_format = %Y-%m-%d %H:%M:%S - diff --git a/conf/mentions.cfg b/conf/mentions.cfg deleted file mode 100644 index d324a2d..0000000 --- a/conf/mentions.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[gui_information] -category = messaging - -[config__gui] -for = mentions, address -view = list -addable = true - -[mentions] - -[address] - diff --git a/conf/messaging.cfg b/conf/messaging.cfg deleted file mode 100644 index 496247d..0000000 --- a/conf/messaging.cfg +++ /dev/null @@ -1,19 +0,0 @@ -[gui_information] -category = main - -[messaging__gui] -for = messaging -view = choose_multiple -check_type = files -check = modules/messaging -file_extension = False - -[messaging] -blacklist -df -logger -webchat -c2b -levels -mentions - diff --git a/conf/sc2tv.cfg b/conf/sc2tv.cfg deleted file mode 100644 index 52a1dc6..0000000 --- a/conf/sc2tv.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[gui_information] -category = chat - -[config__gui] -for = config -hidden = socket - -[config] -socket = ws://funstream.tv/socket.io/ -nick = CzT - diff --git a/conf/twitch.cfg b/conf/twitch.cfg deleted file mode 100644 index 3c21b88..0000000 --- a/conf/twitch.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[gui_information] -category = chat - -[config__gui] -for = config -hidden = host, port - -[config] -host = irc.twitch.tv -port = 6667 -channel = CzT1 -bttv = true - diff --git a/conf/webchat.cfg b/conf/webchat.cfg deleted file mode 100644 index 39f1052..0000000 --- a/conf/webchat.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[gui_information] -category = main -id = 9001 - -[style__gui] -for = style -view = choose_single -check_type = dir -check = http - -[style] -czt - -[server] -host = 127.0.0.1 -port = 14589 - diff --git a/http/czt/img/levels/default/0.png b/http/czt/img/levels/0.png similarity index 100% rename from http/czt/img/levels/default/0.png rename to http/czt/img/levels/0.png diff --git a/http/czt/img/levels/default/1.png b/http/czt/img/levels/1.png similarity index 100% rename from http/czt/img/levels/default/1.png rename to http/czt/img/levels/1.png diff --git a/http/czt/img/levels/10.png b/http/czt/img/levels/10.png new file mode 100644 index 0000000000000000000000000000000000000000..1ea1251266f544a72e850c70583cfe899e9948d2 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKvjVt%=q>FyjY+hdx@v7EBk#GRuMV9e^J>YK%pI;E{-7CfZf-u3K#@#ex;eSY)05;?fdTIYD?6?}XB>?lX)&YKc# z28(X*ScSzb?dc-s5WU%BkBb&sIM2q7mTF$brpDk|u!K2&Qz`)>u zY4^2bNnge8G%V%umjHo%=Wn+z5=;}=6rPY}c&Nd+QtR;doi_`7Pn>fLYc`ctIBvgg lh08WcRe?@VmmNYP3i35R|g(d+*TXO@FoFjeJDUJ&K5o+e|Rr3gUi zx0#X+rfKfC>>7sM;B#iS1ZpqOWR`Vjv3rj1k?HvPfch&hx z{o7gg0C@(goF(=*0XRR{K~EFhx;Zh#ku^Tt#C$x>asQs?PO`ZuR@?wU9^&dn%=&3a zq&mDUZ=9dL002ov JPDHLkV1iRmt)>6~ literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/12.png b/http/czt/img/levels/12.png new file mode 100644 index 0000000000000000000000000000000000000000..8c94a5979e1fa4974d4f3fe8fe6f60e161633174 GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=I50S^h-E752+Bfr9KMp1!W^_gPp)c+GllZn^*z`tRxD7-DfcIbngSftlGq|B27! z%D(+?;YmECo_XYq&&;>KckJNU)xP{Km$I|JT>f{VypY@h?Bl^s#-Qo&($S{+xszr7_;-SB&&95X zt((uW^6b0JXJh~bZ)_{(Gy=iF@>`B=K#2(5q=RY^r;580BadsgnJ+5i(eD>Gp7P1S zpv1UBF#Ujje>zXj@-q?=XBJ4g%$1Pv%T50A^kdJ#BK>8IJv$a%^!&tpc;9oTf>}T_ zAHKP{xyOa|(Gwr-wgU_u+)T`SB-GNQCe9N|)N@R`%)-F%SvT>%#8akDU{El4y85}S Ib4q9e0JgZ6T>t<8 literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/13.png b/http/czt/img/levels/13.png new file mode 100644 index 0000000000000000000000000000000000000000..68786388ec88ad1875bfaedf0aba52099bb7558a GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=I50S^h-E752+Bfr9KMp1!W^_gPqltvR>7k&tCzU}W}maSX9Iotz+%aiGK7$=&-m zPfzXBTcN^}e6C)+WcT^+<=6kMqHd+9`Og0&f777kK#TXImrE>pOy|uz)}nJb^T5pS z`I0^?t&(zfHAf~)pPkurUesc5;qs+_|Id8f{(rt@-4FX+;Wa%=T?=;L!jUwcpdLZ3&Jz^`8$lG&PS7TW z5+YV&CH^ZF3vESExWhZ#g9yhpx=D5e9-Cw}ao64NeaB+g6}9nc24) zY@!!O#u$HF10eN**a}8yqgM9-)V)$qLzCdd;hhvG3tYQ-m*QlBJ-_Y-Ko!!Kva^OX zXe+NY((sj_x38a(1KR-FFc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc&_u!9QqR!T z(8R(}N5ROz&{*HVSl`fC*U-qyz|zXlQ~?TIxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7KMf<|~|UP^v> zu_jo#udkJ7UU5lcUUI6Zi>(sS0KLr26e}kuV`D=n3lmEdLq|hHR}%{t6DLP=OG76& zQ&&SLM^~6$m;B_?+|;}hnBEkGUQ?WUK`9}(0BEyIYEfocYKmJ?ey#%8$5xrR-C~5( zJgD9j+-@<(saGH97=2K@BE>UI2$*<4On9mVa^UGcH4m8Bi-4&*c~Zq@1_nk=PZ!6K zid#v4{{OdUR&8LN-qP90*>y7g+?>QC%lZUob34p(y-~NQWAD$SeOCo|m>p)_+;8V9 z_*hirU?zv3euIf*_dbTrS5@vczC4+(YIw!);U?K7mH(?1+qU`UOMEHaDk+p^dpJu_ zc%OjZ^*@I;DEM-nX}f4~m|^yP-UhS#wV#CY9gGy+FZ<_Zvh~?m?@;kE*3tP;#rTBj zUrMUM@3pc=cFw=QpYbw#p5q}YmHv5l28SNJY_(4KwO>QNOHn~e%{|2AP>fRU0w(i{ z)^!GlUE5YCgdaG>beLg+lE97=ADR}_gD%k9AJ3G)U)UM S7TbPMIpXQ+=d#Wzp$Py=ft&{b literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/16.png b/http/czt/img/levels/16.png new file mode 100644 index 0000000000000000000000000000000000000000..eaab90e197c90e64f4a059faed9fcf9a30c0af6f GIT binary patch literal 1356 zcmaJ>drTX39KW`#D^Ms#0u+qgI)a$l-d!Jqo>cmlI*PUHpy* zi7rmUh%zt}rY?)dWx;5oi3wwiaUlVGY?I+;Vj`F^jb_m(;z+$R%KSsTku(v z)7?ob><@r0mM1}r!J@}u#0=J24TuFX*C7vqMi?*n_yZQd7un_9z zNGM1OY!{D9gNyCVgyK*aPhuj=hgh~V+r>aTE3!g6%YiNzSkp=|1e+8dT!;JpsE-ju zjKN8t+oqEQ3=~D6PN&(4m}?QM8F3(p$6V(&I~}!F#Obwo5U0bF<+@qCizXQ{%O&n| zjazavPM|p{vYX_oXGp@!voyF~F-mQj%Wm(MdK+9~>s;V1xsa3$l$qh=D`krJYv-6Ux?|rfDH~`4b``nID>f7k;bh<&I9vKxV)kwtNP%N}+tH(XB>WdYIbW1dnUM)VO%_+Pd#a5=y zPIG@w@9AGUKCbW_F8i@cb!e&DU{mZ?-T$((zdEw|z{lpk_Yy_d1B0<5xa2w6Y3S+6 zywAt0=p7#byt3wIXy3l`@{<9jEZ1*>*Zx|o_#|QfzW!O@%Zeejrqbp~$v(3Wym9gI zvEJph{A=~m%CQRtvaew4YvHMwO5M9({z~&;Y-Bc!%ak2&PP*3qK7n0IP{plpDZGm_ zIeWgD7@T`@wb1j+JUcUU_{z3?#v#8vQ#^DtBFp~}SSV7Lo{VF^PdJh?d#?;Q^3Gh_ TB79Dj`M>!*&F-_#$P51fA6C-M literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/17.png b/http/czt/img/levels/17.png new file mode 100644 index 0000000000000000000000000000000000000000..682e71eb80de513dc39012151281afc13f774570 GIT binary patch literal 15449 zcmeI3dvFv*9>)iy;u+0JL<%vAa|@LC*qxbuB|C05B-y}5*$|STL8ZuKrn8yL?#yOq zlHJ5Yb07)_mI%eEyi^p5Nb&H2RB2EV;{%a9E}Wi$($iF3z>~weRG~S`<9c>CyPHnZ zm#g#su&TFeAHV+g@7vR#{&nyCGixd<=I3NzpG{FzPPxxp1-~a7?_XrW&zlA=3GnNR zuy2V*QCChe-V>d#;`Vqvza+7 z&$@WdK__1(Pd5DJjz|rBm3LlpI2aY08g)I)GfXrZwM1o>I!yaa> zP0@vzSs_E4-5A%tjqht7!`ZrV40kOGE@^tw7Odj&>1}nDPm?M1pZXlE{D{ z2*DH$UOYGIC4?JQUDX=ZG3K3;$DF+`H>4M5*c1$9%rp>_$4E1jL|VKQ5-a3}^~aY+ zfS{|98dVK?5>-|?boF#;DLv;NS&`JJc8i-qd#9H=Z3Mi64m_|F9cGp@v-TR!!P}fX z%iYGpnq)If5OVHY$Z+8hU z!3tdq?B@IeyJ!}il3;cU4K~rrIVE7V4_RlVkFZ`Ck>MdE1T*>=SO4D*F^bKIp?tCi zOQ$WPq+nsikC|%FJiK*C2+Hx}A}mBSVC=#|)6h0doiC~5!^ny6W?m4DgT^BowF)FR zGpsdzS*grqnmlp=$45EgpOHTH7|}+c;0iur74J2+iKaH_Q6U0~1F$Ck!!}G94$nZH z-HdT22j&068fZf6|F#0-+d@D06-d{v*eECgAbFUfvK?v|-=Za!a`=84ItE7WKer_E z4QeDL=pH#F1OO9O0&XVVm>$!e`WNC$)u0;js}k_o+{|dr8Ck~v4-d}t<_*4X30mU#bsD+^x?XM848Gi5Y&2|hJbMpM(7ixpY-Sd*h6%^6w7pJW0?HN2k# z9;d@$bGR9_8O^AaV<1@TmEn1=8K)HIOy;1%sEJF)O3V7tUf!r^0#|;mdz>=TmI?1qhQVS&3f*S_uo6Pa>K8d z-Ee2_yG3m27R6bYyQOb^QAyvaBd?q}dicAp?+*7bfBc%oRMn6`VPGh*`7t2(NrbzA>@zIDgRIY;W&gTB2w z=gVtb^M2pi*DZa!%Cn@BfjyqqMSgbwr+3}DX(GL2@YMDh?gyez9yoaXho?3*_skNd zvdTG~mxUWI7XP3u-F(%3x5nHvCY;UpPweU0`gzRzuT6ir^ue8f;W7pcXMQ>W) zdikC6Uo6fN@3vf(!+qbo;)|03AS^eIVzJcy*-(UD+&#{u;Ijg&uetGVMv;V@h z39-SKn!nch!7~?j6u7%jZs|Vpig|i}An)!IT_0X}df)25R?9PQp0au2!EbK(<=~%= kAHDg;j!VwR9=e=*ptEcHr0)+LHXi;hFRSqGE2&%YZwy};AOHXW literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/18.png b/http/czt/img/levels/18.png new file mode 100644 index 0000000000000000000000000000000000000000..246369af36741338f1ee324abb8c53698ab27f9d GIT binary patch literal 15395 zcmeI3du$X%9LKi>8(KgR>#IRsPQaqx?e0C=-g-T$y<(ekaFiNaBFc7mu3fm>z3y&% zM@54ed8xrbeFOy_x?@8bY4`$HbGJwfGrk|z}^()xi1zG#D&118$hG1lv;j%XTOD( zrBcfrm!I`V%0ZJ{*`|TnZ8K`cwuPcwvfSs*^Tc>45C(=o$HE~+=VPUoxGoRx&1S|z z$GaE{OD$#QfOMTdK$oi;pj|eXRb)9QUF^1TF3wrP-9y`1&cUz_hI3dsJI}g#&P69b z7H=NB^Jr3#uklSw4hOALOOs(lc!r5aqqeBSrfQ80=XSdp*3Q`NR@lR;FH#I4W>xe% z5+c1iKA?-595G~7p-o+(L2WTgEf#a2)F-*Fa3nR5q9@rwicCz1Fr1BL1_|=}@nPZc zfRVaU(F$jhT-ksF>a~j^fT;nx+Mq;n7A+L#BZ&+MfiMiw;pDji zrx0mU4OMSa2U&N@J?QEUIhfv@K1(n?gNA{aJV==7Nrc5yA+bXqn16h^1_VRZYE?Dl zO=MZ1clLC7IbAqMRwOm5Pw_Bl@AOuug@8{mfET8s%gS+HBct;V>Iqzm+PO=#y ziJpjtAEvz|7{X9g`t(J0R7nml8j?!7XI~A!pRZDMLr_Fe<@3U|+hkedOIQGk>_Las z-5^TV2A31w2?A@iyBi!OlE4N57mP2mZ+JgxpDMPPIh2%^pmcGuLlh+uSnb88pyYI0 zg(4PM1*t(OVT(D=DY$y2Gs62x&(vgCgoIE=A9MD9cZdOG`VCbn>o9c|Wuz2LtazE3 z4VwG5_Bujxyj(;CO$X*FEVc9=!&H4ql@Bu}ewukfGz*PaG;ji{i3vPPH_e{l>Gf_)=UWe;Q4%1d^BOP21jvp>0}XEBl_O-ZIet{COmi52{*NFuZbDXar0| zY4kAZ#`Kt;)V~m4u7*_2uS&q{@Gt{4XGEF*KRm1rFi(Z}ndCf7zc#dgoq5JXE%E-v zb{2jZ&iqY=X1dYPdVFZ68x2iIKB&ls*Pa{=Y0ii;|0EMIX2a(>;4N~w9I)h~&1ghG zj)72}PlokeH>(s^l#D?g0|wR)7MS5k1}0J=e5ws{hp#)Sc>{# zK1J~_QPfT9nnw=8zF9}Ad}Xz<&p%kZODQNDyKMiN-?KgM?HlgQUly>oFPU1qV%1XH zs_i@1uPR(wx#`n6vo>5Se*T3mXJl^f#CtY8(fI0wFE_nCZ2Fob6&;`TEI51h>?@b% z)IQ(kTULDN@RUoxoqudyRoh*3;nKTS6t3=>p0%K3;)+P|#b0+^+mL@OzcMiP47YCU zxxIVlT04HNy7lpS)yLXL51-)OJ+e7FJ3sH5_t{OermX6C<0i^qH@WAbJ9~C-xB_FI=5FNifxckGH=i8X)t%rAf z^KIvEp`z-`ACLL!#Yva{xNQkL>O{-D#iuu)I(OahtRGunrbk?PSnQlT>G67d!LuU{ zJok;Zvh#(--ql>r=?l%{m!FR<-tMlxxcKT5TOZr2J>U7lkF6gEcb|!r?3}ypy9<|N z8y+~^{`F7CFFZZQKJNII{EEPB8@sbdIE1 zyS@Os>H@YGxkD3IJ8tnDJYyk}@P)Bp0+^09?%<( z>34e^9=7 z%5@P497iJ2gi(mG0uzPQx7Mq1_2UMUEBLwF_w#NtIY|nlXiRgbR(-Hq%-^}01u2mj zYK>1c{Iz2vC)UybT`vfN!o$^~l~Ph`GyzV)|NO+*bNQ#~1N;QZ-W18prg=?S1^xjid6~o~WRYgRw){>ZQEk4y(D>PP!vU6E|)mxI3ABNgg^*ERQ2+_rfHrhaL(bJ zll^{wHQ#JDzqs~x`)ak~a5!AG?FZs*6R*VE?Kb|U#&^5_w)orNZSjBc2?Z#8vhU{z QJOBUy07*qoM6N<$f@xH_k^lez literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/21.png b/http/czt/img/levels/21.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b185e8ada6a7d8de4e6c30818578149a8b201a GIT binary patch literal 407 zcmV;I0cie-P)03OR1bVHl`9BZ`Q(j{xi7wA{N=Kg|qL^{!*U1!Uli~x9bP8#k**tycfZF_?;m59b&opS&HQWlW1SRUip1pw6b#e-b?cKZeZ-AAhH z%Vd2VOIdjP46~r%F}@TR*BEY^1H{}9T(gX+#2;*0pig9?N5KF9002ovPDHLkV1gib BtPB7E literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/22.png b/http/czt/img/levels/22.png new file mode 100644 index 0000000000000000000000000000000000000000..6939a2f19f825a4b7403c9c31842e99349df67ed GIT binary patch literal 467 zcmV;^0WAKBP);;3=YX)1Tkl+wZ>SB(&^x}gX^1J)J_kMpupuvW1O?7b=a8isJy5!5VC9E(1 zzz@~yRvXhI2`Ni9x8_AW?tQ}#4ct6sxVjrFPKYkK3_6mE?orYDe=u_OF13`4xTluk z(L_ri9MpF?Jepw6eiTmfZ;vLTwBx-DU22I*k=((<#UcPGs(Ay8*g5(VJuu|jtBnqP z+C+ay;15&0yhS+KUqH3d!RLJwt@g(ZnKFg`>pRA`b>Si(-}b>XHrH0LYS{pQY!ZRT zBd~yziq4)#6Omj*Hi^nNkumnSajMnp1}hz-Xrg7-z~hmyDPzC`#Xf-95?m*RW!AJR zGO6pNaGi8^5B$);`5{qM(8&Mp`KQCkr3L)H~QUoDzLp(xVn?i>Jshyk-IyrR7l1?d+LY4@f;?l(- zYo<;O6*5SPLzb3sx#2(v1Z>M4F`xuo&q3eoJ#+ft4e$4U-|z4H`zLtfScV-Z-$CSw zG(Yhaxa!n-nSZ5h2i?6?lFW19b#p`6J8o}DRVo3Xfs-Uvr;cUVv1QotZh7rBK=yIY zRj1B`G3#uk)~4h3WJ*8bpU5O-mp01)ygz=c053iXP1)m=G7=0>DLTq&5dK(-{(F9| zt~}W!yZji|E&=!({$W_Vq&@tMKOJdgRp+6NmSM-G%`%mu!)ks7fb01UU;AG)z-$p} z??TQbh&&-=4U!IpoXKnv@}{(_Y?b1D$iYRQGyjyU+eiRpEyIov-6H^MCkHh5+YB!H z8b|`A&7Y3Ax{dzN!S(zGfaZRi=C_ad(~&BuEUG^paps?t3`2OLSic-j#bljebC|j4@$~)At!T$y$8sPu{002ovPDHLkV1l@C`pN(R literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/24.png b/http/czt/img/levels/24.png new file mode 100644 index 0000000000000000000000000000000000000000..3dcb03e6161d81a03cedc2f60e224a9f56bf9bff GIT binary patch literal 467 zcmV;^0WAKBP)pC|wT0bof) zK~y-)rISBM0#O{tKZ>i1Boq-gG{gfN!kQZTbI@l0?uLda=myt7XlWE$ZpfB|g4%)# zq_HSSXplfe2We=q;Uw@7Bti`0HFcfgc|u=!{2uSU@AvWj{@w!@2qC1ix*_03UR_=S zuxq7K@pU`vcOz?>%1`YZLI`7 zb#%q=L$TN2s_*>?ti^^o+TB1_^UQq;HsiA#?5v}F zMUmCKw?HnJqup*}nkKjTGM~W_0ItgxrfGT${2M|D=^VYj_cw8>lX1^ax>f)H002ov JPDHLkV1lST%tHVG literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/25.png b/http/czt/img/levels/25.png new file mode 100644 index 0000000000000000000000000000000000000000..db0975262f3a1b1a0868c399d700143252ae9d10 GIT binary patch literal 809 zcmV+^1J?YBP)%*+=76u^d*ENn`x zF;DJmH#a3CMqTXILt6p3-%nFC#i9TzCc_Mm-YrbnPA03%d{0|rOFHPGxbTY2@gRUH zz*3+lY$xN&>eAAL5M3TycBehjmd+k--@Ct(3q{BV{jHVC(!GMpc(khdSu73oOi_iZ+3D zJ7{T`qrvZ@G2mfa(_7rW2rSQ%cscTK5c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc&_u!9QqR!T z(8R(}N5ROz&{*HVSl`fC*U-qyz|zXlQ~?TIxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7KMf<|~|UP^v> zu_jo#udkJ7UU5lcUUI6Zi>(sS0KLr26e}kuGjk(X7gtLYLq|hHR}%{t6DLP=OG76& zQ&&SLM^~6$m;B_?+|;}hnBEkGUN@Y2K`9}(0BEyIYEfocYKmJ?ey#%8$5xqG-D2Wo zXku=R(>$o&6x?oc!Kqgt=oo!ayduRjObD2GKumb51#;l&J~a=R*o%OvdhNkw-3$zj zM?GB}Ln?0N1p8{Z1d9BdC&=A%;`DnbLzOc<_aZ!WbWD6aBehdEY}~p*@$|(vHy&tO zXLFzN6P#2j`LkQ&sk)Tr$wNst#eCnZ^7pLI`+jHs`|9U&-rLPs#%XBcYrJ-&gx~X| zl*i(Y4hMSN7Ta8|N?FkToj*VB={$@6*c=jY7zVMgd?u4ZrG~5pk8#MN6X2xzPvSI-@Kp9YQNm~Bjo3T6yfk= z(+WzyCn=Y2zxFv{(V{;SIBQ-1dp}?=E@G>F9X5$o<6W@!rEAM7?oN8iv@}_Q%|?#@ zPM*2^gc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc&_u!9QqR!T z(8R(}N5ROz&{*HVSl`fC*U-qyz|zXlQ~?TIxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7KMf<|~|UP^v> zu_jo#udkJ7UU5lcUUI6Zi>(sS0KLr26e}kuGjk(XS0hUkLq|hHR}%{t6DLP=OG76& zQ&&SLM^~6$m;B_?+|;}hnBEkGUSphkK`9}(0BEyIYEfocYKmJ?ey#%8$5xrR-C}^# zJgD9j+-@<%saGH97=2K@BE>UI2$*<4On9mVa^UGcH4m8Bi-4*67t6Nm3=E8GJY5_^ zDsI&T+xs615cqFdrYL$LAIhL&&yRV2uf6;lMl6&0YgT$mt3z?!Q;g>TE$7>b8bBPdqRir;hQ}^Gt=`}Z`|wcx%w=| z>vkez+SNs-=T}@jdL_f;+4R=rE}_}aISEWN85vWuC5nF6*2UngDbk B}e-N{OK+km2WVuuOso~9gZ{GLK41BVze}R+9?O}m8PjlWZkfjpRVJ7y8Z$tBDs=$Bx?2m00001`;qvs{5KYPpINgjZn?E=D!k|=Q% z+`Um^*WLtRF}=*ojW+=N>MsPDGY9R3*PmL=M6{fIsZHkeNj^5;v%4l+_<8>irs0q; z=uD^fC|8nLoe^d|y9X^r@w5BEJKF zo3|y&s~7En$TS>42Vg#@Vb&vC@Bx>WQUEkfho0>QHo#W3kE)Ju^u%%d?b$A-;T%pr zlw>Lqe+O1)M82T2Rqd1UhFFRgRAm~6ZF)m`wobW{WM_K-q{nCAx(BH0G>y6h7w5uE zjV@S*Cky(=dE9kqiN8Wc$=hY4L!P&@Eid(DwBP!#oaN zhUndW3?Rc`wu5xz^9l<{!IK@UK@`J#y-f^HFCJz%e&;=yPYl86pd&H!GrM$J*40}K zGMPqT&0oL%WB>)`4J#=WGeBVh0?0AL1kwzPzC9OTFn}~;10VxImY@T8EWivwR{-Ld ztvtfe+}zA?@yAMr4lx~uob8Zk2DtGOm z>}#+AZRa^r4FHLPoW1!OD_8+2S%bhcR&k89F^TCdSPo$vkb9tHJy?)ITMbNulJ#R( zh!Bk2dGR$cOztxu!6iAEWxEQ{ig#;uh20&oH!22Z1g2T>iTA{xZ@boFyt=akR{0ATyu%>V!Z literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/31.png b/http/czt/img/levels/31.png new file mode 100644 index 0000000000000000000000000000000000000000..b71b90740508eba0779a879e54dba8474e891520 GIT binary patch literal 1166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNn-sSam!jL|Wef}~(w;7kAr^v+0xa);165E47>U(x zY;61=ruOXFvv7TI222tg4boi2%*Phkct+(ga23SiHUQb5D5{{G?aQVxe4DU{q09R`157R4 z1t5XkSW~zJvH>95L7=90K118zzYN-EJmAtSAQnusoQxy`$Pi$ffQLAU4+1Y=T>;bR z1lRyjh=MdtEmi=^i!$t(VhdMy_x@vs8$it(Vy_traxxeuOql_f12Mn`fEXY{vU?f+ z@0cRX0MR50)^y_)g#N~+#~{M+6Qq;@XEcHg@yIz0v=N~h8J)s2*qZw0FZ!3BTN9925FWN v_|A}LeFIq-g^kk%AXOk&z*M6<9VSjO9o5~KyyWWIQjkHOu6{1-oD!MJg3RniD}Z>APo_piKL5G5L8mqAQq`^bk(?WStJk_T(0(y}V#xkM z2)QHvh8&y*tljD4(bEHx$!ArXTE+i35{ZOLM%s*CkByp5#)VF>geAzmL6jfOKn;0d zT3kcm@E%l(OK5#mkk98ij|V!rYTHC*wuo3P23LFs?_YoU357xd@~&QVG_AaenOFP@ z22}?XMZrL$fw#|Ip)_A)p4Nm@-Z;1ddOzBI@L)fjE*F+QFQ8mg;DHTmXd)m=2=;Vi zytz?#;CD+tR$RI$mD?RE?0#S%QC2bJ8k^Z*vRqc1n=sZ4m4NGq2nBHzDr53|o-YyX#kQ>hVbG#lV&KwqK%$RS-2a#K%O+|o2! zT0dbuKV5#0^*1F3vU@<}(ac#!+7~~-$#mm%vN2EOvGMbKGZyIgT=!eETmK2l{jKg# Y-aprOGY_VEkj+wIdT1nh>)6<(9~1xHZ2$lO literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/34.png b/http/czt/img/levels/34.png new file mode 100644 index 0000000000000000000000000000000000000000..fa98e40a0a54800d7a03fe5240b46a52f8d77f15 GIT binary patch literal 1166 zcmZ`&Ye-a45dQAnyL;W;6d$dRbwdiV%p^pkNTHM!-7E=vKp|owyAT#d4}z#4L19RL zG_n;11Hm7WKcZlxq9W)=te{yxih>@iX1lVMkJWwMW{%w;sJYCUbI;5-XI|&p-p0CA zi`@bs)m86oBAL#dVxqNRPCG)vbhM$)35~yjCqvzIVm?`a=rmx>VwTX`mrIB08P}d# z^^?hNE!ud=dGHvZD1L(CAREjM!JsMw+eL?-TeD@j-sYCSAbc|p@rl;OjMd^l6jhNPo0LqPE}u}ua-715#Wk>GaMPxH3 zlURx+AnW;1j@pTRo%lR5Eesj(G@Oa6_d+;OTP7qc_yXaC9Pq`miSlOt7kP^3G2pff zl`b9BH70?h`YBwHFojjV+=9Tn?`XbRhVyRV*?R@EYB4?rrZF@=MUYGZTwA38cL4+8 zl2nAhuIBJx^iQH|@V+o+Fq57??=2RdPGFf*;F*y*AD_<$_dq2o50?t%!|o5l$y_)j z{y7>Zuh$FKajh234vptVs-`w_0oi~Hq!+QEJO_2h3(?&Em{l0O;S}KEH=W|&5(!A$ z03|^!;ofp2dV$ypb5GABq~)H%y229Lx1qh_3-Z+|bdTggrNSrJL5j&B9+YrP%dU!k zpaK{he~X4IW3bt5ctz*IU=R;3Y}U;XOC-TlEbS=C5u?nSACyX8>q@nIyt|Ru`WoXi zD-l@3Z5SOL6%P18@rHar=0flkMxtUk!9ZrFj*bo?^*y(mNdT#h7S*uw7DPMfVZ^94 n{Mv-of0nGoloTfqF}jq8sn@rmWh{8-C7Ziy8=b>7t(SiRj^9Ur literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/35.png b/http/czt/img/levels/35.png new file mode 100644 index 0000000000000000000000000000000000000000..a620df4d67d29273f6316cda9c9cc7f560f3ed0c GIT binary patch literal 1166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNn-sUYyy2V091ILB(w;7kAr^v+0xa);GXj-h1;)n4 z|B)rmo;{0IEeoq?&`G|NqZmkh2R+BkR0z;|7?EVgRy&1Gg}I2bW&AZXLt)>C?f1 z2v-I24@dTOb89qJn!Cjpko=pbmjir|1H~({%>k(0{Q>~Rv`rs}|RN@4i2BNF>-)3OgmdLQ(Yd*vFj$=^Uq!<|P+-C>`CXbgd zU&37gH(>s~?+hT#Ae!Of6Sx8g3o$TTRbGZ+YN!pvN~p}rl`9bm2^9JuNvrmw3~$y< zW@vLzVK{c^CRpi#6R+Tg!5GTQ$}lD>4e}GRA1!Uw{=+aVkU=_-*>Eqwj9UNKnqfWA z-yo;|`o;@SzHT6|lth3t5iBEt^kB_QFvCC!k!?fP2vf6S{^g_%XMC@N_@1tQF6*2U FngIF+^40(V literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/36.png b/http/czt/img/levels/36.png new file mode 100644 index 0000000000000000000000000000000000000000..4f1db46076e87225a2a1be14766d254b71e08a39 GIT binary patch literal 1166 zcmeHEPbh<79Dc?cHfuv>n?EZhjpLVcQZ(5TNgP~+gR|o5;-H+}yr0=lfW%tu4jRlH?rsxaDrsUp z)1PD&bX~W}56e{SfEbA%DGxe&yg1v-A>8dp$M~y-UcM|UvJ3Mhh`_~Z7TLEP-k$e;*M%v`@95b{Xz&3P8#-bN9a=vnfA KM*~1)u@| literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/37.png b/http/czt/img/levels/37.png new file mode 100644 index 0000000000000000000000000000000000000000..d216a83b30ae2336538aae6d9f9d15e78b3031c0 GIT binary patch literal 1166 zcmah|&ubG=5dJpghe=Zt+x%z}X{kkOTj^z~C{;ANp$%dwMG$)s?b(B%e}Om8^`dwv zUWz#gUX|jd&_mgSg_7z)q>-knQKLyJHi_$gFTQnGi%xhu^S(FV%zHDFd(%@Boq=Qk zKxcMRn=y5m>wwq%_En7=rt;2RoX}wKx3IK0ZzBF%lUHv89o<|C9zNL zH`y^9dQjK<0e32^r7xd6q=em{8;a?&uc)eO*bj7FSBO!c9*RYl^E+jpI|4`t>Y(}_ ziM|lRLBEKz`q&L(HT^JrwZa*f3mXjLl3654YKd2B--J1KttlZ$G65?9H_SLYAEfzD zk=Lh_BLIQbmqk>Hdt&Je2FB6}EZyHletlbD^s$RuZde>ZHIB|y1$0X51+@0*g_~?= z04v2!=`Qs6Q0$nah(uX~X7Vk<33eP^b|U{Di*Q%#`-@{Pnv( E0pU*MZ2$lO literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/38.png b/http/czt/img/levels/38.png new file mode 100644 index 0000000000000000000000000000000000000000..600785d23d29ead31a5ccdbb9d824e89826200b6 GIT binary patch literal 1166 zcmZ`%ze_@K5I=p--zk=hs1W584X)8vC~A>J6yXvT6of;OE^g5hK|xScG?YVajcxrA zZY@Dj4GtpcV4!H<&*{CMRwvK9cXyx9ecpY)r^}h7*Bx>bkvE-+uPE=w)@kVz` zIs5ivGEQCmZl516RmOFY%I1kY0X!DEz6q+NqmW)oINt0b&$MgrJiA7uhtu)7)tOO? zU$3=P$DkESG4>5{H5~1lb5i@$n*kEncP0i%{v{g*U^2kXs|b5hB3=|&B!CA=AspqD zZJ|T9Sc{w+AM{mZ3O zQD;u28){wsU6^=@KLH7mCSaBi5KMWzW1*-+Ee1oqhDBf@?UxJg)q)*fTC)`3#pzRd zV;AkRk4a>q!0`y2t$BHvGQ0=8!=xrh$;T)va6Bl$!=MJTF&S~EqVXeO+ym}JfQumo zCSi)+5h4@?(gO_g#u9~O@Kk<)OwzxJvOwheYev|!;d>!@nGCR8W7K{TAPExqVS`H4 YL_X^Kch$r7Qt=*fI+2M#&Tk%n1Kl0w85Isrr<%^Lt5-CYRLTid-VI?%W5~^v_AQnGC>BcHuxD$Mvh;F111a}q1 z@8UvnQBi~nQa9pC2y zdBDNAQcO6v`kg)|JJ#db=ViPIyRd8F7lyln(6RjMdCX13(42MRQn>^caq8qqyoNmk zKh@(tXgc|8-OPqcz z;B1elu{9$+TKs}*(s?zRgejeS#itPO^>M5k8h5+Z7>Y$%{ut`TKZ>J3w#{Ol5(~>I zO3{$md*)kAx@$OE{jGMOQZ;?jB5nE{W#&}a%7}m7V<=0EV=%4~MLG3_mQ}~r=wqgg>mZ6C=R`*-mQq<7CYfaPfe8_1ME#J22#g9u ztSCwUNT6V`3c;F&S~N?FwERGD&dhRBp>%uCvEA}NUpoag{^)dI*WLmcg1%wwdoY?B z?qKxAWAyg+YJ{v}0p#Uu*~9@gnv)YT>TN;SM+akhaUNEft)K@gY~ip#_ZL4=(7A77 z4psXuK_91Qq$(_uXy6ZHfwAXLu(7U#iG*|}JKS30hvPGId{%D()D!jZJg^y-a2XTz z)jW?}s|EdzNsJGTGZM+!RHNpy&lRW#GvI7NXi_v^zIDmCbz=~OZEX*bk$>>t0>0?I z_NTDdr19~!wgJ}4tB782VI1LoRpL-mvZOi#K&NJa!xn&g+G%z%jR2NrV@Rn%B} z9YsJl z8?trTg*=b5{p~76GBmwb8BbFOtP`W#ntBMf!Q@RKiDiFT^pMcoHNI5Dh9w*Bv t<+puyzGHI4^c1KCvi}PBXzH)j7gJ-&vDq`XE7vZgm_0q))@&_0{}Zf}6QKYA literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/41.png b/http/czt/img/levels/41.png new file mode 100644 index 0000000000000000000000000000000000000000..00880953e0b74f0a09e4216abebdc1d395e5a77a GIT binary patch literal 1166 zcmbtTze~bV5Wla8nj#o2pC{gvp-oyF5}VVC zoZ3QYZm6jsd!NJi?Y*x}b@JZb=k9aI-Mz0n`CQ8D_PdG5n@J}MLi=!B4slPs^@~C| zO4(F``uNqZFDk+_vXNfgB=U^m7_@&lE}YJ-%zV=M?C^U+uJprQlE@y&Bw`CQqlVA^ z`Y9Oy6T_Mw4u|_zpNc!3j+UbVBntxbo6V-0NAY-^vEYze#HO(Zz?uyAZ@!^ibRdWr zfe&mewvIT|fo%1>R-?;CgAZ(oj4>Eob``(|IS>qT;$F4N;q`KvM|kP=Xt#m~|B;~% zZdxr)&KC;Q{}SJbIIz(TVp8V9fl1irD`2*%P>2qWPpE!&s*ypQjYer{d4<+WMY`{H z&6m&$v~Sy-j1kZ-G(_6aC=!{Dm<5=C3mu4ddHc}VKD25J8e{b(v?Zc-h+#8$b_U{# zMPuv(mK+(=3Sdd{6(m7w(GicLE)p?w2LNbI{gg2?1iO&mfZ%BJYXv}7=L5Ei`aiJ7 X{)Dq1S5NQtqemoXlDR}9zPkMl0_NIb literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/42.png b/http/czt/img/levels/42.png new file mode 100644 index 0000000000000000000000000000000000000000..3a48399ea110b51be9a97e8f978edb9ac8f172e3 GIT binary patch literal 1166 zcmZ`&O=uHA6#in*k-`-UTC&k~eee1;NhXKId8q@bBwDqng_qRVTM)~hhRn>BC8iuio@3sjCoFtX0f|JTQ6W+&6ga6c z`3O^=f8c303q_%yC=VfE!{OE{F0%9X3y{dwDKD^&*Dt?C_4byPS; z$-TQeFqWIgV{@$#5$8aic?jr<6#?c~FH|r(t0MCRc<^Rv>!Ufl!eO3tIYcFFW3YCP z6Z82zB9Vyj$%!``m?){d3aJP5ZB)tmV1=K3p0&KtU5LlyJhGE1kSbW_iu+*4PU~zS X;rE}vKit3RvPOQavqvA_f9%R%0e1LI literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/43.png b/http/czt/img/levels/43.png new file mode 100644 index 0000000000000000000000000000000000000000..a68a199f4e9c15b11ebbe70451f6aad1aca9b67a GIT binary patch literal 1166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNn-sS`_v80}YZ(|=q&;06Lo5Ut1z6tyW&|q13XF}7 z|D#KsJ$n{IJ%#{C6G*eItu2G3q$Gocgam`Owl>4nt5+E&O`61jZU_^)Eu`{U@M%~z zy^Z1CMGAtMvOcWTdT)6@l2Qg5>03-mi`P9Ri3}%TtKwJip<|XaU3W;k~27+4%eU>E?BFuS{p;qyi}ux60WR#sLF6PE7=>xqw#hv@~=SPcNlWVW4R z$XnG3cFBZWz{|~r7pxf;eK0|=0iZMhiUH(!mSlRz0K&#H91I^md|r=1wntfXh OQse3B=d#Wzp$PzUGPei- literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/5.png b/http/czt/img/levels/5.png new file mode 100644 index 0000000000000000000000000000000000000000..1887163850a68d710d12ce76776ad59ec54d13da GIT binary patch literal 504 zcmV}!SIU-9GqXqM&+!fPu)BYY-&m&G<>WqBU^=>olu|PTG})nc_ACHPtZi&DJ>q8j zaq5lAH}cL5+fH%>YEN<$`Qd`>d@ zRE>fWinbpBEa|_=dz_MkjL@f;f0000NP|fn=pe}tgo4Hz8ib&tph=>*C2k2KXb>TaAf!nY z0@oUZ)}TdDh~Cm7I7NenBpB6F#%qXsoO)M{{owKA_vicJ3-3MPUj-3yE8CBK_M`ay z>W~u=FJ@%ktcLmLLzWjaGAAN_Q!u#`M79@G+h?dAEdv15&=y*ECs$!<$EBWPu70D#%iXDlUxIKOV-^6?u!eY${3sssRFj7b7u zMPhG`E4n7?cD)Hj*AR#Wp<)=7R7nV}keqJAGp|C?HMHwZOe{{~>9&DZw$>+h1Xz&W zAtvhm7jhK4I#A6>-=doX*GIKF4sOqGyRzFLJlLK83?L$IdRbS`^s?XoLNBEEW4Y~q Y0iTzWB25W{iU0rr07*qoM6N<$f(!t^ZvX%Q literal 0 HcmV?d00001 diff --git a/http/czt/img/levels/7.png b/http/czt/img/levels/7.png new file mode 100644 index 0000000000000000000000000000000000000000..85df85b81878bd5fa285d382c4e5def89fa2fd03 GIT binary patch literal 613 zcmV-r0-F7aP)aU9X`wbEOXg~$Ak-RNni6$Y?v zoA~4?GsmOwaFpol?*ZIsZ1U-2jY#Xw(GGmyr#iR6v%NOexea{Z?>ThwQl{@YTE?IZ zB4=iTo4@`%-2rC87pty{49?(V}hBn|ya%T#X0{p3T6=IrE(}%*gS*eXIu|t|K^( z5Qd5kl~lr|8CU>BAm$jXD%L8YDn!+y>x_$F_+aYPh*Z?42TFKU=psu zT1AOID(o9#_1iiJj_o90%u?7l#GzxC$?w_-K+H8HVh$S;4#~KKX|^nFtF+q6rr?u| zoPP{J<3rSN`sH(;-ag38+i&EHS?VUM0D)D4c8J?*E5-mJtaN!gIzAEw_M*}NF5Z8| zlY4c*2OLzDwpFYuZaii%0?YA!9UUKGyEi~jZyJE5dV^WNN;I%mPus-09;l08q4X>=?nlX3xW2y(KJMO8b?@jvLX^U}50v<_3 zK~y-)g_GTC6Hyd}*FK49nxCdLO$sspAZ-$Jtpwv!Tf+(^95PdFH*Blf4O%YXdaqo=qhsR9I#`n_i%H;)_ zn9B$Nz)o4Bppd4NYAMGA%#7vvD2$$M>K$8*o1S<<>1hRp0R{kK} z-F;@4WC$TZbFn~Z$|pj5+R=l#i|8c+F$@rUv8>WvTIAN zr$-bisxdR)S)56R!_&~)J!rc%gnTZ%`Ffx!rL&8~L_~q$B*=XZ69IufGum>}|vTafDWxddzPK)3rnOm|+hGg5>Owvv3u1hwh`(`IIC&}qfX3{e! zyV(^>t3umH1+gH4)+a#(t@z@DK3VI7&?m(QL47NVmwi!c(f`aO)5&hsLP1=z*_}E6 z|9#(oIsZ8q7v_)bnRsX-kx1;R&KfoNdq4l(c`tnL+xXK=Bz7Gq^(D46_mpONos?;N z4V>zCy0D%|6b|*frnQV2YTy=ei^5MIeJmhi7ljj7i9y~o-f^%p#!@R~t4QHBgcvBf+ZsJd-iqSz)79Pfx0 zNO5q}v~UWFw#m>i83tqchCWv$SxQPWd;+U@iL|QAu;Tz%&vcGpmzT9mfVoA@5EEk4 z=AhqglbIYf2B+2)SyNR_PCp^Znj{72LBX`AAy(p=j^SB7p0lb^6ksJ~6I)YCnM$Ri zmU40>Ym{Xxl983NIlYok>oJ(Sbg#NTGhGW0*$J?#dRdy%)vTVa|JH(6;b2+Br^Bc4(IG(+5DGS&28ju}*Ed(N9cmpekuhbsqb2|~A^2(=!^VjE zSgFgBrsTAY9BaJD*lL?@i}$_A=QQtIA&hJ=An#6iM$TtdNm7lOuzU49%yqRa>9Ueh zXDY^M=v#!tj*(?e$^ZAl|F!W)%DGAS*sXpC883+Z2pV=yLEPF~1>4dXfk_tYG~HpN zoyN~C&4IGQ6iM1J^m+~xrbpWyH7Ul3Sa9t5n1#d+8K4F-hOh;3gp(`qdyP{t1Y;Uz z%+{!eX%0OKJKPA<(a0QK51)oe0d1U!6Wg~>>lpb^Y1Faf6HspxAHj#U2Z1-K*FiAG zV+X_SwD>$PDKt*vkS~z9SrV6N@w3FEF^R*PMiQrW2lq|a#uObRKAe>+r8LGvCmFeNJ{0|$Sc z#35-QF(!!*##(TMYsY=Fh3lAh{Qr;Gzf%{67`qjM|H6*%ZXNz( z-_ffNyj9(M;pVyDiuD89nfqRO^=j+k_a=XM{Lxc4UvtE>2X9 0: + style, null_element = config.items('style')[0] + path = os.path.abspath(os.path.join(HTTP_FOLDER, style)) + if os.path.exists(path): + gui_settings['style'] = style + else: + gui_settings['style'] = fallback_style + else: + gui_settings['style'] = fallback_style + loaded_modules['config']['http_folder'] = os.path.join(HTTP_FOLDER, gui_settings['style']) logger.info("Loading Messaging Handler") logger.info("Loading Queue for message handling") @@ -105,7 +124,7 @@ def init(): queue = Queue.Queue() # Loading module for message processing... msg = messaging.Message(queue) - loaded_modules.update(msg.load_modules(main_config)) + loaded_modules.update(msg.load_modules(main_config, loaded_modules['config'])) msg.start() logger.info("Loading Chats") @@ -142,7 +161,7 @@ def init(): tmp = imp.load_source(module, module_location) chat_init = getattr(tmp, module) - class_module = chat_init(queue, python_folder) + class_module = chat_init(queue, PYTHON_FOLDER) loaded_modules[module] = class_module.conf_params loaded_modules[module]['class'] = class_module else: diff --git a/messaging.py b/messaging.py index 72e12ee..e89dd4f 100644 --- a/messaging.py +++ b/messaging.py @@ -1,13 +1,13 @@ # This Python file uses the following encoding: utf-8 # -*- coding: utf-8 -*- import os -import ConfigParser import threading import imp import operator import logging from modules.helpers.system import ModuleLoadException +from modules.helpers.parser import self_heal log = logging.getLogger('messaging') MODULE_PRI_DEFAULT = '100' @@ -23,18 +23,27 @@ def __init__(self, queue): self.queue = queue self.module_tag = "modules.messaging" - def load_modules(self, config_dict): + def load_modules(self, config_dict, settings): log.info("Loading configuration file for messaging") modules_list = {} conf_file = os.path.join(config_dict['conf_folder'], "messaging.cfg") - config = ConfigParser.RawConfigParser(allow_no_value=True) - + conf_dict = [ + {'gui_information': { + 'category': 'main'}}, + {'messaging__gui': {'check': 'modules/messaging', + 'check_type': 'files', + 'file_extension': False, + 'for': 'messaging', + 'view': 'choose_multiple'}}, + {'messaging': { + 'webchat': None}} + ] + config = self_heal(conf_file, conf_dict) modules_list['messaging_modules'] = {'folder': config_dict['conf_folder'], 'file': conf_file, 'filename': ''.join(os.path.basename(conf_file).split('.')[:-1]), 'parser': config} - config.read(conf_file) modules = {} # Loading modules from cfg. if config.items("messaging") > 0: @@ -49,7 +58,8 @@ def load_modules(self, config_dict): try: tmp = imp.load_source(module, file_path) class_init = getattr(tmp, module) - class_module = class_init(config_dict['conf_folder'], root_folder=config_dict['root_folder']) + class_module = class_init(config_dict['conf_folder'], root_folder=config_dict['root_folder'], + main_settings=settings) if 'id' in class_module.conf_params: priority = class_module.conf_params['id'] diff --git a/modules/chats/goodgame.py b/modules/chats/goodgame.py index 87110f4..5612338 100644 --- a/modules/chats/goodgame.py +++ b/modules/chats/goodgame.py @@ -12,11 +12,22 @@ log = logging.getLogger('goodgame') SOURCE = 'gg' SOURCE_ICON = 'http://goodgame.ru/images/icons/favicon.png' +CONF_DICT = [ + {'gui_information': { + 'category': 'chat'}}, + {'config__gui': { + 'for': 'config', + 'hidden': 'socket'}}, + {'config': { + 'channel_name': 'CHANGE_ME', + 'socket': 'ws://chat.goodgame.ru:8081/chat/websocket'}} + ] class GoodgameMessageHandler(threading.Thread): - def __init__(self, queue, gg_queue, **kwargs): + def __init__(self, ws_class, queue, gg_queue, **kwargs): super(self.__class__, self).__init__() + self.ws_class = ws_class # type: GGChat self.daemon = True self.message_queue = queue self.gg_queue = gg_queue @@ -77,16 +88,21 @@ def process_message(self, msg): if re.match('^{0},'.format(self.nick).lower(), comp['text'].lower()): comp['pm'] = True self.message_queue.put(comp) + elif msg['type'] == 'error': + log.info("Received error message: {0}".format(msg)) + if msg['data']['errorMsg'] == 'Invalid channel id': + self.ws_class.close(reason='INV_CH_ID') + log.error("Failed to find channel on GoodGame, please check channel name") -class ggChat(WebSocketClient): +class GGChat(WebSocketClient): def __init__(self, ws, protocols=None, queue=None, ch_id=None, nick=None, **kwargs): super(self.__class__, self).__init__(ws, protocols=protocols) # Received value setting. self.ch_id = ch_id self.gg_queue = Queue.Queue() - message_handler = GoodgameMessageHandler(queue, self.gg_queue, nick=nick, **kwargs) + message_handler = GoodgameMessageHandler(self, queue, self.gg_queue, nick=nick, **kwargs) message_handler.start() def opened(self): @@ -99,7 +115,10 @@ def opened(self): def closed(self, code, reason=None): log.info("Connection Closed Down") - self.connect() + if 'INV_CH_ID' in reason: + pass + else: + self.connect() def received_message(self, mes): # Deserialize message to json for easier parsing @@ -107,7 +126,7 @@ def received_message(self, mes): self.gg_queue.put(message) -class ggThread(threading.Thread): +class GGThread(threading.Thread): def __init__(self, queue, address, nick): threading.Thread.__init__(self) # Basic value setting. @@ -121,7 +140,6 @@ def __init__(self, queue, address, nick): self.kwargs = {} def load_config(self): - error = False try: self.kwargs['smiles'] = {} smile_request = requests.get("http://api2.goodgame.ru/smiles") @@ -155,12 +173,12 @@ def load_config(self): except Exception as exc: log.warning("Unable to get channel name, error {0}\nArgs: {1}".format(exc.message, exc.args)) - return error + return True def run(self): - if not self.load_config(): + if self.load_config(): # Connecting to goodgame websocket - ws = ggChat(self.address, protocols=['websocket'], queue=self.queue, ch_id=self.ch_id, nick=self.nick, + ws = GGChat(self.address, protocols=['websocket'], queue=self.queue, ch_id=self.ch_id, nick=self.nick, **self.kwargs) ws.connect() ws.run_forever() @@ -173,17 +191,7 @@ def __init__(self, queue, python_folder, **kwargs): log.info("Initializing goodgame chat") conf_file = os.path.join(conf_folder, "goodgame.cfg") - conf_dict = [ - {'gui_information': { - 'category': 'chat'}}, - {'config__gui': { - 'for': 'config', - 'hidden': 'socket'}}, - {'config': { - 'channel_name': 'CzT', - 'socket': 'ws://chat.goodgame.ru:8081/chat/websocket'}} - ] - config = self_heal(conf_file, conf_dict) + config = self_heal(conf_file, CONF_DICT) self.conf_params = {'folder': conf_folder, 'file': conf_file, 'filename': ''.join(os.path.basename(conf_file).split('.')[:-1]), 'parser': config} @@ -195,5 +203,5 @@ def __init__(self, queue, python_folder, **kwargs): # ch_id # Creating new thread with queue in place for messaging transfers - gg = ggThread(queue, address, channel_name) + gg = GGThread(queue, address, channel_name) gg.start() diff --git a/modules/chats/sc2tv.py b/modules/chats/sc2tv.py index 155c709..634cd15 100644 --- a/modules/chats/sc2tv.py +++ b/modules/chats/sc2tv.py @@ -12,17 +12,27 @@ log = logging.getLogger('sc2tv') SOURCE = 'fs' SOURCE_ICON = 'http://funstream.tv/build/images/icon_home.png' +CONF_DICT = [ + {'gui_information': { + 'category': 'chat'}}, + {'config__gui': { + 'for': 'config', + 'hidden': 'socket'}}, + {'config': { + 'channel_name': 'CHANGE_ME', + 'socket': 'ws://funstream.tv/socket.io/'}} + ] -class fsChat(WebSocketClient): - def __init__(self, ws, queue, nick, protocols=None, smiles=None): - super(self.__class__, self).__init__(ws, protocols=None) +class FsChat(WebSocketClient): + def __init__(self, ws, queue, channel_name, protocols=None, smiles=None): + super(self.__class__, self).__init__(ws, protocols=protocols) # Received value setting. self.source = SOURCE self.queue = queue - self.nick = nick + self.channel_name = channel_name - self.channel_id = self.fsGetId() + self.channel_id = self.fs_get_id() self.smiles = smiles self.smile_regex = ':(\w+|\d+):' @@ -30,7 +40,7 @@ def __init__(self, ws, queue, nick, protocols=None, smiles=None): # Because funstream API is fun, we have to iterate the # requests in "proper" format: # - # 42Iterator["command",{"params":"param"}] + # 42Iterator["command",{"params":"param"}] # ex: 420["/chat/join",{'channel':"stream/30000"} # ex: 421["/chat/join",{'channel':"stream/30000"} # ex: 429["/chat/join",{'channel':"stream/30000"} @@ -51,7 +61,8 @@ def opened(self): def closed(self, code, reason=None): log.info("Websocket Connection Closed Down") - def allow_smile(self, smile, subscriptions): + @staticmethod + def allow_smile(smile, subscriptions): allow = False if smile['user']: @@ -88,12 +99,12 @@ def received_message(self, mes): # "Funstream" has some interesting infrastructure, so # we first need to find the channel ID from # nickname of streamer we need to connect to. - self.fsJoin() - self.fsPing() + self.fs_join() + self.fs_ping() elif dict_item == 'id': try: self.duplicates.index(message[dict_item]) - except: + except IndexError: comp = {'source': self.source, 'source_icon': SOURCE_ICON, 'user': message['from']['name'], @@ -101,7 +112,7 @@ def received_message(self, mes): 'emotes': []} if message['to'] is not None: comp['to'] = message['to']['name'] - if comp['to'] == self.nick: + if comp['to'] == self.channel_name: comp['pm'] = True else: comp['to'] = None @@ -118,10 +129,10 @@ def received_message(self, mes): if len(self.duplicates) > self.bufferForDup: self.duplicates.pop(0) - def fsGetId(self): + def fs_get_id(self): # We get ID from POST request to funstream API, and it hopefuly # answers us the correct ID of the channel we need to connect to - payload = "{'id': null, 'name': \"" + self.nick + "\"}" + payload = "{'id': null, 'name': \"" + self.channel_name + "\"}" request = requests.post("http://funstream.tv/api/user", data=payload) if request.status_code == 200: channel_id = json.loads(re.findall('{.*}', request.text)[0])['id'] @@ -134,19 +145,20 @@ def fsGetId(self): channel_id = None return channel_id - def fsJoin(self): + def fs_join(self): # Because we need to iterate each message we iterate it! - iter = "42"+str(self.iter) + iter_sio = "42"+str(self.iter) self.iter += 1 # Then we send the message acording to needed format and # hope it joins us if self.channel_id: - join = str(iter) + "[\"/chat/join\", " + json.dumps({'channel': "stream/" + str(self.channel_id)}, sort_keys=False) + "]" + join = str(iter_sio) + "[\"/chat/join\", " + json.dumps({'channel': "stream/" + str(self.channel_id)}, + sort_keys=False) + "]" self.send(join) log.info("Joined channel {0}".format(self.channel_id)) - def fsPing(self): + def fs_ping(self): # Because funstream is not your normal websocket they # have own "ping/pong" algorithm, and WE have to send ping. # Yes, I don't know why. @@ -154,11 +166,11 @@ def fsPing(self): # disconnect us. So we have to create separate thread for it. # Dont understand why server is not sending his own pings, it # would be sooooo easier. - pingThr = pingThread(self) - pingThr.start() + ping_thread = FsPingThread(self) + ping_thread.start() -class pingThread(threading.Thread): +class FsPingThread(threading.Thread): def __init__(self, ws): threading.Thread.__init__(self) self.daemon = "True" @@ -181,8 +193,8 @@ def run(self): time.sleep(30) -class fsThread(threading.Thread): - def __init__(self, queue, socket, nick): +class FsThread(threading.Thread): + def __init__(self, queue, socket, channel_name): threading.Thread.__init__(self) # Basic value setting. # Daemon is needed so when main programm exits @@ -190,7 +202,7 @@ def __init__(self, queue, socket, nick): self.daemon = "True" self.queue = queue self.socket = socket - self.nick = nick + self.channel_name = channel_name self.smiles = [] def run(self): @@ -201,11 +213,11 @@ def run(self): smiles_answer = smiles.json() for smile in smiles_answer: self.smiles.append(smile) - except: + except requests.ConnectionError: log.error("Unable to get smiles") # Connecting to funstream websocket - ws = fsChat(self.socket, self.queue, self.nick, protocols=['websocket'], smiles=self.smiles,) + ws = FsChat(self.socket, self.queue, self.channel_name, protocols=['websocket'], smiles=self.smiles) ws.connect() ws.run_forever() @@ -217,29 +229,19 @@ def __init__(self, queue, python_folder, **kwargs): # Reading config from main directory. conf_folder = os.path.join(python_folder, "conf") conf_file = os.path.join(conf_folder, "sc2tv.cfg") - conf_dict = [ - {'gui_information': { - 'category': 'chat'}}, - {'config__gui': { - 'for': 'config', - 'hidden': 'socket'}}, - {'config': { - 'nick': 'CzT', - 'socket': 'ws://funstream.tv/socket.io/'}} - ] - config = self_heal(conf_file, conf_dict) + config = self_heal(conf_file, CONF_DICT) self.conf_params = {'folder': conf_folder, 'file': conf_file, 'filename': ''.join(os.path.basename(conf_file).split('.')[:-1]), 'parser': config} # Checking config file for needed variables config_tag = 'config' socket = config.get(config_tag, 'socket') - nick = config.get(config_tag, 'nick') + channel_name = config.get(config_tag, 'channel_name') # If any of the value are non-existent then exit the programm with error. - if (socket is None) or (nick is None): + if (socket is None) or (channel_name is None): log.critical("Config for funstream is not correct!") # Creating new thread with queue in place for messaging tranfers - fs = fsThread(queue, socket, nick) + fs = FsThread(queue, socket, channel_name) fs.start() diff --git a/modules/chats/twitch.py b/modules/chats/twitch.py index 2d8085f..68e9414 100644 --- a/modules/chats/twitch.py +++ b/modules/chats/twitch.py @@ -19,6 +19,18 @@ NOT_FOUND = 'none' SOURCE = 'tw' SOURCE_ICON = 'https://www.twitch.tv/favicon.ico' +CONF_DICT = [ + {'gui_information': { + 'category': 'chat'}}, + {'config__gui': { + 'for': 'config', + 'hidden': 'host, port'}}, + {'config': { + 'bttv': 'true', + 'channel': 'CHANGE_ME', + 'host': 'irc.twitch.tv', + 'port': '6667'}} + ] class TwitchMessageHandler(threading.Thread): @@ -170,15 +182,23 @@ def __init__(self, queue, host, port, channel, bttv_smiles, anon=True): self.nickname += str(random.randint(0, 9)) def run(self): - self.load_config() - - # We are connecting via IRC handler. - irc_client = IRC(self.queue, self.channel, **self.kwargs) - irc_client.connect(self.host, self.port, self.nickname) - irc_client.start() + if self.load_config(): + # We are connecting via IRC handler. + irc_client = IRC(self.queue, self.channel, **self.kwargs) + irc_client.connect(self.host, self.port, self.nickname) + irc_client.start() def load_config(self): - error = False + try: + request = requests.get("https://api.twitch.tv/kraken/channels/{0}".format(self.channel), headers=headers) + if request.status_code == 200: + log.info("Channel found, continuing") + else: + raise Exception("Not successful status code: {0}".format(request.status_code)) + except Exception as exc: + log.error("Unable to get channel ID, error: {0}\nArgs: {1}".format(exc.message, exc.args)) + return False + try: # Getting random IRC server to connect to request = requests.get("http://tmi.twitch.tv/servers?channel={0}".format(self.channel)) @@ -188,7 +208,7 @@ def load_config(self): raise Exception("Not successful status code: {0}".format(request.status_code)) except Exception as exc: log.error("Unable to get server list, error: {0}\nArgs: {1}".format(exc.message, exc.args)) - error = True + return False try: # Getting Better Twitch TV smiles @@ -224,7 +244,7 @@ def load_config(self): log.warning("Unable to get twitch undocumented api badges, error {0}\n" "Args: {1}".format(exc.message, exc.args)) - return error + return True class twitch: @@ -234,19 +254,8 @@ def __init__(self, queue, python_folder, **kwargs): # Reading config from main directory. conf_folder = os.path.join(python_folder, "conf") conf_file = os.path.join(conf_folder, "twitch.cfg") - conf_dict = [ - {'gui_information': { - 'category': 'chat'}}, - {'config__gui': { - 'for': 'config', - 'hidden': 'host, port'}}, - {'config': { - 'bttv': 'true', - 'channel': 'CzT1', - 'host': 'irc.twitch.tv', - 'port': '6667'}} - ] - config = self_heal(conf_file, conf_dict) + + config = self_heal(conf_file, CONF_DICT) self.conf_params = {'folder': conf_folder, 'file': conf_file, 'filename': ''.join(os.path.basename(conf_file).split('.')[:-1]), 'parser': config} diff --git a/modules/messaging/levels.py b/modules/messaging/levels.py index 37ae272..0b14e17 100644 --- a/modules/messaging/levels.py +++ b/modules/messaging/levels.py @@ -11,13 +11,6 @@ from modules.helpers.system import system_message, ModuleLoadException logger = logging.getLogger('levels') -TEMPLATE = """ - -{% for name, url in levels -%} - -{% endfor -%} - -""" class levels: @@ -34,24 +27,18 @@ def create_db(db_location): def __init__(self, conf_folder, **kwargs): # Creating filter and replace strings. + main_settings = kwargs.get('main_settings') + conf_file = os.path.join(conf_folder, "levels.cfg") conf_dict = [ {'gui_information': { 'category': u'messaging'}}, {'config': { 'message': u'{0} has leveled up, now he is {1}', - 'file': u'conf/levels.xml', 'db': u'levels.db', 'experience': u'geometrical', 'exp_for_level': 200}} ] - levels_dict = [ - ("Ghost", "img/levels/default/0.png"), - ("Baby", "img/levels/default/1.png"), - ("Child", "img/levels/default/2.png"), - ("Mystical Person", "img/levels/default/3.png"), - ("King", "img/levels/default/4.png"), - ] config = self_heal(conf_file, conf_dict) self.conf_params = {'folder': conf_folder, 'file': conf_file, @@ -63,7 +50,7 @@ def __init__(self, conf_folder, **kwargs): self.experience = config.get(tag_config, 'experience') self.exp_for_level = int(config.get(tag_config, 'exp_for_level')) self.exp_for_message = 1 - self.filename = os.path.abspath(config.get(tag_config, 'file')) + self.filename = os.path.abspath(os.path.join(main_settings['http_folder'], 'levels.xml')) self.levels = [] self.special_levels = {} self.db_location = os.path.join(conf_folder, config.get(tag_config, 'db')) @@ -72,10 +59,7 @@ def __init__(self, conf_folder, **kwargs): # Load levels if not os.path.exists(self.filename): logger.error("{0} not found, generating from template".format(self.filename)) - if not os.path.exists(os.path.dirname(self.filename)): - os.makedirs(os.path.dirname(self.filename)) - with open(self.filename, 'w') as levels_file: - levels_file.write(jinja2.Template(TEMPLATE).render(levels=levels_dict)) + raise ModuleLoadException("{0} not found, generating from template".format(self.filename)) if self.experience == 'random': self.db_location += '.random' diff --git a/modules/messaging/webchat.py b/modules/messaging/webchat.py index c15a698..bedb6ef 100644 --- a/modules/messaging/webchat.py +++ b/modules/messaging/webchat.py @@ -128,7 +128,7 @@ def __init__(self, host, port, root_folder, **kwargs): cherrypy.tools.websocket = WebSocketTool() def run(self): - http_folder = os.path.join(self.root_folder, '..', 'http', self.style) + http_folder = self.style cherrypy.log.access_file = '' cherrypy.log.error_file = '' cherrypy.log.screen = False @@ -150,22 +150,15 @@ def run(self): class webchat(): def __init__(self, conf_folder, **kwargs): + main_settings = kwargs.get('main_settings') conf_file = os.path.join(conf_folder, "webchat.cfg") conf_dict = [ {'gui_information': { 'category': 'main', 'id': DEFAULT_PRIORITY}}, - {'style__gui': { - 'check': 'http', - 'check_type': 'dir', - 'for': 'style', - 'view': 'choose_single'}}, - {'style': 'czt'}, {'server': { 'host': '127.0.0.1', 'port': '8080'}}] - root_folder = kwargs.get('root_folder') - http_folder = 'http' config = self_heal(conf_file, conf_dict) self.conf_params = {'folder': conf_folder, 'file': conf_file, @@ -176,16 +169,7 @@ def __init__(self, conf_folder, **kwargs): tag_server = 'server' host = config.get(tag_server, 'host') port = config.get(tag_server, 'port') - - # Fallback if style folder not found - fallback_style = 'czt' - if len(config.items('style')) > 0: - style, null_element = config.items('style')[0] - path = os.path.abspath(os.path.join(root_folder, http_folder, style)) - if not os.path.exists(path): - style = fallback_style - else: - style = fallback_style + style = main_settings['http_folder'] self.conf_params['port'] = port diff --git a/translations/en/goodgame.key b/translations/en/goodgame.key index 2890e94..45bd609 100644 --- a/translations/en/goodgame.key +++ b/translations/en/goodgame.key @@ -1,4 +1,4 @@ goodgame = GoodGame -goodgame.main = Main Settings -goodgame.main.socket = WebSocket parameters -goodgame.main.channelname = Channel name \ No newline at end of file +goodgame.config = Main Settings +goodgame.config.socket = WebSocket parameters +goodgame.config.channel_name = Channel name \ No newline at end of file diff --git a/translations/en/main.key b/translations/en/main.key index 8c39901..a5172ab 100644 --- a/translations/en/main.key +++ b/translations/en/main.key @@ -20,6 +20,9 @@ config.gui.reload.button = Reload config.language = Program Language config.language.list_box = +config.style = +config.style.list_box = Available styles + messaging_modules = Message modules messaging_modules.messaging = messaging_modules.messaging.list_box = List of available modules diff --git a/translations/en/sc2tv.key b/translations/en/sc2tv.key index 1db3268..8f7cba9 100644 --- a/translations/en/sc2tv.key +++ b/translations/en/sc2tv.key @@ -1,4 +1,4 @@ sc2tv = sc2tv -sc2tv.main = Main settings -sc2tv.main.socket = WebSocket parameters -sc2tv.main.nick = Channel name \ No newline at end of file +sc2tv.config = Main settings +sc2tv.config.socket = WebSocket parameters +sc2tv.config.channel_name = Channel name \ No newline at end of file diff --git a/translations/en/twitch.key b/translations/en/twitch.key index 64816f4..90d0d58 100644 --- a/translations/en/twitch.key +++ b/translations/en/twitch.key @@ -1,5 +1,5 @@ twitch = Twitch.TV -twitch.main.host = IRC hostname -twitch.main.port = IRC port -twitch.main.channel = Channel name -twitch.main.bttv = Show BTTV smiles \ No newline at end of file +twitch.config.host = IRC hostname +twitch.config.port = IRC port +twitch.config.channel = Channel name +twitch.config.bttv = Show BTTV smiles \ No newline at end of file diff --git a/translations/en/webchat.key b/translations/en/webchat.key index b8f4394..2b4a758 100644 --- a/translations/en/webchat.key +++ b/translations/en/webchat.key @@ -1,6 +1,4 @@ webchat = WebChat -webchat.style = -webchat.style.list_box = Available styles webchat.server = Local server settings webchat.server.host = Host diff --git a/translations/ru/goodgame.key b/translations/ru/goodgame.key index 25b32bb..3956511 100644 --- a/translations/ru/goodgame.key +++ b/translations/ru/goodgame.key @@ -1,4 +1,4 @@ goodgame = GoodGame -goodgame.main = Основные параметры GoodGame -goodgame.main.socket = Настройки WebSocket -goodgame.main.channelname = Название канала \ No newline at end of file +goodgame.config = Основные параметры GoodGame +goodgame.config.socket = Настройки WebSocket +goodgame.config.channel_name = Название канала \ No newline at end of file diff --git a/translations/ru/main.key b/translations/ru/main.key index e3cd0d7..0b003dd 100644 --- a/translations/ru/main.key +++ b/translations/ru/main.key @@ -20,6 +20,9 @@ config.gui.reload.button = Перезагрузить config.language = Язык Интерфейса config.language.list_box = +config.style = +config.style.list_box = Доступные Стили + messaging_modules = Модули Сообщений messaging_modules.messaging = messaging_modules.messaging.list_box = Список доступных модулей diff --git a/translations/ru/sc2tv.key b/translations/ru/sc2tv.key index d1286ca..cd0b1e4 100644 --- a/translations/ru/sc2tv.key +++ b/translations/ru/sc2tv.key @@ -1,4 +1,4 @@ sc2tv = sc2tv -sc2tv.main = Основные параметры -sc2tv.main.socket = WS параметры -sc2tv.main.nick = Название канала \ No newline at end of file +sc2tv.config = Основные параметры +sc2tv.config.socket = WS параметры +sc2tv.config.channel_name = Название канала \ No newline at end of file diff --git a/translations/ru/twitch.key b/translations/ru/twitch.key index d2cd1fe..bdfead4 100644 --- a/translations/ru/twitch.key +++ b/translations/ru/twitch.key @@ -1,5 +1,5 @@ twitch = Twitch.TV -twitch.main.host = IRC хостнейм -twitch.main.port = IRC порт -twitch.main.channel = Имя канала -twitch.main.bttv = Показать BTTV смайлы \ No newline at end of file +twitch.config.host = IRC хостнейм +twitch.config.port = IRC порт +twitch.config.channel = Имя канала +twitch.config.bttv = Показать BTTV смайлы \ No newline at end of file diff --git a/translations/ru/webchat.key b/translations/ru/webchat.key index a0b22c9..26c74e4 100644 --- a/translations/ru/webchat.key +++ b/translations/ru/webchat.key @@ -1,6 +1,4 @@ webchat = Веб Чат -webchat.style = -webchat.style.list_box = Доступные Стили webchat.server = Настройки локального сервера webchat.server.host = Хост