patch
This commit is contained in:
parent
58885932fb
commit
92efd55db5
|
@ -0,0 +1,44 @@
|
|||
# MAPLE+G1MP ML/Irc3 Hybrid
|
||||
```
|
||||
[ Hybrid of machine learning and irc3 framework ]
|
||||
- Maple - [sourcecode](https://git.tcp.direct/decoded/Maple)
|
||||
- g1mp - [sourcecode](https://git.tcp.direct/decoded/g1mp)
|
||||
```
|
||||
## Prerequisites
|
||||
|
||||
1. `apt install python3`
|
||||
2. `apt install python3-pip`
|
||||
3. `python3 -m pip install virtualenv`
|
||||
|
||||
## Instructions
|
||||
|
||||
1. `git clone --recursive https://git.tcp.direct/decoded/m4pl1mp.git`
|
||||
2. `cd m4pl1mp`
|
||||
3. `virtualenv env -p python3`
|
||||
4. `source env/bin/activate`
|
||||
### Append your api keys to env/bin/activate. Example below:
|
||||
```
|
||||
cat env/bin/activate
|
||||
..
|
||||
export DEVELOPER_KEY="1394823190182390182382383215382158321" # <- YOUTUBE API KEY
|
||||
export CONSUMER_KEY="2151235132512351235123512351325231" # <- TWITTER API KEY
|
||||
export CONSUMER_SECRET="514512521345234523452345234523452345234523452" # <- TWITTER API KEY
|
||||
export ACCESS_TOKEN_KEY="24513429875209348502934850294898348034850293485203948592" # <- TWITTER API KEY
|
||||
export ACCESS_TOKEN_SECRET="523490582034985203948520394804884820934850923485" # <- TWITTER API KEY
|
||||
```
|
||||
### If you don't have either 'twitter' or 'youtube' api keys set irc3 will crash
|
||||
### on startup, comment out the youtube_plugin and twitter_plugin in maple.ini
|
||||
### until you get some api keys.
|
||||
5. `pip install -r requirements.txt`
|
||||
6. `change the instance of #tcpdirect in plugins/maple_plugin.py to whatever channel she will communicate`
|
||||
### you should lookover maple.ini and make changes, mostly the names/servers/etc and possibly autojoins.
|
||||
### plugins/auth.py is used to identify to nameserver but you can also use sasl through maple.ini. things
|
||||
### should run now simply running the command below.. if you need to background.. screen/tmux or & disown
|
||||
7. `irc3 maple.ini`
|
||||
|
||||
## TODO:
|
||||
1. update maple_plugin.py to use a queue stack
|
||||
2. do callback exception handling
|
||||
|
||||
## DONE:
|
||||
1. revise maple.py to run async inside irc3
|
|
@ -0,0 +1,426 @@
|
|||
¢‿¢
|
||||
©¿© o
|
||||
ª{•̃̾_•̃̾}ª
|
||||
¬_¬
|
||||
¯\(º_o)/¯
|
||||
¯\(º o)/¯
|
||||
¯\_(⊙︿⊙)_/¯
|
||||
¯\_(ツ)_/¯
|
||||
°ω°
|
||||
°Д°
|
||||
°‿‿°
|
||||
°ﺑ°
|
||||
´ ▽ ` )ノ
|
||||
¿ⓧ_ⓧﮌ
|
||||
Ò,ó
|
||||
ó‿ó
|
||||
ô⌐ô
|
||||
ôヮô
|
||||
ŎםŎ
|
||||
ŏﺡó
|
||||
ʕ•̫͡•ʔ
|
||||
ʕ•ᴥ•ʔ
|
||||
ʘ‿ʘ
|
||||
˚•_•˚
|
||||
˚⌇˚
|
||||
˚▱˚
|
||||
̿ ̿̿'̿'\̵͇̿̿\=(•̪●)=/̵͇̿̿/'̿̿ ̿ ̿ ̿
|
||||
͡° ͜ʖ ͡°
|
||||
Σ ◕ ◡ ◕
|
||||
Σ (゚Д゚;)
|
||||
Σ(゚Д゚;≡;゚д゚)
|
||||
Σ(゚Д゚ )
|
||||
Σ(||゚Д゚)
|
||||
Φ,Φ
|
||||
δﺡό
|
||||
σ_σ
|
||||
д_д
|
||||
ф_ф
|
||||
щ(゚Д゚щ)
|
||||
щ(ಠ益ಠщ)
|
||||
щ(ಥДಥщ)
|
||||
Ծ_Ծ
|
||||
أ‿أ
|
||||
ب_ب
|
||||
ح˚௰˚づ
|
||||
ح˚ᆺ˚ว
|
||||
حᇂﮌᇂ)
|
||||
٩๏̯͡๏۶
|
||||
٩๏̯͡๏)۶
|
||||
٩◔̯◔۶
|
||||
٩(×̯×)۶
|
||||
٩(̾●̮̮̃̾•̃̾)۶
|
||||
٩(͡๏̯͡๏)۶
|
||||
٩(͡๏̯ ͡๏)۶
|
||||
٩(ಥ_ಥ)۶
|
||||
٩(•̮̮̃•̃)۶
|
||||
٩(●̮̮̃•̃)۶
|
||||
٩(●̮̮̃●̃)۶
|
||||
٩(。͡•‿•。)۶
|
||||
٩(-̮̮̃•̃)۶
|
||||
٩(-̮̮̃-̃)۶
|
||||
۞_۞
|
||||
۞_۟۞
|
||||
۹ↁﮌↁ
|
||||
۹⌤_⌤۹
|
||||
॓_॔
|
||||
१✌◡✌५
|
||||
१|˚–˚|५
|
||||
ਉ_ਉ
|
||||
ଘ_ଘ
|
||||
இ_இ
|
||||
ఠ_ఠ
|
||||
రృర
|
||||
ಠ¿ಠi
|
||||
ಠ‿ಠ
|
||||
ಠ⌣ಠ
|
||||
ಠ╭╮ಠ
|
||||
ಠ▃ಠ
|
||||
ಠ◡ಠ
|
||||
ಠ益ಠ
|
||||
ಠ益ಠ
|
||||
ಠ︵ಠ凸
|
||||
ಠ , ಥ
|
||||
ಠ.ಠ
|
||||
ಠoಠ
|
||||
ಠ_ృ
|
||||
ಠ_ಠ
|
||||
ಠ_๏
|
||||
ಠ~ಠ
|
||||
ಡ_ಡ
|
||||
ತಎತ
|
||||
ತ_ತ
|
||||
ಥдಥ
|
||||
ಥ‿ಥ
|
||||
ಥ⌣ಥ
|
||||
ಥ◡ಥ
|
||||
ಥ﹏ಥ
|
||||
ಥ_ಥ
|
||||
ಭ_ಭ
|
||||
ರ_ರ
|
||||
ಸ , ໖
|
||||
ಸ_ಸ
|
||||
ക_ക
|
||||
อ้_อ้
|
||||
อ_อ
|
||||
โ๏௰๏ใ ื
|
||||
๏̯͡๏﴿
|
||||
๏̯͡๏
|
||||
๏̯͡๏﴿
|
||||
๏[-ิิ_•ิ]๏
|
||||
๏_๏
|
||||
໖_໖
|
||||
ლ(´ڡ`ლ)
|
||||
ლ(́◉◞౪◟◉‵ლ)
|
||||
ლ(ಠ益ಠლ)
|
||||
ლ(╹◡╹ლ)
|
||||
ლ(◉◞౪◟◉‵ლ)
|
||||
ლ,ᔑ•ﺪ͟͠•ᔐ.ლ
|
||||
ᄽὁȍ ̪ őὀᄿ
|
||||
ᕕ( ᐛ )ᕗ
|
||||
ᕙ(⇀‸↼‶)ᕗ
|
||||
ᕦ(ò_óˇ)ᕤ
|
||||
ᶘ ᵒᴥᵒᶅ
|
||||
‘︿’
|
||||
•▱•
|
||||
•✞_✞•
|
||||
•ﺑ•
|
||||
•(⌚_⌚)•
|
||||
•_•)
|
||||
‷̗ↂ凸ↂ‴̖
|
||||
‹•.•›
|
||||
‹› ‹(•¿•)› ‹›
|
||||
‹(ᵒᴥᵒ)›
|
||||
‹(•¿•)›
|
||||
ↁ_ↁ
|
||||
⇎_⇎
|
||||
∩(︶▽︶)∩
|
||||
∩( ・ω・)∩
|
||||
≖‿≖
|
||||
≧ヮ≦
|
||||
⊂•⊃_⊂•⊃
|
||||
⊂⌒~⊃。Д。)⊃
|
||||
⊂(◉‿◉)つ
|
||||
⊂(゚Д゚,,⊂⌒`つ
|
||||
⊙ω⊙
|
||||
⊙▂⊙
|
||||
⊙▃⊙
|
||||
⊙△⊙
|
||||
⊙︿⊙
|
||||
⊙﹏⊙
|
||||
⊙0⊙
|
||||
⊛ठ̯⊛
|
||||
⋋ō_ō`
|
||||
━━━ヽ(ヽ(゚ヽ(゚ヽ(゚゚ヽ(゚゚)ノ゚゚)ノ゚)ノ゚)ノ)ノ━━━
|
||||
┌∩┐(◕_◕)┌∩┐
|
||||
┌( ಠ_ಠ)┘
|
||||
┌( ಥ_ಥ)┘
|
||||
╚(•⌂•)╝
|
||||
╭╮╭╮☜{•̃̾_•̃̾}☞╭╮╭╮
|
||||
╭✬⌢✬╮
|
||||
╮(▽)╭
|
||||
╯‵Д′)╯彡┻━┻
|
||||
╰☆╮
|
||||
□_□
|
||||
►_◄
|
||||
◃┆◉◡◉┆▷
|
||||
◉△◉
|
||||
◉︵◉
|
||||
◉_◉
|
||||
○_○
|
||||
●¿●\ ~
|
||||
●_●
|
||||
◔̯◔
|
||||
◔ᴗ◔
|
||||
◔ ⌣ ◔
|
||||
◔_◔
|
||||
◕ω◕
|
||||
◕‿◕
|
||||
◕◡◕
|
||||
◕ ◡ ◕
|
||||
◖♪_♪|◗
|
||||
◖|◔◡◉|◗
|
||||
◘_◘
|
||||
◙‿◙
|
||||
◜㍕◝
|
||||
◪_◪
|
||||
◮_◮
|
||||
☁ ☝ˆ~ˆ☂
|
||||
☆¸☆
|
||||
☉‿⊙
|
||||
☉_☉
|
||||
☐_☐
|
||||
☜ق❂Ⴢ❂ق☞
|
||||
☜(⌒▽⌒)☞
|
||||
☜(゚ヮ゚☜)
|
||||
☜-(ΘLΘ)-☞
|
||||
☝☞✌
|
||||
☮▁▂▃▄☾ ♛ ◡ ♛ ☽▄▃▂▁☮
|
||||
☹_☹
|
||||
☻_☻
|
||||
☼.☼
|
||||
☾˙❀‿❀˙☽
|
||||
♀ح♀ヾ
|
||||
♥‿♥
|
||||
♥╣[-_-]╠♥
|
||||
♥╭╮♥
|
||||
♥◡♥
|
||||
✌♫♪˙❤‿❤˙♫♪✌
|
||||
✌.ʕʘ‿ʘʔ.✌
|
||||
✌.|•͡˘‿•͡˘|.✌
|
||||
✖‿✖
|
||||
✖_✖
|
||||
❐‿❑
|
||||
_
|
||||
_Ꙩ
|
||||
⨂_⨂
|
||||
〆(・・@)
|
||||
《〠_〠》
|
||||
【•】_【•】
|
||||
〠_〠
|
||||
〴⋋_⋌〵
|
||||
の<EFBFBD> <20>の
|
||||
ニガー? ━━━━━━(゚゚)━━━━━━ ニガー?
|
||||
ペ㍕˚\
|
||||
ヽ(´ー` )ノ
|
||||
ヽ(๏๏ )ノ
|
||||
ヽ(`Д´)ノ
|
||||
ヽ(o`皿′o)ノ
|
||||
ヽ(`Д´)ノ
|
||||
ㅎ_ㅎ
|
||||
乂◜◬◝乂
|
||||
凸ಠ益ಠ)凸
|
||||
句_句
|
||||
Ꙩ⌵Ꙩ
|
||||
Ꙩ_Ꙩ
|
||||
ꙩ_ꙩ
|
||||
Ꙫ_Ꙫ
|
||||
ꙫ_ꙫ
|
||||
ꙮ_ꙮ
|
||||
흫_흫
|
||||
句_句
|
||||
﴾͡๏̯͡๏﴿ O'RLY?
|
||||
¯\(ºдಠ)/¯
|
||||
(·×·)
|
||||
(⌒Д⌒)
|
||||
(╹ェ╹)
|
||||
(♯・・)⊃
|
||||
( ´`)☆
|
||||
( ´`)
|
||||
(゜Д゜)
|
||||
(・・)
|
||||
(・A・)
|
||||
(゚゚)
|
||||
( ̄へ ̄)
|
||||
( ´☣///_ゝ///☣`)
|
||||
( つ Д `)
|
||||
_☆( ´_⊃`)☆_
|
||||
。◕‿‿◕。
|
||||
。◕ ‿ ◕。
|
||||
!⑈ˆ~ˆ!⑈
|
||||
!(`・ω・。)
|
||||
(¬‿¬)
|
||||
(¬▂¬)
|
||||
(¬_¬)
|
||||
(°ℇ °)
|
||||
(°°)
|
||||
(´ω`)
|
||||
(´◉◞౪◟◉)
|
||||
(´ヘ`;)
|
||||
(´・ω・`)
|
||||
(´ー`)
|
||||
(ʘ‿ʘ)
|
||||
(ʘ_ʘ)
|
||||
(˚இ˚)
|
||||
(͡๏̯͡๏)
|
||||
(ΘεΘ;)
|
||||
(ι´Д`)ノ
|
||||
(Ծ‸ Ծ)
|
||||
(॓_॔)
|
||||
(० ्०)
|
||||
(ு८ு_ .:)
|
||||
(ಠ‾ಠ)
|
||||
(ಠ‿ʘ)
|
||||
(ಠ‿ಠ)
|
||||
(ಠ⌣ಠ)
|
||||
(ಠ益ಠ ╬)
|
||||
(ಠ益ಠ)
|
||||
(ಠ_ృ)
|
||||
(ಠ_ಠ)
|
||||
(ಥ﹏ಥ)
|
||||
(ಥ_ಥ)
|
||||
(๏̯͡๏ )
|
||||
(ღ˘⌣˘ღ) ♫・*:.。. .。.:*・
|
||||
(ღ˘⌣˘ღ)
|
||||
(ᵔᴥᵔ)
|
||||
(•ω•)
|
||||
(•‿•)
|
||||
(•⊙ω⊙•)
|
||||
(• ε •)
|
||||
(∩▂∩)
|
||||
(∩︵∩)
|
||||
(∪ ◡ ∪)
|
||||
(≧ω≦)
|
||||
(≧◡≦)
|
||||
(≧ロ≦)
|
||||
(⊙ヮ⊙)
|
||||
(⊙_◎)
|
||||
(⋋▂⋌)
|
||||
(⌐■_■)
|
||||
(‿‿)
|
||||
(┛◉Д◉)┛┻━┻
|
||||
(╥_╥)
|
||||
(╬ಠ益ಠ)
|
||||
(╬◣д◢)
|
||||
(╬ ಠ益ಠ)
|
||||
(╯°□°)╯︵ ┻━┻
|
||||
(╯ಊ╰)
|
||||
(╯◕_◕)╯
|
||||
(╯︵╰,)
|
||||
(╯3╰)
|
||||
(╯_╰)
|
||||
(╹◡╹)凸
|
||||
(▰˘◡˘▰)
|
||||
(●´ω`●)
|
||||
(●´`●)
|
||||
(◑‿◐)
|
||||
(◑◡◑)
|
||||
(◕‿◕✿)
|
||||
(◕‿◕)
|
||||
(◕‿-)
|
||||
(◕︵◕)
|
||||
(◕ ^ ◕)
|
||||
(◕_◕)
|
||||
(◜௰◝)
|
||||
(◡‿◡✿)
|
||||
(◣_◢)
|
||||
(☞゚゚)☞
|
||||
(☞゚ヮ゚)☞
|
||||
(☞゚ ゚ )☞
|
||||
(☼◡☼)
|
||||
(☼_☼)
|
||||
(✌゚゚)☞
|
||||
(✖╭╮✖)
|
||||
(✪㉨✪)
|
||||
(✿◠‿◠)
|
||||
(✿ ♥‿♥)
|
||||
( ・・)
|
||||
( ・ัω・ั)?
|
||||
( ゚゚)o彡゜えーりんえーりん!!
|
||||
(。・_・。)
|
||||
(つд`)
|
||||
(づ。◕‿‿◕。)づ
|
||||
(ノಠ益ಠ)ノ彡┻━┻
|
||||
(ノ ◑‿◑)ノ
|
||||
(ノ_・。)
|
||||
(・・ )
|
||||
(屮゚Д゚)屮
|
||||
(︶ω︶)
|
||||
(︶︹︺)
|
||||
(ﺧ益ﺨ)
|
||||
(;一_一)
|
||||
(`・ω・´)”
|
||||
(。◕‿‿◕。)
|
||||
(。◕‿◕。)
|
||||
(。◕ ‿ ◕。)
|
||||
(。♥‿♥。)
|
||||
(。・ω..・)っ
|
||||
(・ェ-)
|
||||
(ノ◕ヮ◕)ノ*:・゚✧
|
||||
(゚Д゚)
|
||||
(゚Д゚)y┛~~
|
||||
(゚゚)
|
||||
(゚ヮ゚)
|
||||
( ̄□ ̄)
|
||||
( ̄。 ̄)
|
||||
( ̄ー ̄)
|
||||
( ̄(エ) ̄)
|
||||
( °٢° )
|
||||
( ´_ゝ`)
|
||||
( ͡° ͜ʖ ͡°)
|
||||
( ͡~ ͜ʖ ͡°)
|
||||
( ಠ◡ಠ )
|
||||
( •_•)>⌐■-■
|
||||
( ゚,_ゝ゚)
|
||||
( ・ิз・ิ)
|
||||
( ゚д゚)、
|
||||
( ^▽^)σ)~O~)
|
||||
((((゜д゜;))))
|
||||
(*´д`*)
|
||||
(*..Д`)
|
||||
(*..д`*)
|
||||
(*~▽~)
|
||||
(-’๏_๏’-)
|
||||
(-_- )ノ
|
||||
(/◔ ◡ ◔)/
|
||||
(///_ಥ)
|
||||
(;´Д`)
|
||||
(=ω=;)
|
||||
(=゜ω゜)
|
||||
(>'o')> ♥ <('o'<)
|
||||
(n˘v˘•)¬
|
||||
(o´ω`o)
|
||||
(V)(°,,°)(V)
|
||||
(\/) (°,,°) (\/)
|
||||
(^▽^)
|
||||
(`・ω・´)
|
||||
(~ ̄▽ ̄)~
|
||||
/╲/\╭ºoꍘoº╮/\╱\
|
||||
<【☯】‿【☯】>
|
||||
= (゚д゚)ウ
|
||||
@_@
|
||||
d(*⌒▽⌒*)b
|
||||
o(≧≦)o
|
||||
o(≧o≦)o
|
||||
q(❂‿❂)p
|
||||
y=ー( ゚д゚)・∵.
|
||||
\˚ㄥ˚\
|
||||
\ᇂ_ᇂ\
|
||||
\(ಠ ὡ ಠ )/
|
||||
\(◕ ◡ ◕\)
|
||||
^̮^
|
||||
^ㅂ^
|
||||
_(͡๏̯͡๏)_
|
||||
{´◕ ◡ ◕`}
|
||||
{ಠ_ಠ}__,,|,
|
||||
{◕ ◡ ◕}
|
|
@ -0,0 +1,73 @@
|
|||
[bot]
|
||||
nick = not_maple
|
||||
username = not_g1mp
|
||||
realname = "[ not_g1mp'n ain't easy unless you're not_maple ]"
|
||||
host = ircd.chat
|
||||
port = 6697
|
||||
version = 1
|
||||
url = ircd.chat
|
||||
ssl = true
|
||||
ssl_verify = CERT_NONE
|
||||
|
||||
includes =
|
||||
irc3.plugins.command
|
||||
irc3.plugins.asynchronious
|
||||
irc3.plugins.uptime
|
||||
irc3.plugins.ctcp
|
||||
irc3.plugins.cron
|
||||
irc3.plugins.logger
|
||||
irc3.plugins.userlist
|
||||
plugins.storage_plugin
|
||||
plugins.base_plugin
|
||||
plugins.emote_plugin
|
||||
plugins.youtube_plugin
|
||||
plugins.crypto_plugin
|
||||
plugins.auth_plugin
|
||||
plugins.url_grabber_plugin
|
||||
plugins.notes_plugin
|
||||
plugins.quote_plugin
|
||||
plugins.ratesex_plugin
|
||||
plugins.remind_plugin
|
||||
plugins.sed_plugin
|
||||
plugins.seen_plugin
|
||||
plugins.strain_plugin
|
||||
plugins.tell_plugin
|
||||
plugins.twitter_plugin
|
||||
plugins.ud_plugin
|
||||
plugins.figlet_plugin
|
||||
plugins.soundcloud_plugin
|
||||
plugins.isup_plugin
|
||||
plugins.maple_plugin
|
||||
|
||||
autojoins =
|
||||
${#}tcpdirect
|
||||
|
||||
flood_burst = 0
|
||||
flood_rate = 1
|
||||
flood_rate_delay = 1
|
||||
storage = json://databases/maple_db.json
|
||||
|
||||
[irc3.plugins.command]
|
||||
cmd = ?
|
||||
guard = irc3.plugins.command.mask_based_policy
|
||||
|
||||
[irc3.plugins.command.masks]
|
||||
d!*dr1p@* = all_permissions
|
||||
* = view
|
||||
|
||||
ignore_list =
|
||||
GitServ!*@*
|
||||
GitServ_!*@*
|
||||
g1mp!*@*
|
||||
g1mp_!*@*
|
||||
maple!*@*
|
||||
maple_!*@*
|
||||
[0]!*@*
|
||||
[0]_!*@*
|
||||
nav!*@*
|
||||
nav_!*@*
|
||||
van!*@*
|
||||
van_!*@*
|
||||
professorOak!*@*
|
||||
professorOak_!*@*
|
||||
*!van@*
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.cron import cron
|
||||
import irc3
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
NICKSERV_USERNAME='not_maple'
|
||||
NICKSERV_PASSWORD='CHANGEYOURPASSWORD'
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
def __init__(self,bot):
|
||||
self.bot=bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.CONNECTED)
|
||||
def connected(self, **kw):
|
||||
MSG=f"identify {NICKSERV_USERNAME} {NICKSERV_PASSWORD}"
|
||||
self.bot.privmsg('NICKSERV',MSG)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@cron('*/1 * * * *')
|
||||
def cron_auth(bot):
|
||||
if not bot.nick==bot.original_nick:
|
||||
MSG=f"identify {NICKSERV_USERNAME} {NICKSERV_PASSWORD}"
|
||||
bot.privmsg('NICKSERV',MSG)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,239 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
from irc3.utils import IrcString
|
||||
import irc3
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import re
|
||||
import functools
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
USER_STRING_MATCH = re.compile('(.+)!(.+)@(.+)')
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def __init__(self, bot):
|
||||
staff_set = set()
|
||||
self.bot = bot
|
||||
self.bot.auto_kick_list = set(self.bot.db.getlist("auto_kick_list", []))
|
||||
self.bot.ignore_list = set(self.bot.db.getlist("ignore_nicks_list", []))
|
||||
self.bot.staff_list = set(self.bot.db.getlist("staff_list", []))
|
||||
current_masks = self.bot.config.get('irc3.plugins.command.masks')
|
||||
for k, v in current_masks.items():
|
||||
if v in ["staff", "all_permissions"]:
|
||||
staff_set.add(k)
|
||||
if not self.bot.ignore_list:
|
||||
self.bot.ignore_list = set(self.bot.config.get('irc3.plugins.command.masks', {}).get("ignore_list", []))
|
||||
if not self.bot.staff_list:
|
||||
self.bot.staff_list = set(staff_set)
|
||||
self.bot.db.setlist("staff_list", self.bot.staff_list)
|
||||
for hostname in self.bot.staff_list:
|
||||
if not current_masks.get(hostname):
|
||||
self.bot.config['irc3.plugins.command.masks'][hostname] = "staff"
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.extend
|
||||
def check_if_ignored(self, hostmask):
|
||||
global_hostmask = hostmask.replace(hostmask.nick, ".+")
|
||||
nick_mask = hostmask.replace(hostmask.host,".+@.+")
|
||||
host_pattern = re.compile(global_hostmask)
|
||||
nick_pattern = re.compile(nick_mask)
|
||||
for mask in self.bot.ignore_list:
|
||||
if host_pattern.match(mask):
|
||||
return True
|
||||
if nick_pattern.match(mask):
|
||||
return True
|
||||
return False
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.event(irc3.rfc.CONNECTED)
|
||||
def _add_hostmask(self, *args, **kwargs):
|
||||
def handle_who(self, response):
|
||||
result = response.result()
|
||||
self.bot.hostmask = result.get('mask')
|
||||
task = self.bot.who(self.bot.get_nick())
|
||||
task.add_done_callback(functools.partial(handle_who, self))
|
||||
opper_password = self.bot.config.get("opper_password")
|
||||
opper_username = self.bot.config.get("opper_username")
|
||||
self.bot.send_line("GOD {} {}".format(opper_username, opper_password))
|
||||
self.bot.privmsg("nickserv", "IDENTIFY {} {}".format(self.bot.nick, opper_password))
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.event(irc3.rfc.JOIN)
|
||||
def auto_kick_handler(self, mask, channel, **kw):
|
||||
msg = "g1mp'n ain't easy unless you're maple"
|
||||
if mask.nick in self.bot.auto_kick_list:
|
||||
cmd = "MODE {} +b {}!*@*".format(channel, mask.nick)
|
||||
self.bot.send(cmd)
|
||||
self.bot.kick(channel, mask.nick, msg)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='view', public=True, show_in_help_list=False)
|
||||
def v(self, mask, target, args):
|
||||
channel = self.bot.channels[target]
|
||||
|
||||
has_voice_list = []
|
||||
for _, nick in channel.modes.items():
|
||||
has_voice_list.append(nick)
|
||||
for nick in channel:
|
||||
if nick not in has_voice_list:
|
||||
cmd = "MODE {} +v {}".format(target, nick)
|
||||
self.bot.send(cmd)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=False)
|
||||
def op(self, mask, target, args):
|
||||
if args['<nick>']:
|
||||
nick = args['<nick>']
|
||||
cmd = "MODE {} +o {}".format(target, nick)
|
||||
self.bot.send(cmd)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=False)
|
||||
def deop(self, mask, target, args):
|
||||
if args['<nick>']:
|
||||
nick = args['<nick>']
|
||||
cmd = "MODE {} -o {}".format(target, nick)
|
||||
self.bot.send(cmd)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission="admin", show_in_help_list=False)
|
||||
def stats(self, mask, target, args):
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
if args['<channel>']:
|
||||
channel = args['<channel>']
|
||||
target = mask.nick
|
||||
else:
|
||||
channel = target
|
||||
if channel in self.bot.channels:
|
||||
channel = self.bot.channels[channel]
|
||||
message = '{0} users'.format(len(channel))
|
||||
for mode, nicknames in sorted(channel.modes.items()):
|
||||
message += ' - {0}({1})'.format(mode, len(nicknames))
|
||||
self.bot.privmsg(target, message)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='admin', public=False, show_in_help_list=False)
|
||||
def restart(self, mask, target, args):
|
||||
self.bot.privmsg(target, 'BOT RESTARTING')
|
||||
time.sleep(1)
|
||||
os.execl(sys.executable, sys.executable, *sys.argv)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='admin', public=False, show_in_help_list=False)
|
||||
def uptime(self, mask, target, args):
|
||||
pass
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='admin', public=False, show_in_help_list=False)
|
||||
def ping(self, mask, target, args):
|
||||
pass
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@command(permission='staff', public=True, show_in_help_list=True)
|
||||
def staff(self, mask, target, args):
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
def __staff_list(self, mask, target, args):
|
||||
current_masks = self.bot.config.get("irc3.plugins.command.masks", "")
|
||||
current_staff_list = [k for k,v in current_masks.items() if v in ["all_permissions", "staff"]]
|
||||
self.bot.privmsg(target, "\x02༺Staff List༻\x0F\x02\x0303 ▶ \x0F\x0302{}".format(", ".join(current_staff_list)))
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
def __staff_del(self, mask, target, args):
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
def del_hostmask(self, host_string):
|
||||
current_masks = self.bot.config.get("irc3.plugins.command.masks", "")
|
||||
if host_string in current_masks.keys():
|
||||
mask_list = current_masks.get(host_string, "").split(",")
|
||||
if "all_permissions" in mask_list:
|
||||
self.bot.privmsg(target, "Don't fuck with the admin")
|
||||
return
|
||||
elif "staff" in mask_list:
|
||||
del(self.bot.config["irc3.plugins.command.masks"][host_string])
|
||||
self.bot.staff_list.remove(host_string)
|
||||
self.bot.db.setlist("staff_list", self.bot.staff_list)
|
||||
self.bot.privmsg(target, '{} removed from staff'.format(host_string))
|
||||
return
|
||||
else:
|
||||
pass # pass for brevarity
|
||||
else:
|
||||
self.bot.privmsg(target, '{} is not a staff member'.format(host_string))
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
def handle_who(self, response):
|
||||
result = response.result()
|
||||
nick = result.get("nick")
|
||||
mask = result.get('mask')
|
||||
host_string = mask.replace(nick,"*")
|
||||
del_hostmask(self, host_string)
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
nick = args.get("<nick>")
|
||||
match_list = USER_STRING_MATCH.findall(nick)
|
||||
if match_list and len(match_list[0]) == 3:
|
||||
del_hostmask(self, nick)
|
||||
return
|
||||
else:
|
||||
task = self.bot.who(nick)
|
||||
task.add_done_callback(functools.partial(handle_who, self))
|
||||
return
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
def __staff_add(self, mask, target, args):
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
def add_hostmask(self, host_string):
|
||||
current_masks = self.bot.config.get("irc3.plugins.command.masks", "")
|
||||
if host_string in current_masks.keys():
|
||||
mask_list = current_masks.get(host_string, "").split(",")
|
||||
if "staff" or "all_permissions" in mask_list:
|
||||
self.bot.privmsg(target, "{} is already a staff member".format(host_string))
|
||||
return
|
||||
else:
|
||||
self.bot.config["irc3.plugins.command.masks"][host_string] = "staff"
|
||||
self.bot.staff_list.add(host_string)
|
||||
self.bot.db.setlist("staff_list", self.bot.staff_list)
|
||||
self.bot.privmsg(target, '{} added to staff'.format(host_string))
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
def handle_who(self, response):
|
||||
result = response.result()
|
||||
nick = result.get("nick")
|
||||
mask = result.get('mask')
|
||||
host_string = mask.replace(nick,"*")
|
||||
add_hostmask(self, host_string)
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
nick = args.get("<nick>")
|
||||
match_list = USER_STRING_MATCH.findall(nick)
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
if match_list and len(match_list[0]) == 3:
|
||||
add_hostmask(self, nick)
|
||||
return
|
||||
else:
|
||||
task = self.bot.who(nick)
|
||||
task.add_done_callback(functools.partial(handle_who, self))
|
||||
return
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
cmd = args.get("<cmd>")
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
if not cmd:
|
||||
self.bot.privmsg(target, "please specify add/del/list")
|
||||
elif cmd in ["d","del","delete","remove"]:
|
||||
__staff_del(self, mask, target, args)
|
||||
elif cmd in ["l", "list"]:
|
||||
__staff_list(self, mask, target, args)
|
||||
elif cmd in ["w", "write","a", "add"]:
|
||||
__staff_add(self, mask, target, args)
|
||||
###################################################################################
|
||||
###################################################################################
|
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import async_timeout
|
||||
headers = { 'authorization': 'Apikey 94e50805f19646893ee16424918998caad5ec6accff539a23ffee8e546eda4e3' }
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def cc(self, mask, target, args):
|
||||
"""Show Crypto Value
|
||||
%%cc <coin>
|
||||
"""
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
coin = args['<coin>'].upper()
|
||||
async def fetch(session, url):
|
||||
async with async_timeout.timeout(10):
|
||||
async with session.get(url) as response:
|
||||
return await response.json()
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
async def grab_url(url):
|
||||
async with aiohttp.ClientSession(headers=headers) as session:
|
||||
json_response = await fetch(session, url)
|
||||
return json_response
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
def parse_coin(response):
|
||||
try:
|
||||
task_result, _ = response.result()
|
||||
task1, task2, task3 = task_result
|
||||
rlist = sorted([task1.result(), task2.result(), task3.result()], key=lambda item: len(item.keys()))
|
||||
if rlist[1].get("USD"):
|
||||
price = rlist[1].get("USD")
|
||||
price_multi = rlist[2].get("DISPLAY")[coin].get("USD", {})
|
||||
daily_avg = rlist[0].get("USD")
|
||||
|
||||
elif rlist[2].get("USD"):
|
||||
price_multi = rlist[1].get("DISPLAY")[coin].get("USD", {})
|
||||
price = rlist[2].get("USD")
|
||||
daily_avg = rlist[0].get("USD")
|
||||
data_dict = {}
|
||||
for k, v in price_multi.items():
|
||||
if isinstance(v, str):
|
||||
v = v.replace("$","").replace(" ","").replace(",","")
|
||||
data_dict[k] = v
|
||||
price_multi = data_dict
|
||||
|
||||
X = float(daily_avg) # AVERAGE OF THE DAY
|
||||
P = float(price_multi.get('PRICE')) # PRICE CURRENTLY
|
||||
H = float(price_multi.get('HIGHDAY')) # HIGH OF THE DAY
|
||||
L = float(price_multi.get('LOWDAY')) # LOW OF THE DAY
|
||||
A = float(price) # AGGREGATED EXCHANGE
|
||||
Y = float(price_multi.get('CHANGE24HOUR')) # PRICE PERCENT DIFFERENTIAL 24 HOURS AGO
|
||||
C = float(price_multi.get('CHANGEPCT24HOUR'))
|
||||
|
||||
if C <= 0:
|
||||
C = "\x0304{}\x0F".format(C)
|
||||
else:
|
||||
C = "\x0303{}\x0F".format(C)
|
||||
if Y <= 0:
|
||||
Y = "\x0304{}\x0F".format(Y)
|
||||
else:
|
||||
Y = "\x0303{}\x0F".format(Y)
|
||||
|
||||
symbol = price_multi.get('FROMSYMBOL')
|
||||
msg = "\x02\x0302[ {coin:}/{symbol:} ]\x0F @\x0303${p:,}\x0F ::: H\x0303${h:,}\x0F L\x0303${l:,}\x0F ::: Y${y:} @ %{c:} ::: X\x0303${x:,}\x0F A\x0303${a:,}\x0F".format(coin=coin, symbol=symbol, p=P, h=H, l=L, y=Y,c=C, x=X, a=A)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
except Exception as e:
|
||||
msg = self.bot.emo('their api is glitching: check back later')
|
||||
self.bot.privmsg(target, msg)
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
def process_lookups(response):
|
||||
try:
|
||||
html = response.result()
|
||||
except Exception as e:
|
||||
msg = self.bot.emo('site error: {}'.format(e.message))
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
coin_result = html.get("Data",{}).get(coin, None)
|
||||
if not coin_result:
|
||||
msg = self.bot.emo('Invalid coin - see https://min-api.cryptocompare.com/data/all/coinlist data keys')
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
day_avg_url = "https://min-api.cryptocompare.com/data/dayAvg?fsym={}&tsym=USD&api_key=94e50805f19646893ee16424918998caad5ec6accff539a23ffee8e546eda4e3".format(coin)
|
||||
price_multi_url = "https://min-api.cryptocompare.com/data/pricemultifull?fsyms={}&tsyms=USD&api_key=94e50805f19646893ee16424918998caad5ec6accff539a23ffee8e546eda4e3".format(coin)
|
||||
price_url = "https://min-api.cryptocompare.com/data/price?fsym={}&tsyms=USD&api_key=94e50805f19646893ee16424918998caad5ec6accff539a23ffee8e546eda4e3".format(coin)
|
||||
tasks = [asyncio.ensure_future(grab_url(day_avg_url)),
|
||||
asyncio.ensure_future(grab_url(price_multi_url)),
|
||||
asyncio.ensure_future(grab_url(price_url))]
|
||||
task = self.bot.create_task(asyncio.wait(tasks))
|
||||
task.add_done_callback(parse_coin)
|
||||
###################################################################################
|
||||
###################################################################################
|
||||
url = "https://min-api.cryptocompare.com/data/all/coinlist"
|
||||
asyncio.ensure_future(grab_url(url), loop=self.bot.loop).add_done_callback(process_lookups)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import random
|
||||
import os
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
def emo(self,s):
|
||||
emote_db = '%s/../databases/emote.db' % dir_path
|
||||
emoj = random.choice(list(open(emote_db)))
|
||||
random.randint(0,1)
|
||||
if random.randint(0,1) == 0:
|
||||
emoj = "\x0304{}\x0F".format(emoj)
|
||||
else:
|
||||
emoj = "\x0303{}\x0F".format(emoj)
|
||||
s = s + '\x0303 ▶ ' + emoj
|
||||
return s
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def emote(self, mask, target, args):
|
||||
"""Show Emotion
|
||||
%%emote
|
||||
"""
|
||||
def __random_line():
|
||||
emote_db = '%s/../databases/emote.db' % dir_path
|
||||
return random.choice(list(open(emote_db)))
|
||||
emoj = __random_line()
|
||||
self.bot.privmsg(target, "%s" % emoj)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import pyfiglet
|
||||
import random
|
||||
fig = pyfiglet.Figlet(width=100)
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.fig_fonts = set(self.bot.db.getlist("fig_font_list", []))
|
||||
if not self.fig_fonts:
|
||||
self.fig_fonts = fig.getFonts()
|
||||
self.bot.db.setlist("fig_font_list", self.fig_fonts)
|
||||
@irc3.extend
|
||||
def fig(self, text, font=None):
|
||||
if font in self.fig_fonts:
|
||||
fig.setFont(font=font)
|
||||
else:
|
||||
font = random.choice(list(self.fig_fonts))
|
||||
return fig.renderText(text)
|
||||
@command(permission='view', name="fig", public=True, show_in_help_list=True)
|
||||
def figcmd(self, mask, target, args):
|
||||
"""Print figlet Text
|
||||
%%fig <cmdmsg>...
|
||||
"""
|
||||
cmdmsg = ' '.join(args['<cmdmsg>'])
|
||||
cmd = ' '.join(cmdmsg.split()[:1])
|
||||
msg = ' '.join(cmdmsg.split()[1:])
|
||||
font = cmd
|
||||
text = msg
|
||||
if font == "list":
|
||||
font_list = self.bot.db.getlist("fig_font_list")
|
||||
self.bot.privmsg(target, "Current Fig Fonts {}".format(",".join(font_list)))
|
||||
return
|
||||
if font == "ignore":
|
||||
ignored_font = args.get("<text>")
|
||||
self.fig_fonts.remove(ignored_font)
|
||||
self.bot.db.setlist("fig_font_list", self.fig_fonts)
|
||||
self.bot.privmsg(target, "Ignoring {}".format(ignored_font))
|
||||
return
|
||||
if text is not None and font in self.fig_fonts:
|
||||
msg = self.bot.emo(font)
|
||||
self.bot.privmsg(target, msg)
|
||||
fig_text = self.fig(text=text, font=font)
|
||||
else:
|
||||
newfont = random.choice(list(self.fig_fonts))
|
||||
msg = self.bot.emo(newfont)
|
||||
self.bot.privmsg(target, msg)
|
||||
fig_text = self.fig(text=font, font=newfont) # Cause weird command format
|
||||
for line in fig_text.split("\n"):
|
||||
self.bot.privmsg(target, line)
|
|
@ -0,0 +1,85 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import URLError, HTTPError
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def isup_check(self, domain_or_ip):
|
||||
msg=''
|
||||
try:
|
||||
url=f'http://{domain_or_ip}'
|
||||
try:
|
||||
req = Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
|
||||
}
|
||||
)
|
||||
response=urlopen(req,timeout=10).read().decode('utf-8')
|
||||
except HTTPError as e:
|
||||
msg='maybe -> could not complete the request. error code: {}'.format(e.code)
|
||||
except URLError as e:
|
||||
msg='down -> failed to reach the server. reason: {}'.format(e.reason)
|
||||
else:
|
||||
msg=f'up -> http://{domain_or_ip} is communicating'
|
||||
except:
|
||||
url=f'https://{domain_or_ip}'
|
||||
try:
|
||||
req = Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
|
||||
}
|
||||
)
|
||||
response=urlopen(req,timeout=10).read().decode('utf-8')
|
||||
except HTTPError as e:
|
||||
msg='maybe -> could not complete the request. error code: {}'.format(e.code)
|
||||
except URLError as e:
|
||||
msg='down -> failed to reach the server. reason: {}'.format(e.reason)
|
||||
else:
|
||||
msg=f'up -> https://{domain_or_ip} is communicating'
|
||||
finally:
|
||||
return msg
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def isup(self, mask, target, args):
|
||||
"""isup domain
|
||||
%%isup <domain>
|
||||
"""
|
||||
domain=args.get('<domain>')
|
||||
domain_noise=domain
|
||||
try:
|
||||
domain_noise=domain.split('://')[1]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if not domain_noise:
|
||||
domain_noise=domain[:domain.find('.')+domain[domain.find('.')+1:].find('/')+1].split('://')[1]
|
||||
except:
|
||||
if not domain_noise.find('/')==-1:
|
||||
domain_noise=domain[:domain.find('.')+domain[domain.find('.')+1:].find('/')+1].split('://')[0]
|
||||
if domain_noise[-1]=="/": domain_noise=domain_noise[:-1]
|
||||
if domain_noise[:domain_noise.find(':')].replace('.','').isnumeric() and (len(domain_noise[:domain_noise.find(':')])-3)==len(domain_noise[:domain_noise.find(':')].replace('.','')):
|
||||
domain=domain_noise
|
||||
elif domain_noise.replace('.','').isnumeric() and (len(domain_noise)-3) == len(domain_noise.replace('.','')):
|
||||
domain=domain_noise
|
||||
elif domain_noise.find('/') == -1 and not domain_noise.find('.') == -1 and domain_noise.replace('.','').isalnum():
|
||||
domain=domain_noise
|
||||
else:
|
||||
self.bot.privmsg(target,self.bot.emo("{}: doesn't sanitize towards a valid domain/ip".format(domain)))
|
||||
return
|
||||
self.bot.privmsg(target,self.bot.emo("{}".format(self.isup_check(domain))))
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
###############################################################################################
|
||||
###############################################################################################
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
###############################################################################################
|
||||
###############################################################################################
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import URLError, HTTPError
|
||||
###############################################################################################
|
||||
###############################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot=bot
|
||||
self.site_url="https://icanhazdadjoke.com"
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def urlget(self,url):
|
||||
USER_AGENT_CURL="curl/7.78.0"
|
||||
ACCEPT_MODES="text/plain"
|
||||
STATUS_BAD_CODE=":( - error code: {}"
|
||||
STATUS_BAD_REASON=":( - failed reason: {}"
|
||||
STATUS_OK=":)"
|
||||
r = Request(url,data=None,headers={ 'user-agent': USER_AGENT_CURL, 'accept': ACCEPT_MODES })
|
||||
try: response = urlopen(r,timeout=15).read().decode('utf-8')
|
||||
except HTTPError as e: return STATUS_BAD_CODE.format(e.code)
|
||||
except URLError as e: return STATUS_BAD_REASON.format(e.reason)
|
||||
else: return STATUS_OK + response
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.extend
|
||||
@command(permission='view')
|
||||
def joke(self, mask, target, args):
|
||||
"""joke
|
||||
%%joke
|
||||
"""
|
||||
response=self.urlget(self.site_url)[2:]
|
||||
for msg in response.splitlines():
|
||||
if len(msg) > 1:
|
||||
self.bot.privmsg(target, self.bot.emo(msg))
|
|
@ -0,0 +1,357 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import io
|
||||
import irc3
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
from glob import glob
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
import numpy as np
|
||||
import logging
|
||||
import signal
|
||||
import configparser
|
||||
import logging
|
||||
import random
|
||||
from transformers import GPT2Config,GPT2LMHeadModel,GPT2Tokenizer
|
||||
from datetime import datetime
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
#import ipdb
|
||||
###########################################################################################################
|
||||
###########################################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################################
|
||||
#######################################################################################################
|
||||
PoolExecutor=ThreadPoolExecutor
|
||||
#######################################################################################################
|
||||
#######################################################################################################
|
||||
terminate=False
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
|
||||
logger=logging.getLogger(__name__)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
CONFIG_FILE={
|
||||
'small':'https://convaisharables.blob.core.windows.net/lsp/117M/config.json',
|
||||
'medium':'https://convaisharables.blob.core.windows.net/lsp/345M/config.json'
|
||||
}
|
||||
VOCAB_FILE={
|
||||
'small':'https://convaisharables.blob.core.windows.net/lsp/117M/vocab.json',
|
||||
'medium':'https://convaisharables.blob.core.windows.net/lsp/345M/vocab.json'
|
||||
}
|
||||
MERGE_FILE={
|
||||
'small':'https://convaisharables.blob.core.windows.net/lsp/117M/merges.txt',
|
||||
'medium':'https://convaisharables.blob.core.windows.net/lsp/345M/merges.txt'
|
||||
}
|
||||
LSP_MODEL_URL={
|
||||
'multiref':{
|
||||
'medium_fs':'https://convaisharables.blob.core.windows.net/lsp/multiref/medium_fs.pkl',
|
||||
'medium_ft':'https://convaisharables.blob.core.windows.net/lsp/multiref/medium_ft.pkl',
|
||||
'small_fs':'https://convaisharables.blob.core.windows.net/lsp/multiref/small_fs.pkl',
|
||||
'small_ft':'https://convaisharables.blob.core.windows.net/lsp/multiref/small_ft.pkl'
|
||||
},
|
||||
'dstc':{
|
||||
'small_ft':'https://convaisharables.blob.core.windows.net/lsp/DSTC/medium_ft.pkl'
|
||||
}
|
||||
}
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
REVERSE_MODEL_URL='https://convaisharables.blob.core.windows.net/lsp/multiref/small_reverse.pkl'
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
PERSONALITY="""
|
||||
[model]
|
||||
data_folder=models
|
||||
model_size=medium
|
||||
dataset=multiref
|
||||
from_scratch=False
|
||||
no_cuda=False
|
||||
use_mmi=False
|
||||
[decoder]
|
||||
seed=0
|
||||
temperature=0.6474
|
||||
top_k=40
|
||||
top_p=0
|
||||
max_length=128
|
||||
num_samples=1
|
||||
max_turns_history=1
|
||||
[personality]
|
||||
telegram_token=YOUR_TOKEN_HERE
|
||||
giphy_token=YOUR_TOKEN_HERE
|
||||
giphy_weirdness=5
|
||||
"""
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self,bot):
|
||||
self.maple_message=''
|
||||
self.PERSONALITY=self.PERSONALITY.format(RND=datetime.now().microsecond)
|
||||
self.bot=bot
|
||||
self.delay=0.025
|
||||
self.cycle=0
|
||||
CONFIG=io.StringIO(self.PERSONALITY)
|
||||
self.config=configparser.ConfigParser()
|
||||
self.config.read_file(CONFIG)
|
||||
self.target_folder_name=self.download_model_folder(self.config)
|
||||
self.model,self.tokenizer=self.load_model(self.target_folder_name,self.config)
|
||||
self.use_mmi=self.config.getboolean('model','use_mmi')
|
||||
if self.use_mmi:
|
||||
self.mmi_target_folder_name=self.download_reverse_model_folder(self.config)
|
||||
self.mmi_model,mmi_tokenizer=self.load_model(self.mmi_target_folder_name,self.config)
|
||||
else:
|
||||
self.mmi_model=None
|
||||
self.mmi_tokenizer=None
|
||||
loop=self.bot.loop
|
||||
loop.call_later(self.delay,self.main)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_maple(self, mask=None, target=None, data=None, **kw):
|
||||
##############################################
|
||||
if mask.nick == 'maple':
|
||||
data=data.lower().replace('maple','').strip()
|
||||
# ##############################################
|
||||
# if not data.lower().find('maple') > -1:
|
||||
# return
|
||||
#data=data.lower().replace('maple','').strip()
|
||||
##############################################
|
||||
self.maple_message=data
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def signal_handling(self,signum,frame):
|
||||
self.terminate=True
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def http_get(self,url,temp_file):
|
||||
req=requests.get(url,stream=True)
|
||||
content_length=req.headers.get('Content-Length')
|
||||
total=int(content_length) if content_length is not None else None
|
||||
progress=tqdm(unit="B",total=total)
|
||||
for chunk in req.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
progress.update(len(chunk))
|
||||
temp_file.write(chunk)
|
||||
progress.close()
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def download_file(self,url,folder):
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder,exist_ok=True)
|
||||
file_name=os.path.basename(url)
|
||||
if 'pytorch_model.bin' in file_name:
|
||||
file_name='pytorch_model.bin'
|
||||
if os.path.isfile(os.path.join(folder,file_name)):
|
||||
return
|
||||
with open(os.path.join(folder,file_name),'wb') as f:
|
||||
self.http_get(url,f)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def download_model_folder(self,config):
|
||||
data_folder=config.get('model','data_folder')
|
||||
model_size=config.get('model','model_size')
|
||||
dataset=config.get('model','dataset')
|
||||
from_scratch=config.getboolean('model','from_scratch')
|
||||
if not os.path.exists(data_folder):
|
||||
os.makedirs(data_folder, exist_ok=True)
|
||||
target_folder_name=model_size+"_"+dataset+("_fs" if from_scratch else "_ft")
|
||||
target_folder=os.path.join(data_folder,target_folder_name)
|
||||
self.logger.info(f"Downloading model files to {target_folder_name}...")
|
||||
self.download_file(self.CONFIG_FILE[model_size],target_folder)
|
||||
self.download_file(self.VOCAB_FILE[model_size],target_folder)
|
||||
self.download_file(self.MERGE_FILE[model_size],target_folder)
|
||||
model_train_type=model_size+('_fs' if from_scratch else '_ft')
|
||||
if model_train_type not in self.LSP_MODEL_URL[dataset]:
|
||||
k=','.join(list(self.LSP_MODEL_URL[dataset].keys()))
|
||||
raise ValueError(f"'{model_train_type}' not exist for dataset '{dataset}', please choose from [{k}]")
|
||||
self.download_file(self.LSP_MODEL_URL[dataset][model_train_type],target_folder)
|
||||
return target_folder_name
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def download_reverse_model_folder(self,config):
|
||||
data_folder=config.get('model','data_folder')
|
||||
model_size='medium'
|
||||
if not os.path.exists(data_folder):
|
||||
os.makedirs(data_folder,exist_ok=True)
|
||||
target_folder_name=model_size+'_reverse'
|
||||
target_folder=os.path.join(data_folder,target_folder_name)
|
||||
self.logger.info(f"Downloading model files to {target_folder_name}...")
|
||||
self.download_file(self.CONFIG_FILE[model_size],target_folder)
|
||||
self.download_file(self.VOCAB_FILE[model_size],target_folder)
|
||||
self.download_file(self.MERGE_FILE[model_size],target_folder)
|
||||
self.download_file(self.REVERSE_MODEL_URL,target_folder)
|
||||
return target_folder_name
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def load_model(self,target_folder_name,config):
|
||||
data_folder=config.get('model','data_folder')
|
||||
model_size=config.get('model','model_size')
|
||||
no_cuda=config.getboolean('model', 'no_cuda')
|
||||
self.logger.info(f"Loading model from {target_folder_name}...")
|
||||
device=torch.device("cuda" if torch.cuda.is_available() and not no_cuda else "cpu")
|
||||
target_folder=os.path.join(data_folder,target_folder_name)
|
||||
tokenizer=GPT2Tokenizer(os.path.join(target_folder, 'vocab.json'), os.path.join(target_folder, 'merges.txt'))
|
||||
config=GPT2Config.from_json_file(os.path.join(target_folder, 'config.json'))
|
||||
state_dict_path=glob(os.path.join(target_folder,f'*.pkl'))[0]
|
||||
state_dict=torch.load(state_dict_path,map_location=device)
|
||||
if model_size=='small':
|
||||
for key in list(state_dict.keys()):
|
||||
state_dict[key.replace('module.','')]=state_dict.pop(key)
|
||||
state_dict['lm_head.weight']=state_dict['lm_head.decoder.weight']
|
||||
state_dict.pop("lm_head.decoder.weight",None)
|
||||
model=GPT2LMHeadModel(config)
|
||||
model.load_state_dict(state_dict)
|
||||
model.to(device)
|
||||
model.eval()
|
||||
return model,tokenizer
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def set_seed(self,seed):
|
||||
random.seed(seed)
|
||||
np.random.seed(seed)
|
||||
torch.manual_seed(seed)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def top_k_top_p_filtering(self,logits,top_k=0,top_p=0.0,filter_value=-float('Inf')):
|
||||
top_k=min(top_k,logits.size(-1))
|
||||
if top_k>0:
|
||||
indices_to_remove=logits<torch.topk(logits,top_k)[0][...,-1,None]
|
||||
logits[indices_to_remove]=filter_value
|
||||
if top_p>0.0:
|
||||
sorted_logits,sorted_indices=torch.sort(logits,descending=True)
|
||||
cumulative_probs=torch.cumsum(F.softmax(sorted_logits,dim=-1),dim=-1)
|
||||
sorted_indices_to_remove=cumulative_probs>top_p
|
||||
sorted_indices_to_remove[...,1:]=sorted_indices_to_remove[...,:-1].clone()
|
||||
sorted_indices_to_remove[...,0]=0
|
||||
indices_to_remove=sorted_indices_to_remove.scatter(dim=1,index=sorted_indices,src=sorted_indices_to_remove)
|
||||
logits[indices_to_remove]=filter_value
|
||||
return logits
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def sample_sequence(self,model,tokenizer,context_ids,config):
|
||||
no_cuda=config.getboolean('model','no_cuda')
|
||||
num_samples=config.getint('decoder','num_samples')
|
||||
max_length=config.getint('decoder','max_length')
|
||||
temperature=config.getfloat('decoder','temperature')
|
||||
top_k=config.getint('decoder','top_k')
|
||||
top_p=config.getfloat('decoder','top_p')
|
||||
device=torch.device("cuda" if torch.cuda.is_available() and not no_cuda else "cpu")
|
||||
context_tensor=torch.tensor(context_ids,dtype=torch.long,device=device)
|
||||
context_tensor=context_tensor.unsqueeze(0).repeat(num_samples,1)
|
||||
generated=context_tensor
|
||||
with torch.no_grad():
|
||||
while True:
|
||||
inputs={'input_ids':generated}
|
||||
outputs=model(**inputs)
|
||||
next_token_logits=outputs[0][:,-1,:]/(temperature if temperature>0 else 1.)
|
||||
filtered_logits=self.top_k_top_p_filtering(next_token_logits,top_k=top_k,top_p=top_p)
|
||||
if temperature==0.0:
|
||||
next_token=torch.argmax(filtered_logits,dim=-1).unsqueeze(-1)
|
||||
else:
|
||||
next_token=torch.multinomial(F.softmax(filtered_logits,dim=-1),num_samples=1)
|
||||
generated=torch.cat((generated,next_token),dim=1)
|
||||
if (generated[:,len(context_ids):]==tokenizer.eos_token_id).any(dim=1).all():
|
||||
break
|
||||
if generated.shape[1]-len(context_ids)>=max_length:
|
||||
break
|
||||
return generated
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def select_using_mmi(self,mmi_model,mmi_tokenizer,candidates,config):
|
||||
no_cuda=config.getboolean('model','no_cuda')
|
||||
device=torch.device("cuda" if torch.cuda.is_available() and not no_cuda else "cpu")
|
||||
scores=[]
|
||||
for i,candidate in enumerate(candidates):
|
||||
context=[]
|
||||
for response in reversed(candidate):
|
||||
context.extend(response)
|
||||
context.append(mmi_tokenizer.eos_token_id)
|
||||
context_ids=mmi_tokenizer.encode(context)
|
||||
context_tensor=torch.tensor(context_ids,dtype=torch.long,device=device)
|
||||
loss,_,_=mmi_model(input_ids=context_tensor,labels=context_tensor)
|
||||
scores.append(-loss.float())
|
||||
scores=torch.stack(scores, dim=0)
|
||||
winner=torch.multinomial(F.softmax(scores,dim=0),num_samples=1).item()
|
||||
return winner
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def generate_response(self,model,tokenizer,context,config,mmi_model=None,mmi_tokenizer=None):
|
||||
use_mmi=config.getboolean('model','use_mmi')
|
||||
num_samples=config.getint('decoder','num_samples')
|
||||
max_length=config.getint('decoder','max_length')
|
||||
seed=config.get('decoder','seed')
|
||||
seed=int(seed) if seed is not None else None
|
||||
if seed is not None:
|
||||
self.set_seed(seed)
|
||||
context_ids=tokenizer.encode(context)
|
||||
samples=self.sample_sequence(model, tokenizer, context_ids, config)
|
||||
samples=samples[:, len(context_ids):].tolist()
|
||||
texts=[]
|
||||
for sample in samples:
|
||||
text=tokenizer.decode(sample,clean_up_tokenization_spaces=True)
|
||||
text=text[: text.find(tokenizer.eos_token)]
|
||||
texts.append(text)
|
||||
if use_mmi:
|
||||
assert(num_samples > 1)
|
||||
candidates=[context+text for text in texts]
|
||||
best_i=self.select_using_mmi(mmi_model,mmi_tokenizer,candidates,config)
|
||||
return [texts[best_i]]
|
||||
return texts
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def run_chat(self,model,tokenizer,config,mmi_model=None,mmi_tokenizer=None):
|
||||
num_samples=config.getint('decoder','num_samples')
|
||||
max_turns_history=config.getint('decoder','max_turns_history')
|
||||
turns=[]
|
||||
signal.signal(signal.SIGINT,self.signal_handling)
|
||||
# print("*** RUNNING ***")
|
||||
# while True:
|
||||
# if self.terminate:
|
||||
# break
|
||||
config.set('decoder','seed',f'{datetime.now().microsecond}')
|
||||
s=self.maple_message
|
||||
if len(s)>1:
|
||||
prompt=s.strip();del(s)
|
||||
del(self.maple_message)
|
||||
print(f'human > {prompt}')
|
||||
if max_turns_history==0:
|
||||
turns=[]
|
||||
turn={
|
||||
'human_messages':[],
|
||||
'maple_messages':[]
|
||||
}
|
||||
turns.append(turn)
|
||||
turn['human_messages'].append(prompt)
|
||||
history=""
|
||||
from_index=max(len(turns)-max_turns_history-1,0) if max_turns_history>=0 else 0
|
||||
for turn in turns[from_index:]:
|
||||
for message in turn['human_messages']:
|
||||
history+=message+tokenizer.eos_token
|
||||
for message in turn['maple_messages']:
|
||||
history+=message+tokenizer.eos_token
|
||||
maple_messages=self.generate_response(
|
||||
model,
|
||||
tokenizer,
|
||||
history,
|
||||
config,
|
||||
mmi_model=mmi_model,
|
||||
mmi_tokenizer=mmi_tokenizer
|
||||
)
|
||||
if num_samples==1:
|
||||
maple_message=maple_messages[0]
|
||||
else:
|
||||
maple_message=random.choice(maple_messages)
|
||||
turn['maple_messages'].append(maple_message)
|
||||
print(f'maple > {maple_message}')
|
||||
print(maple_message)
|
||||
self.bot.privmsg('#staff',self.bot.emo(maple_message))
|
||||
print('cya')
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def main(self):
|
||||
loop=self.bot.loop
|
||||
loop.call_later(self.delay,self.main)
|
||||
tasks=[]
|
||||
task=loop.run_in_executor(None,self.run_chat(self.model,self.tokenizer,self.config,mmi_model=self.mmi_model,mmi_tokenizer=self.mmi_tokenizer))
|
||||
tasks.append(task)
|
||||
print('l8r')
|
||||
###########################################################################################################
|
||||
###########################################################################################################
|
|
@ -0,0 +1,145 @@
|
|||
import os
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
from glob import glob
|
||||
import torch
|
||||
import configparser
|
||||
import argparse
|
||||
import logging
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
from transformers import GPT2Config, GPT2LMHeadModel, GPT2Tokenizer
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
CONFIG_FILE = {
|
||||
'small': 'https://convaisharables.blob.core.windows.net/lsp/117M/config.json',
|
||||
'medium': 'https://convaisharables.blob.core.windows.net/lsp/345M/config.json'
|
||||
}
|
||||
VOCAB_FILE = {
|
||||
'small': 'https://convaisharables.blob.core.windows.net/lsp/117M/vocab.json',
|
||||
'medium': 'https://convaisharables.blob.core.windows.net/lsp/345M/vocab.json'
|
||||
}
|
||||
MERGE_FILE = {
|
||||
'small': 'https://convaisharables.blob.core.windows.net/lsp/117M/merges.txt',
|
||||
'medium': 'https://convaisharables.blob.core.windows.net/lsp/345M/merges.txt'
|
||||
}
|
||||
LSP_MODEL_URL = {
|
||||
'multiref': {
|
||||
'medium_fs': 'https://convaisharables.blob.core.windows.net/lsp/multiref/medium_fs.pkl',
|
||||
'medium_ft': 'https://convaisharables.blob.core.windows.net/lsp/multiref/medium_ft.pkl',
|
||||
'small_fs': 'https://convaisharables.blob.core.windows.net/lsp/multiref/small_fs.pkl',
|
||||
'small_ft': 'https://convaisharables.blob.core.windows.net/lsp/multiref/small_ft.pkl'
|
||||
},
|
||||
'dstc': {
|
||||
'small_ft': 'https://convaisharables.blob.core.windows.net/lsp/DSTC/medium_ft.pkl'
|
||||
}
|
||||
}
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
REVERSE_MODEL_URL = 'https://convaisharables.blob.core.windows.net/lsp/multiref/small_reverse.pkl'
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def http_get(url, temp_file):
|
||||
req = requests.get(url, stream=True)
|
||||
content_length = req.headers.get('Content-Length')
|
||||
total = int(content_length) if content_length is not None else None
|
||||
progress = tqdm(unit="B", total=total)
|
||||
for chunk in req.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
progress.update(len(chunk))
|
||||
temp_file.write(chunk)
|
||||
progress.close()
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def download_file(url, folder):
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
file_name = os.path.basename(url)
|
||||
if 'pytorch_model.bin' in file_name:
|
||||
file_name = 'pytorch_model.bin'
|
||||
if os.path.isfile(os.path.join(folder, file_name)):
|
||||
return
|
||||
with open(os.path.join(folder, file_name), 'wb') as f:
|
||||
http_get(url, f)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def download_model_folder(config):
|
||||
data_folder = config.get('model', 'data_folder')
|
||||
model_size = config.get('model', 'model_size')
|
||||
dataset = config.get('model', 'dataset')
|
||||
from_scratch = config.getboolean('model', 'from_scratch')
|
||||
if not os.path.exists(data_folder):
|
||||
os.makedirs(data_folder, exist_ok=True)
|
||||
target_folder_name = model_size + "_" + dataset + ("_fs" if from_scratch else "_ft")
|
||||
target_folder = os.path.join(data_folder, target_folder_name)
|
||||
logger.info(f"Downloading model files to {target_folder_name}...")
|
||||
download_file(CONFIG_FILE[model_size], target_folder)
|
||||
download_file(VOCAB_FILE[model_size], target_folder)
|
||||
download_file(MERGE_FILE[model_size], target_folder)
|
||||
model_train_type = model_size + ('_fs' if from_scratch else '_ft')
|
||||
if model_train_type not in LSP_MODEL_URL[dataset]:
|
||||
k = ','.join(list(LSP_MODEL_URL[dataset].keys()))
|
||||
raise ValueError(f"'{model_train_type}' not exist for dataset '{dataset}', please choose from [{k}]")
|
||||
download_file(LSP_MODEL_URL[dataset][model_train_type], target_folder)
|
||||
return target_folder_name
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def download_reverse_model_folder(config):
|
||||
data_folder = config.get('model', 'data_folder')
|
||||
model_size = 'medium'
|
||||
if not os.path.exists(data_folder):
|
||||
os.makedirs(data_folder, exist_ok=True)
|
||||
target_folder_name = model_size + '_reverse'
|
||||
target_folder = os.path.join(data_folder, target_folder_name)
|
||||
logger.info(f"Downloading model files to {target_folder_name}...")
|
||||
download_file(CONFIG_FILE[model_size], target_folder)
|
||||
download_file(VOCAB_FILE[model_size], target_folder)
|
||||
download_file(MERGE_FILE[model_size], target_folder)
|
||||
download_file(REVERSE_MODEL_URL, target_folder)
|
||||
return target_folder_name
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def load_model(target_folder_name, config):
|
||||
data_folder = config.get('model', 'data_folder')
|
||||
model_size = config.get('model', 'model_size')
|
||||
no_cuda = config.getboolean('model', 'no_cuda')
|
||||
logger.info(f"Loading model from {target_folder_name}...")
|
||||
device = torch.device("cuda" if torch.cuda.is_available() and not no_cuda else "cpu")
|
||||
target_folder = os.path.join(data_folder, target_folder_name)
|
||||
tokenizer = GPT2Tokenizer(os.path.join(target_folder, 'vocab.json'), os.path.join(target_folder, 'merges.txt'))
|
||||
config = GPT2Config.from_json_file(os.path.join(target_folder, 'config.json'))
|
||||
state_dict_path = glob(os.path.join(target_folder, f'*.pkl'))[0]
|
||||
state_dict = torch.load(state_dict_path, map_location=device)
|
||||
if model_size == 'small':
|
||||
for key in list(state_dict.keys()):
|
||||
state_dict[key.replace('module.', '')] = state_dict.pop(key)
|
||||
state_dict['lm_head.weight'] = state_dict['lm_head.decoder.weight']
|
||||
state_dict.pop("lm_head.decoder.weight", None)
|
||||
model = GPT2LMHeadModel(config)
|
||||
model.load_state_dict(state_dict)
|
||||
model.to(device)
|
||||
model.eval()
|
||||
return model, tokenizer
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('--config', type=str, default="personality.cfg")
|
||||
args = arg_parser.parse_args()
|
||||
config = configparser.ConfigParser(allow_no_value=True)
|
||||
with open(args.config) as f:
|
||||
config.read_file(f)
|
||||
download_model_folder(config)
|
||||
use_mmi = config.getboolean('model', 'use_mmi')
|
||||
if use_mmi:
|
||||
download_reverse_model_folder(config)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,166 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
from datetime import datetime
|
||||
import dateutil.parser
|
||||
import timeago
|
||||
import uuid
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def notes(self, *args, **kwargs):
|
||||
"""list/write/del notes
|
||||
%%notes [<cmd>] [<operation>]
|
||||
"""
|
||||
return self.note(*args)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def note(self, mask, target, args):
|
||||
"""list/write/del notes
|
||||
%%note [<cmd>] [<operation>]
|
||||
"""
|
||||
cmd = args.get("<cmd>")
|
||||
if not cmd:
|
||||
msg = "Please specify read/write/delete/list"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
elif cmd in ["d","del","delete","remove"]:
|
||||
self.note_del(mask, target, args)
|
||||
elif cmd in ["w", "write","a", "add"]:
|
||||
self.note_write(mask, target, args)
|
||||
elif cmd in ["l", "list"]:
|
||||
self.note_list(mask, target, args)
|
||||
elif cmd in ["r", "read"]:
|
||||
self.note_read(mask, target, args)
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def note_del(self, mask, target, args):
|
||||
"""Delete Note or * for all notes
|
||||
%%note <cmd> <operation>
|
||||
"""
|
||||
note_uuid_hash = args.get("<operation>")
|
||||
if not note_uuid_hash:
|
||||
msg = "Please specify note"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
if note_uuid_hash == "*":
|
||||
self.bot.db.setlist("notes", [])
|
||||
msg = "All notes cleared!"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
else:
|
||||
note_list = self.bot.db.getlist("notes", [])
|
||||
if not note_list:
|
||||
msg = "{} Not Found".format(note_uuid_hash)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
else:
|
||||
if note_uuid_hash in [item.get("uuid") for item in note_list]:
|
||||
new_note_list = [item for item in note_list if item.get("uuid") != note_uuid_hash]
|
||||
self.bot.db.setlist("notes", new_note_list)
|
||||
msg = "{} Removed".format(note_uuid_hash)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def note_list(self, mask, target, args):
|
||||
"""List All Note Names
|
||||
%%note list
|
||||
"""
|
||||
note_list = self.bot.db.getlist("notes")
|
||||
if not note_list:
|
||||
msg = "No notes!"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
for note in note_list:
|
||||
note_uuid = note.get("uuid")
|
||||
note_from = note.get("from")
|
||||
note_time = dateutil.parser.parse(note.get("time"))
|
||||
note_time = timeago.format(note_time, datetime.now())
|
||||
note_msg = note.get("note_msg")
|
||||
msg = "<{}> {} | {} | {}".format(note_from, note_time, note_msg, note_uuid)
|
||||
self.bot.privmsg(target, msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def note_read(self, mask, target, args):
|
||||
"""Display Note
|
||||
%%note read <operation>
|
||||
"""
|
||||
note_name = args.get("<operation>")
|
||||
if not note_name:
|
||||
msg = "Please specify name or note id"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
note_list = self.bot.db.getlist("notes")
|
||||
if not note_list:
|
||||
msg = "No Notes in DB"
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
if not any(note_name in d["uuid"] for d in note_list):
|
||||
msg = "No notes with {} found".format(note_name)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
else:
|
||||
note = [d for d in note_list if d.get("uuid") == note_name]
|
||||
if note:
|
||||
note = note.pop()
|
||||
else:
|
||||
try:
|
||||
note = note_list[int(note_name)]
|
||||
except:
|
||||
msg = "No notes with {} found".format(note_name)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
note_uuid = note.get("uuid")
|
||||
note_from = note.get("from")
|
||||
note_time = dateutil.parser.parse(note.get("time"))
|
||||
note_time = timeago.format(note_time, datetime.now())
|
||||
note_msg = note.get("note_msg")
|
||||
msg = "<{}> {} | {} | {}".format(note_from, note_time, note_msg, note_uuid)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='admin', public=True, show_in_help_list=True)
|
||||
def note_write(self, mask, target, args):
|
||||
"""Add Note
|
||||
%%note write <note>
|
||||
"""
|
||||
note_msg = args.get("<operation>")
|
||||
note_list = self.bot.db.getlist("notes")
|
||||
if not note_list:
|
||||
note_list = []
|
||||
self.bot.db.setlist("notes", note_list)
|
||||
note_uuid = uuid.uuid4().hex
|
||||
note = {"time": datetime.now().isoformat(),
|
||||
"from": mask.nick, "uuid": note_uuid,
|
||||
"note_msg": note_msg}
|
||||
note_list.append(note)
|
||||
self.bot.db.setlist("notes", note_list)
|
||||
msg = "Note Added! {}".format(note_uuid)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),note)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import random
|
||||
import uuid
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self,bot):
|
||||
self.bot=bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.JOIN)
|
||||
def quote_user_join(self, mask, channel, **kw):
|
||||
"""quote a user when they join"""
|
||||
quote_list=self.bot.db.getlist("quotes")
|
||||
if not quote_list:
|
||||
quote_list=[]
|
||||
self.bot.db.setlist('quotes',[])
|
||||
quote_user=[]
|
||||
for i in range(len(quote_list)):
|
||||
user=mask.nick.lower()
|
||||
if mask.nick==self.bot.nick: user=self.bot.original_nick.lower()
|
||||
if(quote_list[i]['user']==user):
|
||||
quote_user.append(quote_list[i]['message'])
|
||||
if quote_user:
|
||||
msg=random.choice(quote_user)+' \x02\x0303▶\x0F '+user
|
||||
msg=self.bot.emo(msg)
|
||||
print(f'\n{msg}\n')
|
||||
self.bot.privmsg(channel,msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def quote(self,mask,target, args):
|
||||
"""quote user message
|
||||
%%quote <noise>...
|
||||
"""
|
||||
noise=' '.join(args['<noise>'])
|
||||
user=noise.split(' ')[0]
|
||||
noise=noise.split(' ')[1:]
|
||||
message=' '.join(noise)
|
||||
status=''
|
||||
try:
|
||||
quote_list=self.bot.db.getlist("quotes")
|
||||
if not quote_list:
|
||||
quote_list=[]
|
||||
self.bot.db.setlist("quotes",quote_list)
|
||||
quote_uuid=uuid.uuid4().hex
|
||||
quote={"user":user.lower(),"message":message,"uuid":quote_uuid}
|
||||
quote_list.append(quote)
|
||||
self.bot.db.setlist("quotes",quote_list)
|
||||
status=f"TCPDIRECT/QUOTED: {user} "
|
||||
status+=f"\x02\x0303▶\x0F {message} "
|
||||
status+=f"\x02\x0303▶\x0F {quote_uuid}"
|
||||
except Exception as e:
|
||||
status=f"\x02\x0304error \x02\x0303▶\x0F {e.message[0]['message']}'"
|
||||
msg=self.bot.emo(status)
|
||||
self.bot.privmsg(target,msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),message)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def quotes(self, mask, target, args):
|
||||
"""quotes user
|
||||
%%quotes <nick>
|
||||
"""
|
||||
user=args.get("<nick>")
|
||||
quote_list=self.bot.db.getlist("quotes")
|
||||
if not quote_list:
|
||||
quote_list=[]
|
||||
self.bot.db.setlist('quotes',[])
|
||||
quote_user=[]
|
||||
for i in range(len(quote_list)):
|
||||
if(quote_list[i]['user']==user):
|
||||
quote_user.append(quote_list[i]['message'])
|
||||
for i in range(len(quote_user)):
|
||||
msg=user+' \x02\x0303▶\x0F '+quote_user[i]
|
||||
msg=self.bot.emo(msg)
|
||||
self.bot.privmsg(target,msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,355 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
from irc3.plugins.cron import cron
|
||||
import irc3
|
||||
__doc__ = '''##########################################################################################################
|
||||
####################################################################################################################'''
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import URLError, HTTPError
|
||||
from random import randint
|
||||
__doc__ = '''##########################################################################################################
|
||||
#######################################################################################################################
|
||||
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy` yMMMMMMMMMMMMMMM- -mMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMs+dMMMMMMMMMM+ sMMMMMMMMMMMMMMM- `dMMMMMMMMMMms/NMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMM+ .omMMMMMM: -MMMMMMMMMMMMMMo `yMMMMMMMy: `dMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMM- /dMMM+ sMMMMMMMMMMMMh `hMMMNo` sMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMd :dm `mMMMMMMMMMMN. .NNo` .MMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMM: - :MMMMMMMMMMs :` sMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMs ymNMMMMMNm. NMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMy `-/-` .MMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMo .NMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMNh+. :sdMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMhso+:. `-/+syMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMM- dMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMM` `.:+/. `/s+:. sMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMNo -oms. .//-` `:/:` `+md+` .hMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMNs` .odNdo. .ohmd+` :dMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMNo` .. .- :hMMMMMMMMMMM
|
||||
MMMMMMMMMd+` -sNMMMMMMMM
|
||||
MMMMMMNs- `.. `/-. `+dMMMMMM
|
||||
MMMNy: ./sdNMMMh: `sNMMMNds/. .odMMM
|
||||
MM+ :ymMMMMMMMMMMh. +NMMMMMMMMMMmo- /NM
|
||||
MMMh: .sNMMMMMMMMMMMMMMN- `hMMMMMMMMMMMMMMMm+` :hMMM
|
||||
MMMMMd:` ``-:+shmMMMMMMMMMMMMMMMMMMN. hMMMMMMMMMMMMMMMMMMMmhs+/-..``````./dMMMMM
|
||||
MMMMMMMMMNNNNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMo .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN. /MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN+` `+NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs. -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMdyymMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|
||||
#######################################################################################################################
|
||||
####################################################################################################################'''
|
||||
|
||||
rgb2irc = { 52: '16', 94: '17', 100: '18', 58: '19', 22: '20', 29: '21', 23: '22', 24: '23', 17: '24', 54: '25', 53: '26', 89: '27',
|
||||
88: '28', 130: '29', 142: '30', 64: '31', 28: '32', 35: '33', 30: '34', 25: '35', 18: '36', 91: '37', 90: '38', 125: '39',
|
||||
124: '40', 166: '41', 184: '42', 106: '43', 34: '44', 49: '45', 37: '46', 33: '47', 19: '48', 129: '49', 127: '50', 161: '51',
|
||||
196: '52', 208: '53', 226: '54', 154: '55', 46: '56', 86: '57', 51: '58', 75: '59', 21: '60', 171: '61', 201: '62', 198: '63',
|
||||
203: '64', 215: '65', 227: '66', 191: '67', 83: '68', 122: '69', 87: '70', 111: '71', 63: '72', 177: '73', 207: '74', 205: '75',
|
||||
217: '76', 223: '77', 229: '78', 193: '79', 157: '80', 158: '81', 159: '82', 153: '83', 147: '84', 183: '85', 219: '86', 212: '87',
|
||||
16: '88', 233: '89', 235: '90', 237: '91', 239: '92', 241: '93', 244: '94', 247: '95', 250: '96', 254: '97', 231: '98', }
|
||||
|
||||
__doc__ = '''##########################################################################################################
|
||||
####################################################################################################################'''
|
||||
|
||||
rgb2set = { "ef0": "#000000", "ef1": "#CD0000", "ef2": "#00CD00", "ef3": "#CDCD00", "ef4": "#0000EE", "ef5": "#CD00CD", "ef6": "#00CDCD", "ef7": "#E5E5E5",
|
||||
"ef8": "#7F7F7F", "ef9": "#FF0000", "ef10": "#00FF00", "ef11": "#FFFF00", "ef12": "#5C5CFF", "ef13": "#FF00FF", "ef14": "#00FFFF", "ef15": "#FFFFFF",
|
||||
"eb8": "#7F7F7F", "eb9": "#FF0000", "eb10": "#00FF00", "eb11": "#FFFF00", "eb12": "#5C5CFF", "eb13": "#FF00FF", "eb14": "#00FFFF", "eb15": "#FFFFFF", "ef16": "#000000",
|
||||
"ef17": "#00005f", "ef18": "#000087", "ef19": "#0000af", "ef20": "#0000d7", "ef21": "#0000ff", "ef22": "#005f00", "ef23": "#005f5f", "ef24": "#005f87", "ef25": "#005faf",
|
||||
"ef26": "#005fd7", "ef27": "#005fff", "ef28": "#008700", "ef29": "#00875f", "ef30": "#008787", "ef31": "#0087af", "ef32": "#0087d7", "ef33": "#0087ff", "ef34": "#00af00",
|
||||
"ef35": "#00af5f", "ef36": "#00af87", "ef37": "#00afaf", "ef38": "#00afd7", "ef39": "#00afff", "ef40": "#00d700", "ef41": "#00d75f", "ef42": "#00d787", "ef43": "#00d7af",
|
||||
"ef44": "#00d7d7", "ef45": "#00d7ff", "ef46": "#00ff00", "ef47": "#00ff5f", "ef48": "#00ff87", "ef49": "#00ffaf", "ef50": "#00ffd7", "ef51": "#00ffff", "ef52": "#5f0000",
|
||||
"ef53": "#5f005f", "ef54": "#5f0087", "ef55": "#5f00af", "ef56": "#5f00d7", "ef57": "#5f00ff", "ef58": "#5f5f00", "ef59": "#5f5f5f", "ef60": "#5f5f87", "ef61": "#5f5faf",
|
||||
"ef62": "#5f5fd7", "ef63": "#5f5fff", "ef64": "#5f8700", "ef65": "#5f875f", "ef66": "#5f8787", "ef67": "#5f87af", "ef68": "#5f87d7", "ef69": "#5f87ff", "ef70": "#5faf00",
|
||||
"ef71": "#5faf5f", "ef72": "#5faf87", "ef73": "#5fafaf", "ef74": "#5fafd7", "ef75": "#5fafff", "ef76": "#5fd700", "ef77": "#5fd75f", "ef78": "#5fd787", "ef79": "#5fd7af",
|
||||
"ef80": "#5fd7d7", "ef81": "#5fd7ff", "ef82": "#5fff00", "ef83": "#5fff5f", "ef84": "#5fff87", "ef85": "#5fffaf", "ef86": "#5fffd7", "ef87": "#5fffff", "ef88": "#870000",
|
||||
"ef89": "#87005f", "ef90": "#870087", "ef91": "#8700af", "ef92": "#8700d7", "ef93": "#8700ff", "ef94": "#875f00", "ef95": "#875f5f", "ef96": "#875f87", "ef97": "#875faf",
|
||||
"ef98": "#875fd7", "ef99": "#875fff", "ef100": "#878700", "ef101": "#87875f", "ef102": "#878787", "ef103": "#8787af", "ef104": "#8787d7", "ef105": "#8787ff", "ef106": "#87af00",
|
||||
"ef107": "#87af5f", "ef108": "#87af87", "ef109": "#87afaf", "ef110": "#87afd7", "ef111": "#87afff", "ef112": "#87d700", "ef113": "#87d75f", "ef114": "#87d787", "ef115": "#87d7af",
|
||||
"ef116": "#87d7d7", "ef117": "#87d7ff", "ef118": "#87ff00", "ef119": "#87ff5f", "ef120": "#87ff87", "ef121": "#87ffaf", "ef122": "#87ffd7", "ef123": "#87ffff", "ef124": "#af0000",
|
||||
"ef125": "#af005f", "ef126": "#af0087", "ef127": "#af00af", "ef128": "#af00d7", "ef129": "#af00ff", "ef130": "#af5f00", "ef131": "#af5f5f", "ef132": "#af5f87", "ef133": "#af5faf",
|
||||
"ef134": "#af5fd7", "ef135": "#af5fff", "ef136": "#af8700", "ef137": "#af875f", "ef138": "#af8787", "ef139": "#af87af", "ef140": "#af87d7", "ef141": "#af87ff", "ef142": "#afaf00",
|
||||
"ef143": "#afaf5f", "ef144": "#afaf87", "ef145": "#afafaf", "ef146": "#afafd7", "ef147": "#afafff", "ef148": "#afd700", "ef149": "#afd75f", "ef150": "#afd787", "ef151": "#afd7af",
|
||||
"ef152": "#afd7d7", "ef153": "#afd7ff", "ef154": "#afff00", "ef155": "#afff5f", "ef156": "#afff87", "ef157": "#afffaf", "ef158": "#afffd7", "ef159": "#afffff", "ef160": "#d70000",
|
||||
"ef161": "#d7005f", "ef162": "#d70087", "ef163": "#d700af", "ef164": "#d700d7", "ef165": "#d700ff", "ef166": "#d75f00", "ef167": "#d75f5f", "ef168": "#d75f87", "ef169": "#d75faf",
|
||||
"ef170": "#d75fd7", "ef171": "#d75fff", "ef172": "#d78700", "ef173": "#d7875f", "ef174": "#d78787", "ef175": "#d787af", "ef176": "#d787d7", "ef177": "#d787ff", "ef178": "#d7af00",
|
||||
"ef179": "#d7af5f", "ef180": "#d7af87", "ef181": "#d7afaf", "ef182": "#d7afd7", "ef183": "#d7afff", "ef184": "#d7d700", "ef185": "#d7d75f", "ef186": "#d7d787", "ef187": "#d7d7af",
|
||||
"ef188": "#d7d7d7", "ef189": "#d7d7ff", "ef190": "#d7ff00", "ef191": "#d7ff5f", "ef192": "#d7ff87", "ef193": "#d7ffaf", "ef194": "#d7ffd7", "ef195": "#d7ffff", "ef196": "#ff0000",
|
||||
"ef197": "#ff005f", "ef198": "#ff0087", "ef199": "#ff00af", "ef200": "#ff00d7", "ef201": "#ff00ff", "ef202": "#ff5f00", "ef203": "#ff5f5f", "ef204": "#ff5f87", "ef205": "#ff5faf",
|
||||
"ef206": "#ff5fd7", "ef207": "#ff5fff", "ef208": "#ff8700", "ef209": "#ff875f", "ef210": "#ff8787", "ef211": "#ff87af", "ef212": "#ff87d7", "ef213": "#ff87ff", "ef214": "#ffaf00",
|
||||
"ef215": "#ffaf5f", "ef216": "#ffaf87", "ef217": "#ffafaf", "ef218": "#ffafd7", "ef219": "#ffafff", "ef220": "#ffd700", "ef221": "#ffd75f", "ef222": "#ffd787", "ef223": "#ffd7af",
|
||||
"ef224": "#ffd7d7", "ef225": "#ffd7ff", "ef226": "#ffff00", "ef227": "#ffff5f", "ef228": "#ffff87", "ef229": "#ffffaf", "ef230": "#ffffd7", "ef231": "#ffffff", "ef232": "#080808",
|
||||
"ef233": "#121212", "ef234": "#1c1c1c", "ef235": "#262626", "ef236": "#303030", "ef237": "#3a3a3a", "ef238": "#444444", "ef239": "#4e4e4e", "ef240": "#585858", "ef241": "#626262",
|
||||
"ef242": "#6c6c6c", "ef243": "#767676", "ef244": "#808080", "ef245": "#8a8a8a", "ef246": "#949494", "ef247": "#9e9e9e", "ef248": "#a8a8a8", "ef249": "#b2b2b2", "ef250": "#bcbcbc",
|
||||
"ef251": "#c6c6c6", "ef252": "#d0d0d0", "ef253": "#dadada", "ef254": "#e4e4e4", "ef255": "#eeeeee", }
|
||||
|
||||
__doc__ = '''##########################################################################################################
|
||||
####################################################################################################################'''
|
||||
|
||||
set2rgb = { 52: '#470000', 94: '#472100', 100: '#474700', 58: '#324700', 22: '#004700', 29: '#00472C', 23: '#004747', 24: '#002747', 17: '#000047', 54: '#2E0047', 53: '#470047', 89: '#47002A',
|
||||
88: '#740000', 130: '#743A00', 142: '#747400', 64: '#517400', 28: '#007400', 35: '#007449', 30: '#007474', 25: '#004074', 18: '#000074', 91: '#4B0074', 90: '#740074', 125: '#740045',
|
||||
124: '#B50000', 166: '#B56300', 184: '#B5B500', 106: '#7DB500', 34: '#00B500', 49: '#00B571', 37: '#00B5B5', 33: '#0063B5', 19: '#0000B5', 129: '#7500B5', 127: '#B500B5', 161: '#B5006B',
|
||||
196: '#FF0000', 208: '#FF8C00', 226: '#FFFF00', 154: '#B2FF00', 46: '#00FF00', 86: '#00FFA0', 51: '#00FFFF', 75: '#008CFF', 21: '#0000FF', 171: '#A500FF', 201: '#FF00FF', 198: '#FF0098',
|
||||
203: '#FF5959', 215: '#FFB459', 227: '#FFFF71', 191: '#CFFF60', 83: '#6FFF6F', 122: '#65FFC9', 87: '#6DFFFF', 111: '#59B4FF', 63: '#5959FF', 177: '#C459FF', 207: '#FF66FF', 205: '#FF59BC',
|
||||
217: '#FF9C9C', 223: '#FFD39C', 229: '#FFFF9C', 193: '#E2FF9C', 157: '#9CFF9C', 158: '#9CFFDB', 159: '#9CFFFF', 153: '#9CD3FF', 147: '#9CD3FF', 183: '#DC9CFF', 219: '#FF9CFF', 212: '#FF94D3',
|
||||
16: '#000000', 233: '#131313', 235: '#282828', 237: '#363636', 239: '#4D4D4D', 241: '#656565', 244: '#818181', 247: '#9F9F9F', 250: '#BCBCBC', 254: '#E2E2E2', 231: '#FFFFFF', }
|
||||
|
||||
__doc__ = '''##########################################################################################################
|
||||
####################################################################################################################'''
|
||||
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def __init__(self, bot):
|
||||
__doc__ = ''' ##############################################################################################'''
|
||||
|
||||
self.bot = bot
|
||||
|
||||
__doc__ = ''' ##############################################################################################'''
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def ratesex_request(self,site,commands):
|
||||
USER_AGENT_BROWSER="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
|
||||
USER_AGENT_CURL="curl/7.29.0"
|
||||
STATUS_BAD_CODE=":( - error code: {}"
|
||||
STATUS_BAD_REASON=":( - failed reason: {}"
|
||||
STATUS_OK=":)"
|
||||
|
||||
if site != 'rate':
|
||||
url = f"https://{site}.rate.sx/{commands}"
|
||||
else:
|
||||
url = f"https://rate.sx/{commands}"
|
||||
r = Request(url,data=None,headers={ 'User-Agent': USER_AGENT_CURL })
|
||||
try:
|
||||
response = urlopen(r,timeout=10).read().decode('utf-8')
|
||||
except HTTPError as e:
|
||||
return STATUS_BAD_CODE.format(e.code)
|
||||
except URLError as e:
|
||||
return STATUS_BAD_REASON.format(e.reason)
|
||||
else:
|
||||
return STATUS_OK + response
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def escape_ansi(self,line):
|
||||
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
|
||||
return ansi_escape.sub('', str(line))
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def invert_dict(self,d):
|
||||
return {v: k for k, v in d.items()}
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def enumerate_dict(self,d):
|
||||
return list(zip(list(d),list(invert_dict(d)),range(len(d))))
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def organize_dict(self,d):
|
||||
_d=list(d.values())
|
||||
return _d.sort()
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def escape_ansi(self,line):
|
||||
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
|
||||
return ansi_escape.sub('', str(line))
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def hex2gravity(self,h):
|
||||
r,g,b=int(h[1:3],16),int(h[3:5],16),int(h[5:7],16)
|
||||
o=list(set2rgb.values()); o.sort()
|
||||
_R=[]; _G=[]; _B=[];
|
||||
|
||||
for _ in o:
|
||||
R,G,B=(''.join([x for x in _[1:][:2]]).zfill(2)),(''.join([x for x in _[1:][2:4]]).zfill(2)),(''.join([x for x in _[1:][4:6]]).zfill(2))
|
||||
_R.append(int(R,16)); _G.append(int(G,16)); _B.append(int(B,16));
|
||||
|
||||
_r = []
|
||||
for _ in _R:
|
||||
if r < _:
|
||||
rsub = _ - r
|
||||
else:
|
||||
rsub = r - _
|
||||
_r.append(rsub)
|
||||
|
||||
_g = []
|
||||
for _ in _G:
|
||||
if g < _:
|
||||
gsub = _ - g
|
||||
else:
|
||||
gsub = g - _
|
||||
_g.append(gsub)
|
||||
|
||||
_b = []
|
||||
for _ in _B:
|
||||
if b < _:
|
||||
bsub = _ - b
|
||||
else:
|
||||
bsub = b - _
|
||||
_b.append(bsub)
|
||||
rgb = []
|
||||
for _ in range(len(_r)):
|
||||
rgb.append(_r[_]+_g[_]+_b[_])
|
||||
nearest_color_minus = min(rgb)
|
||||
nearest_color_index = [i for i, x in enumerate(rgb) if x == nearest_color_minus]
|
||||
nearest_color = o[nearest_color_index[0]]
|
||||
return str(f"\x03{rgb2irc[self.invert_dict(set2rgb)[nearest_color]]}")
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def parse_control(self,s):
|
||||
px=[]
|
||||
py=[]
|
||||
_s=s
|
||||
px=self.findall(_s,'\x1b')
|
||||
for i,_ in enumerate(px):
|
||||
py.append( _s.find('m',_)+1 )
|
||||
return px,py
|
||||
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def findall(self,s,w):
|
||||
return [i for i in range(len(s)) if s.startswith(w, i)]
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
def color_line(self,s,t):
|
||||
codes=["\x1b[0m","\x1b[30m","\x1b[31m","\x1b[32m","\x1b[33m","\x1b[34m","\x1b[35m","\x1b[36m","\x1b[37m","\x1b[40m","\x1b[41m","\x1b[42m","\x1b[43m","\x1b[44m","\x1b[45m","\x1b[46m","\x1b[47m","\x1b(B","\x1b[m","\x1b[2m"]
|
||||
colors=["\x0f","\x0301","\x0304","\x0303","\x0308","\x03002","\x0313","\x0311","\x0300","\x03,01","\x03,04","\x03,03","\x03,08","\x03,02","\x03,13","\x03,11","\x03,00","","\x0f",""] #f.write('\x0301,00decoded\n')
|
||||
_s=s
|
||||
p=[]
|
||||
for _ in range(len(t[0])):
|
||||
r=self.findall(s[t[0][_]:t[1][_]],'\x1b')
|
||||
|
||||
for __ in range(len(r)):
|
||||
if not __ == len(r)-1:
|
||||
p.append(s[t[0][_]:t[1][_]][r[__]:r[__+1]])
|
||||
else:
|
||||
check = s[t[0][_]:t[1][_]][r[__]:]
|
||||
if check.find('mm') == -1:
|
||||
p.append(check)
|
||||
else:
|
||||
p.append(check[:-1])
|
||||
for __ in p:
|
||||
_s = _s.replace(__,"{}")
|
||||
c=[]
|
||||
for _ in p:
|
||||
for i,__ in enumerate(codes):
|
||||
if _ == __:
|
||||
c.append(colors[i])
|
||||
if _.find('\x1b[38;5;') != -1:
|
||||
gravity = _.replace('\x1b[38;5;','')[:-1]
|
||||
farthest_color_hex = rgb2set['ef{}'.format(gravity)]
|
||||
result = self.hex2gravity(farthest_color_hex)
|
||||
c.append(result)
|
||||
|
||||
r=self.findall(_s,'{}')
|
||||
|
||||
for _ in range(len(r)):
|
||||
_s=_s.replace('{}',c[_],1)
|
||||
return _s
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
@command(permission='view')
|
||||
def ratesex(self, mask, target, args):
|
||||
"""ratesex - help/commands: visit 'https://rate.sx/:help' or try '?ratesex rate :help', to check exchange rates for top 10 ^cripdoeocurrencies try '?ratesex rate top10.. sites added. rate,eur,btc,rub.. e.g. ?ratesex rate command, ?ratesex eur, ?ratesex btc, ?ratesex rub'
|
||||
%%ratesex [<site>] [<command>]
|
||||
"""
|
||||
|
||||
site = args.get("<site>")
|
||||
command = args.get("<command>")
|
||||
|
||||
if command == "":
|
||||
msg="error: no command issued.. ?ratesex rate, ?ratesex rate eth, ?ratesex rate :help, ?ratesex btc top10"
|
||||
self.bot.privmsg(target, msg)
|
||||
|
||||
sites=['rate','rub','eur','btc']
|
||||
FLAG=0
|
||||
for _ in sites:
|
||||
if site == _:
|
||||
FLAG=1
|
||||
if not FLAG==1:
|
||||
msg="error: no site issued. sites: rate,rub,eur,btc. e.g. ?ratesex rate :help, ?ratesex btc top10, ?ratesex rub top10"
|
||||
self.bot.privmsg(target, msg)
|
||||
if command.lower() == 'top10': command = ''
|
||||
response=self.ratesex_request(site,command)
|
||||
s = ''
|
||||
for _ in response:
|
||||
s = s + ''.join(_)
|
||||
r1=s[2:].splitlines()
|
||||
for i in range(len(r1)-1):
|
||||
d=self.parse_control(r1[i])
|
||||
r=self.color_line(r1[i],d)
|
||||
if not r == '':
|
||||
msg = r+'\n'
|
||||
self.bot.privmsg(target, msg)
|
||||
|
||||
__doc__ = ''' ##################################################################################################'''
|
||||
|
||||
|
||||
__doc__ = ''':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.
|
||||
/mMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNd-
|
||||
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN`
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmNMMMMMMMMMMMmMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh:NMMMMMMMMMMoyMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm -NMMMMMMMMMs.NMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy -hmmmmmNNm- sMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmdyo+:` ```````.` .NMMMymMMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmy+-.` -hNm-+MMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMms:` `.. /MMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh/. /MMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMmMMMMMMMMMMMmhN:` /MMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMM+sNMMMMMMMMMN-h: `-+syyys/- -NMMMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMs +NMMMMMMMhm--d` :. -sdNMMMMMNNmy. :ydMMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMM+ :yhyyyhhso` os yhshNMMMMMMMh+:-:. :s- .NMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMmho` ` `yo.h:sMMMMMMMMMMNd+. -NNs- yMMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMMMNh/. :++`-MMMMMMMMMMMMMm+` :ymds. -NMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMMMmo- .MMMMMMMMMMMMMMMdo. `.-` yMMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMMMmo. `NMMMMMMMMMMMMMMMMNy/.` `mMMMMMMMMMMMMMMM-
|
||||
/MMMMMMMNs. hMMMMMMMMMMMMMMMMMMMNho-` :NMMMMMMMMMMMMMM-
|
||||
/MMMMMMm: ./syyyo- -hmNMMMMMMMMMMMMMMMMMMMMmho:.` /NMMMMMMMMMMMMM-
|
||||
/MMMMMd. .smMMMNNNms` ` `+MMMMMMMMMMMMMMMMMMMMMMMMNdy/ `.yMMMMMMMMMMMMM-
|
||||
/MMMMd. /mMMMMMy/:--` so. `mMMMMMMMMMMMMMMMMMMMMMMMNdo--:+sdNMMMMMMMMMMMMMM-
|
||||
/MMMN- /NMMMMMMMMdo. oMm+. /MMMMMMMMMMMMMMMMdNMMMMMMNNNMMmMMMMMMMMMMMMMMMMM-
|
||||
/MMMo -NMMMMMMMMMMdso-` /hmm+ sMMMMMMMMMMMMMMMs-mMMMMMMMMMM:dMMMMMMMMMMMMMMMM-
|
||||
/MMN. sMMMMMMMMMMMo .os/.``.. `dMMMMMMMMMMMMMMs -NMMMMMMMMM-:MMMMMMMMMMMMMMMM-
|
||||
/MMd mMMMMMMMMMMM/ `:os+-` .dMMMMMMMMMMMNm. -soosyhdms `mMMMMMMMMMMMMMMM-
|
||||
/MMs mMMMMMMMMMMM: .hNhs/.` .dMMMMNmhs+:-` +MMMNoMMMMMMMMMM-
|
||||
/MMy hMMMMMMMMMMM: oMMMMMNdyo/. .mNh+-` +mNy`mMMMMMMMMM-
|
||||
/MMd +MMMMMMMMMMM/ :MMMMMMMMNs.`.:ohh/` ` mMMMMMMMMM-
|
||||
/MMN. `mMMMMMMMMMMo `NMMMMMMNhhdNMMh: mMMMMMMMMM-
|
||||
/MMM+ /MMMMMMMMMMh yMMMMMMMMMMMN+ `NMMMMMMMMM-
|
||||
/MMMm` +MMMMMMMMMN` .NMMMMMMMMMN- :sdmNNNdy+` dMMMMMMMMM-
|
||||
/MMMMo +MMMMMMMMM+ +MMMMMMMMM/ -dMMMMMMNmmNN/ .sdMMMMMMM-
|
||||
/MMMMN: :mMMMMMMMm` oMMMMMMMh .mMMMMMMMms- `` /o` `mMMMMMM-
|
||||
/MMMMMm. .yMMMMMMMo oMMMMMM/ sMMMMMMMMMMMh: :NNo. sMMMMMM-
|
||||
/MMMMMMm. -hMMMMMN: /NMMMM. dMMMMMMMMMMMMMh- :hmNy` .NMMMMM-
|
||||
/MMMMMMMm- -yNMMMm. .yMMM. dMMMMMMMMMMMMMMNh:` `..` yMMMMM-
|
||||
/MMMMMMMMN+ .+hNMd. :hM: dMMMMMMMMMMMMMMMMNmo- .NMMMM-
|
||||
/MMMMMMMMMMh- ./ss. `:: sMMMMMMMMMMMMMMMMMMMNms/. /MMMM-
|
||||
/MMMMMMMMMMMNo. ` :MMMMMMMMMMMMMMMMMMMMMMMNdo:.` oMMM-
|
||||
/MMMMMMMMMMMMMmo. `mMMMMMMMMMMMMMMMMMMMMMMMMMMNmh: .dMM-
|
||||
/MMMMMMMMMMMMMMMNy:` +MMMMMMMMMMMMMMMMMMMMMMMMMMNh+::/+sdNMMM-
|
||||
/MMMMMMMMMMMMMMMMMNdo- `dMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNMMMMMMMM-
|
||||
/MMMMMMMMMMMMMMMMMMMMNd+-` -NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
|
||||
-NMMMMMMMMMMMMMMMMMMMMMMNdo:` /NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMd`
|
||||
-ymNNNNNNNNNNNNNNNNNNNNNNNNdo-` +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNmy.
|
||||
............................ .-...............................`
|
||||
`````` ````````` `````````````` `````````` ```'''
|
|
@ -0,0 +1,107 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
from irc3.plugins.cron import cron
|
||||
import irc3
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
import re
|
||||
REMIND_RE = re.compile('maple.remind\s(.+?)\s(.+)')
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __triggered(i):
|
||||
time_now = int(str(time()).split('.')[0])
|
||||
if i <= time_now:
|
||||
print('triggered')
|
||||
else:
|
||||
print('not triggered')
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_remind(self, mask=None, target=None, data=None, **kw):
|
||||
match_list = REMIND_RE.findall(data)
|
||||
if len(match_list) > 0:
|
||||
stime = ""
|
||||
trigger = ""
|
||||
bhours = False
|
||||
bminutes = False
|
||||
tell_nick, message = match_list[0]
|
||||
if tell_nick == 'me': tell_nick = mask.nick
|
||||
if not message.split()[0].lower() == 'in':
|
||||
irc_message = "TCPDIRECT/REMIND: reminding {} the format is maple remind ircnick in 2h15m to pet cat, or maple remind me in 1h to pet cat.".format(mask.nick)
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
return
|
||||
else:
|
||||
message = message[3:]
|
||||
trigger = message.split()[0]
|
||||
message = message[len(trigger)+1:]
|
||||
message_list = self.bot.db.getlist("remind_%s" % tell_nick.lower())
|
||||
ihours = 0
|
||||
iminutes = 0
|
||||
xpos = 0
|
||||
ypos = 0
|
||||
itrigger = 0
|
||||
epoch_time = int(str(time()).split('.')[0])
|
||||
stime = trigger
|
||||
try:
|
||||
if not stime.lower().find('h') == -1:
|
||||
xpos = stime.lower().find('h')+1
|
||||
hours = int(stime[:stime.lower().find('h')])
|
||||
ihours = hours * (60*60)
|
||||
if not stime.lower().find('m') == -1:
|
||||
ypos = stime.lower().find('m')
|
||||
minutes = int(stime[xpos:ypos])
|
||||
if minutes < 1:
|
||||
irc_message = "TCPDIRECT/REMIND: reminding {} to quit wasting my time. format is maple remind ircnick in 2h15m to pet cat, or maple remind me in 1h to pet cat.".format(mask.nick)
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
return
|
||||
iminutes = minutes * 60
|
||||
except:
|
||||
irc_message = "TCPDIRECT/REMIND: reminding {} to go and fuck themself err i mean, format is maple remind ircnick in 2h15m to pet cat, or maple remind me in 1h to pet cat.".format(mask.nick)
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
return
|
||||
epoch_trigger = epoch_time + ihours + iminutes
|
||||
if epoch_trigger <= epoch_time:
|
||||
irc_message = "TCPDIRECT/REMIND: reminding {} to quit wasting my time. format is maple remind ircnick in 2h15m to pet cat, or maple remind me in 1h to pet cat.".format(mask.nick)
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
return
|
||||
new_message = {"from": mask.nick.lower(), "target": target, "message": message, "time": datetime.now().isoformat(), "etime": epoch_time, "etrigger": epoch_trigger }
|
||||
if not message_list:
|
||||
message_list = self.bot.db.setlist("remind_%s" % tell_nick.lower(), [new_message])
|
||||
else:
|
||||
message_list.append(new_message)
|
||||
self.bot.db.setlist("remind_%s" % tell_nick.lower(), message_list)
|
||||
irc_message = "TCPDIRECT/REMIND: {} < {} > reminding < {} > {}".format(new_message.get("time"),new_message.get("from"),tell_nick,new_message.get("message"))
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@cron('* * * * *')
|
||||
def _reminding(bot):
|
||||
nicks = ','.join(bot.db.context.nicks.keys()).split(',')
|
||||
for _ in nicks:
|
||||
if bot.db.getlist('remind_{}'.format(_)):
|
||||
_keys = []
|
||||
for __ in bot.db.getlist('remind_{}'.format(_)):
|
||||
etime = __['etime']
|
||||
etrigger = __['etrigger']
|
||||
_from = __['from']
|
||||
_target = __['target']
|
||||
_message = __['message']
|
||||
etime_now = int(str(time()).split('.')[0])
|
||||
if etime_now >= etrigger:
|
||||
msg = "TCPDIRECT/REMIND: < {} > reminded < {} > - {}".format(_from,_,_message)
|
||||
bot.privmsg(_target,msg)
|
||||
else:
|
||||
_keys.append(__)
|
||||
bot.db.setlist("remind_{}".format(_),_keys)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import irc3
|
||||
import os
|
||||
import random
|
||||
from string import ascii_lowercase as alpha
|
||||
SED1_RE = "juggle s/"
|
||||
SED2_RE = "j/"
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
class TCPSED():
|
||||
buffer_text=[]
|
||||
buffer_nick=[]
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self):
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def push(self,data,nick):
|
||||
self.buffer_text=self.buffer_text[-1:]+self.buffer_text[:-1]
|
||||
self.buffer_text[0]=data
|
||||
self.buffer_nick=self.buffer_nick[-1:]+self.buffer_nick[:-1]
|
||||
self.buffer_nick[0]=nick
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.d=TCPSED()
|
||||
for _ in range(2000):
|
||||
self.d.buffer_text.append('')
|
||||
self.d.buffer_nick.append('')
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_sed(self, mask=None, target=None, data=None, **kw):
|
||||
if self.bot.config.nick == mask.nick:
|
||||
return
|
||||
if mask.nick.lower() == 'nickserv':
|
||||
return
|
||||
flag=0
|
||||
offset = -1
|
||||
offset = data.find(SED1_RE)
|
||||
if not offset == 0:
|
||||
offset = data.find(SED2_RE)
|
||||
if offset == 0:
|
||||
flag=1
|
||||
if flag==0:
|
||||
self.d.push(data,mask.nick)
|
||||
return
|
||||
_data=data.split('/')
|
||||
_from=''
|
||||
_to=''
|
||||
_mode=''
|
||||
try:
|
||||
_from=_data[1]
|
||||
_to=_data[2]
|
||||
if len(_data) == 4:
|
||||
if _data[3].lower() == 'g': _mode='g'
|
||||
except Exception as e:
|
||||
irc_message = f'TCPDIRECT/SED - Error: {e}'
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
return
|
||||
itwist=-1
|
||||
count=0
|
||||
for i,_ in enumerate(self.d.buffer_text):
|
||||
if not _ == '':
|
||||
itwist=i
|
||||
count = len([_i for _i in range(len(_)) if _.startswith(_from, _i)])
|
||||
if count == 1:
|
||||
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to)
|
||||
break
|
||||
elif count > 1:
|
||||
if _mode == 'g':
|
||||
for y in range(count):
|
||||
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to)
|
||||
break
|
||||
else:
|
||||
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to,1)
|
||||
break
|
||||
if count != 0:
|
||||
irc_message = "{}: {}".format(self.d.buffer_nick[itwist],self.d.buffer_text[itwist])
|
||||
else:
|
||||
irc_message = f"TCPDIRECT/SED - Error: no result for: {data}"
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,92 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
from datetime import datetime
|
||||
import operator
|
||||
import irc3
|
||||
import timeago
|
||||
import dateutil.parser
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.NEW_NICK)
|
||||
def on_nick_change_for_seen(self, nick, new_nick):
|
||||
new_key = "last_msg_for_{}".format(new_nick).lower()
|
||||
msg_list = self.bot.db.getlist(new_key)
|
||||
if not msg_list:
|
||||
msg_list = []
|
||||
seen_msg = { "type": "newnick",
|
||||
"time": datetime.now().isoformat(),
|
||||
"msg": "{} changed nick to {}".format(nick.nick, new_nick)}
|
||||
msg_list.append(seen_msg)
|
||||
self.bot.db.setlist(new_key, msg_list)
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_for_seen(self, mask=None, target=None, data=None, **kw):
|
||||
if data.startswith("?"): return # no ?
|
||||
if mask.lnick == self.bot.get_nick().lower(): return # Ignore ourseves
|
||||
key = "last_msg_for_{}".format(mask.nick).lower()
|
||||
priv_msg = { "type": "privmsg",
|
||||
"time": datetime.now().isoformat(),
|
||||
"msg": data }
|
||||
messages = self.bot.db.getlist(key)
|
||||
if not messages:
|
||||
messages = []
|
||||
else:
|
||||
for count, msg in enumerate(messages):
|
||||
if msg.get("type") == "privmsg":
|
||||
del(messages[count])
|
||||
messages.append(priv_msg)
|
||||
self.bot.db.setlist(key, messages)
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def seen(self, mask, target, args):
|
||||
"""Display last time user was seen
|
||||
%%seen <nick>
|
||||
"""
|
||||
nick = args.get("<nick>")
|
||||
if nick.lower() == self.bot.get_nick().lower():
|
||||
msg = "please don't spy on me..."
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
key = "last_msg_for_{}".format(nick).lower()
|
||||
message_list = self.bot.db.getlist(key)
|
||||
if message_list:
|
||||
message_list.sort(key=operator.itemgetter('time'), reverse=True)
|
||||
nick_seen_set = set()
|
||||
for msg in message_list:
|
||||
if msg.get("type") == "newnick":
|
||||
notice_msg = msg.get("msg").lower()
|
||||
nick_to_remember = [ item.strip() for item in notice_msg.split("changed nick to")].pop()
|
||||
if nick_to_remember in nick_seen_set:
|
||||
continue
|
||||
else:
|
||||
nick_seen_set.add(nick_to_remember)
|
||||
msg_time = dateutil.parser.parse(msg.get("time"))
|
||||
time_since = timeago.format(msg_time, datetime.now())
|
||||
msg = "\x02{}\x0F \x0303▶\x0F \x02\x0302{}\x0F \x0306፨ \x0F\x1F\x1D{}\x0F".format(nick, msg.get("msg"), time_since.capitalize())
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),f"have you seen {nick}")
|
||||
else:
|
||||
msg = "{} Has Not Been Seen".format(nick)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),f"have you seen {nick}")
|
||||
return
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,86 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import URLError, HTTPError
|
||||
from urllib.parse import quote_plus
|
||||
import html
|
||||
import requests
|
||||
from lxml.html import fromstring
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __soundcloud__request(self,command,query):
|
||||
USER_AGENT_CURL="curl/7.29.0"
|
||||
STATUS_BAD_CODE=":( - error code: {}"
|
||||
STATUS_BAD_REASON=":( - failed reason: {}"
|
||||
STATUS_OK=":)"
|
||||
COMMANDS=['search']
|
||||
for _ in COMMANDS:
|
||||
if _==command.lower():
|
||||
url=f'https://soundcloud.com/{_}?q={quote_plus(query)}'
|
||||
r=Request(url,data=None,headers={'User-Agent':USER_AGENT_CURL})
|
||||
try:
|
||||
response=urlopen(r,timeout=10).read().decode('utf-8')
|
||||
except HTTPError as e:
|
||||
return STATUS_BAD_CODE.format(e.code)
|
||||
except URLError as e:
|
||||
return STATUS_BAD_REASON.format(e.reason)
|
||||
else:
|
||||
return STATUS_OK+response
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def sc(self, mask, target, args):
|
||||
"""Soundcloud artist/song search.. example: ?sc yung innanet nano tapes cronjob
|
||||
%%sc <query>...
|
||||
"""
|
||||
NICK=mask.nick
|
||||
query=' '.join(args['<query>'])
|
||||
result=self.__soundcloud__request('search',query)
|
||||
pop=[];_path=[];_name=[];title='';
|
||||
for _ in result.splitlines():
|
||||
if _.find('<li><h2>') != -1:
|
||||
pop.append(_.strip())
|
||||
for _ in pop:
|
||||
_path.append(_.split('="/').pop().split('">')[0])
|
||||
_name.append(_.split('="/').pop().split('">')[1].split('<')[0])
|
||||
try:
|
||||
url=f'https://soundcloud.com/{_path[0]}'
|
||||
try:
|
||||
read_size = 0
|
||||
r=requests.get(url,timeout=3,stream=True)
|
||||
content_length=r.headers.get('Content-Length')
|
||||
if not content_length:
|
||||
content_length=0
|
||||
while read_size<=(2000*10):
|
||||
for content in r.iter_content(chunk_size=2000):
|
||||
tree=fromstring(content)
|
||||
title=tree.find(".//title")
|
||||
if title is not None:
|
||||
title=title.text.strip()[:100]
|
||||
break
|
||||
except:
|
||||
pass
|
||||
URL=f'https://soundcloud.com/{_path[0]}'
|
||||
TITLE=title.split('|')[0].split('by')[-1].strip()
|
||||
NAME=html.unescape(_name[0]);
|
||||
msg=f"\x02\x0302{NICK}\x0F\x02\x0304 ▶ "
|
||||
msg+=f"\x0F\x02\x0313{NAME}\x0F\x02\x0304 ▶ "
|
||||
msg+=f"\x0F\x02\x0312{URL}\x0F\x02\x0313\x0F\x02\x0304 ▶ "
|
||||
msg+=f"\x0F\x1D\x0314{TITLE}\x0F\x02\x0304 "
|
||||
except:
|
||||
MSG='no result'
|
||||
msg=f"\x02\x0302{NICK}\x0F\x02\x0304 ▶ "
|
||||
msg+=f"\x0F\x02\x0313{MSG}\x0F\x02\x0304 "
|
||||
self.bot.privmsg(target,self.bot.emo(f"{msg}"))
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),f'{TITLE} {NAME}')
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,473 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
import irc3
|
||||
import shelve
|
||||
|
||||
__doc__ = '''
|
||||
==========================================
|
||||
:mod:`irc3.plugins.storage` Storage plugin
|
||||
==========================================
|
||||
|
||||
Add a ``db`` attribute to the bot
|
||||
|
||||
..
|
||||
>>> from irc3.testing import IrcBot
|
||||
>>> from irc3.testing import ini2config
|
||||
>>> import tempfile
|
||||
>>> fd = tempfile.NamedTemporaryFile(prefix='irc3', suffix='.db')
|
||||
>>> db_file = fd.name
|
||||
>>> fd.close()
|
||||
>>> fd = tempfile.NamedTemporaryFile(prefix='irc3', suffix='.json')
|
||||
>>> json_file = fd.name
|
||||
>>> fd.close()
|
||||
>>> fd = tempfile.NamedTemporaryFile(prefix='irc3', suffix='.sqlite')
|
||||
>>> sqlite_file = fd.name
|
||||
>>> fd.close()
|
||||
|
||||
Usage::
|
||||
|
||||
>>> config = ini2config("""
|
||||
... [bot]
|
||||
... includes =
|
||||
... irc3.plugins.storage
|
||||
... storage = json://%s
|
||||
... """ % json_file)
|
||||
>>> bot = IrcBot(**config)
|
||||
|
||||
Then use it::
|
||||
|
||||
>>> bot.db['mykey'] = dict(key='value')
|
||||
>>> 'mykey' in bot.db
|
||||
True
|
||||
>>> bot.db['mykey']
|
||||
{'key': 'value'}
|
||||
>>> bot.db.setdefault('mykey', key='default')
|
||||
{'key': 'value'}
|
||||
>>> bot.db.setdefault('mykey', item='default')
|
||||
{'item': 'default'}
|
||||
>>> bot.db.set('mykey', item='value')
|
||||
>>> bot.db.setdefault('mykey', item='default')
|
||||
{'item': 'value'}
|
||||
>>> del bot.db['mykey']
|
||||
>>> bot.db.get('mykey')
|
||||
>>> bot.db.get('mykey', 'default')
|
||||
'default'
|
||||
>>> bot.db['mykey']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'mykey'
|
||||
>>> 'mykey' in bot.db
|
||||
False
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> bot.db.getlist('mylist')
|
||||
['foo', 'bar']
|
||||
>>> del bot.db['mylist']
|
||||
|
||||
You can use an instance as key::
|
||||
|
||||
>>> class MyPlugin:
|
||||
... pass
|
||||
>>> plugin = MyPlugin()
|
||||
>>> bot.db[plugin] = dict(key='value')
|
||||
>>> bot.db[plugin]
|
||||
{'key': 'value'}
|
||||
>>> del bot.db[plugin]
|
||||
>>> bot.db.get(plugin)
|
||||
|
||||
..
|
||||
>>> bot.db.SIGINT()
|
||||
|
||||
You can also use shelve::
|
||||
|
||||
>>> config = ini2config("""
|
||||
... [bot]
|
||||
... includes =
|
||||
... irc3.plugins.storage
|
||||
... storage = shelve://%s
|
||||
... """ % db_file)
|
||||
>>> bot = IrcBot(**config)
|
||||
>>> bot.db['mykey'] = dict(key='value')
|
||||
>>> bot.db['mykey']
|
||||
{'key': 'value'}
|
||||
>>> del bot.db['mykey']
|
||||
>>> bot.db.get('mykey')
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> bot.db.getlist('mylist')
|
||||
['foo', 'bar']
|
||||
>>> del bot.db['mylist']
|
||||
|
||||
..
|
||||
>>> bot.db.getlist('mylist', ['foo', 'bar'])
|
||||
['foo', 'bar']
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> del bot.db['mylist']
|
||||
>>> bot.db.SIGINT()
|
||||
|
||||
|
||||
Or redis::
|
||||
|
||||
>>> config = ini2config("""
|
||||
... [bot]
|
||||
... includes =
|
||||
... irc3.plugins.storage
|
||||
... storage = redis://localhost:6379/10
|
||||
... """)
|
||||
>>> bot = IrcBot(**config)
|
||||
|
||||
..
|
||||
>>> bot.db.backend.flushdb() # require redis
|
||||
>>> bot.db.SIGINT()
|
||||
|
||||
Then use it::
|
||||
|
||||
>>> bot.db['mykey'] = dict(key='value')
|
||||
>>> bot.db['mykey']
|
||||
{'key': 'value'}
|
||||
>>> del bot.db['mykey']
|
||||
>>> bot.db.get('mykey')
|
||||
>>> bot.db['mykey']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'mykey'
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> bot.db.getlist('mylist')
|
||||
['foo', 'bar']
|
||||
>>> del bot.db['mylist']
|
||||
|
||||
Or sqlite::
|
||||
|
||||
>>> config = ini2config("""
|
||||
... [bot]
|
||||
... includes =
|
||||
... irc3.plugins.storage
|
||||
... storage = sqlite://%s
|
||||
... """ % sqlite_file)
|
||||
>>> bot = IrcBot(**config)
|
||||
|
||||
..
|
||||
>>> bot.db.backend.flushdb() # require redis
|
||||
>>> bot.db.SIGINT()
|
||||
|
||||
Then use it::
|
||||
|
||||
>>> bot.db['mykey'] = dict(key='value')
|
||||
>>> bot.db['mykey']
|
||||
{'key': 'value'}
|
||||
>>> del bot.db['mykey']
|
||||
>>> bot.db.get('mykey')
|
||||
>>> bot.db['mykey']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'mykey'
|
||||
>>> bot.db.setlist('mylist', ['foo', 'bar'])
|
||||
>>> bot.db.getlist('mylist')
|
||||
['foo', 'bar']
|
||||
>>> del bot.db['mylist']
|
||||
|
||||
Api
|
||||
===
|
||||
|
||||
.. autoclass:: Storage
|
||||
:members: __getitem__,__setitem__,__delitem__,__contains__,get,set,setdefault
|
||||
|
||||
'''
|
||||
|
||||
|
||||
class Shelve:
|
||||
|
||||
def __init__(self, uri=None, **kwargs):
|
||||
self.filename = uri[9:]
|
||||
self.db = shelve.open(self.filename)
|
||||
|
||||
def set(self, key, value):
|
||||
self.db[key] = value
|
||||
self.db.sync()
|
||||
|
||||
def get(self, key):
|
||||
return self.db[key]
|
||||
|
||||
def delete(self, key):
|
||||
del self.db[key]
|
||||
self.sync()
|
||||
|
||||
def contains(self, key):
|
||||
return key in self.db
|
||||
|
||||
def sync(self):
|
||||
self.db.sync()
|
||||
|
||||
def close(self):
|
||||
self.db.close()
|
||||
|
||||
|
||||
class JSON:
|
||||
|
||||
def __init__(self, uri=None, **kwargs):
|
||||
self.filename = uri[7:]
|
||||
if os.path.isfile(self.filename): # pragma: no cover
|
||||
with open(self.filename) as fd:
|
||||
self.db = json.load(fd)
|
||||
else:
|
||||
self.db = {}
|
||||
|
||||
def set(self, key, value):
|
||||
self.db[key] = value
|
||||
self.sync()
|
||||
|
||||
def get(self, key):
|
||||
return self.db[key]
|
||||
|
||||
def delete(self, key):
|
||||
del self.db[key]
|
||||
self.sync()
|
||||
|
||||
def contains(self, key):
|
||||
return key in self.db
|
||||
|
||||
def sync(self):
|
||||
with open(self.filename, 'w') as fd:
|
||||
json.dump(self.db, fd, indent=2, sort_keys=True)
|
||||
|
||||
def close(self):
|
||||
self.sync()
|
||||
|
||||
|
||||
class Redis:
|
||||
|
||||
def __init__(self, uri=None, **kwargs):
|
||||
ConnectionPool = irc3.utils.maybedotted(
|
||||
'redis.connection.ConnectionPool')
|
||||
pool = ConnectionPool.from_url(uri)
|
||||
StrictRedis = irc3.utils.maybedotted('redis.client.StrictRedis')
|
||||
self.db = StrictRedis(connection_pool=pool)
|
||||
|
||||
def set(self, key, value):
|
||||
self.db.hmset(key, value)
|
||||
|
||||
def get(self, key):
|
||||
keys = self.db.hkeys(key)
|
||||
if not keys:
|
||||
raise KeyError()
|
||||
values = self.db.hmget(key, keys)
|
||||
keys = [k.decode('utf8') for k in keys]
|
||||
values = [v.decode('utf8') for v in values]
|
||||
values = dict(zip(keys, values))
|
||||
return values
|
||||
|
||||
def delete(self, key):
|
||||
self.db.delete(key)
|
||||
|
||||
def contains(self, key):
|
||||
return self.db.exists(key)
|
||||
|
||||
def flushdb(self):
|
||||
self.db.flushdb()
|
||||
|
||||
def sync(self):
|
||||
self.db.save()
|
||||
|
||||
def close(self):
|
||||
self.sync()
|
||||
|
||||
|
||||
class SQLite:
|
||||
|
||||
CREATE_TABLE = """
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
irc3_storage (
|
||||
key text not null,
|
||||
value text default '',
|
||||
PRIMARY KEY (key)
|
||||
);
|
||||
"""
|
||||
UPSERT = """
|
||||
INSERT OR REPLACE INTO irc3_storage(key,value) VALUES(?, ?);
|
||||
"""
|
||||
|
||||
def __init__(self, uri=None, **kwargs):
|
||||
self.sqlite = irc3.utils.maybedotted('sqlite3')
|
||||
self.uri = uri.split('://')[-1]
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(self.CREATE_TABLE)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def set(self, key, value):
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(self.UPSERT, (key, json.dumps(value)))
|
||||
cursor.fetchall()
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def get(self, key):
|
||||
value = None
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT value FROM irc3_storage where key=?;", (key,))
|
||||
for row in cursor.fetchall():
|
||||
value = json.loads(row[0])
|
||||
break
|
||||
cursor.close()
|
||||
conn.close()
|
||||
if value is None:
|
||||
raise KeyError(key)
|
||||
return value
|
||||
|
||||
def delete(self, key):
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM irc3_storage where key=?;", (key,))
|
||||
cursor.close()
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def contains(self, key):
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT value FROM irc3_storage where key=?;", (key,))
|
||||
res = False
|
||||
if len(list(cursor.fetchall())) == 1:
|
||||
res = True
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return res
|
||||
|
||||
def flushdb(self):
|
||||
conn = self.sqlite.connect(self.uri)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DROP TABLE IF EXISTS irc3_storage;")
|
||||
cursor.execute(self.CREATE_TABLE)
|
||||
cursor.close()
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def sync(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
@irc3.plugin
|
||||
class Storage:
|
||||
|
||||
backends = {
|
||||
'shelve': Shelve,
|
||||
'json': JSON,
|
||||
'unix': Redis,
|
||||
'redis': Redis,
|
||||
'rediss': Redis,
|
||||
'sqlite': SQLite,
|
||||
}
|
||||
|
||||
def __init__(self, context):
|
||||
uri = context.config.storage
|
||||
name = uri.split('://', 1)[0]
|
||||
try:
|
||||
factory = self.backends[name]
|
||||
except KeyError: # pragma: no cover
|
||||
raise LookupError('No such backend %s' % name)
|
||||
self.backend = factory(uri)
|
||||
self.context = context
|
||||
self.context.db = self
|
||||
|
||||
def setdefault(self, key_, **kwargs):
|
||||
"""Update storage value for key with kwargs iif the keys doesn't
|
||||
exist. Return stored values"""
|
||||
stored = self[key_]
|
||||
changed = False
|
||||
for k, v in kwargs.items():
|
||||
if k not in stored:
|
||||
stored[k] = v
|
||||
changed = True
|
||||
else:
|
||||
kwargs[k] = stored[k]
|
||||
if changed:
|
||||
self[key_] = stored
|
||||
return kwargs
|
||||
|
||||
def get(self, key_, default=None):
|
||||
"""Get storage value for key or return default"""
|
||||
if key_ not in self:
|
||||
return default
|
||||
else:
|
||||
return self[key_]
|
||||
|
||||
def getlist(self, key_, default=None):
|
||||
"""Get storage value (as list) for key or return default"""
|
||||
if key_ not in self:
|
||||
return default
|
||||
else:
|
||||
value = self[key_]
|
||||
value = [(int(i), v) for i, v in value.items()]
|
||||
return [v for k, v in sorted(value)]
|
||||
|
||||
def set(self, key_, **kwargs):
|
||||
"""Update storage value for key with kwargs"""
|
||||
stored = self.get(key_, dict())
|
||||
changed = False
|
||||
for k, v in kwargs.items():
|
||||
if k not in stored or stored[k] != v:
|
||||
stored[k] = v
|
||||
changed = True
|
||||
if changed:
|
||||
self[key_] = stored
|
||||
|
||||
def setlist(self, key_, value):
|
||||
"""Update storage value (as list)"""
|
||||
value = dict([(str(i), v) for i, v in enumerate(value)])
|
||||
if key_ in self:
|
||||
del self[key_]
|
||||
self.set(key_, **value)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Set storage value for key"""
|
||||
key = getattr(key, '__module__', key)
|
||||
if not isinstance(value, dict): # pragma: no cover
|
||||
raise TypeError('value must be a dict')
|
||||
try:
|
||||
return self.backend.set(key, value)
|
||||
except Exception as e: # pragma: no cover
|
||||
self.context.log.exception(e)
|
||||
raise
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Get storage value for key"""
|
||||
key = getattr(key, '__module__', key)
|
||||
try:
|
||||
return self.backend.get(key)
|
||||
except KeyError:
|
||||
raise KeyError(key)
|
||||
except Exception as e: # pragma: no cover
|
||||
self.context.log.exception(e)
|
||||
raise
|
||||
|
||||
def __delitem__(self, key):
|
||||
"""Delete key in storage"""
|
||||
key = getattr(key, '__module__', key)
|
||||
try:
|
||||
self.backend.delete(key)
|
||||
except Exception as e: # pragma: no cover
|
||||
self.context.log.exception(e)
|
||||
raise
|
||||
|
||||
def __contains__(self, key):
|
||||
"""Return True if storage contains key"""
|
||||
key = getattr(key, '__module__', key)
|
||||
try:
|
||||
return self.backend.contains(key)
|
||||
except Exception as e: # pragma: no cover
|
||||
self.context.log.exception(e)
|
||||
raise
|
||||
|
||||
def SIGINT(self):
|
||||
self.backend.close()
|
|
@ -0,0 +1,92 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import requests
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def _get_weed(self,t,s):
|
||||
try:
|
||||
url=""
|
||||
if t == "search":
|
||||
s = s.lower().replace(' ','-')
|
||||
url = 'https://api.wikileaf.com/api/v7/search/all/?type=S&num=24&offset=0&sort=popular&query={}'.format(s)
|
||||
if t == "review":
|
||||
url = 'https://api.wikileaf.com/api/v6/reviews/?content_type__model=strain&object_id={}'.format(s)
|
||||
r = requests.get(url)
|
||||
try:
|
||||
if r.json()['detail'] == 'Not found.':
|
||||
return 'Not Found.'
|
||||
except:
|
||||
return r.json()
|
||||
except:
|
||||
return -1
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def strain(self, mask, target, args):
|
||||
"""strain
|
||||
%%strain <message>...
|
||||
"""
|
||||
try:
|
||||
msg = ' '.join(args['<message>'])
|
||||
r_strain_id = -1
|
||||
r = self._get_weed('search',msg)
|
||||
b = r['results'][0]
|
||||
try:
|
||||
r_name = b['name']
|
||||
r_score = b['score']
|
||||
r_review_avg = b['review_avg']
|
||||
r_review_count = b['review_count']
|
||||
r_type = b['type']
|
||||
r_compound_thc_min = b['compound']['THC']['min']
|
||||
r_compound_thc_max = b['compound']['THC']['max']
|
||||
r_compound_cbd_min = b['compound']['CBD']['min']
|
||||
r_compound_cbd_max = b['compound']['CBD']['max']
|
||||
r_consumption_time = b['consumption_time']
|
||||
r_uses = b['uses']
|
||||
r_effects = b['effects']
|
||||
r_logo_url = "https://assets.wikileaf.com/{}".format(b['logo_url'])
|
||||
r_strain_id = b['strain_id']
|
||||
msg = "▶ name: {}".format(r_name)
|
||||
msg = msg + " ▶ " + "score: {}".format(r_score)
|
||||
msg = msg + " ▶ " + "review avg: {}".format(r_review_avg)
|
||||
msg = msg + " ▶ " + "review count: {}".format(r_review_count)
|
||||
msg = msg + " ▶ " + "type: {}".format(r_type)
|
||||
msg = msg + " ▶ " + "compound thc min: {} / max: {}".format(r_compound_thc_min,r_compound_thc_max)
|
||||
msg = msg + " ▶ " + "compound cbd min: {} / max: {}".format(r_compound_cbd_min,r_compound_cbd_max)
|
||||
msg = msg + " ▶ " + "consumption time: {}".format(r_consumption_time)
|
||||
msg = msg + " ▶ " + "uses: {}".format(r_uses)
|
||||
msg = msg + " ▶ " + "effects: {}".format(r_effects)
|
||||
msg = msg + " ▶ " + "logo: {}".format(r_logo_url)
|
||||
self.bot.privmsg(target, msg)
|
||||
except:
|
||||
msg = "strain: not found"
|
||||
self.bot.privmsg(target, msg)
|
||||
try:
|
||||
r = self._get_weed('review',r_strain_id)
|
||||
b = r['results']
|
||||
for i,_ in enumerate(b):
|
||||
msg = "▶▶ " + "review {} - rating: {} / comment: {}".format(i+1,_['rating'],_['comment'])
|
||||
self.bot.privmsg(target, msg)
|
||||
if i >= 2: break
|
||||
url = b[0]['url']
|
||||
msg = "▶▶▶ " + "url: {}".format(url)
|
||||
self.bot.privmsg(target, msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),msg)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
msg = "strain: not found"
|
||||
self.bot.privmsg(target, msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,46 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
import irc3
|
||||
import re
|
||||
TELL_RE = re.compile('maple.tell\s(.+?)\s(.+)')
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_to_tell(self, mask=None, target=None, data=None, **kw):
|
||||
if mask.nick.lower() == "maple":
|
||||
return
|
||||
messages_to_send = self.bot.db.getlist("tell_%s" % mask.nick.lower())
|
||||
if messages_to_send:
|
||||
msg = messages_to_send[0]
|
||||
irc_message = "TCPDIRECT/TOLD: {} <{}> told <{}> {}".format(msg.get("time"),msg.get("from"),mask.nick,msg.get("message"))
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
self.bot.db.setlist("tell_%s" % mask.nick.lower(), messages_to_send[1:])
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_tell(self, mask=None, target=None, data=None, **kw):
|
||||
match_list = TELL_RE.findall(data)
|
||||
if len(match_list) > 0:
|
||||
tell_nick, message = match_list[0]
|
||||
if tell_nick == 'me' or tell_nick == 'us' or tell_nick == 'a' or tell_nick == 'some': return
|
||||
message_list = self.bot.db.getlist("tell_%s" % tell_nick.lower())
|
||||
new_message = {"from": mask.nick.lower(), "message": message, "time": datetime.now().isoformat() }
|
||||
if not message_list:
|
||||
message_list = self.bot.db.setlist("tell_%s" % tell_nick.lower(), [new_message])
|
||||
else:
|
||||
message_list.append(new_message)
|
||||
self.bot.db.setlist("tell_%s" % tell_nick.lower(), message_list)
|
||||
irc_message = "TCPDIRECT/TELL: {} <{}> telling <{}> {}".format(new_message.get("time"),new_message.get("from"),tell_nick,new_message.get("message"))
|
||||
self.bot.privmsg(target, self.bot.emo(irc_message))
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,193 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import irc3
|
||||
from datetime import datetime
|
||||
import twitter
|
||||
import re
|
||||
import os
|
||||
import time
|
||||
import timeago
|
||||
import os
|
||||
import requests
|
||||
from lxml.html import fromstring
|
||||
from difflib import SequenceMatcher
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
CONSUMER_KEY = os.environ['CONSUMER_KEY']
|
||||
CONSUMER_SECRET = os.environ['CONSUMER_SECRET']
|
||||
ACCESS_TOKEN_KEY = os.environ['ACCESS_TOKEN_KEY']
|
||||
ACCESS_TOKEN_SECRET = os.environ['ACCESS_TOKEN_SECRET']
|
||||
TOO_LONG = 2000
|
||||
YOUTUBE_REGEX = re.compile('http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?', re.IGNORECASE)
|
||||
TWITTER_REGEX = re.compile('https?:\/\/twitter\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)$', re.IGNORECASE)
|
||||
URL_REGEX = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
|
||||
twitter = twitter.Api(consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET,
|
||||
access_token_key=ACCESS_TOKEN_KEY, access_token_secret=ACCESS_TOKEN_SECRET)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
def _similar(self, a, b):
|
||||
return SequenceMatcher(None, a, b).ratio()
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
def _check_for_url(self, og_tweet, d_nick, d_url, d_unrolled, d_text, d_target):
|
||||
match_list = URL_REGEX.findall(d_unrolled)
|
||||
read_size = 0
|
||||
if match_list:
|
||||
url = match_list.pop()
|
||||
try:
|
||||
if not d_unrolled.find('https://twitter.com/') == -1:
|
||||
if not d_unrolled.find('status') == -1:
|
||||
try:
|
||||
e_status = d_unrolled.split('/')[-1]
|
||||
e_tweet = twitter.GetStatus(e_status)
|
||||
e_text = e_tweet.text
|
||||
if self._similar(og_tweet.text,e_text) > 0.7: return
|
||||
msg = "\x02\x0302{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ {e_text:} \x0F".format(nick1=d_nick,nick2='UNROLLED',e_text=e_text)
|
||||
if e_tweet.media:
|
||||
for y in range(len(e_tweet.media)):
|
||||
m_turl = e_tweet.media[y].url
|
||||
m_murl = e_tweet.media[y].media_url
|
||||
m_eurl = e_tweet.media[y].expanded_url
|
||||
msg = msg + " ▶▶ [media] \x0F\x02\x0312{media_url:}".format(media_url=m_murl)
|
||||
if e_tweet.urls:
|
||||
for y in range(len(e_tweet.urls)):
|
||||
e_turl = e_tweet.urls[y].url
|
||||
e_eurl = e_tweet.urls[y].expanded_url
|
||||
msg = msg + " ▶▶ [url] \x0F\x02\x0312{e_url:}".format(e_url=e_eurl)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(d_target, msg)
|
||||
return
|
||||
except Exception as e:
|
||||
msg = "wu/tang >>>>>>>>>>> sub-unrolling: {}".format(e)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(d_target, msg)
|
||||
return
|
||||
r = requests.get(d_unrolled, timeout=3, stream=True)
|
||||
content_type = r.headers.get("Content-Type")
|
||||
content_length = r.headers.get('Content-Length')
|
||||
if not content_length:
|
||||
content_length = 0
|
||||
if content_type.startswith('image'):
|
||||
msg = "\x02\x0302{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ [media] {media:} \x0F".format(nick1=d_nick,nick2='UNROLLED',media=d_unrolled)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(d_target, msg)
|
||||
return
|
||||
if not content_type.startswith("text/html"):
|
||||
return
|
||||
if int(content_length) > 200000:
|
||||
self.bot.privmsg(d_target, "pre-fetch aborted -> fuck your large ass content -> {} -> {}".format(d_url,d_unrolled))
|
||||
while read_size <= (2000 * 10):
|
||||
for content in r.iter_content(chunk_size=2000):
|
||||
tree = fromstring(content)
|
||||
title = tree.find(".//title")
|
||||
if title is not None:
|
||||
title = title.text.strip()[:100]
|
||||
print('title: {}'.format(title))
|
||||
similarity = self.bot._similar(title,d_text)
|
||||
if similarity > 0.4:
|
||||
print('wu/tang: similarity')
|
||||
return
|
||||
msg = "\x02\x0302{nick1:}:{nick2:}\x0F\x02\x0304 ▶▶ \x0F\x1D\x0314{url:}\x0F\x0304 ▶▶ \x0F\x0303{unrolled:} \x0F\x0304▶▶ \x0F\x1D\x0314{title:}\x0F".format(nick1=d_nick,nick2='UNROLLED',url=d_url,unrolled=d_unrolled,title=title)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(d_target, msg)
|
||||
return
|
||||
read_size = read_size + 2000
|
||||
except Exception as e:
|
||||
self.bot.privmsg("_debug_check_for_url_error: {}".format(e))
|
||||
print("original: {} nick: {} url: {} unrolled: {} text: {} error: {}".format(og_tweet,d_nick,d_url,d_unrolled,d_text,e))
|
||||
pass
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def _check_for_twitter(self, mask=None, data=None, target=None, **kw):
|
||||
match_list = TWITTER_REGEX.findall(data)
|
||||
if match_list:
|
||||
status_id = match_list[0][2]
|
||||
try:
|
||||
tweet = twitter.GetStatus(status_id=status_id)
|
||||
tweet_text = tweet.text
|
||||
user = tweet.user.screen_name
|
||||
fav_count = tweet.favorite_count
|
||||
retweet_count = tweet.retweet_count
|
||||
if tweet.coordinates:
|
||||
location = tweet.coordinates
|
||||
else:
|
||||
location = ""
|
||||
tweet_time = time.strptime(tweet.created_at, '%a %b %d %H:%M:%S +0000 %Y')
|
||||
time_since = timeago.format(time.strftime('%Y-%m-%d %H:%M:%S', tweet_time), datetime.now())
|
||||
msg = "\x02\x0302{} \x0F\x0303▶\x0F \x02\x0301{}\x0F\x0314 | Retweets:\x0F \x1D\x0306{}\x0F\x0314 Favorites:\x0F\x1D\x0306 {} \x0F⑆\x1D\x0314\x1D {} {}".format(user, tweet_text, retweet_count, fav_count, time_since, location)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
match_list = URL_REGEX.findall(msg)
|
||||
try:
|
||||
if(match_list):
|
||||
try:
|
||||
if len(tweet.urls) == 0:
|
||||
if tweet.media:
|
||||
for y in range(len(tweet.media)):
|
||||
m_turl = tweet.media[y].url
|
||||
m_murl = tweet.media[y].media_url
|
||||
m_eurl = tweet.media[y].expanded_url
|
||||
msg = "\x02\x0302{nick1:}:{nick2:}\x0F\x02\x0304 ▶▶ [media] \x0F\x02\x0312{m_turl:}\x0F\x0304 ▶▶ \x0F\x0303{m_murl:} \x0F\x0304▶▶ \x0F\x1D\x0314{m_eurl:}\x0F".format(nick1=user,nick2='UNROLLED',m_turl=m_turl,m_murl=m_murl,m_eurl=m_eurl)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
else:
|
||||
for y in range(len(tweet.urls)):
|
||||
t_turl = tweet.urls[y].url
|
||||
try:
|
||||
match_list.remove(t_turl)
|
||||
except:
|
||||
print('cant remove from matchlist, does not exist')
|
||||
t_eurl = tweet.urls[y].expanded_url
|
||||
yt_match_list = YOUTUBE_REGEX.findall(t_eurl)
|
||||
if yt_match_list:
|
||||
d_video_id = t_eurl.split('=')[1]
|
||||
self.bot.madjust = "{}:UNROLLED".format(user)
|
||||
self.bot.yt(mask,target,{'<keyword>': [d_video_id],'yt': True})
|
||||
self.bot.madjust = ""
|
||||
else:
|
||||
if not str(tweet.id) == t_eurl.split('/')[-1]:
|
||||
self.bot._check_for_url(tweet,user,t_turl,t_eurl,tweet_text,target)
|
||||
else:
|
||||
print('bypassing original tweet')
|
||||
try:
|
||||
if len(match_list) > 0:
|
||||
print('items in matchlist remain')
|
||||
print(match_list)
|
||||
except:
|
||||
print('errrororororororo: cant remove from matchlist, does not exist')
|
||||
except Exception as e:
|
||||
self.bot.privmsg(target,'twitter_plugin <> _debug_unrolling -> wu/tang: {}'.format(e))
|
||||
except Exception as e:
|
||||
self.bot.privmsg(target,'twitter_plugin <> wu/tang: {}'.format(e))
|
||||
except Exception as e:
|
||||
_msg = e.message[0]['message']
|
||||
_code = e.message[0]['code']
|
||||
_erid = ''
|
||||
if _code == 179:
|
||||
_erid = "PROTECTED TW33T"
|
||||
else:
|
||||
_erid = "DON'T CARE EXCEPTION"
|
||||
msg = "\x02\x0302{} \x0F\x0304▶ \x0F\x02\x0312{} aka {}\x0F\x0303".format(_code,_msg,_erid)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
pass
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_twitter(self, mask=None, target=None, data=None, **kw):
|
||||
if data.startswith("?"): return
|
||||
if mask.nick.lower() not in self.bot.ignore_list:
|
||||
self._check_for_twitter(mask, data, target)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import requests
|
||||
import urllib.parse
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view')
|
||||
def ud(self, mask, target, args):
|
||||
"""Urban Dictonary A Term
|
||||
%%ud <term>...
|
||||
"""
|
||||
term = ' '.join(args['<term>'])
|
||||
term = urllib.parse.quote(term)
|
||||
r = requests.get('https://api.urbandictionary.com/v0/define?term={}'.format(term))
|
||||
d = r.json()
|
||||
term = urllib.parse.unquote(term)
|
||||
try:
|
||||
msg = "{} - {} - example: {}".format(term, d.get("list")[0].get("definition"), d.get("list")[0].get("example"))
|
||||
except:
|
||||
msg = "{} Term Not Found".format(term)
|
||||
self.bot.privmsg(target,msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),msg)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,84 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import irc3
|
||||
import re
|
||||
import requests
|
||||
from lxml.html import fromstring
|
||||
TOO_LONG = 2000
|
||||
URL_REGEX = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
|
||||
YOUTUBE_REGEX = re.compile('http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?', re.IGNORECASE)
|
||||
TWITTER_REGEX = re.compile('https?:\/\/twitter\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)$', re.IGNORECASE)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg(self, mask=None, target=None, data=None, **kw):
|
||||
if not data.find('reacted with :') == -1: return
|
||||
if data.startswith("?"): return
|
||||
if self.bot.check_if_ignored(mask): return
|
||||
if mask.nick == '[0]' or mask.nick == '[0]_': return
|
||||
self.__check_for_url(data, target, mask)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __check_for_url(self, msg, target, mask):
|
||||
match_list = URL_REGEX.findall(msg)
|
||||
read_size = 0
|
||||
if match_list:
|
||||
url = match_list.pop()
|
||||
if not url.lower().find('wp-login') == -1:
|
||||
msg = 'pre-fetch aborted -> hell nah nigga'
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
y_match = YOUTUBE_REGEX.findall(url)
|
||||
if y_match:
|
||||
y_match = y_match.pop()
|
||||
if len(y_match) == 3:
|
||||
return
|
||||
t_match = TWITTER_REGEX.findall(url)
|
||||
if t_match:
|
||||
t_match = t_match.pop()
|
||||
if len(t_match) == 3:
|
||||
return
|
||||
try:
|
||||
if not url.find("giphy.com") == -1:
|
||||
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶ \x0F\x02\x0303{url:}\x0F\x0303".format(nick=mask.nick,url="fuk giphy!!!")
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
if not url.find("facebook.com") == -1:
|
||||
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶ \x0F\x02\x0312{url:}\x0F\x0303".format(nick=mask.nick,url="fuk facebook!!!")
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
r = requests.get(url, timeout=3, stream=True)
|
||||
content_type = r.headers.get("Content-Type")
|
||||
content_length = r.headers.get('Content-Length')
|
||||
if not content_length:
|
||||
content_length = 0
|
||||
if int(content_length) > 200000:
|
||||
return
|
||||
while read_size <= (2000 * 10):
|
||||
for content in r.iter_content(chunk_size=2000):
|
||||
tree = fromstring(content)
|
||||
title = tree.find(".//title")
|
||||
if title is not None:
|
||||
title = title.text.strip()[:100]
|
||||
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶ \x0F\x1D\x0314{title:}\x0F".format(nick=mask.nick,title=title)
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
return
|
||||
read_size = read_size + 2000
|
||||
except Exception as e:
|
||||
print("%s" % e)
|
||||
pass
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,143 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from irc3.plugins.command import command
|
||||
import irc3
|
||||
import os
|
||||
import re
|
||||
import datetime
|
||||
import dateutil.parser
|
||||
import timeago
|
||||
import isodate
|
||||
from apiclient.discovery import build
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
DEVELOPER_KEY = os.environ['DEVELOPER_KEY']
|
||||
YOUTUBE_API_SERVICE_NAME = "youtube"
|
||||
YOUTUBE_API_VERSION = "v3"
|
||||
YOUTUBE_REGEX = re.compile('http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?', re.IGNORECASE)
|
||||
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)
|
||||
###########################################################################################
|
||||
###########################################################################################
|
||||
@irc3.plugin
|
||||
class Plugin:
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.bot.channel_live = []
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
def youtube_search(self, q=None, eventType=None, max_results=1, order="relevance", channelId=None, token=None, location=None, location_radius=None):
|
||||
search_response = youtube.search().list(
|
||||
q=q,
|
||||
channelId=channelId,
|
||||
type="video",
|
||||
pageToken=token,
|
||||
order=order,
|
||||
eventType=eventType,
|
||||
part="id,snippet",
|
||||
maxResults=max_results,
|
||||
location=location,
|
||||
locationRadius=location_radius
|
||||
).execute()
|
||||
for search_result in search_response.get("items", []):
|
||||
if search_result["id"]["kind"] == "youtube#video":
|
||||
return(search_result)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.event(irc3.rfc.PRIVMSG)
|
||||
def on_privmsg_search_for_youtube(self, mask=None, target=None, data=None, **kw):
|
||||
if data.startswith("?"): return
|
||||
if self.bot.check_if_ignored(mask): return
|
||||
self.__check_for_youtube(mask, data, target)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
def __check_for_youtube(self, mask, msg, target):
|
||||
match_list = YOUTUBE_REGEX.findall(msg)
|
||||
if match_list:
|
||||
video_id = match_list.pop()
|
||||
if int(len(video_id)) == 3:
|
||||
video_id = video_id[0]
|
||||
video_info = self.videos_list_by_id(id=video_id)
|
||||
title = video_info.get("snippet",{}).get("title")
|
||||
published_at = video_info.get("snippet",{}).get("publishedAt")
|
||||
view_count = int(video_info.get("statistics").get("viewCount"))
|
||||
if published_at:
|
||||
published_at = dateutil.parser.parse(published_at)
|
||||
published_at = timeago.format(published_at.replace(tzinfo=None), datetime.datetime.now())
|
||||
try:
|
||||
topics = video_info.get("topicDetails",{}).get("topicCategories")
|
||||
topics[:] = [i.replace("https://en.wikipedia.org/wiki/", "").replace("_"," ").title() for i in topics]
|
||||
except:
|
||||
topics = []
|
||||
duration = isodate.parse_duration(video_info.get("contentDetails").get("duration"))
|
||||
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶▶ \x02\x0303\x1D\x1F{title:}\x0F".format(nick=mask.nick, title=title)
|
||||
msg = msg + "\x02\x1D\x0304 ▶ \x0F\x1D\x0314Duration: \x0F\x1D{duration:} \x0F".format(duration=duration)
|
||||
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,}\x0F".format(published=published_at, views=view_count)
|
||||
msg = msg + "\x0F\x02\x0312 ♫ \x0F\x02\x0313\x1D{topics:}\x0F\x02\x0312".format(topics=", ".join(topics))
|
||||
msg = msg
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target,msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),title)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
def videos_list_by_id(self, id):
|
||||
search_response = youtube.videos().list(part="id,snippet,statistics,topicDetails,contentDetails", id=id).execute()
|
||||
for search_result in search_response.get("items", []):
|
||||
if search_result["kind"] == "youtube#video":
|
||||
return(search_result)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@command(permission='view', public=True, show_in_help_list=True)
|
||||
def y(self, *args, **kwargs):
|
||||
"""Search for youtube video
|
||||
%%y <keyword>...
|
||||
"""
|
||||
return self.yt(*args)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
@irc3.extend
|
||||
@command(permission='view')
|
||||
def yt(self, mask, target, args):
|
||||
"""Search for youtube video
|
||||
%%yt <keyword>...
|
||||
"""
|
||||
keyword = ' '.join(args['<keyword>'])
|
||||
video = self.youtube_search(q=keyword)
|
||||
if video:
|
||||
video_id = video.get("id",{}).get("videoId")
|
||||
video = video.get("snippet")
|
||||
video_info = self.videos_list_by_id(id=video_id)
|
||||
title = video_info.get("snippet",{}).get("title")
|
||||
published_at = video_info.get("snippet",{}).get("publishedAt")
|
||||
view_count = int(video_info.get("statistics").get("viewCount"))
|
||||
if published_at:
|
||||
published_at = dateutil.parser.parse(published_at)
|
||||
published_at = timeago.format(published_at.replace(tzinfo=None), datetime.datetime.now())
|
||||
try:
|
||||
topics = video_info.get("topicDetails",{}).get("topicCategories")
|
||||
topics[:] = [i.replace("https://en.wikipedia.org/wiki/", "").replace("_"," ").title() for i in topics]
|
||||
except:
|
||||
topics = []
|
||||
duration = isodate.parse_duration(video_info.get("contentDetails").get("duration"))
|
||||
url = "https://youtu.be/{}".format(video_id)
|
||||
_nick = ""
|
||||
try:
|
||||
if len(self.bot.madjust) > 0:
|
||||
_nick = self.bot.madjust
|
||||
else:
|
||||
_nick = mask.nick
|
||||
except:
|
||||
_nick = mask.nick
|
||||
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶▶ \x02\x0303\x1D\x1F{title:}\x0F".format(nick=_nick, title=title)
|
||||
msg = msg + "\x02\x1D\x0304 ▶ \x0F\x1D\x0314Duration: \x0F\x1D{duration:} \x0F".format(duration=duration)
|
||||
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,}\x0F".format(published=published_at, views=view_count)
|
||||
msg = msg + "\x0F\x02\x0312 ♫ \x0F\x02\x0313\x1D{topics:}\x0F\x02\x0312 ".format(topics=", ".join(topics))
|
||||
msg = msg + url
|
||||
msg = self.bot.emo(msg)
|
||||
self.bot.privmsg(target, msg)
|
||||
self.bot.history.push_user_messages(mask.nick.lower(),title)
|
||||
#######################################################################################
|
||||
#######################################################################################
|
||||
###########################################################################################
|
||||
###########################################################################################
|
|
@ -0,0 +1,20 @@
|
|||
irc3
|
||||
aiocron
|
||||
timeago
|
||||
isodate
|
||||
google-api-python-client
|
||||
oauth2client
|
||||
aiohttp
|
||||
asyncio
|
||||
async_timeout
|
||||
lxml
|
||||
python-twitter
|
||||
imgaug==0.2.7
|
||||
folium==0.2.1
|
||||
numpy==1.19.2
|
||||
torch==1.9.1
|
||||
transformers==2.3.0
|
||||
googletrans==2.4.0
|
||||
textblob==0.15.3
|
||||
matplotlib==3.1.1
|
||||
pyfiglet
|
Loading…
Reference in New Issue