work in progress

This commit is contained in:
.[d]. 2022-08-08 04:22:30 -05:00
commit ac5a09bd88
71 changed files with 5406 additions and 0 deletions

52
README.md Normal file
View File

@ -0,0 +1,52 @@
# MAPLE+G1MP ML/Irc3 Hybrid VARIANTED INTO NETSPANNING
```
[ Netspanning ]
- irc
- matrix
[ The hybridization ]
- m4plmp - [sourcecode](https://git.tcp.direct/decoded/m4pl1mp)
[ 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/maple_netspan.git`
2. `cd maple_netspan`
3. `virtualenv env -p python3`
4. `source env/bin/activate`
### Append your developer api keys to env/bin/activate. Example below:
```
cat env/bin/activate
..
export BOT_SASL_USERNAME=your_nickserv_username
export BOT_SASL_PASSWORD=your_nickserv_password
export NICKSERV_USERNAME=your_nickserv_username
export NICKSERV_PASSWORD=your_nickserv_password
export MATRIX_HOMESERVER=https://matrix.org
export MATRIX___USERNAME=your_matrix_username
export MATRIX___PASSWORD=your_matrix_password
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
```
5. `pip install -r requirements.txt`
6. `edit maple.py - add your matrix username here so that it self-ignores`
```
guds.add_credentials("@maple.or.g1mp:matrix.org")
guds.add_credentials("@maple:pcriot.org")
```
7. `edit plugins/net_matrix_plugin.py - change this username to your to access commands`
```
if m_sender=="@d:tcp.direct":
```
8. `python3 maple.py`

426
databases/emote.db Normal file
View File

@ -0,0 +1,426 @@
¢‿¢
©¿© o
ª{•̃̾_•̃̾}ª
¬_¬
¯\(º_o)/¯
¯\(º o)/¯
¯\_(⊙︿⊙)_/¯
¯\_(ツ)_/¯
°ω°
°Д°
°‿‿°
°ﺑ°
´ ▽ ` )ノ
¿ⓧ_ⓧﮌ
Ò,ó
ó‿ó
ô⌐ô
ôヮô
ŎםŎ
ŏﺡó
ʕ•̫͡•ʔ
ʕ•ᴥ•ʔ
ʘ‿ʘ
˚•_•˚
˚⌇˚
˚▱˚
̿ ̿̿'̿'\̵͇̿̿\=(•̪●)=/̵͇̿̿/'̿̿ ̿ ̿ ̿
͡° ͜ʖ ͡°
Σ ◕ ◡ ◕
Σ (゚Д゚;
Σ(゚Д゚;≡;゚д゚)
Σ(゚Д゚ )
Σ(||゚Д゚)
Φ,Φ
δﺡό
σ_σ
д_д
ф_ф
щ(゚Д゚щ)
щ(ಠ益ಠщ)
щ(ಥДಥщ)
Ծ_Ծ
أ‿أ
ب_ب
ح˚௰˚づ
ح˚ᆺ˚ว
حᇂﮌᇂ)
٩๏̯͡๏۶
٩๏̯͡๏)۶
٩◔̯◔۶
٩(×̯×)۶
٩(̾●̮̮̃̾•̃̾)۶
٩(͡๏̯͡๏)۶
٩(͡๏̯ ͡๏)۶
٩(ಥ_ಥ)۶
٩(•̮̮̃•̃)۶
٩(●̮̮̃•̃)۶
٩(●̮̮̃●̃)۶
٩(。͡•‿•。)۶
٩(-̮̮̃•̃)۶
٩(-̮̮̃-̃)۶
۞_۞
۞_۟۞
۹ↁﮌↁ
۹⌤_⌤۹
॓_॔
१✌◡✌५
१|˚–˚|५
ਉ_ਉ
ଘ_ଘ
இ_இ
ఠ_ఠ
రృర
ಠ¿ಠi
ಠ‿ಠ
ಠ⌣ಠ
ಠ╭╮ಠ
ಠ▃ಠ
ಠ◡ಠ
ಠ益ಠ
ಠ益ಠ
ಠ︵ಠ凸
ಠ , ಥ
ಠ.ಠ
ಠoಠ
ಠ_ృ
ಠ_ಠ
ಠ_๏
ಠ~ಠ
ಡ_ಡ
ತಎತ
ತ_ತ
ಥдಥ
ಥ‿ಥ
ಥ⌣ಥ
ಥ◡ಥ
ಥ﹏ಥ
ಥ_ಥ
ಭ_ಭ
ರ_ರ
ಸ , ໖
ಸ_ಸ
ക_ക
อ้_อ้
อ_อ
โ๏௰๏ใ ื
๏̯͡๏﴿
๏̯͡๏
๏̯͡๏﴿
๏[-ิิ_•ิ]๏
๏_๏
໖_໖
ლ(´ڡ`ლ)
ლ(́◉◞౪◟◉‵ლ)
ლ(ಠ益ಠლ)
ლ(╹◡╹ლ)
ლ(◉◞౪◟◉‵ლ)
ლ,ᔑ•ﺪ͟͠•ᔐ.ლ
ᄽὁȍ ̪ őὀᄿ
ᕕ( ᐛ )ᕗ
ᕙ(⇀‸↼‶)ᕗ
ᕦ(ò_óˇ)ᕤ
ᶘ ᵒᴥᵒᶅ
‘︿’
•▱•
•✞_✞•
•ﺑ•
•(⌚_⌚)•
•_•)
‷̗ↂ凸ↂ‴̖
‹•.•›
(•¿•)
(ᵒᴥᵒ­­­­­)
(•¿•)
ↁ_ↁ
⇎_⇎
∩(︶▽︶)∩
∩( ・ω・)∩
≖‿≖
≧ヮ≦
⊂•⊃_⊂•⊃
⊂⌒~⊃。Д。)⊃
⊂(◉‿◉)つ
⊂(゚Д゚,,⊂⌒`つ
⊙ω⊙
⊙▂⊙
⊙▃⊙
⊙△⊙
⊙︿⊙
⊙﹏⊙
⊙0⊙
⊛ठ̯⊛
⋋ō_ō`
━━━ヽ(ヽ(゚ヽ(゚ヽ(゚゚ヽ(゚゚)ノ゚゚)ノ゚)ノ゚)ノ)ノ━━━
┌∩┐(◕_◕)┌∩┐
┌( ಠ_ಠ)┘
┌( ಥ_ಥ)┘
╚(•⌂•)╝
╭╮╭╮☜{•̃̾_•̃̾}☞╭╮╭╮
╭✬⌢✬╮
╮(▽)╭
╯‵Д′)╯彡┻━┻
╰☆╮
□_□
►_◄
◃┆◉◡◉┆▷
◉△◉
◉︵◉
◉_◉
○_○
●¿●\ ~
●_●
◔̯◔
◔ᴗ◔
◔ ⌣ ◔
◔_◔
◕ω◕
◕‿◕
◕◡◕
◕ ◡ ◕
◖♪_♪|◗
◖|◔◡◉|◗
◘_◘
◙‿◙
◜㍕◝
◪_◪
◮_◮
☁ ☝ˆ~ˆ☂
☆¸☆
☉‿⊙
☉_☉
☐_☐
☜ق❂Ⴢ❂ق☞
☜(⌒▽⌒)☞
☜(゚ヮ゚☜)
☜-(ΘLΘ)-☞
☝☞✌
☮▁▂▃▄☾ ♛ ◡ ♛ ☽▄▃▂▁☮
☹_☹
☻_☻
☼.☼
☾˙❀‿❀˙☽
♀ح♀ヾ
♥‿♥
♥╣[-_-]╠♥
♥╭╮♥
♥◡♥
✌♫♪˙❤‿❤˙♫♪✌
✌.ʕʘ‿ʘʔ.✌
✌.|•͡˘‿•͡˘|.✌
✖‿✖
✖_✖
❐‿❑
_
_Ꙩ
⨂_⨂
〆(・・@)
《〠_〠》
【•】_【•】
〠_〠
〴⋋_⋌〵
<EFBFBD> <20>
ニガー? ━━━━━━(゚゚)━━━━━━ ニガー?
ペ㍕˚\
ヽ(´ー` )ノ
ヽ(๏๏ )ノ
ヽ(`Д´)ノ
ヽ(`皿′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=ー( ゚д゚)・∵.
\˚ㄥ˚\
\ᇂ_ᇂ\
\(ಠ ὡ ಠ )/
\(◕ ◡ ◕\)
^̮^
^ㅂ^
_(͡๏̯͡๏)_
{´◕ ◡ ◕`}
{ಠ_ಠ}__,,|,
{◕ ◡ ◕}

63
maple.py Normal file
View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import irc3,os,threading,asyncio,ipdb
from time import sleep
from plugins.tool_dims_plugin import dims
from plugins.tool_guds_plugin import guds
from plugins.net_irc_plugin import config_ircbot
from plugins.net_irc_plugin import start_ircbot
from plugins.net_matrix_plugin import start_matrixbot
from plugins.tool_bus_plugin import BUS
##################################################channel##################################
class BOTIO:
#######################################################################################
verbosity=True
log_exit_level=[]
#######################################################################################
def __init__(self):
print(f'<<< ________botio_class >>> [ instantiated ]')
self.ircbot=config_ircbot()
self.net_irc=[]
self.net_matrix=[]
print(f'<<< ________botio_class >>> [ ircbot configured ]')
#######################################################################################
def __boot__irc(self):
print('<<< system_status__info >>> [ booting connection: irc ]')
self=start_ircbot(self)
#######################################################################################
def __boot__matrix(self):
print('<<< system_status__info >>> [ booting connection: matrix ]')
self=start_matrixbot(self)
#######################################################################################
def __boot__empty(self):
print('<<< system_status__info >>> [ booting connection: empty ]')
#######################################################################################
def __main__(self,index):
if index==0:
t=threading.Thread(target=self.__boot__irc)
print(f'<<< system_status__info >>> [ irc thread setup ]')
t.start()
print(f'<<< system_status__info >>> [ irc thread started ]')
elif index==1:
t=threading.Thread(target=self.__boot__matrix)
print(f'<<< system_status__info >>> [ matrix thread setup ]')
t.start()
t.join()
print(f'<<< system_status__info >>> [ matrix thread started ]')
# elif index==2:
# print(f'<<< system_status__info >>> [ empty thread setup ]')
# t=threading.Thread(target=self.__boot__empty)
# t.start()
# print(f'<<< system_status__info >>> [ empty thread started ]')
###########################################################################################
if __name__ == '__main__':
print('<<< system_status__info >>> [ main startup ]')
guds.add_credentials("@maple.or.g1mp:matrix.org")
guds.add_credentials("@maple:pcriot.org")
bio=BOTIO()
globals()['guds'].memories.append([bio,'maple:__main__.bio'])
for i in range(3):
bio.log_exit_level.append(bio.__main__(i))
while True:
if bio.verbosity: print('<<< system_status__info >>> [ eventloop idler thread ]')
sleep(1)
####################################################################################### EOF

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

30
plugins/auth_plugin.py Normal file
View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.cron import cron
import irc3, os
###########################################################################################
###########################################################################################
NICKSERV_USERNAME=os.environ['NICKSERV_USERNAME']
NICKSERV_PASSWORD=os.environ['NICKSERV_PASSWORD']
###########################################################################################
###########################################################################################
@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)
###########################################################################################
####################################################################################### EOF

267
plugins/base_plugin.py Normal file
View File

@ -0,0 +1,267 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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):
self.bot=bot
staff_set=set()
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(f"GOD {opper_username} {opper_password}")
self.bot.privmsg("nickserv", f"IDENTIFY {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 = f"MODE {channel} +b {mask.nick}!*@*"
self.bot.send(cmd)
self.bot.kick(channel, mask.nick, msg)
###########################################################################################
###########################################################################################
@command(permission='view', public=True, show_in_help_list=True)
def v(self, mask, target, args):
"""Voices all present users in channel
%%v
"""
channel = self.bot.channels[target]
try:
OP_FLAG=False
channel = self.bot.channels[target]
for _, nick in channel.modes.items():
for __ in _:
modes=["%","@","&","~"]
if __ in modes:
if mask.nick in nick:
OP_FLAG=True
if OP_FLAG:
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 = f"MODE {target} +v {mask.nick}"
self.bot.send(cmd)
except Exception as e:
msg=f'error: base_plugin > v: {e}'
print(msg)
self.bot.privmsg(target,self.bot.emo(msg))
pass
###########################################################################################
###########################################################################################
@command(permission='admin', public=True, show_in_help_list=False)
def op(self, mask, target, args):
"""Ops user
%%op <nick>
"""
if args['<nick>']:
nick = args['<nick>']
cmd = f"MODE {target} +o {mask.nick}"
self.bot.send(cmd)
###########################################################################################
###########################################################################################
@command(permission='admin', public=True, show_in_help_list=False)
def deop(self, mask, target, args):
"""Deops user
%%op <nick>
"""
if args['<nick>']:
nick = args['<nick>']
cmd = f"MODE {target} -o {mask.nick}"
self.bot.send(cmd)
###########################################################################################
###########################################################################################
@command(permission="admin", show_in_help_list=False)
def stats(self, mask, target, args):
"""Stats
%%stats
"""
channel = target
if channel in self.bot.channels:
channel = self.bot.channels[channel]
message = f'{len(channel)} users'
for mode, nicknames in sorted(channel.modes.items()):
message += f' - {mode}({len(nicknames)})'
self.bot.privmsg(target, message)
###########################################################################################
###########################################################################################
@command(permission='admin', public=False, show_in_help_list=False)
def restart(self, mask, target, args):
"""restart
%%restart
"""
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):
"""staff
%%staff <noise>...
"""
###################################################################################
###################################################################################
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, f'{host_string} removed from staff')
return
else:
pass # pass for brevarity
else:
self.bot.privmsg(target, f'{host_string} is not a staff member')
###############################################################################
###############################################################################
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, f"{host_string} is already a staff member")
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, f'{host_string} added to staff')
###############################################################################
###############################################################################
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 = ' '.join(args['<noise>'])[0]
args = ' '.join(args['<noise>'])[1:]
###################################################################################
###################################################################################
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)
###################################################################################
###################################################################################
####################################################################################### EOF

772
plugins/boombox_plugin.py Normal file
View File

@ -0,0 +1,772 @@
# -*- coding: utf-8 -*- ############################################################### SOF
###########################################################################################
import irc3
from irc3.plugins.command import command
from urllib.parse import urlparse
from datetime import datetime
from glob import glob
from typing import Type
import random
import string
import os
########################################################################## THE ASCII LOGO TO BE USED
MOTD="""
_________ _________ _________ ___ ___ _________ _________ ____ ____
| o ) / O \ / O \ | \ / | | o ) / O \ \ \_/ /
|_____O___) \_________/ \_________/ |____|____| |_____O___) \_________/ /___/%\___\\
'BBBBBBB' 'BBBBBBB' 'BBBBBBB' 'BBBBBBB' 'BBBBBBB' 'BBBBBBB' 'BB' 'BB'
"""
######################################################################## BOOMBOX MAIN ENTRY
@irc3.plugin
class Plugin:
##################################################################### BOOMBOX MAIN INIT
def __init__(self, bot):
###################################################################################
self.bot=bot
self.bot.diagnostic_flag=False
self.bot.bbs=BOOMBOX_CONFIG(self.bot)
#################################################################### SOF COLOR INIT
self.bot.bbs.c=[]
self.bot.bbs.b1,self.bot.bbs.b2,self.bot.bbs.b3,self.bot.bbs.b4=self.bot.bbs.palette()[0:4]
self.bot.bbs.b5,self.bot.bbs.b6,self.bot.bbs.b7,self.bot.bbs.b8=self.bot.bbs.palette()[0:4]
######################################################################## COLOR INIT
self.bot.bbs.sites=['soundcloud','youtube','spotify','bandcamp']
self.bot.bbs.floor__top_songs=15
self.bot.bbs.floor__last_songs=15
self.bot.bbs.floor__top_users=5
self.bot.bbs.floor__top_sites=len(self.bot.bbs.sites)
self.bot.bbs.ceiling__top_songs=50
self.bot.bbs.ceiling__last_songs=50
self.bot.bbs.ceiling__top_users=25
self.bot.bbs.ceiling__top_sites=len(self.bot.bbs.sites)
#################################################################### EOF COLOR INIT
self.bot.bbs.bot=self.bot
################################################################## CHECK OR PREP DB
######################################################################## BOOMBOX MAIN 1
@command(permission='view',public=True, show_in_help_list=False)
def dbdo(self, mask, target, args):
"""dbdo sync
%%dbdo <noise>...
"""
noise=' '.join(args['<noise>'])
commands=noise.split()
db=noise.split()[0]
op=noise.split()[1]
data=' '.join(noise.split()[2:])
result=self.bot.bbs.dbdo(db,op,data)
######################################################################## BOOMBOX MAIN 1
@command(permission='view',public=True, show_in_help_list=False)
def bb(self, mask, target, args):
"""Convert boombox token to a url
%%bb <token>...
"""
c=self.bot.bbs.palette()
self.bot.bbs.c=c
token=''.join(args['<token>'])
tokens=self.bot.db.getlist("bbs_token")
url=''
for t in tokens:
if token in t:
url=t[token]
msg=f"{c[0]}{mask.nick} {c[1]}> {c[2]}boombox"
if url:
title_prefetch_data=self.bot.prefetch_title(url,target,mask)
if url.find('soundcloud'):
try:
if title_prefetch_data:
title=title_prefetch_data.split('|')[0].strip().replace('Stream','').strip()
msg+=f"{c[1]} > {c[4]}{title} {c[1]}> {c[3]}{url}{c[1]}"
else:
msg+=f"{c[2]}url{c[1]} > {c[3]}{url}"
except:
msg+=f"{c[2]}url{c[1]} > {c[3]}{url}"
else:
msg+=f"{c[2]}error{c[1]}: {c[3]}{token} is an invalid token"
self.bot.privmsg(target,self.bot.emo(msg))
######################################################################## BOOMBOX MAIN 2
@command(permission='view',error_format="{cmd} error - usage: ?{cmd} all,top,old,user,site - example: ?{cmd} all".format)
def boombox(self, mask, target, args):
"""boombox
%%boombox
"""
command='all'
###################################################################################
commands=['top','old','user','site','all']
###################################################################################
if not command in commands:
msg="boombox - usage: ?boombox top, ?boombox old, ?boombox user, ?boombox site, ?boombox all"
self.bot.privmsg(target,self.bot.emo(msg))
return
###################################################################################
bbs_last=self.bot.db.getlist("bbs_last")
bbs_data=self.bot.db.getlist('bbs_data')
###################################################################################
if bbs_data:
###############################################################################
c1,c2,c3,c4,c5,c6,c7,c8=self.bot.bbs.c
###############################################################################
if command=='all':
for _ in MOTD.splitlines():
if _:
self.bot.privmsg(target,f'{self.bot.bbs.palette()[0]}{_}')
###################################################################################
if command=='top' or command=='all':
# TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP
# TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP
# TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP SONGS TOP
msg=f'TOP SONGS ◸{c2}◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸'
###########################################################################
self.bot.privmsg(target,msg)
bbs_data=self.bot.db.getlist('bbs_data')
hits=[]
for i,data in enumerate(bbs_data):
hits.append(data['hits'])
lot=[(k,v) for k, v in zip(range(len(hits)),hits)]
nl=[]
while len(lot)> 0:
nl.append(max(lot,key=lambda x: x[1]))
lot.remove(nl[-1])
nl[0:len(bbs_data)]
###########################################################################
mode_length=0
if command=='top':
mode_length=self.bot.bbs.ceiling__top_songs
elif command=='all':
mode_length=self.bot.bbs.floor__top_songs
###########################################################################
top_songs=[]
for i in range(mode_length):
try:
base=bbs_data[nl[i][0]]
except:
pass
title=base['title'].lower()
token=base['token']
url=base['url']
site=base['site']
hits=base['hits']
lot_nicks=[(k,v) for k, v in zip(range(len(base['nicks'].values())),base['nicks'].values())]
buf_nicks=[]
while len(lot_nicks)>0:
buf_nicks.append(max(lot_nicks,key=lambda x: x[1]))
lot_nicks.remove(buf_nicks[-1])
nick_hits=buf_nicks[0][1]
nick=list(base['nicks'])[buf_nicks[0][0]]
msg=f'{c4}{self.bot.bbs.tailor(title.lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site.lower(),10)} {c1}{c8}{self.bot.bbs.tailor(nick.lower(),10)} {c1}{c7}{str(nick_hits).zfill(2)}{c1}/{c7}{str(hits).zfill(2)} {c6}plays {c1}{c5}?bb {token}'
top_songs.append(msg)
last_song=""
for song in top_songs:
if song==last_song:
break
last_song=song
self.bot.privmsg(target,song)
###############################################################################
if command=='old' or command=='all':
# OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD
# OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD
# OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD SONGS OLD
msg=f'OLD SONGS ◸{c2}◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸'
self.bot.privmsg(target,msg)
bbs_data=self.bot.db.getlist('bbs_data')
last_songs=[]
try:
for i,lastdb in enumerate(bbs_last):
nick=lastdb[0]
site=lastdb[1]
title=lastdb[2]
token=lastdb[3]
url=lastdb[4]
try:
reverse_index=self.bot.bbs.dbgaze('bbs_data','token',token)
hits=bbs_data[reverse_index]['hits']
db_key_nicks=list(zip(list(bbs_data[reverse_index]['nicks'].values()),list(bbs_data[reverse_index]['nicks'].keys())))
db_key_nicks.sort()
user=db_key_nicks[-1][1]
plays=user=db_key_nicks[-1][0]
if len(lastdb)>0:
msg=f'{c4}{self.bot.bbs.tailor(title.lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site.lower(),10)} {c1}{c8}{self.bot.bbs.tailor(nick.lower(),10)} {c1}{c7}{str(plays).zfill(2)}{c1}/{c7}{str(hits).zfill(2)} {c6}plays {c1}{c5}?bb {token}'
last_songs.append(msg)
except Exception as e:
print(f'<<< _____boombox_plugin >>> boombox:last - error: {e}')
except Exception as e:
pass
###########################################################################
mode_length=0
if command=='old':
mode_length=self.bot.bbs.ceiling__last_songs
elif command=='all':
mode_length=self.bot.bbs.floor__last_songs
###########################################################################
try:
for i in range(mode_length):
self.bot.privmsg(target,last_songs[i])
except:
pass
###############################################################################
if command=='user' or command=='all':
# TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP
# TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP
# TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP USERS TOP
msg=f'TOP USERS ◸{c2}◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸'
self.bot.privmsg(target,msg)
top_data=self.bot.db.getlist('bbs_data')
bbs_nicks=self.bot.db.getlist("bbs_nicks")
top_nicks=list(bbs_nicks[0].keys())
top_users_tally=[]; top_users=[]
for _ in [ x for x in bbs_nicks[0] ]:
top_users_tally.append(bbs_nicks[0][_]['tally'])
for _ in [ x for x in bbs_nicks[0] ]:
top_users.append(_)
userlist=list(zip(top_users_tally,top_users))
userlist.sort()
userlist.reverse()
for i,userdata in enumerate(userlist):
tally,user=userdata
top_users=[]
for _user in userlist:
top_user=_user[1]
user_hits=[]
for i,_ in enumerate(bbs_data):
try:
user_hits.append(f"{_['nicks'][_user[1]]},{i}")
except:
pass
user_hits.sort()
user_hits.reverse()
top_hits=int(user_hits[0].split(',')[0])
top_index=int(user_hits[0].split(',')[1])
top_hits_site=int(bbs_data[top_index]['hits'])
top_site=bbs_data[top_index]['site']
top_title=bbs_data[top_index]['title']
top_token=bbs_data[top_index]['token']
msg=f'{c4}{self.bot.bbs.tailor(top_title.lower(),50)} {c1}{c3}{self.bot.bbs.tailor(top_site.lower(),10)} {c1}{c8}{self.bot.bbs.tailor(top_user.lower(),10)} {c1}{c7}{str(top_hits).zfill(2)}{c1}/{c7}{str(top_hits_site).zfill(2)} {c6}plays {c1}{c5}?bb {top_token}'
top_users.append(msg)
###########################################################################
mode_length=0
if command=='user':
mode_length=self.bot.bbs.ceiling__top_users
elif command=='all':
mode_length=self.bot.bbs.floor__top_users
###########################################################################
try:
for i in range(mode_length):
self.bot.privmsg(target,top_users[i])
except:
pass
###############################################################################
if command=='site' or command=='all':
# TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP
# TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP
# TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP SITES TOP
bbs_sites=self.bot.db.getlist("bbs_sites")
msg=f'TOP SITES ◸{c2}◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸◹◸'
self.bot.privmsg(target,msg)
bbs_nicks=self.bot.db.getlist('bbs_nicks')
site_nicks=list(bbs_nicks[0].keys())
site_users_bandcamp=[]; site_users_soundcloud=[];
site_users_youtube=[]; site_users_spotify=[];
for _ in [ x for x in site_nicks ]:
site_users_bandcamp.append([bbs_nicks[0][_]['bandcamp'],_])
site_users_soundcloud.append([bbs_nicks[0][_]['soundcloud'],_])
site_users_youtube.append([bbs_nicks[0][_]['youtube'],_])
site_users_spotify.append([bbs_nicks[0][_]['spotify'],_])
site_users_bandcamp.sort(); site_users_bandcamp.reverse()
site_users_soundcloud.sort(); site_users_soundcloud.reverse()
site_users_youtube.sort(); site_users_youtube.reverse()
site_users_spotify.sort(); site_users_spotify.reverse()
###########################################################################
bandcamp_top_user_hits=[]
for i,_ in enumerate(bbs_data):
if _['site']=='bandcamp':
bandcamp_top_user_hits.append(f'{_["hits"]},{i}')
bandcamp_top_user_hits.sort()
bandcamp_top_user_hits.reverse()
bandcamp_index=int(bandcamp_top_user_hits[0].split(',')[1])
bandcamp_title=bbs_data[bandcamp_index]['title']
bandcamp_site=bbs_data[bandcamp_index]['site']
bandcamp_user=site_users_bandcamp[0][1]
bandcamp_userhits=bandcamp_top_user_hits[0].split(',')[0]
bbs_sites=self.bot.db.getlist('bbs_sites')
bandcamp_sitehits=bbs_sites[0]['bandcamp']
bandcamp_token=bbs_data[bandcamp_index]['token']
site_bandcamp=[bandcamp_title,bandcamp_site,bandcamp_user,bandcamp_userhits,bandcamp_sitehits,bandcamp_token,bandcamp_index]
###########################################################################
soundcloud_top_user_hits=[]
for i,_ in enumerate(bbs_data):
if _['site']=='soundcloud':
soundcloud_top_user_hits.append(f'{_["hits"]},{i}')
soundcloud_top_user_hits.sort()
soundcloud_top_user_hits.reverse()
soundcloud_index=int(soundcloud_top_user_hits[0].split(',')[1])
soundcloud_title=bbs_data[soundcloud_index]['title']
soundcloud_site=bbs_data[soundcloud_index]['site']
soundcloud_user=site_users_soundcloud[0][1]
soundcloud_userhits=soundcloud_top_user_hits[0].split(',')[0]
bbs_sites=self.bot.db.getlist('bbs_sites')
soundcloud_sitehits=bbs_sites[0]['soundcloud']
soundcloud_token=bbs_data[soundcloud_index]['token']
site_soundcloud=[soundcloud_title,soundcloud_site,soundcloud_user,soundcloud_userhits,soundcloud_sitehits,soundcloud_token,soundcloud_index]
###########################################################################
youtube_top_user_hits=[]
for i,_ in enumerate(bbs_data):
if _['site']=='youtube':
youtube_top_user_hits.append(f'{_["hits"]},{i}')
youtube_top_user_hits.sort()
youtube_top_user_hits.reverse()
youtube_index=int(youtube_top_user_hits[0].split(',')[1])
youtube_title=bbs_data[youtube_index]['title']
youtube_site=bbs_data[youtube_index]['site']
youtube_user=site_users_youtube[0][1]
youtube_userhits=youtube_top_user_hits[0].split(',')[0]
bbs_sites=self.bot.db.getlist('bbs_sites')
youtube_sitehits=bbs_sites[0]['youtube']
youtube_token=bbs_data[youtube_index]['token']
site_youtube=[youtube_title,youtube_site,youtube_user,youtube_userhits,youtube_sitehits,youtube_token,youtube_index]
###########################################################################
spotify_top_user_hits=[]
for i,_ in enumerate(bbs_data):
if _['site']=='spotify':
spotify_top_user_hits.append(f'{_["hits"]},{i}')
spotify_top_user_hits.sort()
spotify_top_user_hits.reverse()
spotify_index=int(spotify_top_user_hits[0].split(',')[1])
spotify_title=bbs_data[spotify_index]['title']
spotify_site=bbs_data[spotify_index]['site']
spotify_user=site_users_spotify[0][1]
spotify_userhits=spotify_top_user_hits[0].split(',')[0]
bbs_sites=self.bot.db.getlist('bbs_sites')
spotify_sitehits=bbs_sites[0]['spotify']
spotify_token=bbs_data[spotify_index]['token']
site_spotify=[spotify_title,spotify_site,spotify_user,spotify_userhits,spotify_sitehits,spotify_token,spotify_index]
###########################################################################
bbs_sites=self.bot.db.getlist("bbs_sites")
hits=[]
for i,data in enumerate(bbs_sites[0].keys()):
hits.append(bbs_sites[0][data])
lot=[(k,v) for k, v in zip(range(len(hits)),hits)]
nl=[]
while len(lot)> 0:
nl.append(max(lot,key=lambda x: x[1]))
lot.remove(nl[-1])
siteorder=[]
for i in range(len(nl)): siteorder.append(list(bbs_sites[0].keys())[nl[i][0]])
top_sites=[]
for site in siteorder:
if site=='soundcloud':
msg=f'{c4}{self.bot.bbs.tailor(site_soundcloud[0].lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site_soundcloud[1].lower(),10)} {c1}{c8}{self.bot.bbs.tailor(site_soundcloud[2].lower(),10)} {c1}{c7}{str(site_soundcloud[3]).zfill(2)}{c1}/{c7}{str(site_soundcloud[4]).zfill(2)} {c6}plays {c1}{c5}?bb {site_soundcloud[5]}'
top_sites.append(msg)
elif site=='bandcamp':
msg=f'{c4}{self.bot.bbs.tailor(site_bandcamp[0].lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site_bandcamp[1].lower(),10)} {c1}{c8}{self.bot.bbs.tailor(site_bandcamp[2].lower(),10)} {c1}{c7}{str(site_bandcamp[3]).zfill(2)}{c1}/{c7}{str(site_bandcamp[4]).zfill(2)} {c6}plays {c1}{c5}?bb {site_bandcamp[5]}'
top_sites.append(msg)
elif site=='youtube':
msg=f'{c4}{self.bot.bbs.tailor(site_youtube[0].lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site_youtube[1].lower(),10)} {c1}{c8}{self.bot.bbs.tailor(site_youtube[2].lower(),10)} {c1}{c7}{str(site_youtube[3]).zfill(2)}{c1}/{c7}{str(site_youtube[4]).zfill(2)} {c6}plays {c1}{c5}?bb {site_youtube[5]}'
top_sites.append(msg)
elif site=='spotify':
msg=f'{c4}{self.bot.bbs.tailor(site_spotify[0].lower(),50)} {c1}{c3}{self.bot.bbs.tailor(site_spotify[1].lower(),10)} {c1}{c8}{self.bot.bbs.tailor(site_spotify[2].lower(),10)} {c1}{c7}{str(site_spotify[3]).zfill(2)}{c1}/{c7}{str(site_spotify[4]).zfill(2)} {c6}plays {c1}{c5}?bb {site_spotify[5]}'
top_sites.append(msg)
###########################################################################
mode_length=0
if command=='site':
mode_length=self.bot.bbs.ceiling__top_sites
elif command=='all':
mode_length=self.bot.bbs.floor__top_sites
###########################################################################
try:
for i in range(mode_length):
self.bot.privmsg(target,top_sites[i])
except:
pass
###################################################################################
###################################################################### BOOMBOX CONFIG ENTRY
class BOOMBOX_CONFIG:
################################################################### BOOMBOX CONFIG INIT
def __init__(self,bot):
self.bot=bot
self.db=[]
self.bot.bbdb=[]
self.database_names=['bbs_data','bbs_last','bbs_nicks','bbs_sites','bbs_token','bbs_tokenmirror']
print(f'<<< _____boombox_plugin >>> [ database diagnostics ]')
for index,database in enumerate(self.database_names):
db=self.bot.db.getlist(database)
if not db:
print(f'<<< _____boombox_plugin >>> [ {" "*19}{index+1}/{len(self.database_names)} ] - [ missing database: {self.database_names[index]} ]')
self.db_diagnostics(database)
else:
print(f'<<< _____boombox_plugin >>> [ {index+1}/{len(self.database_names)} ] - [ located database: {self.database_names[index]} ]')
#print(f'{"#"*80} SOF')
#print(f' pre - a database name: {database}')
#print(f' pre - database memory: \n{self.db}')
#print(f' pre - a datbase entry: \n{db}')
#print(f'post - database merged: \n{db}')
#print(f'{"#"*80} EOF')
for _ in self.database_names:
self.bot.bbdb.append(self.bot.db.getlist(_))
############################################################ BOOMBOX CONFIG COLOR CODES
def color(self,c):
try:
c=str(c.lower())
if c=='0': return '\x0300'
if c=='1': return '\x0301'
if c=='2': return '\x0302'
if c=='3': return '\x0303'
if c=='4': return '\x0304'
if c=='5': return '\x0305'
if c=='6': return '\x0306'
if c=='7': return '\x0307'
if c=='8': return '\x0308'
if c=='9': return '\x0309'
if c=='a': return '\x0310'
if c=='b': return '\x0311'
if c=='c': return '\x0312'
if c=='d': return '\x0313'
if c=='e': return '\x0314'
if c=='f': return '\x0315'
if c=='n': return ''
if c=='t': return '\x0f'
print('color: empty')
return '\x0f'
except:
print('color: error')
return '\x0f'
############################################################# BOOMBOX CONFIG COLOR SETS
def palette(self):
self.c=[]; self.n=[]
for i in range(0,8):
n=random.randint(0,15)
c=self.color(hex(n)[2:])
self.c.append(c); self.n.append(n)
return self.c
######################################################## BOOMBOX CONFIG TEXT ALIGNMENTS
def tailor(self,s,n):
if len(s)<=n:
result=s+"."*(n-len(s))
return result
else:
return s[0:n]
######################################################## BOOMBOX CONFIG TEXT ALIGNMENTS
def dbsync(self,db):
for i,database in enumerate(['bbs_data','bbs_last','bbs_nicks','bbs_sites','bbs_token','bbs_tokenmirror']):
if db == database:
try:
db_stored=self.bot.db.getlist(database)
db_memory=self.bot.bbdb[i]
if not db_memory==db_stored:
self.bot.db.setlist(database,db_memory)
print('<<< _____boombox_plugin >>> success: storage database updated from memory')
else:
print('<<< _____boombox_plugin >>> aborted: storage database same as memory content')
except Exception as e:
print('<<< _____boombox_plugin >>> dbsync:error - failed in writing to storage database from memory: {e}')
######################################################## BOOMBOX CONFIG TEXT ALIGNMENTS
def dbdo(self,database,operation,data=""):
database_names=(['bbs_data','bbs_last','bbs_nicks','bbs_sites','bbs_token','bbs_tokenmirror'])
operations=['get','set','update','append']
if database in database_names:
index=database_names.index(database)
if operation in operations:
if operation=="get":
return self.bot.bbdb[index]
elif operation=='set':
db_stored=self.bot.db.getlist(database)
print(f'<<< _____boombox_plugin >>> pre:{database} db_stored: {db_stored}')
print(f'<<< _____boombox_plugin >>> pre:{database} db_memory: {self.bot.bbdb[index]}')
print(f'<<< _____boombox_plugin >>> pre:{database} db_sent: {data}')
self.bot.bbdb[index]=data
print(f'<<< _____boombox_plugin >>> post:{database} db_memory: {self.bot.bbdb[index]}')
print(f'<<< _____boombox_plugin >>> writing from memory to storage')
self.dbsync(database)
elif operation=='append':
db_stored=self.bot.db.getlist(database)
print(f'<<< _____boombox_plugin >>> pre:{database} db_stored: {db_stored}')
print(f'<<< _____boombox_plugin >>> pre:{database} db_memory: {self.bot.bbdb[index]}')
self.bot.bbdb[index].append(data)
print(f'<<< _____boombox_plugin >>> post:{database} db_memory: {self.bot.bbdb[index]}')
print(f'<<< _____boombox_plugin >>> writing from memory to storage')
self.dbsync(database)
#################################################### BOOMBOX CONFIG DATABASE OPERATIONS
def push(self,nick,site,title,token,url):
nick=self.no_unicode(nick)
title=self.no_unicode(title)
bbs_data=self.dbdo('bbs_data','get')
bbs_last=self.dbdo('bbs_last','get')
bbs_last=bbs_last[-1:]+bbs_last[:-1]
bbs_last[0]=[nick,site,title,token,url]
self.dbdo('bbs_last','set',bbs_last)
#################################################### BOOMBOX CONFIG DATABASE OPERATIONS
def check(self,nick,site,data):
###################################################################################
bbs_nicks=self.dbdo('bbs_nicks','get')
bbs_sites=self.dbdo('bbs_sites','get')
bbs_data=self.dbdo('bbs_data','get')
bbs_token=self.dbdo('bbs_token','get')
bbs_tokenmirror=self.dbdo('bbs_tokenmirror','get')
###################################################################################
try:
if bbs_data:
for i,_data in enumerate(bbs_data):
if data['url']==_data['url']:
_data['hits']+=1
try:
_data['nicks'][nick]+=1
except:
_data['nicks'].update({nick:1})
try:
bbs_nicks[0][nick]['tally']+=1
bbs_nicks[0][nick][site]+=1
except:
bbs_nicks[0].update({nick:{'tally':1,'bandcamp':0,'soundcloud':0,'spotify':0,'youtube':0}})
bbs_nicks[0][nick][site]+=1
bbs_sites[0][site]+=1
bbs_data[i]=_data
self.dbdo("bbs_nicks",'set',bbs_nicks)
self.dbdo("bbs_sites",'set',bbs_sites)
self.dbdo("bbs_data",'set',bbs_data)
return
###########################################################################
try:
bbs_nicks[0][nick]['tally']+=1
bbs_nicks[0][nick][site]+=1
except:
bbs_nicks[0].update({nick:{'tally':1,'bandcamp':0,'soundcloud':0,'spotify':0,'youtube':0}})
bbs_nicks[0][nick][site]+=1
###########################################################################
self.dbdo("bbs_nicks",'set',bbs_nicks)
bbs_sites[0][site]+=1
self.dbdo("bbs_sites",'set',bbs_sites)
bbs_data.append(data)
self.dbdo("bbs_data",'set',bbs_data)
URL=data['url']; TOKEN=data['token']
self.dbdo('bbs_token','append',{TOKEN:URL})
self.dbdo("bbs_token",'set',bbs_token)
self.dbdo('bbs_tokenmirror','append',{TOKEN:URL})
self.dbdo('bbs_tokenmirror','set',bbs_tokenmirror)
except:
bbs_nicks=[]
self.dbdo('bbs_nicks','append',{nick:{'tally':1,'bandcamp':0,'soundcloud':0,'spotify':0,'youtube':0}})
bbs_nicks[0][nick][site]+=1 ############################################ NOTICE
self.dbdo('bbs_nicks','set',bbs_nicks)
self.dbdo('bbs_sites','set',[{'soundcloud':0,'youtube':0,'spotify':0,'bandcamp':0}])
bbs_sites=self.dbdo('bbs_sites','get')
bbs_sites[0][site]+=1 ################################################## NOTICE
self.dbdo('bbs_sites','set',bbs_sites)
self.dbdo('bbs_data','set',[data])
URL=data['url']; TOKEN=data['token']
self.dbdo('bbs_token',{TOKEN:URL})
self.dbdo('bbs_token','set', bbs_token)
self.dbdo('bbs_token',{TOKEN:URL})
self.dbdo('bbs_tokenmirror','append',{URL:TOKEN})
self.dbdo('bbs_tokenmirror','set',bbs_tokenmirror)
################################### BOOMBOX CONFIG HOOKED EXTERNALS DATABASE OPERATIONS
def getsite(self,url):
###################################################################################
sites=['soundcloud','youtube','spotify','bandcamp']
if not url.find('soundcloud.com')==-1:
return sites[0]
if not url.find('youtube.com')==-1 or not url.find('youtu.be')==-1:
return sites[1]
if not url.find('spotify.com')==-1:
return sites[2]
if not url.find('bandcamp.com')==-1:
return sites[3]
################################### BOOMBOX CONFIG HOOKED EXTERNALS DATABASE OPERATIONS
def enter(self,nick,url,title):
###################################################################################
timestamp=datetime.now().timestamp()
token=self.token(url)
bbs_token=self.dbdo('bbs_token','get')
nick=self.no_unicode(nick)
title=self.no_unicode(title).lower()
site=self.getsite(url)
###################################################################################
data={'nicks':{nick:1},'title':title.lower(),'url':url,'token':token,'timestamp':timestamp,'site':site,'hits':1}
###################################################################################
if site=='soundcloud':
title=title[:title.rfind('by')].replace('Stream','').strip().lower()
if not title=='SoundCloud - Hear the worlds sound':
data['title']=title.split('music |')[0].rstrip().lower()
data=self.check(nick,site,data)
self.push(nick.lower(),site,title.lower(),token,url)
###################################################################################
if site=='youtube':
id=url[-11:]
result=self.bot.videos_list_by_id(id=id)
if result:
data=self.check(nick,site,data)
self.push(nick.lower(),site,title.lower(),token,url)
###################################################################################
if site=='spotify':
offset=url.rfind('/')+1
try:
track=title.split('|')[0].split('- song by')[0].strip()
try:
artist=title.split('|')[0].split('- song by')[1].strip()
except:
artist=title.split('|')[0].split('- Album by')[0].strip()
try:
artist=title.split('|')[0].split('- Album by')[1].strip()
except:
artist=title.split('by ')[1].split(' | ')[0]
try:
track=title.split(' - ')[0]
except:
pass
except:
title=title.lower()
if track and artist:
title=f'{artist} - {track}'.lower()
data['title']=title
data=self.check(nick,site,data)
self.push(nick.lower(),site,title.lower(),token,url)
###################################################################################
if site=='bandcamp':
offset=url.rfind('/')+1
try:
track=title.split('|')[0].lower().strip()
except:
pass
try:
artist=title.split('|')[1].lower().strip()
title=f'{artist} - {track}'.lower()
except:
artist=""
title=f'{artist}{track}'.lower()
data['title']=title.lower()
data=self.check(nick,site,data)
self.push(nick.lower(),site,title.lower(),token,url)
########################################### BOOMBOX CONFIG DATABASE OPERATIONS FOR URLS
def token(self,url):
bbs_token=self.dbdo('bbs_token','get')
bbs_tokenmirror=self.dbdo('bbs_tokenmirror','get')
S=list(string.ascii_letters+string.digits)
random.shuffle(S)
S=''.join(S)[:5]
while S in [list(x.keys())[0] for x in bbs_token]:
S=list(string.ascii_letters+string.digits)
random.shuffle(S); S=''.join(S)[:5]
return f'{S}'
#################################### BOOMBOX CONFIG TEXT FILTERING BY STRIPPING UNICODE
def no_unicode(self,s):
if len(s) < 1: return s
s=s.encode('ascii','ignore').decode()
s=s.strip().replace(' ',' ')
return s
##### BOOMBOX CONFIG DB OPERATIONS - SUB-SCANNING RECORDS RETURNING CONDITIONAL BOOLEAN
def dbskim(self,db,s):
buffer=self.dbdo(db,'get')
for _ in buffer:
try:
result=_[s]
if result:
return result
except:
pass
##### BOOMBOX CONFIG DB OPERATIONS - SUB-SCANNING RECORDS RETURNING CONDITIONAL BOOLEAN
def dbgaze(self,db,key,s):
buffer=self.dbdo(db,'get')
for i,_ in enumerate(buffer):
try:
result=(_[key]==s)
if result:
return i
except:
pass
##### BOOMBOX CONFIG DB OPERATIONS - AUTOMATICALLY CREATES/REPAIRS/STAGES THE DATABASES
@irc3.extend
def db_diagnostics(self,database_name,*args):
#######################################################################################
# database_names = ['bbs_data','bbs_last','bbs_nicks','bbs_sites','bbs_token','bbs_tokenmirror']
###################################################################################
index=-1
###################################################################################
for i, database in enumerate(self.database_names):
if database_name==database:
index=i
break
print(f"<<< _____boombox_plugin >>> [ db_diagnostics - index: {index} - database: {database_name} ]")
###################################################################################
print(f'<<< _____boombox_plugin >>> [{index+1}/{len(self.database_names)}] - [ creating database: {self.database_names[index]} ]')
automation_flag=False
########################################################## database: 0/5 - bbs_data
if database_name==self.database_names[0]:
###############################################################################
try:
db=[]
db.append({'nicks':{"dr1p":1},'title':'fenix flexin - 10 toes ( dr1ph0p m1x )','url':'https://soundcloud.com/vanta_sec/fenix-flexin-10-toes-dr1ph0p-m1x','token':'06660','timestamp':1658706829.869036,'site':'soundcloud','hits':1})
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
########################################################## database: 1/5 - bbs_last
elif database_name==self.database_names[1]:
###############################################################################
try:
db=[]
for _ in range(0,self.bot.bbs.ceiling__last_songs):
db.append('')
db.pop()
db.append(["dr1p","soundcloud","fenix flexin - 10 toes ( dr1ph0p m1x )","06660","https://soundcloud.com/vanta_sec/fenix-flexin-10-toes-dr1ph0p-m1x"])
db.reverse()
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
######################################################### database: 2/5 - bbs_nicks
elif database_name==self.database_names[2]:
###############################################################################
try:
db=[]
db.append({'dr1p':{'tally':1,'bandcamp':0,'soundcloud':1,'spotify':0,'youtube':0}})
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
##########################################################database: 3/5 - bbs_sites
elif database_name==self.database_names[3]:
###############################################################################
try:
db=[]
db.append({'soundcloud':1,'youtube':0,'spotify':0,'bandcamp':0})
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
######################################################### database: 4/5 - bbs_token
elif database_name==self.database_names[4]:
###############################################################################
try:
db=[]
db.append({'06660':'https://soundcloud.com/vanta_sec/fenix-flexin-10-toes-dr1ph0p-m1x'})
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
################################################### database: 5/5 - bbs_tokenmirror
elif database_name==self.database_names[5]:
###############################################################################
try:
db=[]
db.append({'https://soundcloud.com/vanta_sec/fenix-flexin-10-toes-dr1ph0p-m1x':'06660'})
self.bot.db.setlist(database_name,db)
if db: automation_flag=not automation_flag
except:
pass
###############################################################################
###################################################################################
msg=f'<<< _____boombox_plugin >>> [{index+1}/{len(self.database_names)}] - [ {self.database_names[index]} created ]'
if automation_flag:
status='+++ success +++'
else:
status='--- failure ---'
print(f'{msg} {status}')
###################################################################################
################################################################################### EOF
####################################################################################### EOF

46
plugins/cmd_irc_plugin.py Normal file
View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
import irc3,ipdb
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self, bot):
self.bot = bot
#######################################################################################
@command(permission='view')
def dr1pjack(self, mask, target, args):
"""dr1pjack
%%dr1pjack <message>...
"""
message=' '.join(args['<message>'])
ipdb.set_trace()
try:
bio=globals()['dug'].memories[2][0]
bio.motapi
bio.roomid
msg=f'bio.motapi:{bio.motapi}->{bio.roomid}->rebouncing<-message'
bio.motapi(bio.roomid,msg)
except Exception as e:
print(f'dr1p_plugin:error - {e}')
#######################################################################################
@command(permission='view')
def dr1p(self, mask, target, args):
"""dr1p
%%dr1p
"""
ipdb.set_trace()
msg=''
self.bot.privmsg(target, msg)
#######################################################################################
@command(permission='view')
def list_rooms(self, mask, target, args):
"""list_rooms
%%list_rooms
"""
msg=f'{mask.nick}: [ list_rooms_plugin ] - api calling'
self.bot.privmsg(target, self.bot.emo(msg))
from plugins.net_matrix_plugin import joined_rooms as matrix_list_rooms
result=matrix_list_rooms()
#######################################################################################
####################################################################################### EOF

112
plugins/crypto_plugin.py Normal file
View File

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
#######################################################################################
#######################################################################################
###########################################################################################
####################################################################################### EOF

41
plugins/emote_plugin.py Normal file
View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
###########################################################################################
####################################################################################### EOF

101
plugins/fifo_plugin.py Normal file
View File

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import os
import irc3
from stat import S_ISFIFO
###########################################################################################
@irc3.plugin
class Fifo:
#######################################################################################
BLOCK_SIZE = 1024
MAX_BUFFER_SIZE = 800
#######################################################################################
def __init__(self, context):
self.context = context
self.config = self.context.config
self.send_blank_line = self.config.get('send_blank_line', True)
self.runpath = self.config.get('runpath', f'{os.getcwd()}/fifo')
if not os.path.exists(self.runpath):
os.makedirs(self.runpath)
self.loop = self.context.loop
self.fifos = {}
self.buffers = {}
self.create_fifo(None)
#######################################################################################
@classmethod
def read_fd(cls, fd):
while True:
try:
return os.read(fd, cls.BLOCK_SIZE)
except InterruptedError:
continue
except BlockingIOError:
return b""
#######################################################################################
def handle_line(self, line, channel):
if not line:
return
line = line.decode("utf8")
if not self.send_blank_line and not line.strip():
return
if channel is None:
self.context.send_line(line)
else:
self.context.privmsg(channel, line)
#######################################################################################
def data_received(self, data, channel):
if not data:
return
prev = self.buffers.get(channel, b"")
lines = (prev + data).splitlines(True)
last = lines[-1]
for line in lines[:-1]:
line = line.rstrip(b'\r\n')
self.handle_line(line, channel)
if last.endswith(b'\n'):
line = last.rstrip(b'\r\n')
self.handle_line(line, channel)
self.buffers[channel] = b""
return
if len(last) > self.MAX_BUFFER_SIZE:
self.handle_line(last, channel)
self.buffers[channel] = b""
else:
self.buffers[channel] = last
#######################################################################################
def watch_fd(self, fd, channel):
reading = True
while reading:
data = self.read_fd(fd)
reading = len(data) == self.BLOCK_SIZE
self.data_received(data, channel)
#######################################################################################
def create_fifo(self, channel):
if channel is None:
path = os.path.join(self.runpath, ':raw')
else:
path = os.path.join(self.runpath, channel.strip('#&+'))
try:
mode = os.stat(path).st_mode
except OSError:
pass
else:
if not S_ISFIFO(mode):
self.context.log.warn(
'file %s created without mkfifo. remove it',
path)
os.remove(path)
if not os.path.exists(path):
os.mkfifo(path)
fd = os.open(path, os.O_RDWR | os.O_NONBLOCK)
self.loop.add_reader(fd, self.watch_fd, fd, channel)
self.context.log.debug("%s's fifo is %s %r",
channel or ':raw', path, fd)
return fd
#######################################################################################
@irc3.event(irc3.rfc.JOIN)
def join(self, mask=None, channel=None, **kwargs):
if mask.nick == self.context.nick:
if channel not in self.fifos:
self.fifos[channel] = self.create_fifo(channel)
####################################################################################### EOF

58
plugins/figlet_plugin.py Normal file
View File

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
####################################################################################### EOF

55
plugins/google_plugin.py Normal file
View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
from lxml.html import fromstring
from googlesearch import search
import irc3,os,sys,requests
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self, bot):
self.bot = bot
#######################################################################################
def __get_tiny_url(self, url):
tiny_url = 'http://tinyurl.com/api-create.php?url=%s' % url
r = requests.get(tiny_url)
return r.text
#######################################################################################
@command(permission='view', public=True, show_in_help_list=True)
def g(self, mask, target, args):
"""Google Query
%%g <query>...
"""
query = ' '.join(args['<query>'])
for j in search(query):
result = "{}".format(j)
url = result
read_size = 0
try:
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 not content_type.startswith("text/html"):
return
if int(content_length) > 200000:
self.bot.privmsg(target, "pre-fetch aborted -> fuck your large ass content")
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]
#Tiny URL
#if len(url) >= 60:
# url = self.__get_tiny_url(url)
#url = archiveis.capture(url)
msg = "\x02{nick:}\x0F\x02\x0303 > \x0F\x02\x0312{url:}\x0F\x0303 > \x0F\x1D\x0314{title:}\x0F".format(nick=mask.nick,url=url,title=title)
msg = self.bot.emo(msg)
self.bot.privmsg(target,self.bot.emo(msg))
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass
####################################################################################### EOF

128
plugins/highlight_plugin.py Normal file
View File

@ -0,0 +1,128 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
import irc3
import random
import os
###########################################################################################
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self, bot):
self.bot=bot
#######################################################################################
def __color(self,c):
try:
c=str(c.lower())
if c=='0': return '\x0300'
if c=='1': return '\x0301'
if c=='2': return '\x0302'
if c=='3': return '\x0303'
if c=='4': return '\x0304'
if c=='5': return '\x0305'
if c=='6': return '\x0306'
if c=='7': return '\x0307'
if c=='8': return '\x0308'
if c=='9': return '\x0309'
if c=='a': return '\x0310'
if c=='b': return '\x0311'
if c=='c': return '\x0312'
if c=='d': return '\x0313'
if c=='e': return '\x0314'
if c=='f': return '\x0315'
if c=='n': return ''
if c=='t': return '\x0f'
print('_color: empty')
return '\x0f'
except:
print('_color: error')
return '\x0f'
#######################################################################################
#######################################################################################
@command(permission='view',public=True,show_in_help_list=True)
def hl(self, mask, target, args):
"""hl - use a chosen or random color palette that will iterate a message to whichever ircnick you pick.
c1,c2,c3,c4,s1,s2,s3,s4,s5,s6 accept a color range of 0-15 and symbol range of 0-30. usage: ?hl c1,c2,c3,c4,s1,s2,s3,s4,s5,s6 ircnick n message.
uses specified colors & symbols, tags ircnick dr1p with hello message 10 times. example 1: ?hl 8,12,9,13,3,4 dr1p 10 hello.
uses a random color palette, tags ircnick dr1p with hello message 10 times. example 2: ?hl dr1p 10 hello.
uses a random color palette, tags ircnick dr1p with hello message 1 time. example 3: ?hl dr1p hello.
%%hl <message>...
"""
###################################################################################
try:
message=' '.join(args['<message>']).strip()
channel=self.bot.channels[target]
c1=random.randint(0,15)
c2=random.randint(0,15)
c3=random.randint(0,15)
c4=random.randint(0,15)
symbols=['╲╱','══','╀╀','▓▓','◨◧','◎◎','','░░','◅▻','▖▗','▤▤','╼╾','▒▒','┹┺','╮╭','╷╷','┒┎','┿┿','▛▜','◸◹','▚▞','┓┏','╏╏','┥┝','╽╽','┛┗','◊◊','','║║','◫◫','▭▭']
n1=random.randint(0,len(symbols)-1),random.randint(0,len(symbols)-1),random.randint(0,len(symbols)-1)
s1=[f'{symbols[n1[0]][0]}{symbols[n1[1]][0]}{symbols[n1[2]][0]}',f'{symbols[n1[2]][1]}{symbols[n1[1]][1]}{symbols[n1[0]][1]}']
n2=random.randint(0,len(symbols)-1),random.randint(0,len(symbols)-1),random.randint(0,len(symbols)-1)
s2=[f'{symbols[n2[0]][0]}{symbols[n2[1]][0]}{symbols[n2[2]][0]}',f'{symbols[n2[2]][1]}{symbols[n2[1]][1]}{symbols[n2[0]][1]}']
GOT_PALETTE=''; palette=''
GOT_IRCNICK=''; ircnick=mask.nick
GOT_ITERATIONS=''; iterations=1
###############################################################################
for palette in message.split():
try:
if len(palette.split(','))==10:
GOT_PALETTE=palette
break
except:
pass
###############################################################################
for ircnick in message.split():
try:
if ircnick in channel:
GOT_IRCNICK=ircnick
break
except:
pass
###############################################################################
for iterations in message.split():
try:
if int(iterations)>0:
GOT_ITERATIONS=int(iterations)
break
except:
pass
###############################################################################
if GOT_IRCNICK:
message=message.replace(GOT_IRCNICK,'')
ircnick=GOT_IRCNICK
else:
ircnick=mask.nick
if GOT_PALETTE:
message=message.replace(GOT_PALETTE,'')
palette=GOT_PALETTE
c1=int(palette.split(',')[0])
c2=int(palette.split(',')[1])
c3=int(palette.split(',')[2])
c4=int(palette.split(',')[3])
n1=int(palette.split(',')[4]),int(palette.split(',')[5]),int(palette.split(',')[6])
n2=int(palette.split(',')[7]),int(palette.split(',')[8]),int(palette.split(',')[9])
s1=[f'{symbols[n1[0]][0]}{symbols[n1[1]][0]}{symbols[n1[2]][0]}',f'{symbols[n1[2]][1]}{symbols[n1[1]][1]}{symbols[n1[0]][1]}']
s2=[f'{symbols[n2[0]][0]}{symbols[n2[1]][0]}{symbols[n2[2]][0]}',f'{symbols[n2[2]][1]}{symbols[n2[1]][1]}{symbols[n2[0]][1]}']
if GOT_ITERATIONS:
message=message.replace(str(GOT_ITERATIONS),'')
iterations=GOT_ITERATIONS
else:
iterations=1
###############################################################################
message=message.strip()
for i in range(int(iterations)):
h1=self.__color(hex(c1)[2:])
h2=self.__color(hex(c2)[2:])
h3=self.__color(hex(c3)[2:])
h4=self.__color(hex(c4)[2:])
msg=f'{h1}{s1[0]} {h2}{ircnick} {h1}{s1[1]} {h3}{s2[0]} {h4}{message} {h3}{s2[1]} {h1}{s1[0]} {h2}{ircnick} {h1}{s1[1]}\x20'
if not GOT_PALETTE: msg+=f"{h1}{str(c1).zfill(2)},{h2}{str(c2).zfill(2)},{h3}{str(c3).zfill(2)},{h4}{str(c4).zfill(2)},{h1}{str(n1[0]).zfill(2)},{str(n1[1]).zfill(2)},{str(n1[2]).zfill(2)},{h3}{str(n2[0]).zfill(2)},{str(n2[1]).zfill(2)},{str(n2[2]).zfill(2)}"
self.bot.privmsg(target,self.bot.emo(msg))
###############################################################################
###################################################################################
except Exception as e:
msg=f"{mask.nick}: highlight_plugin:hl - error: {e}"
self.bot.privmsg(target,self.bot.emo(msg))
####################################################################################### EOF

84
plugins/isup_plugin.py Normal file
View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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))))
####################################################################################### EOF

42
plugins/joke_plugin.py Normal file
View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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))
####################################################################################### EOF

522
plugins/maple_plugin.py Normal file
View File

@ -0,0 +1,522 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import os
import io
import irc3
from difflib import SequenceMatcher
import requests
from tqdm import tqdm
from glob import glob
import torch
import torch.nn.functional as F
import numpy as np
import signal
import configparser
import logging
import random
from transformers import GPT2Config,GPT2LMHeadModel,GPT2Tokenizer
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
from time import time
###########################################################################################
class MESSAGE_HISTORY():
#######################################################################################
maple_messages = []
maple_emotions = []
user_messages = []
user_users = []
last_message = ''
last_emotion = ''
maple_message = ''
#######################################################################################
def __init__(self):
self.processing=0
self.bounce=False
self.loopcount=0
#######################################################################################
def push_maple_messages(self,data):
self.maple_messages = self.maple_messages[-1:] + self.maple_messages[:-1]
self.maple_messages[0] = data
#######################################################################################
def push_user_messages(self,user,data):
self.user_users.append(user)
self.user_messages.append(data)
#######################################################################################
def push_maple_emotions(self,data):
self.maple_emotions.append(data)
#######################################################################################
def similar(self,a,b):
return SequenceMatcher(None,a,b).ratio()
###########################################################################################
@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'
OPINION="""
"""
#######################################################################################
WISDOM="""
"""
#######################################################################################
PERSONALITY="""
[model]
data_folder=models
model_size=medium
dataset=multiref
from_scratch=True
no_cuda=False
use_mmi=False
[decoder]
seed=0
temperature=0.6474
top_k=40
top_p=0
max_length=1024
num_samples=1
max_turns_history=-1
"""
#######################################################################################
def __init__(self,bot):
self.bot=bot
self.bot.history=MESSAGE_HISTORY()
#############################################
for _ in range(5):
self.bot.history.maple_messages.append("")
#############################################
self.mode=0
self.span=0
self.epoch_time_last=0
self.epoch_time_now=0
self.epoch_time_boolean=False
self.maple_io=[]
self.PERSONALITY=self.PERSONALITY.format(RND=datetime.now().microsecond)
self.delay=0.05
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
self.main()
loop=self.bot.loop
loop.call_later(self.delay,self.main)
#######################################################################################
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
#######################################################################################
@irc3.event(irc3.rfc.PRIVMSG)
def on_privmsg_search_for_maple(self, mask=None, target=None, data=None, **kw):
##############################################
if mask.nick == self.bot.config["nick"] or mask.nick == 'nickserv':
print('returning, message data from bot not user')
return
##############################################
if self.epoch_time_boolean==True:
print('[ checking flood protection status ]')
epoch_time_now=int(str(time()).split('.')[0])
if epoch_time_now-self.epoch_time_last>=30:
self.epoch_time_boolean=False
print('[ turned off flood protection ]')
else:
print('[ flood protection still on ]')
return
##############################################
data=data.strip().lower()
self.bot.history.last_message=data
##############################################
self.span=0
for _ in data.split():
for __ in self.OPINION.split():
if _ == __:
self.span=1
break
##############################################
if mask.nick == "d":
if data.find(self.bot.config["nick"])>-1:
if data.find('hang with us')>-1:
msg="ok, i'll hang out for a bit"
self.bot.privmsg(target,self.bot.emo(msg))
self.mode=1
if data.find('leave us alone')>-1:
msg="ok, gotta go"
self.bot.privmsg(target,self.bot.emo(msg))
self.mode=0
##############################################
if self.mode==0:
if not data.find(self.bot.config["nick"])>-1:
if self.span==0:
return
##############################################
self.span=0
##############################################
emotion=random.choices(['neutral','anger','joy','fear','sadness'])[0]
print(f'emote > {emotion}')
self.bot.history.push_maple_emotions(emotion)
#self.bot.history.last_emotion = emotion
body = {'context': [f'{self.bot.history.last_message}'], 'emotion': emotion}
url = 'http://127.0.0.1:8080/cakechat_api/v1/actions/get_response'
response = requests.post(url, json=body)
caple_message=response.json()['response'].lower()
self.maple_io.append({'user':mask.nick,'message':f'{data} {caple_message}','target':target})
if len(self.maple_io) > 5:
self.maple_io=[]
self.epoch_time_now=int(str(time()).split('.')[0])
self.epoch_time_last=self.epoch_time_now
self.epoch_time_boolean=True
msg=f"kind of busy at the moment {mask.nick}, i'll be right back"
print('[ turned on flood protection ]')
self.bot.privmsg(target,msg)
#######################################################################################
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)
config.set('decoder','seed',f'{datetime.now().microsecond}')
try:
if not type(self.bot.history.bounce)==bool:
print('<received bounce message>')
USER=self.bot.history.bounce['user']
MESSAGE=self.bot.history.bounce['message']
TARGET=self.bot.history.bounce['target']
self.maple_io.append({'user':USER,'message':MESSAGE,'target':TARGET})
self.bot.history.bounce=False
except:
pass
try:
self.maple_io.reverse()
maple_io=self.maple_io.pop()
self.maple_io.reverse()
USER=maple_io['user']
MESSAGE=maple_io['message'].strip()
TARGET=maple_io['target']
except:
return self.exit_strategy
print(f'human > {MESSAGE}')
self.bot.history.maple_message=MESSAGE
if max_turns_history==0:
turns=[]
turn={
'human_messages':[],
'maple_messages':[]
}
turns.append(turn)
turn['human_messages'].append(f'{USER} {MESSAGE}')
history=""
from_index=max(len(turns)-max_turns_history-1,0) if max_turns_history>=0 else 0
WISDOM=self.WISDOM.splitlines()
try:
WISDOM.remove('')
except:
pass
for i,_ in enumerate(WISDOM):
WISDOM[i]=_.strip()
static_history=WISDOM
for message in static_history:
history += message + tokenizer.eos_token
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)
################################################################################### REPROCESSOR SOF
# SIMILARITY
for i in range(len(self.bot.history.maple_messages)):
if self.bot.history.similar(maple_message,str(self.bot.history.maple_messages[i]))>0.9:
self.maple_io.append({'user':USER,'message':f'{MESSAGE}','target':TARGET})
print(f'maple - logic ! rejected // maple similarity - repeat of previous response')
self.bot.history.loopcount+=1
return self.exit_strategy
###################################################################################
# MOCK / DUPE
if self.bot.history.similar(maple_message,MESSAGE)>0.9:
self.maple_io.append({'user':USER,'message':f'{MESSAGE}','target':TARGET})
print(f'maple - logic ! rejected // human mock - maple response same as human')
self.bot.history.loopcount+=1
return self.exit_strategy
###################################################################################
# GPT LOOP GLITCH
n=len(maple_message.split())
i=len(set(maple_message.split()))
if i<int(n/2):
self.maple_io.append({'user':USER,'message':f'{MESSAGE}','target':TARGET})
print(f'maple - logic ! rejected // gpt loop glitch - reiterating same thing in multiples')
self.bot.history.loopcount+=1
return self.exit_strategy
###################################################################################
# LIMITED RESPONSE
n=len(maple_message.split())
if i<3:
self.maple_io.append({'user':USER,'message':f'{MESSAGE}','target':TARGET})
print(f'maple - logic ! rejected // limited response - skip an unfinished token chain')
self.bot.history.loopcount+=1
return self.exit_strategy
###################################################################################
self.bot.history.push_maple_messages(maple_message)
################################################################################### REPROCESSOR EOF
#emotion=random.choices(['neutral','anger','joy','fear','sadness'])[0]
#body = {'context': [f'{self.bot.history.last_message}'], 'emotion': emotion}
#body = {'context': [f'{self.bot.history.last_message} {maple_message}'], 'emotion': emotion}
#url = 'http://127.0.0.1:8080/cakechat_api/v1/actions/get_response'
#response = requests.post(url, json=body)
#caple_message=response.json()['response']
emojis=["😐","😡","😂","👻","😭"]
emotions=['neutral','anger','joy','fear','sadness']
emotion=self.bot.history.maple_emotions[0]
emoji=emojis[emotions.index(emotion)]
neutral=["ª{•̃̾_•̃̾}ª","¬_¬","¯\(º_o)/¯","ʕ•̫͡•ʔv","˚•_•˚","σ_σ","д_д","ф_ф","Ծ_Ծ"]
anger=["(⋋▂⋌)","(┛◉Д◉)┛┻━┻","(╯°□°)╯︵ ┻━┻","(╯◕.◕)╯","(╹◡╹)凸","(ノಠ益ಠ)ノ彡┻━┻","(屮゚Д゚)屮","〴⋋_⋌〵"]
joy=["(•‿•)","(◑‿◐)","(◑◡◑)","(◕‿◕✿)","(◕‿◕)","(◕‿-)"]
fear=["˚▱˚","٩(×̯×)۶","⊂(◉.◉)つ"]
sadness=["¯\_(⊙︿⊙)_/¯","ಠ╭╮ಠ","ಠ︵ಠ凸","ᕙ(⇀‸↼‶)ᕗ","◉︵◉"]
emote=random.choices(locals()[emotion])[0]
print(f'maple ! {maple_message}')
MAPLE_MESSAGE=maple_io['message'].replace(self.bot.history.last_message,'').strip().lower()
MAPLE_MESSAGE=MAPLE_MESSAGE.replace('lt 3','<3')
caple_message=maple_message.lower().replace('lt 3','<3')
print(f'maple > {USER}: {MAPLE_MESSAGE} {caple_message} {emoji} {emotion} {emote}')
colors=['\x0300','\x0304','\x0308','\x0306','\x0312']
color=colors[emotions.index(emotion)]
# msg=f'{USER}: {MAPLE_MESSAGE} {caple_message} {emoji} {color}{emotion} > {emote}'
msg=f'{USER}: {MAPLE_MESSAGE} {caple_message} {color}{emote}\x0f'
# msg=self.bot.emo(msg)
self.bot.privmsg(TARGET,msg)
self.bot.history.maple_emotions.reverse()
self.bot.history.maple_emotions.pop()
self.bot.history.maple_emotions.reverse()
self.bot.history.loopcount=0
return self.exit_strategy
#######################################################################################
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)
#######################################################################################
def exit_strategy(self):
if self.bot.history.loopcount>25:
self.bot.history.loopcount=0
self.maple_io=[]
pass
####################################################################################### EOF

224
plugins/net_irc_plugin.py Normal file
View File

@ -0,0 +1,224 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import irc3,os,ipdb
import simplematrixbotlib as botlib
from plugins.tool_dims_plugin import dims
from plugins.tool_guds_plugin import guds
from irc3.testing import ini2config
from irc3.plugins.command import command
from plugins.tool_bus_plugin import BUS
################################### NET IRC - SERVER CREDENTIALS FOR SASL OR NICKSERV [1/4]
BOT_SASL_USERNAME=os.environ['BOT_SASL_USERNAME']
BOT_SASL_PASSWORD=os.environ['BOT_SASL_PASSWORD']
NICKSERV_USERNAME=os.environ['NICKSERV_USERNAME']
NICKSERV_PASSWORD=os.environ['NICKSERV_PASSWORD']
################################################################ NET IRC - BOT CONFIG [2/4]
def config_ircbot():
config=ini2config("""
[bot]
nick = n0tmaple
username = n0tg1mp
realname = "[ g1mp'n ain't easy unless you're 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.log
irc3.plugins.logger
irc3.plugins.userlist
plugins.tool_dims_plugin
plugins.tool_guds_plugin
plugins.tool_bus_plugin
plugins.sasl_custom_plugin
plugins.net_irc_plugin
plugins.net_matrix_plugin
plugins.cmd_irc_plugin
plugins.storage_plugin
plugins.base_plugin
plugins.emote_plugin
plugins.fifo_plugin
plugins.youtube_plugin
plugins.crypto_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.tcpac_plugin
plugins.google_plugin
plugins.highlight_plugin
plugins.boombox_plugin
plugins.whoami_plugin
autojoins =
'#b0tsh0p'
'#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!*@1.3.3.7 = all_permissions
d*!~dtcpdirect@* = all_permissions
d*!~dvaccine@* = all_permissions
GregJ!*@* = all_permissions
kayos!*@* = all_permissions
moony!*@* = all_permissions
Dillinger!*@* = all_permissions
Civil!*@* = all_permissions
chunk!*@* = all_permissions
sniff!*@* = all_permissions
* = view
ignore_list =
GitServ!*@*
GitServ_!*@*
g1mp!*@*
g1mp_!*@*
maple!*@*
maple_!*@*
[0]!*@*
[0]_!*@*
nav!*@*
nav_!*@*
van!*@*
van_!*@*
professorOak!*@*
professorOak_!*@*
*!van@*
[plugins.fifo_plugin]
runpath = {PATH}/fifo""".format(PATH=os.getcwd()))
ircbot=irc3.IrcBot.from_config(config)
for i,_ in enumerate(config['autojoins']):
config['autojoins'][i]=_.replace("'","")
return ircbot
############################################################### NET IRC - BOT STARTUP [3/4]
def start_ircbot(self):
globals()['guds'].memories.append([self,'net_irc_plugin:start_ircbot.self'])
ircbot=guds.memories[2][0]._BOTIO__boot__ircbot=self.ircbot
print(f'<<< _____net_irc_plugin >>> [ ircbot started ]')
self.ircbot.run(forever=True)
return self
###################################################################### NET IRC - MAIN [4/4]
@irc3.plugin
###########################################################################################
def __init__(self,bot):
self.ircbot=bot
print(f'<<< _____net_irc_plugin >>> [ plugin loaded ]')
guds.memories.append([self,'net_irc_plugin:__init__.self'])
###########################################################################################
def connection_made(self):
print(f'<<< _____net_irc_plugin:event >>> [ connection made ]')
###########################################################################################
def server_ready(self):
print(f'<<< _____net_irc_plugin:event >>> [ server ready ]')
###########################################################################################
def connection_lost(self):
print(f'<<< _____net_irc_plugin:event >>> [ connection lost ]')
###########################################################################################
@irc3.event(irc3.rfc.PRIVMSG)
async def on_privmsg(self, mask=None, target=None, data=None, **kw):
msg=f"{mask.nick}: target: {target} - event: privmsg - data: {data}"
if not mask.nick==self.config['nick']: # user
netschanlist=dims.list_channels()
matrixbot=guds.memories[2][0]._BOTIO__boot__matrix
oldbot=guds.memories[2][0]._BOTIO__boot__irc
ircbot=self
if oldbot==ircbot: # no variance, no problem
bridgedbus=(BUS(netschanlist,matrixbot,ircbot))
await bridgedbus.input(target,f'{mask.nick}: {data}')
else: # variance
pass # exposing variance, <research>
else: # bot
pass
###########################################################################################
@irc3.event(irc3.rfc.JOIN_PART_QUIT)
def on_join_part_quit(self,mask=None,target=None,data=None,**kw):
target=kw['channel']
###################################################################################
if not mask.nick==self.config['nick']: # this section is the user
msg=f"{mask.nick}: target: {target} - event: join_part_quit:{kw['event']} - data: {data}"
self.privmsg(target,msg); print(msg)
###################################################################################
else: # this section is the bot
###############################################################################
if kw['event']=='JOIN':
result,i,ii=dims.ischannel(target)
if not result:
dims.__create__('irc',target)
print(f"<<< ___tool_dims_plugin:event:join >>> [ dims.__create__(irc,{target}) ] - active channel record created")
###############################################################################
elif kw['event']=='PART':
###########################################################################
result,i,ii=dims.ischannel(target)
###########################################################################
dims.__delete__('irc',i)
print(f"<<< ___tool_dims_plugin:event:part >>> [ dims.__delete__(irc,{target}) ] - active channel record deleted")
###############################################################################
elif kw['event']=='QUIT':
###########################################################################
result,i,ii=dims.ischannel(target)
###########################################################################
dims.__delete__('irc',i)
print(f"<<< ___tool_dims_plugin:event:quit >>> [ dims.__delete__(irc,{target}) ] - active channel record deleted")
###########################################################################################
@irc3.event(irc3.rfc.TOPIC)
def on_topic(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: topic - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
###########################################################################################
@irc3.event(irc3.rfc.INVITE)
def on_invite(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: invite - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
###########################################################################################
@irc3.event(irc3.rfc.KICK)
def on_kick(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: kick - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
###########################################################################################
@irc3.event(irc3.rfc.MODE)
def on_mode(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: mode - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
###########################################################################################
@irc3.event(irc3.rfc.NEW_NICK)
def on_new_kick(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: new_nick - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
###########################################################################################
@irc3.event(irc3.rfc.CTCP)
def on_ctcp(self,mask=None,target=None,data=None,**kw):
if not mask.nick==self.config['nick']:
msg=f"{mask.nick}: target: {target} - event: ctcp - data: {data}"
self.privmsg(target,msg); print("<<< _____net_irc_plugin >>> [ "+msg+" ]")
####################################################################################### EOF

View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import irc3,os,re,ipdb
import simplematrixbotlib as botlib
from plugins.tool_dims_plugin import dims
from plugins.tool_guds_plugin import guds
from irc3.plugins.command import command
from plugins.tool_bus_plugin import BUS as bus
###########################################################################################
MATRIX_HOMESERVER=os.environ['MATRIX_HOMESERVER']
MATRIX___USERNAME=os.environ['MATRIX___USERNAME']
MATRIX___PASSWORD=os.environ['MATRIX___PASSWORD']
###########################################################################################
###########################################################################################
creds=botlib.Creds(MATRIX_HOMESERVER,MATRIX___USERNAME,MATRIX___PASSWORD)
matrixbot=botlib.Bot(creds)
###########################################################################################
def start_matrixbot(self):
globals()['guds'].memories.append([self,'net_matrix_plugin:start_matrixbot.self'])
ircbot=guds.memories[2][0]._BOTIO__boot__ircbot=self.ircbot
guds.memories[2][0]._BOTIO__boot__irc=ircbot
guds.memories[2][0]._BOTIO__boot__matrix=matrixbot
matrixbot.run()
return self
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self,bot):
self.bot=bot
print(f'<<< __net_matrix_plugin >>> [ plugin loaded ]')
globals()['guds'].memories.append([self,'net_matrix_plugin:__init__.self'])
@matrixbot.listener.on_message_event
async def scan(room,message):
bridgedbus=''
print('<<< __net_matrix_plugin >>> [ event: listener ]')
bio=guds.memories[2][0]
dims.__create__('matrix',room)
m_message=message.source['content']['body']
m_sender=message.sender
print(f"{m_sender}: {m_message}")
############################################################# MESSAGE SENDER FILTER
trigger_command="??"
if not guds.check_credentials(message.sender):
####################################################################### TRIGGER
if m_message.lower().startswith(trigger_command):
commands=['d_breakpoint','d_listrooms']
################################################################## COMMANDS
if m_message.lower().split()[0][len(trigger_command):] in commands:
command=m_message.lower().split()[0][len(trigger_command):]
#######################################################################
if command==commands[0]: # ??d_breakpoint - triggered message
if m_sender=="@d:tcp.direct":
ipdb.set_trace()
#######################################################################
if command==commands[1]: # ??d_listrooms - triggered message
if m_sender=="@d:tcp.direct":
await joined_rooms(room.room_id)
#######################################################################
else:
pass
msg=f'{m_sender}: {m_message} - triggered message but with a non-listed command'
print(msg)
###########################################################################
else:
msg=f'{m_sender}: {m_message} - message not prefixed with a {trigger_command} trigger'
print(msg)
####################################################################################### EOF

164
plugins/notes_plugin.py Normal file
View File

@ -0,0 +1,164 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
#######################################################################################
#######################################################################################
####################################################################################### EOF

84
plugins/quote_plugin.py Normal file
View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
#######################################################################################
#######################################################################################
@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)
#######################################################################################
#######################################################################################
####################################################################################### EOF

349
plugins/ratesex_plugin.py Normal file
View File

@ -0,0 +1,349 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
###########################################################################################
###########################################################################################
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', }
###########################################################################################
###########################################################################################
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", }
###########################################################################################
###########################################################################################
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', }
###########################################################################################
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self, bot):
self.bot = bot
#######################################################################################
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
#######################################################################################
def escape_ansi(self,line):
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', str(line))
#######################################################################################
def invert_dict(self,d):
return {v: k for k, v in d.items()}
#######################################################################################
def enumerate_dict(self,d):
return list(zip(list(d),list(invert_dict(d)),range(len(d))))
#######################################################################################
def organize_dict(self,d):
_d=list(d.values())
return _d.sort()
#######################################################################################
def escape_ansi(self,line):
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', str(line))
#######################################################################################
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]]}")
#######################################################################################
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
#######################################################################################
def findall(self,s,w):
return [i for i in range(len(s)) if s.startswith(w, i)]
#######################################################################################
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
#######################################################################################
@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__ = ''':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.
/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.
............................ .-...............................`
`````` ````````` `````````````` `````````` ```'''
####################################################################################### EOF

107
plugins/remind_plugin.py Normal file
View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
###########################################################################################
####################################################################################### EOF

View File

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*- ########################################################## SOF
import irc3,os,base64
######################################################################################
BOT_SASL_USERNAME=os.environ['BOT_SASL_USERNAME']
BOT_SASL_PASSWORD=os.environ['BOT_SASL_PASSWORD']
######################################################################################
@irc3.plugin
class DR1PSASL:
##################################################################################
def __init__(self, bot):
print('<<< _sasl_custom_plugin >>> [ custom sasl initiated ]')
self.bot=bot
self.auth=(f'{BOT_SASL_USERNAME}\0{BOT_SASL_USERNAME}\0{BOT_SASL_PASSWORD}')
self.auth=base64.encodebytes(self.auth.encode('utf8'))
self.auth=self.auth.decode('utf8').rstrip('\n')
self.events = [
irc3.event(r'^:\S+ CAP \S+ LS :(?P<data>.*)', self.cap_ls),
irc3.event(r'^:\S+ CAP \S+ ACK sasl', self.cap_ack),
irc3.event(r'AUTHENTICATE +', self.authenticate),
irc3.event(r'^:\S+ 903 \S+ :Authentication successful',self.cap_end),
]
##################################################################################
def connection_ready(self, *args, **kwargs):
print('<<< _sasl_custom_plugin >>> [ CAP LS ]')
self.bot.send('CAP LS\r\n')
self.bot.attach_events(*self.events)
##################################################################################
def cap_ls(self, data=None, **kwargs):
print('<<< _sasl_custom_plugin >>> [ CAP REQ :sasl ]')
if 'sasl' in data.lower():
self.bot.send_line('CAP REQ :sasl')
else:
self.cap_end()
##################################################################################
def cap_ack(self, **kwargs):
print('<<< _sasl_custom_plugin >>> [ AUTHENTICATE PLAIN ]')
self.bot.send_line('AUTHENTICATE PLAIN')
##################################################################################
def authenticate(self, **kwargs):
print(f'<<< _sasl_custom_plugin >>> [ AUTHENTICATE {self.auth} ]')
self.bot.send_line(f'AUTHENTICATE {self.auth}\n')
##################################################################################
def cap_end(self, **kwargs):
print('<<< _sasl_custom_plugin >>> [ CAP END ]')
self.bot.send_line('CAP END\r\n')
self.bot.detach_events(*self.events)
##################################################################################
################################################################################## EOF

96
plugins/sed_plugin.py Normal file
View File

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import irc3
import os
import random
from string import ascii_lowercase as alpha
SED1_RE = "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
else:
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]
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:
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}"
try:
if irc_message.find('\x01ACTION'):
nick,msg=irc_message.split(': ')
msg="\x01ACTION "+nick+": "+msg.split('\x01ACTION ')[1]
self.bot.privmsg(target,msg)
else:
self.bot.privmsg(target,self.bot.emo(irc_message))
except:
self.bot.privmsg(target,self.bot.emo(irc_message))
#######################################################################################
#######################################################################################
####################################################################################### EOF

128
plugins/seen_plugin.py Normal file
View File

@ -0,0 +1,128 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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):
# record of nickchanges, these are kept
# "5": {
# "msg": "_d changed nick to d",
# "time": "2021-10-03T00:24:03.040916",
# "type": "newnick"
# },
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()
messages = self.bot.db.getlist(key)
# record of did a user speak this day and if so how many words spoken
# if there is a record that day, they spoke. if there is no record for that
# day then they didn't speak. this data is used as historicals to discern
# true lurkers from idlers which are two very different things entirely.
# <<< this record specifically will be used in plugins/dsa_plugin.py >>>
# record created:
# "41": {
# "msg": 5,
# "time": "2022-07-27",
# "type": "activity"
# },
words_count=0
if not messages:
messages = []
else:
for count, msg in enumerate(messages):
if msg.get("type") == "activity":
if msg.get("time") == datetime.now().isoformat().split('T')[0]:
words_count+=int(msg.get('msg'))
del(messages[count])
activity_msg = { "type": "activity",
"time": datetime.now().isoformat().split('T')[0],
"msg": len(data.split())+words_count }
messages.append(activity_msg)
self.bot.db.setlist(key, messages)
# all historical privmsg destroyed, and only one retained for seen
# "42": {
# "msg": "a b c d e",
# "time": "2022-07-27T07:26:41.937448",
# "type": "privmsg"
# },
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)
else:
msg = "{} Has Not Been Seen".format(nick)
msg = self.bot.emo(msg)
self.bot.privmsg(target, msg)
return
#######################################################################################
#######################################################################################
####################################################################################### EOF

View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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]);
######## SOUNDCLOUD <-> BOOMBOX_PLUGIN HOOK ######## SOUNDCLOUD <-> BOOMBOX_PLUGIN HOOK ########
self.bot.bbs.enter(NICK,URL,TITLE)
######## SOUNDCLOUD <-> BOOMBOX_PLUGIN HOOK ######## SOUNDCLOUD <-> BOOMBOX_PLUGIN HOOK ########
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}"))
###########################################################################################
####################################################################################### EOF

293
plugins/storage_plugin.py Normal file
View File

@ -0,0 +1,293 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import os
try:
import ujson as json
except ImportError:
import json
import irc3
import shelve
###########################################################################################
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()
####################################################################################### EOF

90
plugins/strain_plugin.py Normal file
View File

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
except:
pass
except:
msg = "strain: not found"
self.bot.privmsg(target, msg)
#######################################################################################
#######################################################################################
####################################################################################### EOF

32
plugins/tcpac_plugin.py Normal file
View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- ############################################################################# SOF
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
import socket
#########################################################################################################
@irc3.plugin
class Plugin:
#########################################################################################################
def __init__(self, bot):
self.bot = bot
#####################################################################################################
@command(permission='view')
def tcpac(self, mask, target, args):
"""tcpac - the irc version of `cat file - | nc tcp.ac 9999`, usage: ?tcpac message
%%tcpac <message>...
"""
msg=' '.join(args['<message>'])
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("tcp.ac", 9999))
s.sendall(bytes(msg.encode()))
data = s.recv(1024)
response=f'{data!r}'
response=response.replace('\\n',' - ').replace("b'","")[:-1]
delmsg=response.split(',')[0].split('":"')[1][:-1]
txtmsg=response.split(',')[1].split('":"')[1][:-2]
msg=f"{mask.nick}: irc version of `cat file - | nc tcp.ac 9999` -> txt: {txtmsg}"
self.bot.privmsg(target,msg)
msg=f"{mask.nick}: irc version of `cat file - | nc tcp.ac 9999` -> del: {delmsg}"
self.bot.privmsg(mask.nick,msg)
#####################################################################################################
##################################################################################################### EOF

45
plugins/tell_plugin.py Normal file
View File

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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))
#######################################################################################
#######################################################################################
####################################################################################### EOF

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*- ############################################################### SOF
global bus, dims, matrixbot, ircbot
from async_timeout import timeout
from plugins.tool_dims_plugin import dims
from plugins.tool_guds_plugin import guds
import asyncio, ipdb
###########################################################################################
class BUS:
#######################################################################################
results=[]
#######################################################################################
def __init__(self,bridged_network_roomchans,matrixbot=None,ircbot=None):
self.bridged_network_roomchans=bridged_network_roomchans
print(f'<<< ____tool_bus_plugin:BUS.__init__ >>> [ BUS.bridged_network_roomchans={self.bridged_network_roomchans} ]')
self.list_of_tasks=[]
self.matrixbot=matrixbot
print(f'<<< ____tool_bus_plugin:BUS.__init__ >>> [ BUS.matrixbot={self.matrixbot} ]')
self.ircbot=ircbot
print(f'<<< ____tool_bus_plugin:BUS.__init__ >>> [ BUS.ircbot={self.ircbot} ]')
#######################################################################################
async def input(self,network_chanroom_src,data):
for network_chanroom_dest in self.bridged_network_roomchans:
if not str(network_chanroom_src)==network_chanroom_dest:
#################################################################### MATRIX
if network_chanroom_dest.startswith('!'):
#######################################################################
msg=(f"m{str(network_chanroom_src)}> ")
print('here is the error. press n to step the next line')
ipdb.set_trace()
task=(await self.matrixbot.api.send_text_message(
network_chanroom_dest,str(f'{msg}{data}')))
loop=self.ircbot.loop
asyncio.ensure_future(task,loop=loop)
####################################################################### IRC
elif network_chanroom_dest.startswith('#'):
msg=(f"i{str(network_chanroom_src)}> ")
await self.ircbot.privmsg(
network_chanroom_dest,str(f'{msg}{data}'))
####################################################################################### EOF

171
plugins/tool_dims_plugin.py Normal file
View File

@ -0,0 +1,171 @@
# -*- coding: utf-8 -*- ############################################################### SOF
# usage: d=DIMS('irc','#r3kt')
# usage: d=DIMS('irc','#testing')
# usage: d=DIMS('matrix','#tcpdirect:tcp.direct')
# usage: d=DIMS('matrix','#b0tsh0p:pcriot.org')
# flows: d.irc[n].channels[n] [lots of attributes pertaining to channels on the index ]
# flows: d.irc[n].channels[n].bridge.[irc,matrix]_[channels,rooms]_[inbound,outbound]
# flows: d.matrix[n].rooms[n] [lots of attributes pertaining to rooms on the index ]
# flows: d.matrix[n].rooms[n].bridge.[irc,matrix]_[channels,rooms]_[inbound,outbound]
global dims
global guds
import ipdb
###########################################################################################
class DIMS:
#######################################################################################
class __INIT_MATRIX__:
###################################################################################
class __INIT_ROOM__:
###############################################################################
class __INIT_BRIDGE_MATRIX__:
###########################################################################
def __init__(self,room):
self.matrix_rooms_outbound=[]
self.matrix_rooms_inbound=[]
self.irc_channels_outbound=[]
self.irc_channels_inbound=[]
###############################################################################
def __init__(self,room):
room_flag=False
if len(dir(room))>1:
room_flag=True
for _ in ['canonical_alias','creator','display_name','encrypted',
'federate','fully_read_marker','gen_avatar_url','history_visibility',
'invited_count','invited_users','is_group','is_named','join_rule',
'joined_count','machine_name','member_count','members_synced',
'name','names','own_user_id','power_levels','read_receipts',
'room_avatar_url','room_id','room_version','summary','tags','topic',
'typing_users','unread_highlights','unread_notifications','users']:
if room_flag:
exec(f'self.{_}=room.{_}')
print(f"room.{_}->{eval(f'self.{_}')}")
self.bridge=self.__INIT_BRIDGE_MATRIX__(room.room_id)
else:
exec(f'self.{_}=""')
self.room_id=room
self.bridge=self.__INIT_BRIDGE_MATRIX__(room)
###################################################################################
def __init__(self,room):
self.rooms=[]
self.rooms.append(self.__INIT_ROOM__(room))
#######################################################################################
def __update_matrix__(self,index,room,bridge=""):
for _ in ['canonical_alias','creator','display_name','encrypted',
'federate','fully_read_marker','gen_avatar_url','history_visibility',
'invited_count','invited_users','is_group','is_named','join_rule',
'joined_count','machine_name','member_count','members_synced',
'name','names','own_user_id','power_levels','read_receipts',
'room_avatar_url','room_id','room_version','summary','tags','topic',
'typing_users','unread_highlights','unread_notifications','users']:
cmdp=(f"self.matrix[{index}].rooms[0].{_}")
cmdn=(f"room.{_}")
if not eval(cmdp)==eval(cmdn):
exec(f"self.matrix[{index}].rooms[0].{_}=room.{_}")
cmdf=f"room.{_}"
cmdt=f"self.matrix[{index}].rooms[0].{_}"
print(f"literal: room.{_}->self.matrix[{index}].rooms[0].{_} - explicit: {eval(cmdf)}->{eval(cmdt)}")
#######################################################################################
def isroom(self,room):
###################################################################################
try:
for index_server,_matrix in enumerate(self.matrix):
for index_room,_room in enumerate(_matrix.rooms):
if _room==room:
return True,index_server,index_room
###################################################################################
except: pass
###################################################################################
return False,0,0
#######################################################################################
class __INIT_IRC__:
###################################################################################
class __INIT_CHANNEL__:
###############################################################################
class __INIT_BRIDGE_IRC__:
###########################################################################
def __init__(self,channel):
self.irc_channels_outbound=[]
self.irc_channels_inbound=[]
self.matrix_rooms_outbound=[]
self.matrix_rooms_inbound=[]
###############################################################################
def __init__(self,channel):
self.channel=channel
self.bridge=self.__INIT_BRIDGE_IRC__(channel)
###################################################################################
def __init__(self,channel):
self.channels=[]
self.channels.append(self.__INIT_CHANNEL__(channel))
#######################################################################################
def __update_irc__(self,index,channel,bridge=""):
self.irc[index].channels[0].channel=channel
#######################################################################################
def ischannel(self,channel):
###################################################################################
try:
for index_server,_irc in enumerate(self.irc):
for index_channel,_channel in enumerate(_irc.channels):
if _channel==channel:
return True,index_server,index_channel
###################################################################################
except: pass
###################################################################################
return False,0,0
#######################################################################################
matrix=[]; irc=[]; netschanroom=[]
#######################################################################################
def __init__(self,net="",chanroom=""):
###################################################################################
if not net or not chanroom: return
###################################################################################
net=net.lower()
dupe_flag=False
###################################################################################
if net=='matrix':
for i in range(len(self.matrix)):
if self.matrix[i].rooms[0].room_id==chanroom.room_id:
print(f'<<< ________dims_plugin >>> [ updating pre-existing matrix room data ]')
dupe_flag=True; index=i; self.__update_matrix__(index,chanroom)
if not dupe_flag:
print(f'<<< ________dims_plugin >>> [ new matrix room data entry ]')
self.matrix.append(self.__INIT_MATRIX__(chanroom))
###################################################################################
elif net=='irc':
for i in range(len(self.irc)):
if self.irc[i].channels[0].channel==chanroom:
print(f'<<< ________dims_plugin >>> [ updating pre-existing irc channel data ]')
dupe_flag=True; index=i; self.__update_irc__(index,chanroom)
if not dupe_flag:
print(f'<<< ________dims_plugin >>> [ new irc channel data entry ]')
self.irc.append(self.__INIT_IRC__(chanroom))
#######################################################################################
def __create__(self,net="",chanroom=""):
###################################################################################
if net=='matrix': self.matrix.append(self.__INIT_MATRIX__(chanroom))
###################################################################################
elif net=='irc': self.irc.append(self.__INIT_IRC__(chanroom))
#######################################################################################
def __delete__(self,net="",chanroom_index=-1):
###################################################################################
if net=='matrix': self.matrix.remove(self.matrix[chanroom_index])
###################################################################################
elif net=='irc': self.irc.remove(self.irc[chanroom_index])
#######################################################################################
def list_channels(self):
###################################################################################
from plugins.tool_guds_plugin import guds
matrixbot=guds.memories[2][0]._BOTIO__boot__matrix
localchannels=[]
for _irc in self.irc:
for _channels in _irc.channels:
localchannels.append(_channels.channel)
[ self.netschanroom.append(x) for x in matrixbot.async_client.rooms ]
for _irc in self.irc:
for _channels in _irc.channels:
self.netschanroom.append(_channels.channel)
###################################################################################
return self.netschanroom
###################################################################################
###########################################################################################
dims=DIMS()
####################################################################################### EOF

View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*- ############################################################### SOF
import ipdb
global dims
global guds # global unified data system 2 move instantiated data between processes/threads
###########################################################################################
class GUDS:
#######################################################################################
push_index=0; credentials=[]; memories=[];
#######################################################################################
def __init__(self):
pass
#######################################################################################
def add_credentials(self,credential):
self.credentials.append(credential)
print(f'<<< ________guds_plugin >>> [ added {credential} credentials to guds.credentials ]')
#######################################################################################
def check_credentials(self,against_credential):
flag_match=False
for credential in self.credentials:
if not credential.find(against_credential):
flag_match=True
print(f'<<< ________guds_plugin >>> [ found {credential} against {against_credential} ]')
###################################################################################
if not flag_match:
print(f'<<< ________guds_plugin >>> [ no credentials found matching {against_credential} ]')
return False
#######################################################################################
def push(self,data):
self.push_index+=1
self.memories.append(data)
print(f'<<< ________guds_plugin >>> [ data pushed into guds.memories[{str(self.push_index)}]={guds.memories[-1]} ]')
###########################################################################################
guds=GUDS()
####################################################################################### EOF

192
plugins/twitter_plugin.py Normal file
View File

@ -0,0 +1,192 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
#######################################################################################
#######################################################################################
####################################################################################### EOF

33
plugins/ud_plugin.py Normal file
View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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)
#######################################################################################
#######################################################################################
####################################################################################### EOF

View File

@ -0,0 +1,117 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
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)
######## URL_GRABBER <-> BOOMBOX_PLUGIN HOOK ######## URL_GRABBER <-> BOOMBOX_PLUGIN HOOK ########
self.bot.bbs.enter(mask.nick,url,title)
######## URL_GRABBER <-> BOOMBOX_PLUGIN HOOK ######## URL_GRABBER <-> BOOMBOX_PLUGIN HOOK ########
return
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass
#######################################################################################
#######################################################################################
@irc3.extend
def prefetch_title(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:
print('error: url_grabber_plugin:prefetch_title - aborted')
return
try:
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]
return title
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass
#######################################################################################
#######################################################################################
####################################################################################### EOF

19
plugins/whoami_plugin.py Normal file
View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*- ############################################################### SOF
from irc3.plugins.command import command
import irc3
###########################################################################################
@irc3.plugin
class Plugin:
#######################################################################################
def __init__(self, bot):
self.bot = bot
#######################################################################################
@command(permission='view')
def whoami(self, mask, target, args):
"""whoami - plugin to give some identity information. usage: ?whoami
%%whoami
"""
msg = f'{mask.nick}: mask: {mask} channel: {target}'
self.bot.privmsg(target, self.bot.emo(msg))
#######################################################################################
####################################################################################### EOF

171
plugins/youtube_plugin.py Normal file
View File

@ -0,0 +1,171 @@
# -*- coding: utf-8 -*- ############################################################### SOF
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")
like_count=0
try:
view_count = int(video_info.get("statistics").get("viewCount"))
except:
like_count = int(video_info.get("statistics").get("likeCount"))
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 = []
######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 1 of 2 ######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 1 of 2 ########
MUSIC_FOUND=False
for topic in topics:
if topic.lower().find('music'):
MUSIC_FOUND=True
if MUSIC_FOUND:
url = "https://youtu.be/{}".format(video_id)
self.bot.bbs.enter(mask.nick,url,title)
######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 1 of 2 ######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 1 of 2 ########
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)
if like_count == 0:
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,} \x0F\x1D\x0314Type: \x0F\x1DVideo\x0F".format(published=published_at, views=view_count)
else:
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Likes: \x0F\x1D{views:,} \x0F\x1D\x0314Type: \x0F\x1DMovie\x0F".format(published=published_at, views=like_count)
msg = msg + "\x0F\x02\x0312 ♫ \x0F\x02\x0313\x1D{topics:}\x0F\x02\x0312".format(topics=", ".join(topics))
msg = msg +" \x0304> \x0F\x02\x0312"+ url
msg = self.bot.emo(msg)
self.bot.privmsg(target,msg)
#######################################################################################
#######################################################################################
@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")
like_count=0
try:
view_count = int(video_info.get("statistics").get("viewCount"))
except:
like_count = int(video_info.get("statistics").get("likeCount"))
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"))
######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 2 of 2 ######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 2 of 2 ########
MUSIC_FOUND=False
for topic in topics:
if topic.lower().find('music'):
MUSIC_FOUND=True
if MUSIC_FOUND:
url = "https://youtu.be/{}".format(video_id)
self.bot.bbs.enter(mask.nick,url,title)
######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 2 of 2 ######## YOUTUBE <-> BOOMBOX_PLUGIN HOOK: 2 of 2 ########
_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)
if like_count == 0:
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,} \x0F\x1D\x0314Type: \x0F\x1DVideo\x0F".format(published=published_at, views=view_count)
else:
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Likes: \x0F\x1D{views:,} \x0F\x1D\x0314Type: \x0F\x1DMovie\x0F".format(published=published_at, views=like_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)
#######################################################################################
#######################################################################################
####################################################################################### EOF

16
requirements.txt Normal file
View File

@ -0,0 +1,16 @@
irc3
aiocron
timeago
isodate
google-api-python-client
oauth2client
aiohttp
asyncio
async_timeout
lxml
python-twitter
googlesearch-python
pyfiglet
openai
simplematrixbotlib
ipdb