This commit is contained in:
.[d]. 2021-07-11 06:42:05 +00:00
parent fb16a2ef16
commit a3efabc6fc
62 changed files with 6858 additions and 0 deletions

37
README.md Normal file
View File

@ -0,0 +1,37 @@
## setting up g1mp
1. `apt install python3`
2. `apt install python3-pycurl`
3. `apt install python3-pip`
4. `python3 -m pip install virtualenv`
5. `virtualenv env -p python3`
6. `source env/bin/activate`
7. # append your dev/api keys to env/bin/activate for environmentals
8. `pip install -r requirements.txt`
9. `irc3 _d_g1mp.ini`
## setting up d3vg1mp
1. `irc3 _d_d3vg1mp.ini`
2. when doing development, create a different ini, in your ini use a different database name, your plugins also use
a different filename. you dont want to have your development affecting your main running bot code or database.
e.g.
g1mp non-dev filenames: _d_g1mp.ini, _d_g1mp_db.json
- add a plugin example: add "plugins.youtube_plugin" to the file _d_g1mp.ini
- create the plugin filename: plugins/youtube_plugin.py
g1mp develop filenames: _d_d3vg1mp.ini, _d_d3vg1mp_db.json
- add a plugin example: add "plugins.d3v_youtube_plugin" to the file _d_g1mp.ini
- create the plugin filename: plugins/d3v_youtube_plugin.py
## EXAMPLE OF DEVELOPMENT WORKFLOW
### if you were working on a soundcloud plugin
1. add plugins.d3v_soundcloud_plugin to _d_d3vg1mp.ini
### we will be editing our plugin so we will want to maybe remove the plugin, paste new code
### and then restart the bot over and over again until we are done. see below or run `bash run_d_d3vg1mp`
1. rm plugins/d3v_soundcloud_plugin.py
2. nano plugins/d3v_soundcloud_plugin.py
3. irc3 _d_d3vg1mp.ini
### when we done with development, we either rename or copy the code from plugins/d3v_soundcloud_plugin.py into
### plugins/soundcloud_plugin.py and then add our plugin into the real _d_g1mp.ini.. then run irc3 _d_g1mp.ini

87
_d_d3vg1mp.ini Normal file
View File

@ -0,0 +1,87 @@
[bot]
nick = g1mpd3v
username = m4pl3d3v
realname="[ g1mpd3v'n ain't easy ]"
host = 185.193.37.199
port = 6697
version=1
url=185.193.37.199
ssl = true
ssl_verify = CERT_NONE
includes =
irc3.plugins.command
irc3.plugins.asynchronious
irc3.plugins.storage
irc3.plugins.uptime
irc3.plugins.ctcp
irc3.plugins.cron
irc3.plugins.logger
irc3.plugins.userlist
plugins.emote_plugin
plugins.base_plugin
##################plugins.auth_plugin
#plugins.fifo_plugin
plugins.soundcloud_plugin
plugins.phuq_plugin
plugins.curse_plugin
plugins.ip_plugin
plugins.isup_plugin
plugins.notes_plugin
plugins.figlet_plugin
plugins.url_grabber_plugin
plugins.seen_plugin
plugins.crypto_plugin
plugins.youtube_plugin
plugins.tell_plugin
plugins.twitter_plugin
plugins.ud_plugin
plugins.quote_plugin
plugins.strain_plugin
plugins.remind_plugin
plugins.time_plugin
#plugins.maple_plugin
plugins.recluse_plugin
plugins.dns_plugin
plugins.dr1ppl3s1x_plugin
#plugins.ratesex_plugin
#plugins.lurkers_plugin
#plugins.asciimg_plugin
#plugins.tweet_plugin
#plugins.sweet_plugin
#plugins.lurkers_plugin
#plugins.rip_plugin
plugins.hooker_plugin
plugins.sed_plugin
#plugins.decloak_user_plugin
#plugins.why_plugin
#plugins.google_plugin
autojoins =
${#}b0ts3x
flood_burst = 0
flood_rate = 1
flood_rate_delay = 1
storage = json://_d_g1mpd3v_db.json
[irc3.plugins.command]
cmd = ?
guard = irc3.plugins.command.mask_based_policy
[irc3.plugins.command.masks]
d!*dr1p@* = all_permissions
* = view
ignore_list =
g1mp_!*@*
g1mp!*@*
ken_!*@*
ken!*@*
[0]!*@*
[0]_!*@*
*!*k0de*@*
*!*@*

0
_d_d3vg1mp_db.json Normal file
View File

86
_d_g1mp.ini Normal file
View File

@ -0,0 +1,86 @@
[bot]
nick = g1mp
username = m4pl3
realname="[ g1mp'n ain't easy ]"
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.storage
irc3.plugins.uptime
irc3.plugins.ctcp
irc3.plugins.cron
irc3.plugins.logger
irc3.plugins.userlist
plugins.emote_plugin
plugins.base_plugin
plugins.auth_plugin
plugins.soundcloud_plugin
plugins.phuq_plugin
plugins.curse_plugin
plugins.ip_plugin
plugins.isup_plugin
plugins.notes_plugin
plugins.figlet_plugin
plugins.url_grabber_plugin
plugins.seen_plugin
plugins.crypto_plugin
plugins.youtube_plugin
plugins.tell_plugin
plugins.twitter_plugin
plugins.ud_plugin
plugins.quote_plugin
plugins.strain_plugin
plugins.remind_plugin
plugins.time_plugin
plugins.maple_plugin
plugins.recluse_plugin
plugins.dns_plugin
plugins.ratesex_plugin
plugins.sed_plugin
#plugins.lurkers_plugin
#plugins.asciimg_plugin
#plugins.tweet_plugin
#plugins.sweet_plugin
#plugins.lurkers_plugin
#plugins.rip_plugin
#plugins.hooker_plugin
#plugins.decloak_user_plugin
#plugins.why_plugin
#plugins.google_plugin
#plugins.fifo_plugin
autojoins =
${#}tcpdirect
${#}crypto
flood_burst = 0
flood_rate = 1
flood_rate_delay = 1
storage = json://_d_g1mp_db.json
[irc3.plugins.command]
cmd = ?
guard = irc3.plugins.command.mask_based_policy
[irc3.plugins.command.masks]
d!*dr1p@* = all_permissions
* = view
ignore_list =
g1mp_!*@*
g1mp!*@*
ken_!*@*
ken!*@*
[0]!*@*
[0]_!*@*
*!*k0de*@*
*!*@*

0
_d_g1mp_db.json Normal file
View File

426
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=ー( ゚д゚)・∵.
\˚ㄥ˚\
\ᇂ_ᇂ\
\(ಠ ὡ ಠ )/
\(◕ ◡ ◕\)
^̮^
^ㅂ^
_(͡๏̯͡๏)_
{´◕ ◡ ◕`}
{ಠ_ಠ}__,,|,
{◕ ◡ ◕}

150
plugins/asciimg_plugin.py Normal file
View File

@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from PIL import Image
import urllib
import requests
import irc3
import os
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
def say(self,target,msg):
try:
msg = self.bot._emoj(msg)
self.bot.privmsg(target, msg)
return
except Exception as e:
self.bot.privmsg(target, "say_error: {}".format(e))
def _color(self,c):
try:
c = str(c.lower())
if c == 'a': return '\x0300'
if c == 'b': return '\x0301'
if c == 'c': return '\x0302'
if c == 'd': return '\x0303'
if c == 'e': return '\x0304'
if c == 'f': return '\x0305'
if c == 'g': return '\x0306'
if c == 'h': return '\x0307'
if c == 'i': return '\x0308'
if c == 'j': return '\x0309'
if c == 'k': return '\x0310'
if c == 'l': return '\x0311'
if c == 'm': return '\x0312'
if c == 'n': return '\x0313'
if c == 'o': return '\x0314'
if c == 'p': return '\x0315'
if c == 'x': return ''
if c == 'z': return '\x0f'
print('_color: empty')
return '\x0f'
except:
print('_color: error')
return '\x0f'
@command(permission='admin')
def asciimg_color(self, mask, target, args):
"""asciimg_color
%%asciimg_color [<url>] [<x>] [<intensity>] [<charset>] [<colors>] [<debug>]
"""
try:
url = args.get("<url>")
x = int(args.get("<x>"))
intensity = int(args.get("<intensity>"))
charset = args.get("<charset>")
colors = args.get("<colors>")
debug = args.get("<debug>")
_colors = []
for _ in colors: _colors.append(self._color(_))
colors = _colors
_charset = []
for _ in charset: _charset.append(_)
chars = _charset
img = Image.open(urllib.request.urlopen(url))
width, height = img.size
aspect_ratio = height/width
new_width = x
new_height = aspect_ratio * new_width * 0.55
img = img.resize((new_width, int(new_height)))
img = img.convert('L')
pixels = img.getdata()
new_pixels = [chars[pixel//intensity] for pixel in pixels]
new_pixels = ''.join(new_pixels)
new_pixels_count = len(new_pixels)
ascii_image = [new_pixels[index:index + new_width] for index in range(0, new_pixels_count, new_width)]
ascii_image = "\n".join(ascii_image)
line_debugger=[]
for _ in ascii_image.splitlines():
try:
colored_line=""
for __ in _:
colored_line = "{}{}{}".format(colored_line, colors[charset.index(__)], __)
self.bot.privmsg(target,colored_line)
except Exception as e:
self.bot.privmsg(target,"colored_line_error {}".format(e))
except Exception as e:
self.say(target,"error: rekt on asciimg_color: {}".format(e))
self.say(target,'?asciimg_color "https://urmom.com/ascii.jpg" "100" "25" ".oO0XxiItT|"')
@irc3.extend
@command(permission='admin')
def asciimg(self, mask, target, args):
"""asciimg
%%asciimg [<url>] [<x>] [<intensity>] [<charset>] [<c0l0r>]
"""
try:
url = args.get("<url>")
x = int(args.get("<x>"))
intensity = int(args.get("<intensity>"))
charset = args.get("<charset>")
c0l0r = args.get("<c0l0r>")
user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
headers={'User-Agent':user_agent,}
request=urllib.request.Request(url,None,headers)
#response = urllib.request.urlopen(request)
#data = response.read()
img = Image.open(urllib.request.urlopen(request))
width, height = img.size
aspect_ratio = height/width
new_width = x
new_height = aspect_ratio * new_width * 0.55
img = img.resize((new_width, int(new_height)))
img = img.convert('L')
pixels = img.getdata()
chars = []
for _ in charset: chars.append(_)
new_pixels = [chars[pixel//intensity] for pixel in pixels]
new_pixels = ''.join(new_pixels)
new_pixels_count = len(new_pixels)
ascii_image = [new_pixels[index:index + new_width] for index in range(0, new_pixels_count, new_width)]
ascii_image = "\n".join(ascii_image)
bFlag=0
for _ in ascii_image.splitlines():
self.bot.privmsg(target,"{}{}".format(self._color(c0l0r),_))
except Exception as e:
self.say(target,"error: rekt on asciimg: {}".format(e))
#self.say(target,'?asciimg "https://urmom.com/ascii.jpg" "100" "25" ".oO0XxiItT|"')

45
plugins/asn_plugin.py Normal file
View File

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import ipdb
import aiodns
import socket
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def dns(self, mask, target, args):
"""Show DNS IP delegation
%%dns <domain>
"""
def reverse_domain(response):
try:
task_result = response.result()
self.bot.privmsg(target,task_result[0].host)
except aiodns.error.DNSError:
self.bot.privmsg(target,'invalid domain or ip')
def reverse_ip(response):
self.bot.privmsg(target,response)
domain = args.get('<domain>')
try:
ipaddress.ip_address(domain)
self.bot.privmsg(target,socket.gethostbyaddr(domain)[0])
except:
resolver = aiodns.DNSResolver(loop=self.bot.loop)
f = resolver.query(domain,'A')
asyncio.ensure_future(f).add_done_callback(reverse_domain)

406
plugins/asynchronious.py Normal file
View File

@ -0,0 +1,406 @@
# -*- coding: utf-8 -*-
from collections import OrderedDict
from irc3.asynchronous import AsyncEvents
from irc3 import utils
from irc3 import dec
__doc__ = """
======================================================
:mod:`irc3.plugins.asynchronious` Asynchronious events
======================================================
This module provide a way to catch data from various predefined events.
Usage
=====
You'll have to define a subclass of :class:`~irc3.asynchronous.AsyncEvents`:
.. literalinclude:: ../../irc3/plugins/asynchronious.py
:pyobject: Whois
Notice that regexps and send_line contains some `{nick}`. This will be
substitued later with the keyword arguments passed to the instance.
Then you're able to use it in a plugin:
.. code-block:: py
class MyPlugin:
def __init__(self, bot):
self.bot = bot
self.whois = Whois(bot)
def do_whois(self):
# remember {nick} in the regexp? Here it is
whois = await self.whois(nick='gawel')
if int(whois['idle']) / 60 > 10:
self.bot.privmsg('gawel', 'Wake up dude')
.. warning::
Your code should always check if the result has been set before timeout by
using `result['timeout']` which is True when the bot failed to get a result
before 30s (you can override the default value per call)
.. warning::
Do not over use this feature. If you're making a lot of calls at the same
time you should experience some weird behavior since irc do not allow
to identify responses for a command. That's why the exemple use {nick} in
the regexp to filter events efficiently. But two concurent call for the
same nick can still fail.
API
===
.. autoclass:: irc3.asynchronous.AsyncEvents
:members: process_results, __call__
.. autoclass:: Async
:members:
"""
class Whois(AsyncEvents):
# the command will fail if we do not have a result after 30s
timeout = 20
# send this line before listening to events
send_line = 'WHOIS {nick} {nick}'
# when those events occurs, we can add them to the result list
events = (
# (?i) is for IGNORECASE. This will match either NicK or nick
{'match': "(?i)^:\S+ 301 \S+ {nick} :(?P<away>.*)"},
{'match': "(?i)^:\S+ 311 \S+ {nick} (?P<username>\S+) (?P<host>\S+) . "
":(?P<realname>.*)(?i)"},
{'match': "(?i)^:\S+ 312 \S+ {nick} (?P<server>\S+) "
":(?P<server_desc>.*)"},
{'match': "(?i)^:\S+ 317 \S+ {nick} (?P<idle>[0-9]+).*"},
{'match': "(?i)^:\S+ 319 \S+ {nick} :(?P<channels>.*)", 'multi': True},
{'match': "(?i)^:\S+ 330 \S+ {nick} (?P<account>\S+) "
":(?P<account_desc>.*)"},
{'match': "(?i)^:\S+ 671 \S+ {nick} :(?P<connection>.*)"},
# if final=True then a result is returned when the event occurs
{'match': "(?i)^:\S+ (?P<retcode>(318|401)) \S+ (?P<nick>{nick}) :.*",
'final': True},
)
def process_results(self, results=None, **value):
"""take results list of all events and put them in a dict"""
channels = []
for res in results:
channels.extend(res.pop('channels', '').split())
value.update(res)
value['channels'] = channels
value['success'] = value.get('retcode') == '318'
return value
class WhoChannel(AsyncEvents):
send_line = 'WHO {channel}'
events = (
{"match": "(?i)^:\S+ 352 \S+ {channel} (?P<user>\S+) "
"(?P<host>\S+) (?P<server>\S+) (?P<nick>\S+) "
"(?P<modes>\S+) :(?P<hopcount>\S+) (?P<realname>.*)",
"multi": True},
{"match": "(?i)^:\S+ (?P<retcode>(315|401)) \S+ {channel} :.*",
"final": True},
)
def process_results(self, results=None, **value):
users = []
for res in results:
if 'retcode' in res:
value.update(res)
else:
res['mask'] = utils.IrcString(
'{nick}!{user}@{host}'.format(**res))
users.append(res)
value['users'] = users
value['success'] = value.get('retcode') == '315'
return value
class WhoChannelFlags(AsyncEvents):
flags = OrderedDict([
("u", "(?P<user>\S+)"),
("i", "(?P<ip>\S+)"),
("h", "(?P<host>\S+)"),
("s", "(?P<server>\S+)"),
("n", "(?P<nick>\S+)"),
("a", "(?P<account>\S+)"),
("r", ":(?P<realname>.*)"),
])
send_line = "WHO {channel} c%{flags}"
events = (
{"match": "(?i)^:\S+ (?P<retcode>(315|401)) \S+ {channel} :.*",
"final": True},
)
def process_results(self, results=None, **value):
users = []
for res in results:
if 'retcode' in res:
value.update(res)
else:
# Works in QuakeNet, don't know about other networks
if res.get('account') == '0':
res['account'] = None
users.append(res)
value['users'] = users
value['success'] = value.get('retcode') == '315'
return value
class WhoNick(AsyncEvents):
send_line = 'WHO {nick}'
events = (
{"match": "(?i)^:\S+ 352 \S+ (?P<channel>\S+) (?P<user>\S+) "
"(?P<host>\S+) (?P<server>\S+) (?P<nick>{nick}) "
"(?P<modes>\S+) :(?P<hopcount>\S+)\s*(?P<realname>.*)"},
{"match": "(?i)^:\S+ (?P<retcode>(315|401)) \S+ {nick} :.*",
"final": True},
)
def process_results(self, results=None, **value):
for res in results:
if 'retcode' not in res:
res['mask'] = utils.IrcString(
'{nick}!{user}@{host}'.format(**res))
value.update(res)
value['success'] = value.get('retcode') == '315'
return value
class IsOn(AsyncEvents):
events = (
{"match": "(?i)^:\S+ 303 \S+ :(?P<nicknames>({nicknames}.*|$))",
"final": True},
)
def process_results(self, results=None, **value):
nicknames = []
for res in results:
nicknames.extend(res.pop('nicknames', '').split())
value['names'] = nicknames
return value
class Topic(AsyncEvents):
send_line = 'TOPIC {channel}{topic}'
events = (
{"match": ("(?i)^:\S+ (?P<retcode>(331|332|TOPIC))"
"(:?\s+\S+\s+|\s+){channel} :(?P<topic>.*)"),
"final": True},
)
def process_results(self, results=None, **value):
for res in results:
status = res.get('retcode', '')
if status.upper() in ('332', 'TOPIC'):
value['topic'] = res.get('topic')
else:
value['topic'] = None
return value
class Names(AsyncEvents):
send_line = 'NAMES {channel}'
events = (
{"match": "(?i)^:\S+ 353 .*{channel} :(?P<nicknames>.*)",
'multi': True},
{'match': "(?i)^:\S+ (?P<retcode>(366|401)) \S+ {channel} :.*",
'final': True},
)
def process_results(self, results=None, **value):
nicknames = []
for res in results:
nicknames.extend(res.pop('nicknames', '').split())
value['names'] = nicknames
value['success'] = value.get('retcode') == '366'
return value
class ChannelBans(AsyncEvents):
send_line = 'MODE {channel} +b'
events = (
{"match": "(?i)^:\S+ 367 \S+ {channel} (?P<mask>\S+) (?P<user>\S+) "
"(?P<timestamp>\d+)",
"multi": True},
{"match": "(?i)^:\S+ 368 \S+ {channel} :.*",
"final": True},
)
def process_results(self, results=None, **value):
bans = []
for res in results:
# TODO: fix event so this one isn't needed
if not res:
continue
res['timestamp'] = int(res['timestamp'])
bans.append(res)
value['bans'] = bans
return value
class CTCP(AsyncEvents):
send_line = 'PRIVMSG {nick} :\x01{ctcp}\x01'
events = (
{"match": "(?i):(?P<mask>\S+) NOTICE \S+ :\x01(?P<ctcp>\S+) "
"(?P<reply>.*)\x01",
"final": True},
{"match": "(?i)^:\S+ (?P<retcode>486) \S+ :(?P<reply>.*)",
"final": True}
)
def process_results(self, results=None, **value):
"""take results list of all events and return first dict"""
for res in results:
if 'mask' in res:
res['mask'] = utils.IrcString(res['mask'])
value['success'] = res.pop('retcode', None) != '486'
value.update(res)
return value
@dec.plugin
class Async:
"""Asynchronious plugin.
Extend the bot with some common commands using
:class:`~irc3.asynchronous.AsyncEvents`
"""
def __init__(self, context):
self.context = context
self.context.async_cmds = self
self.async_whois = Whois(context)
self.async_who_channel = WhoChannel(context)
self.async_who_nick = WhoNick(context)
self.async_topic = Topic(context)
self.async_ison = IsOn(context)
self.async_names = Names(context)
self.async_channel_bans = ChannelBans(context)
self.async_ctcp = CTCP(context)
def async_who_channel_flags(self, channel, flags, timeout):
"""
Creates and calls a class from WhoChannelFlags with needed match rule
for WHO command on channels with flags.
"""
# Lowercase flags and sort based on WhoChannelFlags.flags, otherwise
# resulting dict is wrong. Also join flags if it's a sequence.
flags = ''.join([f.lower() for f in WhoChannelFlags.flags
if f in flags])
regex = [WhoChannelFlags.flags[f] for f in flags]
channel = channel.lower()
cls = type(
WhoChannelFlags.__name__,
(WhoChannelFlags,),
{"events": WhoChannelFlags.events + (
{"match": "(?i)^:\S+ 354 \S+ {0}".format(' '.join(regex)),
"multi": True},
)}
)
return cls(self.context)(channel=channel, flags=flags, timeout=timeout)
@dec.extend
def whois(self, nick, timeout=20):
"""Send a WHOIS and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.whois('gawel')
"""
return self.async_whois(nick=nick.lower(), timeout=timeout)
@dec.extend
def who(self, target, flags=None, timeout=20):
"""Send a WHO and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.who('gawel')
result = await bot.async_cmds.who('#irc3')
result = await bot.async_cmds.who('#irc3', 'an')
# or
result = await bot.async_cmds.who('#irc3', ['a', 'n'])
"""
target = target.lower()
if target.startswith('#'):
if flags:
return self.async_who_channel_flags(channel=target,
flags=flags,
timeout=timeout)
return self.async_who_channel(channel=target, timeout=timeout)
else:
return self.async_who_nick(nick=target, timeout=timeout)
def topic(self, channel, topic=None, timeout=20):
if not topic:
topic = ''
else:
topic = ' ' + topic.strip()
return self.async_topic(channel=channel, topic=topic, timeout=timeout)
@dec.extend
def ison(self, *nicknames, **kwargs):
"""Send a ISON and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.ison('gawel', 'irc3')
"""
nicknames = [n.lower() for n in nicknames]
self.context.send_line('ISON :{0}'.format(' '.join(nicknames)))
return self.async_ison(nicknames='(%s)' % '|'.join(nicknames),
**kwargs)
@dec.extend
def names(self, channel, timeout=20):
"""Send a NAMES and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.names('#irc3')
"""
return self.async_names(channel=channel.lower(), timeout=timeout)
@dec.extend
def channel_bans(self, channel, timeout=20):
"""Send a MODE +b and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.channel_bans('#irc3')
"""
return self.async_channel_bans(channel=channel.lower(),
timeout=timeout)
@dec.extend
def ctcp_async(self, nick, ctcp, timeout=20):
"""Send a CTCP and return a Future which will contain recieved data:
.. code-block:: py
result = await bot.async_cmds.ctcp('irc3', 'version')
"""
return self.async_ctcp(nick=nick, ctcp=ctcp.upper(), timeout=timeout)

15
plugins/auth_plugin.py Normal file
View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.CONNECTED)
def connected(self, **kw):
msg = "identify g1mp this_is_not_my_password"
self.bot.privmsg('NICKSERV',msg)

251
plugins/base_plugin.py Normal file
View File

@ -0,0 +1,251 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from irc3.utils import IrcString
import irc3
import os
import sys
import time
import re
import functools
USER_STRING_MATCH = re.compile('(.+)!(.+)@(.+)')
@irc3.plugin
class Plugin:
def __init__(self, bot):
staff_set = set()
self.bot = bot
self.bot.auto_kick_list = set(self.bot.db.getlist("auto_kick_list", []))
self.bot.ignore_list = set(self.bot.db.getlist("ignore_nicks_list", []))
self.bot.staff_list = set(self.bot.db.getlist("staff_list", []))
current_masks = self.bot.config.get('irc3.plugins.command.masks')
# Build out staff set
for k, v in current_masks.items():
if v in ["staff", "all_permissions"]:
staff_set.add(k)
# Hande Creating Default Ignore List
if not self.bot.ignore_list:
self.bot.ignore_list = set(self.bot.config.get('irc3.plugins.command.masks', {}).get("ignore_list", []))
# Handle Creating Default Staff List
if not self.bot.staff_list:
self.bot.staff_list = set(staff_set)
self.bot.db.setlist("staff_list", self.bot.staff_list)
for hostname in self.bot.staff_list:
if not current_masks.get(hostname):
self.bot.config['irc3.plugins.command.masks'][hostname] = "staff"
@irc3.extend
def check_if_ignored(self, hostmask):
global_hostmask = hostmask.replace(hostmask.nick, ".+")
nick_mask = hostmask.replace(hostmask.host,".+@.+")
host_pattern = re.compile(global_hostmask)
nick_pattern = re.compile(nick_mask)
for mask in self.bot.ignore_list:
if host_pattern.match(mask):
return True
if nick_pattern.match(mask):
return True
return False
@irc3.event(irc3.rfc.CONNECTED)
def _add_hostmask(self, *args, **kwargs):
def handle_who(self, response):
result = response.result()
self.bot.hostmask = result.get('mask')
task = self.bot.who(self.bot.get_nick())
task.add_done_callback(functools.partial(handle_who, self))
opper_password = self.bot.config.get("opper_password")
opper_username = self.bot.config.get("opper_username")
self.bot.send_line("GOD {} {}".format(opper_username, opper_password))
self.bot.privmsg("nickserv", "IDENTIFY {} {}".format(self.bot.nick, opper_password))
@irc3.event(irc3.rfc.JOIN)
def auto_kick_handler(self, mask, channel, **kw):
msg = "g1mp'n ain't easy"
if mask.nick in self.bot.auto_kick_list:
cmd = "MODE {} +b {}!*@*".format(channel, mask.nick)
self.bot.send(cmd)
self.bot.kick(channel, mask.nick, msg)
@command(permission='view', public=True, show_in_help_list=False)
def v(self, mask, target, args):
"""Voice all Users
%%v
"""
channel = self.bot.channels[target]
# Create list of Users with modes/voice
has_voice_list = []
for _, nick in channel.modes.items():
has_voice_list.append(nick)
for nick in channel:
if nick not in has_voice_list:
cmd = "MODE {} +v {}".format(target, nick)
self.bot.send(cmd)
@command(permission='admin', public=True, show_in_help_list=False)
def op(self, mask, target, args):
"""Op nick
%%op [<nick>]
"""
if args['<nick>']:
nick = args['<nick>']
cmd = "MODE {} +o {}".format(target, nick)
self.bot.send(cmd)
@command(permission='admin', public=True, show_in_help_list=False)
def deop(self, mask, target, args):
"""DeOp nick
%%deop [<nick>]
"""
if args['<nick>']:
nick = args['<nick>']
cmd = "MODE {} -o {}".format(target, nick)
self.bot.send(cmd)
@command(permission="admin", show_in_help_list=False)
def stats(self, mask, target, args):
"""Show stats of the channel using the userlist plugin
%%stats [<channel>]
"""
if args['<channel>']:
channel = args['<channel>']
target = mask.nick
else:
channel = target
if channel in self.bot.channels:
channel = self.bot.channels[channel]
message = '{0} users'.format(len(channel))
for mode, nicknames in sorted(channel.modes.items()):
message += ' - {0}({1})'.format(mode, len(nicknames))
self.bot.privmsg(target, message)
@command(permission='admin', public=False, show_in_help_list=False)
def restart(self, mask, target, args):
"""Restart bot
%%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 add/list/del User
%%staff [<cmd>] [<nick>]
"""
def __staff_list(self, mask, target, args):
"""Delete nick from staff
%%staff list
"""
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):
"""Delete nick from staff
%%staff del <nick>
"""
# Remove Host Mask
def del_hostmask(self, host_string):
current_masks = self.bot.config.get("irc3.plugins.command.masks", "")
if host_string in current_masks.keys():
mask_list = current_masks.get(host_string, "").split(",")
if "all_permissions" in mask_list:
self.bot.privmsg(target, "Don't fuck with the admin")
return
elif "staff" in mask_list:
del(self.bot.config["irc3.plugins.command.masks"][host_string])
self.bot.staff_list.remove(host_string)
self.bot.db.setlist("staff_list", self.bot.staff_list)
self.bot.privmsg(target, '{} removed from staff'.format(host_string))
return
else:
pass # pass for brevarity
else:
self.bot.privmsg(target, '{} is not a staff member'.format(host_string))
def handle_who(self, response):
result = response.result()
nick = result.get("nick")
mask = result.get('mask')
# We don't care about the nick so make it globally match
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:
# if true - nick is actually a hostmask
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):
"""Add nick to staff
%%staff add <nick>
"""
def add_hostmask(self, host_string):
current_masks = self.bot.config.get("irc3.plugins.command.masks", "")
if host_string in current_masks.keys():
mask_list = current_masks.get(host_string, "").split(",")
if "staff" or "all_permissions" in mask_list:
self.bot.privmsg(target, "{} is already a staff member".format(host_string))
return
else:
self.bot.config["irc3.plugins.command.masks"][host_string] = "staff"
self.bot.staff_list.add(host_string)
self.bot.db.setlist("staff_list", self.bot.staff_list)
self.bot.privmsg(target, '{} added to staff'.format(host_string))
def handle_who(self, response):
result = response.result()
nick = result.get("nick")
mask = result.get('mask')
# We don't care about the nick so make it globally match
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:
# if true - nick is actually a hostmask
add_hostmask(self, nick)
return
else:
task = self.bot.who(nick)
task.add_done_callback(functools.partial(handle_who, self))
return
cmd = args.get("<cmd>")
if not cmd:
self.bot.privmsg(target, "please specify add/del/list")
elif cmd in ["d","del","delete","remove"]:
__staff_del(self, mask, target, args)
elif cmd in ["l", "list"]:
__staff_list(self, mask, target, args)
elif cmd in ["w", "write","a", "add"]:
__staff_add(self, mask, target, args)

68
plugins/bgp_plugin.py Normal file
View File

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import datetime
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import bs4
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()
options.add_argument('--disable-extensions')
options.add_argument('--headless')
options.add_argument('--hide-scrollbars')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument("--window-size=1920x1080")
options.add_experimental_option(
'prefs', {
'download.default_directory': "./",
'download.prompt_for_download': False,
'download.directory_upgrade': True,
'safebrowsing.enabled': True
})
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
self.driver = webdriver.Chrome(chrome_options=options)
self.driver.implicitly_wait(10)
@command(permission='staff')
def bgp(self, mask, target, args):
"""Show Infomation on ip/domain
%%bgp <lookup_string>
"""
lookup_string = args.get("<lookup_string>")
async def fetch():
self.driver.get("https://bgp.he.net/search?search%5Bsearch%5D={}&commit=Search".format(lookup_string))
element = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "tbody"))
)
return self.driver.page_source
async def grab_url(url):
source = await fetch()
dom = bs4.BeautifulSoup(source, "lxml")
as_list = [ "{} : {} : {}".format(a,b,c) for a,b,c in zip(*[iter(item.text.strip() for item in dom.findAll('td'))]*3) ]
# import ipdb; ipdb.set_trace()
self.bot.privmsg(target,"Found: {}".format(" | ".join(as_list)))
url = "https://bgp.he.net/search?search%5Bsearch%5D={}&commit=Search".format(lookup_string)
task = self.bot.create_task(grab_url(url))
#task.add_done_callback(process_lookups)
#asyncio.ensure_future(grab_url(url), loop=self.bot.loop).add_done_callback(process_lookups)

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from google.cloud import bigquery
import irc3
import ipdb
import time
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
self.bigquery_client = bigquery.Client()
@irc3.event(irc3.rfc.PRIVMSG)
def on_privmsg_log(self, mask=None, target=None, data=None, **kw):
dataset_ref = self.bigquery_client.dataset("xmppland")
table_ref = dataset_ref.table("privmsg")
table = self.bigquery_client.get_table(table_ref)
rows_to_insert = [(target,data,mask.nick,mask, time.time(), mask.host)]
self.bigquery_client.insert_rows(table, rows_to_insert)

95
plugins/cron.py Normal file
View File

@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
import venusian
import logging
import irc3
__doc__ = '''
==========================================
:mod:`irc3.plugins.cron` Cron plugin
==========================================
Introduce a ``@cron`` decorator
Install aiocron::
$ pip install aiocron
Create a python module with some crons:
.. literalinclude:: ../../examples/mycrons.py
..
>>> import sys
>>> sys.path.append('examples')
>>> from irc3.testing import IrcBot
And register it::
>>> context = IrcBot()
>>> context.include('mycrons') # register your crons
'''
@irc3.plugin
class Crons(list):
def __init__(self, bot):
self.bot = bot
return
def connection_made(self):
if not self.started:
self.start()
def before_reload(self):
self.stop()
self[:] = []
def after_reload(self):
self.start()
@irc3.extend
def add_cron(self, cronline, callback, uuid=None):
cron = self.factory(cronline, callback, start=False, uuid=uuid,
loop=self.context.loop)
self.append(cron)
if self.started:
cron.start()
return cron
@irc3.extend
def remove_cron(self, cron=None):
cron.stop()
self.remove(cron)
def start(self):
self.started = True
for cron in self:
cron.start()
def stop(self):
self.context.log.info('Stoping existing crons...')
self.started = False
for cron in self:
cron.stop()
def __repr__(self):
return '<Crons ({0}) at {1}>'.format(len(self), id(self))
def cron(cronline, venusian_category='irc3.plugins.cron'):
"""main decorator"""
def wrapper(func):
def callback(context, name, ob):
obj = context.context
crons = obj.get_plugin(Crons)
if info.scope == 'class':
callback = getattr(
obj.get_plugin(ob),
func.__name__)
else:
callback = irc3.utils.wraps_with_context(func, obj)
crons.add_cron(cronline, callback)
info = venusian.attach(func, callback, category=venusian_category)
return func
return wrapper

129
plugins/crypto_plugin.py Normal file
View File

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import datetime
import aiohttp
import asyncio
import async_timeout
import random
import os
import pdb
dir_path = os.path.dirname(os.path.realpath(__file__))
headers = { 'authorization': 'Apikey 94e50805f19646893ee16424918998caad5ec6accff539a23ffee8e546eda4e3' }
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def cc(self, mask, target, args):
"""Show Crypto Value
%%cc <coin>
"""
coin = args['<coin>'].upper()
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using crypto plugins')
return
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
#price_multi = {k:v.replace("$","").replace(" ","").replace(",","") for k,v in price_multi.items()}
X = float(daily_avg) # AVERAGE OF THE DAY
P = float(price_multi.get('PRICE')) # PRICE CURRENTLY
# O = float(price_multi.get('OPENDAY')) # OPENING PRICE
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
# PRICE DIFFERENTIAL 24 HOURS AGO
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.__emoj(msg)
self.bot.privmsg(target, msg)
except Exception as e:
msg = self.__emoj('their api is glitching: check back later')
#msg = self.__emoj('site error: {}'.format(e.message))
#msg = self.__emoj("Invalid coin - see https://min-api.cryptocompare.com/data/all/coinlist data keys")
self.bot.privmsg(target, msg)
def process_lookups(response):
try:
html = response.result()
except Exception as e:
msg = self.__emoj('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.__emoj('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)

118
plugins/curse_plugin.py Normal file
View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import sys
import random
dir_path = os.path.dirname(os.path.realpath(__file__))
hp = \
"""
aberto
accio
aguamenti
alohomora
avada kedavra
caterwauling
colloportus
confringo
confundo
crucio
descendo
diffindo
disillusionment
engorgio
episkey
evanesco
expecto patronum
expelliarmus
finestra
homenum revelio
impedimenta
imperio
impervius
incendio
levicorpus
liberacorpus
locomotor
lumos
morsmordre
muffliato
nox
obliviate
petrificus totalus
portus
priori incantato
protego
reducto
rennervate
relashio
rennervate
reparo
revelio
rictusempra
riddikulus
scourgify
sectumsempra
silencio
sonorus
stupefy
taboo
tergeo
wingardium leviosa
"""
sym = """
ψ
"""
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def curse(self, mask, target, args):
"""
%%curse <nickname>
"""
nickname = args['<nickname>']
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using curse plugins')
return
spells = hp.split()
symbols = sym.split()
spell = []
r = random.randint(0,len(spells))
for n in range(r):
spell.append(random.choice(spells))
r = random.randint(0,len(spells))
d = 0
for n in range(r):
c = random.randint(0,1)
if(c):
spell.insert(n+d, symbols[ random.randint(0,len(symbols)-1) ])
d+=1
cast = ''
for n in spell:
cast += n + ' '
msg = self.__emoj("{}{}".format(cast,nickname))
self.bot.privmsg(target, msg)

242
plugins/d3cl04k_plugin.py Normal file
View File

@ -0,0 +1,242 @@
# -*- coding: utf-8 -*-
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import irc3
from random import shuffle
import string
import pdb
import socket
from urllib import request
import requests
from lxml import etree
from io import BytesIO
VERBOSE = True
TARGET = '#Security'
class upnp():
def __init__(self,bot,ip):
self.bot = bot
self.ip = ip
self.port = 1900
self.timeout = 1
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
self.socket.settimeout(self.timeout)
##################################################################################
self.mx = 1
self.service = 'upnp:rootdevice'
self.msg_ssdp = 'M-SEARCH * HTTP/1.1\r\n' \
'HOST:239.255.255.250:1900\r\n' \
'ST:{st}\r\n' \
'MX:{mx}\r\n' \
'MAN:"ssdp:discover"\r\n\r\n'
self.msg_ssdp = self.msg_ssdp.format(st=self.service,mx=self.mx).encode('utf-8')
##################################################################################
self.msg_hosts = '<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" '\
's:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetGenericPortMappingEntry '\
'xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">\r\n<NewPortMappingIndex>{INDEX}' \
'</NewPortMappingIndex></u:GetGenericPortMappingEntry></s:Body></s:Envelope>\r\n\r\n'
self.msg_binds = 'BLKHAT/DECLOAKED: {EIP}:{EPORT} > {IPORT}:{IIP} ? {DESC}'
##################################################################################
def ssdp(self,target):
pdb.set_trace()
self.socket.sendto( self.msg_ssdp, (self.ip, int(self.port)) )
try:
data_blob = ''
while True:
data, _ = self.socket.recvfrom(1024)
data = str(data,'utf-8')
data_blob = data_blob + data
except socket.timeout:
pass
except UnicodeDecodeError:
pass
for result in data_blob.splitlines():
if(result.find('LOCATION') != -1 or result.find('Location') != -1):
self.ssdp_location = result[len('LOCATION: '):]
self.chop_location(self.ssdp_location)
return
def get_rootdesc(self):
url = 'http://{IP}:{PORT}{PATH}'.format(IP=self.ip,PORT=self.ssdp_location_port,PATH=self.ssdp_location_path)
r = requests.get(url,timeout=2.000)
self.xml_desc = r.text
self.popdesc()
def popdesc(self):
root = etree.XML( self.xml_desc.replace('\r\n','') )
b = BytesIO( etree.tostring(root) )
results_control = []
results_presentation = []
for event, element in etree.iterparse( b ):
if element.tag == root.tag.replace('root','controlURL'):
results_control.append( element.text )
if element.tag == root.tag.replace('root','presentationURL'):
results_presentation.append( element.text )
self.pop_results_control = results_control
self.pop_results_presentation = results_presentation
for i in range(len(self.pop_results_control)):
if self.pop_results_control[i][-len('WANIPConnection:1'):]=='WANIPConnection:1':
self.pop_result_control = 'http://{EIP}:{EPORT}{EPATH}'.format(EIP=self.ip,EPORT=self.ssdp_location_port,EPATH=self.pop_results_control[i])
for i in range(len(self.pop_results_presentation)):
self.pop_result_presentation = self.pop_results_presentation[i]
def get_hosts(self):
self.pop_results_new_internal_port = []
self.pop_results_new_external_port = []
self.pop_results_new_internal_client = []
self.pop_results_new_description = []
i = 0
try:
while True:
i += 1
msg = self.msg_hosts.format(INDEX=str(i)).encode('utf-8')
url = self.pop_result_control
req = request.Request(url, msg)
req.add_header("SOAPACTION", '"urn:schemas-upnp-org:service:WANIPConnection:1#GetGenericPortMappingEntry"')
req.add_header('Content-type', 'application/xml')
req = request.urlopen(req).read()
self.pophosts(req)
except:
pass
stubz = []
stubz.append( self.stub(self.ip) )
stubz.append( self.stub(self.pop_results_new_external_port) )
stubz.append( self.stub(self.pop_results_new_internal_port) )
stubz.append( self.stub(self.pop_results_new_internal_client) )
stubz.append( self.stub(self.pop_results_new_description) )
i = len(self.pop_results_new_external_port)
for x in range(i):
self.log( self.msg_binds.format( EIP = self.space(self.ip,stubz[0],False), \
EPORT= self.space(self.pop_results_new_external_port[x], stubz[1],False), \
IPORT= self.space(self.pop_results_new_internal_port[x], stubz[2],True), \
IIP = self.space(self.pop_results_new_internal_client[x],stubz[3],False), \
DESC = self.space(self.pop_results_new_description[x], stubz[4],False) ) )
def pophosts(self,xml):
root = etree.XML(xml)
b = BytesIO( etree.tostring(root) )
for event, element in etree.iterparse( b ):
if element.tag == 'NewInternalPort':
self.pop_results_new_internal_port.append( element.text )
if element.tag == 'NewExternalPort':
self.pop_results_new_external_port.append( element.text )
if element.tag == 'NewInternalClient':
self.pop_results_new_internal_client.append( element.text )
if element.tag == 'NewPortMappingDescription':
self.pop_results_new_description.append( element.text )
def log(self,s):
self.bot.privmsg(TARGET,s)
def space(self,s,n,d):
if d == False:
if not(len(s)>n):
return s + " " * (n-len(s))
else:
if not(len(s)>n):
return " " * (n-len(s)) + s
def stub(self,l):
if not type(l) == list: return len(l)
w = 0
for i in l:
if len(i) > w:
w = len(i)
return w
def chop_location(self,url):
pos = url.find('http://')
if not pos == -1:
url = url[pos+len('http://'):]
pos = url.find(':')
if not pos == -1:
self.ssdp_location_ip = url[:pos]
url = url[pos+1:]
pos = url.find('/')
if not pos == -1:
self.ssdp_location_port = url[:pos]
self.ssdp_location_path = url[pos:]
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.JOIN)
def decloak_user(self, mask, channel, **kw):
"""upnp scan system"""
if mask.nick != self.bot.nick:
_UHOST = mask.host
bTrap = False
#ipdb.set_trace()
if(_UHOST[:8].find('@') == -1):
try:
aa = int(_UHOST[:2],16)
bb = int(_UHOST[2:4],16)
cc = int(_UHOST[4:6],16)
dd = int(_UHOST[6:8],16)
_CLOAK = 'ASSUMED'
bTrap = True
except:
pass
if 'kiwiirc' in _UHOST:
_CLOAK = 'KIWI'
bTrap = True
elif 'mibbit' in _UHOST:
_CLOAK = 'MIBBIT'
bTrap = True
if(bTrap == True):
_UHOST = _UHOST[:8]
_IP = str(str(int(_UHOST[0:2], 16)) + '.' + str(int(_UHOST[2:4], 16)) + '.' + str(
int(_UHOST[4:6], 16)) + '.' + str(int(_UHOST[6:8], 16)))
r0 = requests.get('http://ip-api.com/json/' + _IP)
d0 = r0.json()
a = d0['as']
b = d0['city']
c = d0['country']
d = d0['countryCode']
e = d0['isp']
f = d0['lat']
g = d0['lon']
h = d0['org']
i = d0['query']
j = d0['region']
k = d0['regionName']
l = d0['status']
m = d0['timezone']
n = d0['zip']
self.bot.privmsg(channel, 'BLKHAT/DECLOAKED: ' + _CLOAK + ' | AS: ' + str(a) + ' | CITY: ' + str(b) + ' | COUNTRY: ' + str(c) + ' | COUNTRY_CODE: ' + str(d) + ' | ISP: ' + str(e) + ' | LAT: ' + str(
f) + ' | LON: ' + str(g) + ' | ORG: ' + str(h) + ' | QUERY: ' + str(i) + ' | REGION: ' + str(j) + ' | REGION_NAME: ' + str(k) + ' | STATUS: ' + str(l) + ' | TIMEZONE: ' + str(m) + ' | ZIP: ' + str(n))
ip = _IP
try:
if(socket.inet_aton(ip)):
###################################
try:
i = upnp(self.bot,ip)
i.ssdp( channel )
try:
if not i.ssdp_location == '':
i.get_rootdesc()
try:
i.get_hosts()
except:
pass
except:
pass
except:
pass
###################################
except Exception as e:
pass

View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import irc3
import requests
import ipdb
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.JOIN)
def decloak_user(self, mask, channel, **kw):
"""Decloak kiwiirc/mibbit users"""
if mask.nick != self.bot.nick:
_UHOST = mask.host
bTrap = False
#ipdb.set_trace()
if(_UHOST[:8].find('@') == -1):
try:
aa = int(_UHOST[:2],16)
bb = int(_UHOST[2:4],16)
cc = int(_UHOST[4:6],16)
dd = int(_UHOST[6:8],16)
_CLOAK = 'ASSUMED'
bTrap = True
except:
pass
if 'kiwiirc' in _UHOST:
_CLOAK = 'KIWI'
bTrap = True
elif 'mibbit' in _UHOST:
_CLOAK = 'MIBBIT'
bTrap = True
if(bTrap == True):
_UHOST = _UHOST[:8]
_IP = str(str(int(_UHOST[0:2], 16)) + '.' + str(int(_UHOST[2:4], 16)) + '.' + str(
int(_UHOST[4:6], 16)) + '.' + str(int(_UHOST[6:8], 16)))
r0 = requests.get('http://ip-api.com/json/' + _IP)
d0 = r0.json()
a = d0['as']
b = d0['city']
c = d0['country']
d = d0['countryCode']
e = d0['isp']
f = d0['lat']
g = d0['lon']
h = d0['org']
i = d0['query']
j = d0['region']
k = d0['regionName']
l = d0['status']
m = d0['timezone']
n = d0['zip']
self.bot.privmsg(channel, 'BLKHAT/DECLOAKED: ' + _CLOAK + ' | AS: ' + str(a) + ' | CITY: ' + str(b) + ' | COUNTRY: ' + str(c) + ' | COUNTRY_CODE: ' + str(d) + ' | ISP: ' + str(e) + ' | LAT: ' + str(
f) + ' | LON: ' + str(g) + ' | ORG: ' + str(h) + ' | QUERY: ' + str(i) + ' | REGION: ' + str(j) + ' | REGION_NAME: ' + str(k) + ' | STATUS: ' + str(l) + ' | TIMEZONE: ' + str(m) + ' | ZIP: ' + str(n))

82
plugins/dns_plugin.py Normal file
View File

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import ipdb
import aiodns
import socket
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def dns(self, mask, target, args):
"""Show DNS IP delegation
%%dns <domain>
"""
domain = args.get('<domain>')
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using url plugins')
return
bip = False
bad = False
try:
socket.gethostbyname(domain)
bad = True
except:
bad = False
try:
socket.gethostbyaddr(domain)
bip = True
except:
bip = False
if(bip==False and bad==False):
msg = 'invalid domain or ip'
self.bot.privmsg(target,'invalid domain or ip')
else:
if(bad):
try:
_ip = socket.gethostbyname(domain)
except:
_ip = 'error'
try:
_ad = socket.gethostbyaddr(_ip)
except:
_ad = 'error'
elif(bip):
try:
_ad = socket.gethostbyaddr(domain)
except:
_ad = 'error'
try:
_ip = socket.gethostbyname(_ad)
except:
_ip = 'error'
msg = self.__emoj("QUERY:['{}'] IP:{} HOST:['{}']".format(domain, _ad[2], _ad[0]))
self.bot.privmsg(target,msg)

29
plugins/emote_plugin.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import datetime
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def emo(self, mask, target, args):
"""Show Emotion
%%emo
"""
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using emo plugins')
return
def __random_line():
emote_db = '%s/../emote.db' % dir_path
return random.choice(list(open(emote_db)))
emoj = __random_line()
self.bot.privmsg(target, "%s" % emoj)

164
plugins/fifo_plugin.py Normal file
View File

@ -0,0 +1,164 @@
# -*- coding: utf-8 -*-
import os
import irc3
from stat import S_ISFIFO
import ipdb
__doc__ = '''
ds notes
mkdir /run/irc3
chown $USER:$USER /run/irc3
cat whatever > /run/irc3/channelname
#this operates like a typical fifo pipe now
#ratesex_plugin depends on this plugin to operate
==========================================
:mod:`irc3.plugins.fifo` Fifo plugin
==========================================
Allow to cat something to a channel using Unix's fifo
..
>>> from irc3.testing import IrcBot
>>> from irc3.testing import ini2config
>>> import shutil
>>> import os
>>> try:
... shutil.rmtree('/tmp/run/irc3')
... except:
... pass
Usage::
>>> config = ini2config("""
... [bot]
... includes =
... irc3.plugins.fifo
... [irc3.plugins.fifo]
... runpath = /tmp/run/irc3
... """)
>>> bot = IrcBot(**config)
When your bot will join a channel it will create a fifo::
>>> bot.test(':irc3!user@host JOIN #channel')
>>> print(sorted(os.listdir('/tmp/run/irc3')))
[':raw', 'channel']
You'll be able to print stuff to a channel from a shell::
$ cat /etc/passwd > /tmp/run/irc3/channel
You can also send raw irc commands using the ``:raw`` file::
$ echo JOIN \#achannel > /tmp/run/irc3/:raw
'''
@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', '/run/irc3')
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): # pragma: no cover
# this required for python < 3.5
# for more info see https://www.python.org/dev/peps/pep-0475/
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)

78
plugins/figlet_plugin.py Normal file
View File

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import pyfiglet
import irc3
import random
import ipdb
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
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)
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@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:])
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using fig plugins')
return
# Backwards I know...
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.__emoj(font)
self.bot.privmsg(target, msg)
fig_text = self.fig(text=text, font=font)
else:
newfont = random.choice(list(self.fig_fonts))
msg = self.__emoj(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)

41
plugins/gif_plugin.py Normal file
View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import ipdb
import time
import safygiphy
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view', public=True, show_in_help_list=True)
def gif(self, mask, target, args):
"""Find a random gif from Giphy
%%gif <search_term>
"""
search_term = args['<search_term>']
gify = safygiphy.Giphy()
gify_data = gify.random(tag=search_term)
if(len(gify_data['data']) > 0 ):
gif_url = gify_data['data']['image_original_url']
else:
gif_url = 'no giphy results / censored / errored'
msg = self.__emoj(gif_url)
self.bot.privmsg(target, msg)

84
plugins/google_plugin.py Normal file
View File

@ -0,0 +1,84 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import sys
import requests
import random
from lxml.html import fromstring
from googlesearch import search
from bs4 import BeautifulSoup
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
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, num=1, start=0, stop=0, pause=0):
result = "{}".format(j)
break
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
# Ignore Non text/html
if not content_type.startswith("text/html"):
return
# Ignore Large Content
if int(content_length) > 200000:
self.bot.privmsg(target, "pre-fetch aborted -> fuck your large ass content")
# 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]
# Comment out 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.__emoj(msg)
self.bot.privmsg(target, msg)
return
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass

27
plugins/hooker_plugin.py Normal file
View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
import ipdb
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def hooker(self, mask, target, args):
"""hooker
%%hooker <message>...
"""
ipdb.set_trace()
msg = 'hooker: '
msg = msg + ' '.join(args['<message>'])
self.bot.privmsg(target, msg)
#@cron('* * * * *')
#def _hooker_test(bot):
#print('hooker test')
#TARGET="#tcpdirect"
#bot.privmsg(TARGET,'_hooker_test: wu/tang')

130
plugins/ibf_plugin.py Normal file
View File

@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import datetime
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipdb
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def ibf(self, mask, target, args):
"""Show IBF Top TWENTY
%%ibf <toptwenty>
"""
toptwenty = args.get("<toptwenty>")
try:
i = int(toptwenty)
except:
self.bot.privmsg(target,'invalid: use only numbers 0-19')
exit
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() as session:
json_response = await fetch(session, url)
return json_response
def process_lookups(response):
html = response.result()
i = int(toptwenty)
data = html['items'][int(i)]
try:
___NAME = data['title']
except:
___NAME = 'NULL'
try:
____DOB = data['dates_of_birth_used'][0]
except:
____DOB = 'NULL'
try:
____POB = data['place_of_birth']
except:
____POB = 'NULL'
try:
___HAIR = data['hair']
except:
___HAIR = 'NULL'
try:
___EYES = data['eyes']
except:
___EYES = 'NULL'
try:
_HEIGHT = data['height_max']
_HEIGHT = "{}'{}{}".format(int(_HEIGHT/12),_HEIGHT%12,'"')
except:
_HEIGHT = 'NULL'
try:
_WEIGHT = data['weight_max']
_WEIGHT = "{} pounds".format(_WEIGHT)
except:
_WEIGHT = 'NULL'
try:
____SEX = data['sex']
except:
____SEX = 'NULL'
try:
___RACE = data['race_raw']
except:
___RACE = 'NULL'
try:
_NATION = data['nationality']
except:
_NATION = 'NULL'
try:
REMARKS = data['remarks']
REMARKS = REMARKS.replace('<p>','')
REMARKS = REMARKS.replace('</p>','')
REMARKS = REMARKS.replace('\xa0',' ')
except:
REMARKS = 'NULL'
try:
CAUTION = data['caution']
CAUTION = CAUTION.replace('<p>','')
CAUTION = CAUTION.replace('</p>','')
CAUTION = CAUTION.replace('\xa0',' ')
except:
CAUTION = 'NULL'
try:
____URL = data['url']
____URL = ____URL.replace('http://','')
____URL = ____URL.replace('https://','')
#____URL = ____URL.replace('fbi','ibf')
except:
____URL = 'NULL'
PAYLOAD = "[{}/19] ::: NAME: {}, DOB: {}, POB: {}, HAIR: {}, EYES: {}, HEIGHT: {}, WEIGHT: {}, SEX: {}, RACE: {}, NATION: {}, REMARKS: {}, CAUTION: {}".format(i,___NAME,____DOB,____POB,___HAIR,___EYES,_HEIGHT,_WEIGHT,____SEX,___RACE,_NATION,REMARKS,CAUTION)
PCHUNKS = [l for l in iter(partial(StringIO(PAYLOAD).read, 445), '')]
for x in range(0,len(PCHUNKS)):
self.bot.privmsg(target,PCHUNKS[x])
msg = "URL: {}".format(____URL)
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)
url = "https://api.fbi.gov/wanted/v1/list"
asyncio.ensure_future(grab_url(url), loop=self.bot.loop).add_done_callback(process_lookups)

36
plugins/ip_plugin.py Normal file
View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import requests
import socket
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def ip(self, mask, target, args):
"""Show ip info
%%ip <ip>
"""
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using ip plugins')
return
ip = args.get('<ip>')
try:
socket.gethostbyname(ip)
except:
return
try:
r = requests.get('http://ipinfo.io/{}'.format(ip))
except:
return
d = r.json()
msg = "ip: {IP} city: {CITY} region: {REGION} country: {COUNTRY} org: {ORG}"
msg = msg.format(IP=d['ip'], CITY=d['city'], REGION=d['region'], COUNTRY=d['country'], ORG=d['org'])
self.bot.privmsg(target,msg)

62
plugins/isup_plugin.py Normal file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import random
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self,bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
def __isup(self,domain):
url = domain
if domain.lower().find('http://') == -1 and domain.lower().find('https://') == -1:
url = 'http://' + domain
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'
}
)
try:
print('trying domain: {}'.format(url))
response = urlopen(req,timeout=10).read().decode('utf-8')
except HTTPError as e:
msg = 'down -> could not complete the request. error code: {}'.format(e.code)
return msg
except URLError as e:
msg = 'down -> failed to reach the server. reason: {}'.format(e.reason)
return msg
else:
msg = 'up -> site is communicating'
return msg
@command(permission='view')
def isup(self, mask, target, args):
"""isup domain
%%isup <domain>
"""
domain = args.get('<domain>')
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using isup plugins')
return
self.bot.privmsg(target,self.__emoj("{} {}".format(domain,self.__isup(domain))))

22
plugins/log_sql_plugin.py Normal file
View File

@ -0,0 +1,22 @@
import irc3
channel = "#ScreenCrack"
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.NEW_NICK)
def new_nick(self, nick, new_nick):
self.bot.privmsg(channel, "\x02༺Nick Change༻\x0308\x0F\x0304 {}\x0F\x0303 ▶ \x0F\x0302{}\x0F\x0304 ፨ \x0F\x1D<{}>\x0F".format(nick.nick, new_nick, nick.host))
# Update new nick for autokick
if nick.nick in self.bot.auto_kick_list:
self.bot.auto_kick_list.remove(nick.nick)
self.bot.auto_kick_list.add(new_nick)
# Update new nick for ignore_list
if nick.lnick in self.bot.ignore_list:
self.bot.ignore_list.remove(nick.lnick)
self.bot.ignore_list.add(new_nick.lower())

74
plugins/lurkers_plugin.py Normal file
View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime, timedelta
from collections import Counter
from operator import itemgetter
from irc3.async import AsyncEvents
import irc3
import timeago
import dateutil.parser
import asyncio
import functools
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
return
@command(permission='staff')
def lurkers(self, mask, target, args):
"""Display users whom have not been seen...
%%lurkers
"""
self.bot.privmsg(target, "Finding the lurkers...")
async def do_whois(self, nick, sleep_duration):
asyncio.sleep(sleep_duration)
whois = await self.bot.whois(nick=nick)
return whois
def handle_lurkers(self, response):
"""Find Longest Idling user"""
print("FIN!!!")
idle_dict = {}
task_results, _ = response.result()
for task_result in task_results:
try:
idle = task_result.result().get('idle')
print(idle)
if idle:
idle_dict.update({str(task_result.result().get('nick')): int(idle)})
except:
continue
msg = ""
print("Sort!!!")
for nick, idle_time in sorted(idle_dict.items(), key=itemgetter(1), reverse=True)[:5]:
idle = timeago.format(timedelta(seconds=idle_time), datetime.now()).capitalize()
msg = msg + "{} {} | ".format(nick, idle)
print("Sort DONE!")
print(msg)
self.bot.privmsg(target, msg)
tasks = []
channel = self.bot.channels[target]
sleep_duration = 0 #len(channel)
count = 0
for count, nick in enumerate(channel):
if len(nick) == 0:
continue
if count % 5 == 0:
sleep_duration = sleep_duration + 3
tasks.append(asyncio.ensure_future(do_whois(self, nick, sleep_duration)))
print("Will sleep for: {}".format(sleep_duration))
task = self.bot.create_task(asyncio.wait(tasks))
task.add_done_callback(functools.partial(handle_lurkers, self))

26
plugins/mybot_plugin.py Normal file
View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.JOIN)
def say_hi(self, mask, channel, **kw):
"""Say hi when someone join a channel"""
if mask.nick != self.bot.nick:
self.bot.privmsg(channel, 'Hi %s!' % mask.nick)
else:
self.bot.privmsg(channel, 'Hi!')
@command(permission='view')
def echo(self, mask, target, args):
"""Echo
%%echo <message>...
"""
yield ' '.join(args['<message>'])

178
plugins/notes_plugin.py Normal file
View File

@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
from collections import Counter
import irc3
import uuid
import timeago
import dateutil.parser
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view', 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='view', public=True, show_in_help_list=True)
def note(self, mask, target, args):
"""list/write/del notes
%%note [<cmd>] [<operation>]
"""
cmd = args.get("<cmd>")
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using note plugins')
return
if not cmd:
msg = "Please specify read/write/delete/list"
msg = self.__emoj(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
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.__emoj(msg)
self.bot.privmsg(target, msg)
return
if note_uuid_hash == "*":
self.bot.db.setlist("notes", [])
msg = "All notes cleared!"
msg = self.__emoj(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.__emoj(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.__emoj(msg)
self.bot.privmsg(target, msg)
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.__emoj(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)
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.__emoj(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.__emoj(msg)
self.bot.privmsg(target, msg)
return
# Check for empty notes
if not any(note_name in d["uuid"] for d in note_list):
msg = "No notes with {} found".format(note_name)
msg = self.__emoj(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.__emoj(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.__emoj(msg)
self.bot.privmsg(target, msg)
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.__emoj(msg)
self.bot.privmsg(target, msg)

23
plugins/phone_plugin.py Normal file
View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import requests
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='staff')
def cid(self, mask, target, args):
"""Grab Caller ID for number
%%cid <number>
"""
number = args['<number>']
sid = os.environ.get("CNAME_SID")
token = os.environ.get("CNAME_TOKEN")
url = "https://api.opencnam.com/v3/phone/+{}?account_sid={}&auth_token={}".format(number, sid, token)
req = requests.get(url)
self.bot.privmsg(target, "CID: {}".format(req.text))

174
plugins/phuq_plugin.py Normal file
View File

@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
from time import time
import re
import ipdb
RE_URL = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
RE_NAME = re.compile('g1mp.tell\s(.+?)\s(.+)', re.IGNORECASE)
class PHUQ():
TEXT=[]
NICK=[]
FLAG=[]
TIME=[]
USER=[]
WHAT=[]
THEN=[]
NOPE=[]
def __init__(self):
return
def push(self,data,nick,flag,time):
print(f'pushed: {flag} {nick} {data} {time}')
self.TEXT=self.TEXT[-1:]+self.TEXT[:-1]
self.TEXT[0]=data
self.NICK=self.NICK[-1:]+self.NICK[:-1]
self.NICK[0]=nick
self.FLAG=self.FLAG[-1:]+self.FLAG[:-1]
self.FLAG[0]=flag
self.TIME=self.TIME[-1:]+self.TIME[:-1]
self.TIME[0]=time
def check(self,who):
for i,_ in enumerate(self.USER):
if _ == who:
print(f'{who} already blocked for {self.WHAT[i]} @ {self.THEN[i]} until {self.NOPE[i]}')
epoch_time = int(str(time()).split('.')[0])
if self.NOPE[i] < epoch_time:
print(f'{who} block time expired, releasing user from ignore')
self.USER[i]='????'
self.WHAT[i]='????'
self.THEN[i]='????'
self.NOPE[i]='????'
self.USER.remove('????')
self.WHAT.remove('????')
self.THEN.remove('????')
self.NOPE.remove('????')
return
else:
return
index = []
sflag = []
stime = []
print(f'{self.NICK} - {who}')
for i,_ in enumerate(self.NICK):
if _ == who:
index.append(i)
sflag.append(self.FLAG[i])
stime.append(self.TIME[i])
print(f'{i} - {self.FLAG[i]} - {self.TIME[i]}')
print(f'{index} - {sflag} - {stime}')
dcmd = 0
dbot = 0
durl = 0
for _ in sflag:
if _ == 'command': dcmd+=1
elif _ == 'name': dbot+=1
elif _ == 'url': durl+=1
print(f'cmd: {dcmd} - name: {dbot} - url: {durl}')
flags = { 'command': dcmd, 'name': dbot, 'url': durl }
key = max(flags, key=flags.get)
fcount = flags[key]
print(f'abuse_flag - {key}: {fcount}')
t=[]
for i,_ in enumerate(sflag):
if _ == key:
t.append(stime[i])
print(f'{i} - sflag: {_} - key: {key} - time: {stime[i]}')
tcount = len(set(t))
print(f'tcount: {tcount}')
if tcount >= 3:
if tcount != len(t):
if key == 'command':
hours=0; minutes=5;
ihours = hours * (60*60)
iminutes = minutes * 60
elif key == 'name':
hours=0; minutes=5;
ihours = hours * (60*60)
iminutes = minutes * 60
elif key == 'url':
hours=0; minutes=5;
ihours = hours * (60*60)
iminutes = minutes * 60
print(f'key: {key} - hours/minutes: {hours}/{minutes} - hours/minutes: {ihours}/{iminutes}')
epoch_time = int(str(time()).split('.')[0])
epoch_trigger = epoch_time + ihours + iminutes
TRAP=0
msg = ''
try:
for i, _ in enumerate(self.USER):
if _ == who:
self.WHAT[i] = key
self.THEN[i] = epoch_time
self.NOPE[i] = epoch_trigger
TRAP=1
msg = f'user: {who.lower()} for {key} at {epoch_time} until {self.NOPE[i]}'
print(f'user: {who.lower()} for {key} at {epoch_time} until {self.NOPE[i]}')
if TRAP==0:
self.USER.append(who.lower())
self.WHAT.append(key)
self.THEN.append(epoch_time)
self.NOPE.append(epoch_trigger)
msg = f'user: {who.lower()} for {key} at {epoch_time} until {epoch_trigger}'
print(f'user: {who.lower()} for {key} at {epoch_time} until {epoch_trigger}')
except:
self.USER.append(who.lower())
self.WHAT.append(key)
self.THEN.append(epoch_time)
self.NOPE.append(epoch_trigger)
msg = f'user: {who.lower()} for {key} at {epoch_time} until {epoch_trigger}'
print(f'exception: user: {who.lower()} for {key} at {epoch_time} until {epoch_trigger}')
return msg
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
self.bot.phuq=PHUQ()
for _ in range(25):
self.bot.phuq.TEXT.append('')
self.bot.phuq.NICK.append('')
self.bot.phuq.FLAG.append('')
self.bot.phuq.TIME.append('')
@irc3.event(irc3.rfc.PRIVMSG)
def phuq(self, mask=None, target=None, data=None, **kw):
if mask.nick.lower() == "g1mp" or mask.nick.lower() == 'nickserv': # Read nick from config in future...
return
flag = 'noise'
if data[0:1] == '?':
flag = 'command'
if data[0:2] == 's/'.lower():
flag = 'command'
match_list = RE_URL.findall(data)
read_size = 0
if match_list:
url = match_list.pop()
flag = 'url'
match_list = RE_NAME.findall(data)
read_size = 0
if match_list:
url = match_list.pop()
flag = 'name'
epoch_time = int(str(time()).split('.')[0])
self.bot.phuq.push(data.lower(),mask.nick.lower(),flag.lower(),epoch_time)
result=self.bot.phuq.check(mask.nick.lower())
#if result != '':
# self.bot.privmsg(target,result)

81
plugins/quote_plugin.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import irc3
import random
import ipdb
import uuid
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self,bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + ' \x02\x0303▶\x0F ' + emoj
return s
@irc3.event(irc3.rfc.JOIN)
def quote_user_join(self, mask, channel, **kw):
"""quote a user when they join"""
if mask.nick != self.bot.nick:
_UHOST = mask.host
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'] == mask.nick):
quote_user.append(quote_list[i]['message'])
if quote_user:
msg = mask.nick
msg = msg + ' \x02\x0303▶\x0F ' + random.choice(quote_user)
msg = self.__emoj(msg)
target = channel
self.bot.privmsg(target,msg)
def __quote(self,user,message):
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,
"message": message,
"uuid": quote_uuid}
quote_list.append(quote)
self.bot.db.setlist("quotes", quote_list)
msg = "TCPDIRECT/QUOTED: {} \x02\x0303▶\x0F {} \x02\x0303▶\x0F {}".format(user,message,quote_uuid)
return msg
except Exception as e:
return 'error: %s' % e.message[0]['message']
@command(permission='view')
def quote(self, mask, target, args):
"""quote user message
%%quote <noise>...
"""
noise = ' '.join(args['<noise>'])
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using quote plugins')
return
user = noise.split(' ')[0]
noise = noise.split(' ')[1:]
message = ' '.join(noise)
status = self.__quote(user,message)
msg = self.__emoj(status)
self.bot.privmsg(target,msg)

360
plugins/ratesex_plugin.py Normal file
View File

@ -0,0 +1,360 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
__doc__ = '''##########################################################################################################
####################################################################################################################'''
import os
import sys
import re
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
from random import randint
__doc__ = '''##########################################################################################################
#######################################################################################################################
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy` yMMMMMMMMMMMMMMM- -mMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMs+dMMMMMMMMMM+ sMMMMMMMMMMMMMMM- `dMMMMMMMMMMms/NMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMM+ .omMMMMMM: -MMMMMMMMMMMMMMo `yMMMMMMMy: `dMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMM- /dMMM+ sMMMMMMMMMMMMh `hMMMNo` sMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMd :dm `mMMMMMMMMMMN. .NNo` .MMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMM: - :MMMMMMMMMMs :` sMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMs ymNMMMMMNm. NMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMy `-/-` .MMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMo .NMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMNh+. :sdMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMhso+:. `-/+syMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMM- dMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMM` `.:+/. `/s+:. sMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMNo -oms. .//-` `:/:` `+md+` .hMMMMMMMMMMMMMMM
MMMMMMMMMMMMMNs` .odNdo. .ohmd+` :dMMMMMMMMMMMMM
MMMMMMMMMMMNo` .. .- :hMMMMMMMMMMM
MMMMMMMMMd+` -sNMMMMMMMM
MMMMMMNs- `.. `/-. `+dMMMMMM
MMMNy: ./sdNMMMh: `sNMMMNds/. .odMMM
MM+ :ymMMMMMMMMMMh. +NMMMMMMMMMMmo- /NM
MMMh: .sNMMMMMMMMMMMMMMN- `hMMMMMMMMMMMMMMMm+` :hMMM
MMMMMd:` ``-:+shmMMMMMMMMMMMMMMMMMMN. hMMMMMMMMMMMMMMMMMMMmhs+/-..``````./dMMMMM
MMMMMMMMMNNNNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMo .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN. /MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN+` `+NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs. -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMdyymMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
#######################################################################################################################
####################################################################################################################'''
rgb2irc = { 52: '16', 94: '17', 100: '18', 58: '19', 22: '20', 29: '21', 23: '22', 24: '23', 17: '24', 54: '25', 53: '26', 89: '27',
88: '28', 130: '29', 142: '30', 64: '31', 28: '32', 35: '33', 30: '34', 25: '35', 18: '36', 91: '37', 90: '38', 125: '39',
124: '40', 166: '41', 184: '42', 106: '43', 34: '44', 49: '45', 37: '46', 33: '47', 19: '48', 129: '49', 127: '50', 161: '51',
196: '52', 208: '53', 226: '54', 154: '55', 46: '56', 86: '57', 51: '58', 75: '59', 21: '60', 171: '61', 201: '62', 198: '63',
203: '64', 215: '65', 227: '66', 191: '67', 83: '68', 122: '69', 87: '70', 111: '71', 63: '72', 177: '73', 207: '74', 205: '75',
217: '76', 223: '77', 229: '78', 193: '79', 157: '80', 158: '81', 159: '82', 153: '83', 147: '84', 183: '85', 219: '86', 212: '87',
16: '88', 233: '89', 235: '90', 237: '91', 239: '92', 241: '93', 244: '94', 247: '95', 250: '96', 254: '97', 231: '98', }
__doc__ = '''##########################################################################################################
####################################################################################################################'''
rgb2set = { "ef0": "#000000", "ef1": "#CD0000", "ef2": "#00CD00", "ef3": "#CDCD00", "ef4": "#0000EE", "ef5": "#CD00CD", "ef6": "#00CDCD", "ef7": "#E5E5E5",
"ef8": "#7F7F7F", "ef9": "#FF0000", "ef10": "#00FF00", "ef11": "#FFFF00", "ef12": "#5C5CFF", "ef13": "#FF00FF", "ef14": "#00FFFF", "ef15": "#FFFFFF",
"eb8": "#7F7F7F", "eb9": "#FF0000", "eb10": "#00FF00", "eb11": "#FFFF00", "eb12": "#5C5CFF", "eb13": "#FF00FF", "eb14": "#00FFFF", "eb15": "#FFFFFF", "ef16": "#000000",
"ef17": "#00005f", "ef18": "#000087", "ef19": "#0000af", "ef20": "#0000d7", "ef21": "#0000ff", "ef22": "#005f00", "ef23": "#005f5f", "ef24": "#005f87", "ef25": "#005faf",
"ef26": "#005fd7", "ef27": "#005fff", "ef28": "#008700", "ef29": "#00875f", "ef30": "#008787", "ef31": "#0087af", "ef32": "#0087d7", "ef33": "#0087ff", "ef34": "#00af00",
"ef35": "#00af5f", "ef36": "#00af87", "ef37": "#00afaf", "ef38": "#00afd7", "ef39": "#00afff", "ef40": "#00d700", "ef41": "#00d75f", "ef42": "#00d787", "ef43": "#00d7af",
"ef44": "#00d7d7", "ef45": "#00d7ff", "ef46": "#00ff00", "ef47": "#00ff5f", "ef48": "#00ff87", "ef49": "#00ffaf", "ef50": "#00ffd7", "ef51": "#00ffff", "ef52": "#5f0000",
"ef53": "#5f005f", "ef54": "#5f0087", "ef55": "#5f00af", "ef56": "#5f00d7", "ef57": "#5f00ff", "ef58": "#5f5f00", "ef59": "#5f5f5f", "ef60": "#5f5f87", "ef61": "#5f5faf",
"ef62": "#5f5fd7", "ef63": "#5f5fff", "ef64": "#5f8700", "ef65": "#5f875f", "ef66": "#5f8787", "ef67": "#5f87af", "ef68": "#5f87d7", "ef69": "#5f87ff", "ef70": "#5faf00",
"ef71": "#5faf5f", "ef72": "#5faf87", "ef73": "#5fafaf", "ef74": "#5fafd7", "ef75": "#5fafff", "ef76": "#5fd700", "ef77": "#5fd75f", "ef78": "#5fd787", "ef79": "#5fd7af",
"ef80": "#5fd7d7", "ef81": "#5fd7ff", "ef82": "#5fff00", "ef83": "#5fff5f", "ef84": "#5fff87", "ef85": "#5fffaf", "ef86": "#5fffd7", "ef87": "#5fffff", "ef88": "#870000",
"ef89": "#87005f", "ef90": "#870087", "ef91": "#8700af", "ef92": "#8700d7", "ef93": "#8700ff", "ef94": "#875f00", "ef95": "#875f5f", "ef96": "#875f87", "ef97": "#875faf",
"ef98": "#875fd7", "ef99": "#875fff", "ef100": "#878700", "ef101": "#87875f", "ef102": "#878787", "ef103": "#8787af", "ef104": "#8787d7", "ef105": "#8787ff", "ef106": "#87af00",
"ef107": "#87af5f", "ef108": "#87af87", "ef109": "#87afaf", "ef110": "#87afd7", "ef111": "#87afff", "ef112": "#87d700", "ef113": "#87d75f", "ef114": "#87d787", "ef115": "#87d7af",
"ef116": "#87d7d7", "ef117": "#87d7ff", "ef118": "#87ff00", "ef119": "#87ff5f", "ef120": "#87ff87", "ef121": "#87ffaf", "ef122": "#87ffd7", "ef123": "#87ffff", "ef124": "#af0000",
"ef125": "#af005f", "ef126": "#af0087", "ef127": "#af00af", "ef128": "#af00d7", "ef129": "#af00ff", "ef130": "#af5f00", "ef131": "#af5f5f", "ef132": "#af5f87", "ef133": "#af5faf",
"ef134": "#af5fd7", "ef135": "#af5fff", "ef136": "#af8700", "ef137": "#af875f", "ef138": "#af8787", "ef139": "#af87af", "ef140": "#af87d7", "ef141": "#af87ff", "ef142": "#afaf00",
"ef143": "#afaf5f", "ef144": "#afaf87", "ef145": "#afafaf", "ef146": "#afafd7", "ef147": "#afafff", "ef148": "#afd700", "ef149": "#afd75f", "ef150": "#afd787", "ef151": "#afd7af",
"ef152": "#afd7d7", "ef153": "#afd7ff", "ef154": "#afff00", "ef155": "#afff5f", "ef156": "#afff87", "ef157": "#afffaf", "ef158": "#afffd7", "ef159": "#afffff", "ef160": "#d70000",
"ef161": "#d7005f", "ef162": "#d70087", "ef163": "#d700af", "ef164": "#d700d7", "ef165": "#d700ff", "ef166": "#d75f00", "ef167": "#d75f5f", "ef168": "#d75f87", "ef169": "#d75faf",
"ef170": "#d75fd7", "ef171": "#d75fff", "ef172": "#d78700", "ef173": "#d7875f", "ef174": "#d78787", "ef175": "#d787af", "ef176": "#d787d7", "ef177": "#d787ff", "ef178": "#d7af00",
"ef179": "#d7af5f", "ef180": "#d7af87", "ef181": "#d7afaf", "ef182": "#d7afd7", "ef183": "#d7afff", "ef184": "#d7d700", "ef185": "#d7d75f", "ef186": "#d7d787", "ef187": "#d7d7af",
"ef188": "#d7d7d7", "ef189": "#d7d7ff", "ef190": "#d7ff00", "ef191": "#d7ff5f", "ef192": "#d7ff87", "ef193": "#d7ffaf", "ef194": "#d7ffd7", "ef195": "#d7ffff", "ef196": "#ff0000",
"ef197": "#ff005f", "ef198": "#ff0087", "ef199": "#ff00af", "ef200": "#ff00d7", "ef201": "#ff00ff", "ef202": "#ff5f00", "ef203": "#ff5f5f", "ef204": "#ff5f87", "ef205": "#ff5faf",
"ef206": "#ff5fd7", "ef207": "#ff5fff", "ef208": "#ff8700", "ef209": "#ff875f", "ef210": "#ff8787", "ef211": "#ff87af", "ef212": "#ff87d7", "ef213": "#ff87ff", "ef214": "#ffaf00",
"ef215": "#ffaf5f", "ef216": "#ffaf87", "ef217": "#ffafaf", "ef218": "#ffafd7", "ef219": "#ffafff", "ef220": "#ffd700", "ef221": "#ffd75f", "ef222": "#ffd787", "ef223": "#ffd7af",
"ef224": "#ffd7d7", "ef225": "#ffd7ff", "ef226": "#ffff00", "ef227": "#ffff5f", "ef228": "#ffff87", "ef229": "#ffffaf", "ef230": "#ffffd7", "ef231": "#ffffff", "ef232": "#080808",
"ef233": "#121212", "ef234": "#1c1c1c", "ef235": "#262626", "ef236": "#303030", "ef237": "#3a3a3a", "ef238": "#444444", "ef239": "#4e4e4e", "ef240": "#585858", "ef241": "#626262",
"ef242": "#6c6c6c", "ef243": "#767676", "ef244": "#808080", "ef245": "#8a8a8a", "ef246": "#949494", "ef247": "#9e9e9e", "ef248": "#a8a8a8", "ef249": "#b2b2b2", "ef250": "#bcbcbc",
"ef251": "#c6c6c6", "ef252": "#d0d0d0", "ef253": "#dadada", "ef254": "#e4e4e4", "ef255": "#eeeeee", }
__doc__ = '''##########################################################################################################
####################################################################################################################'''
set2rgb = { 52: '#470000', 94: '#472100', 100: '#474700', 58: '#324700', 22: '#004700', 29: '#00472C', 23: '#004747', 24: '#002747', 17: '#000047', 54: '#2E0047', 53: '#470047', 89: '#47002A',
88: '#740000', 130: '#743A00', 142: '#747400', 64: '#517400', 28: '#007400', 35: '#007449', 30: '#007474', 25: '#004074', 18: '#000074', 91: '#4B0074', 90: '#740074', 125: '#740045',
124: '#B50000', 166: '#B56300', 184: '#B5B500', 106: '#7DB500', 34: '#00B500', 49: '#00B571', 37: '#00B5B5', 33: '#0063B5', 19: '#0000B5', 129: '#7500B5', 127: '#B500B5', 161: '#B5006B',
196: '#FF0000', 208: '#FF8C00', 226: '#FFFF00', 154: '#B2FF00', 46: '#00FF00', 86: '#00FFA0', 51: '#00FFFF', 75: '#008CFF', 21: '#0000FF', 171: '#A500FF', 201: '#FF00FF', 198: '#FF0098',
203: '#FF5959', 215: '#FFB459', 227: '#FFFF71', 191: '#CFFF60', 83: '#6FFF6F', 122: '#65FFC9', 87: '#6DFFFF', 111: '#59B4FF', 63: '#5959FF', 177: '#C459FF', 207: '#FF66FF', 205: '#FF59BC',
217: '#FF9C9C', 223: '#FFD39C', 229: '#FFFF9C', 193: '#E2FF9C', 157: '#9CFF9C', 158: '#9CFFDB', 159: '#9CFFFF', 153: '#9CD3FF', 147: '#9CD3FF', 183: '#DC9CFF', 219: '#FF9CFF', 212: '#FF94D3',
16: '#000000', 233: '#131313', 235: '#282828', 237: '#363636', 239: '#4D4D4D', 241: '#656565', 244: '#818181', 247: '#9F9F9F', 250: '#BCBCBC', 254: '#E2E2E2', 231: '#FFFFFF', }
__doc__ = '''##########################################################################################################
####################################################################################################################'''
@irc3.plugin
class Plugin:
__doc__ = ''' ##################################################################################################'''
def __init__(self, bot):
__doc__ = ''' ##############################################################################################'''
self.bot = bot
__doc__ = ''' ##############################################################################################'''
__doc__ = ''' ##################################################################################################'''
def ratesex_request(self,site,commands):
USER_AGENT_BROWSER="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
USER_AGENT_CURL="curl/7.29.0"
STATUS_BAD_CODE=":( - error code: {}"
STATUS_BAD_REASON=":( - failed reason: {}"
STATUS_OK=":)"
if site != 'rate':
url = f"https://{site}.rate.sx/{commands}"
else:
url = f"https://rate.sx/{commands}"
r = Request(url,data=None,headers={ 'User-Agent': USER_AGENT_CURL })
try:
response = urlopen(r,timeout=10).read().decode('utf-8')
except HTTPError as e:
return STATUS_BAD_CODE.format(e.code)
except URLError as e:
return STATUS_BAD_REASON.format(e.reason)
else:
return STATUS_OK + response
__doc__ = ''' ##################################################################################################'''
def escape_ansi(self,line):
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', str(line))
__doc__ = ''' ##################################################################################################'''
def invert_dict(self,d):
return {v: k for k, v in d.items()}
__doc__ = ''' ##################################################################################################'''
def enumerate_dict(self,d):
return list(zip(list(d),list(invert_dict(d)),range(len(d))))
__doc__ = ''' ##################################################################################################'''
def organize_dict(self,d):
_d=list(d.values())
return _d.sort()
__doc__ = ''' ##################################################################################################'''
def escape_ansi(self,line):
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', str(line))
__doc__ = ''' ##################################################################################################'''
def hex2gravity(self,h):
r,g,b=int(h[1:3],16),int(h[3:5],16),int(h[5:7],16)
o=list(set2rgb.values()); o.sort()
_R=[]; _G=[]; _B=[];
for _ in o:
R,G,B=(''.join([x for x in _[1:][:2]]).zfill(2)),(''.join([x for x in _[1:][2:4]]).zfill(2)),(''.join([x for x in _[1:][4:6]]).zfill(2))
_R.append(int(R,16)); _G.append(int(G,16)); _B.append(int(B,16));
_r = []
for _ in _R:
if r < _:
rsub = _ - r
else:
rsub = r - _
_r.append(rsub)
_g = []
for _ in _G:
if g < _:
gsub = _ - g
else:
gsub = g - _
_g.append(gsub)
_b = []
for _ in _B:
if b < _:
bsub = _ - b
else:
bsub = b - _
_b.append(bsub)
rgb = []
for _ in range(len(_r)):
rgb.append(_r[_]+_g[_]+_b[_])
nearest_color_minus = min(rgb)
nearest_color_index = [i for i, x in enumerate(rgb) if x == nearest_color_minus]
nearest_color = o[nearest_color_index[0]]
return str(f"\x03{rgb2irc[self.invert_dict(set2rgb)[nearest_color]]}")
__doc__ = ''' ##################################################################################################'''
def parse_control(self,s):
px=[]
py=[]
_s=s
px=self.findall(_s,'\x1b')
for i,_ in enumerate(px):
py.append( _s.find('m',_)+1 )
return px,py
__doc__ = ''' ##################################################################################################'''
def findall(self,s,w):
return [i for i in range(len(s)) if s.startswith(w, i)]
__doc__ = ''' ##################################################################################################'''
def color_line(self,s,t):
codes=["\x1b[0m","\x1b[30m","\x1b[31m","\x1b[32m","\x1b[33m","\x1b[34m","\x1b[35m","\x1b[36m","\x1b[37m","\x1b[40m","\x1b[41m","\x1b[42m","\x1b[43m","\x1b[44m","\x1b[45m","\x1b[46m","\x1b[47m","\x1b(B","\x1b[m","\x1b[2m"]
colors=["\x0f","\x0301","\x0304","\x0303","\x0308","\x03002","\x0313","\x0311","\x0300","\x03,01","\x03,04","\x03,03","\x03,08","\x03,02","\x03,13","\x03,11","\x03,00","","\x0f",""] #f.write('\x0301,00decoded\n')
_s=s
p=[]
for _ in range(len(t[0])):
r=self.findall(s[t[0][_]:t[1][_]],'\x1b')
for __ in range(len(r)):
if not __ == len(r)-1:
p.append(s[t[0][_]:t[1][_]][r[__]:r[__+1]])
else:
check = s[t[0][_]:t[1][_]][r[__]:]
if check.find('mm') == -1:
p.append(check)
else:
p.append(check[:-1])
for __ in p:
_s = _s.replace(__,"{}")
c=[]
for _ in p:
for i,__ in enumerate(codes):
if _ == __:
c.append(colors[i])
if _.find('\x1b[38;5;') != -1:
gravity = _.replace('\x1b[38;5;','')[:-1]
farthest_color_hex = rgb2set['ef{}'.format(gravity)]
result = self.hex2gravity(farthest_color_hex)
c.append(result)
r=self.findall(_s,'{}')
for _ in range(len(r)):
_s=_s.replace('{}',c[_],1)
return _s
__doc__ = ''' ##################################################################################################'''
@command(permission='view')
def ratesex(self, mask, target, args):
"""ratesex - help/commands: visit 'https://rate.sx/:help' or try '?ratesex rate :help', to check exchange rates for top 10 ^cripdoeocurrencies try '?ratesex rate top10.. sites added. rate,eur,btc,rub.. e.g. ?ratesex rate command, ?ratesex eur, ?ratesex btc, ?ratesex rub'
%%ratesex [<site>] [<command>]
"""
site = args.get("<site>")
command = args.get("<command>")
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using ratesex plugins')
return
if command == "":
msg="error: no command issued.. ?ratesex rate, ?ratesex rate eth, ?ratesex rate :help, ?ratesex btc top10"
self.bot.privmsg(target, msg)
sites=['rate','rub','eur','btc']
FLAG=0
for _ in sites:
if site == _:
FLAG=1
if not FLAG==1:
msg="error: no site issued. sites: rate,rub,eur,btc. e.g. ?ratesex rate :help, ?ratesex btc top10, ?ratesex rub top10"
self.bot.privmsg(target, msg)
if command.lower() == 'top10': command = ''
response=self.ratesex_request(site,command)
s = ''
for _ in response:
s = s + ''.join(_)
r1=s[2:].splitlines()
for i in range(len(r1)-1):
d=self.parse_control(r1[i])
r=self.color_line(r1[i],d)
if not r == '':
msg = r+'\n'
self.bot.privmsg(target, msg)
__doc__ = ''' ##################################################################################################'''
__doc__ = ''':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.
/mMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNd-
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN`
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmNMMMMMMMMMMMmMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh:NMMMMMMMMMMoyMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm -NMMMMMMMMMs.NMMMMMMMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy -hmmmmmNNm- sMMMMMMMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmdyo+:` ```````.` .NMMMymMMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmy+-.` -hNm-+MMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMms:` `.. /MMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh/. /MMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMmMMMMMMMMMMMmhN:` /MMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMM+sNMMMMMMMMMN-h: `-+syyys/- -NMMMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMs +NMMMMMMMhm--d` :. -sdNMMMMMNNmy. :ydMMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMMMM+ :yhyyyhhso` os yhshNMMMMMMMh+:-:. :s- .NMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMMMMmho` ` `yo.h:sMMMMMMMMMMNd+. -NNs- yMMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMMMNh/. :++`-MMMMMMMMMMMMMm+` :ymds. -NMMMMMMMMMMMMMMMM-
/MMMMMMMMMMMmo- .MMMMMMMMMMMMMMMdo. `.-` yMMMMMMMMMMMMMMMM-
/MMMMMMMMMmo. `NMMMMMMMMMMMMMMMMNy/.` `mMMMMMMMMMMMMMMM-
/MMMMMMMNs. hMMMMMMMMMMMMMMMMMMMNho-` :NMMMMMMMMMMMMMM-
/MMMMMMm: ./syyyo- -hmNMMMMMMMMMMMMMMMMMMMMmho:.` /NMMMMMMMMMMMMM-
/MMMMMd. .smMMMNNNms` ` `+MMMMMMMMMMMMMMMMMMMMMMMMNdy/ `.yMMMMMMMMMMMMM-
/MMMMd. /mMMMMMy/:--` so. `mMMMMMMMMMMMMMMMMMMMMMMMNdo--:+sdNMMMMMMMMMMMMMM-
/MMMN- /NMMMMMMMMdo. oMm+. /MMMMMMMMMMMMMMMMdNMMMMMMNNNMMmMMMMMMMMMMMMMMMMM-
/MMMo -NMMMMMMMMMMdso-` /hmm+ sMMMMMMMMMMMMMMMs-mMMMMMMMMMM:dMMMMMMMMMMMMMMMM-
/MMN. sMMMMMMMMMMMo .os/.``.. `dMMMMMMMMMMMMMMs -NMMMMMMMMM-:MMMMMMMMMMMMMMMM-
/MMd mMMMMMMMMMMM/ `:os+-` .dMMMMMMMMMMMNm. -soosyhdms `mMMMMMMMMMMMMMMM-
/MMs mMMMMMMMMMMM: .hNhs/.` .dMMMMNmhs+:-` +MMMNoMMMMMMMMMM-
/MMy hMMMMMMMMMMM: oMMMMMNdyo/. .mNh+-` +mNy`mMMMMMMMMM-
/MMd +MMMMMMMMMMM/ :MMMMMMMMNs.`.:ohh/` ` mMMMMMMMMM-
/MMN. `mMMMMMMMMMMo `NMMMMMMNhhdNMMh: mMMMMMMMMM-
/MMM+ /MMMMMMMMMMh yMMMMMMMMMMMN+ `NMMMMMMMMM-
/MMMm` +MMMMMMMMMN` .NMMMMMMMMMN- :sdmNNNdy+` dMMMMMMMMM-
/MMMMo +MMMMMMMMM+ +MMMMMMMMM/ -dMMMMMMNmmNN/ .sdMMMMMMM-
/MMMMN: :mMMMMMMMm` oMMMMMMMh .mMMMMMMMms- `` /o` `mMMMMMM-
/MMMMMm. .yMMMMMMMo oMMMMMM/ sMMMMMMMMMMMh: :NNo. sMMMMMM-
/MMMMMMm. -hMMMMMN: /NMMMM. dMMMMMMMMMMMMMh- :hmNy` .NMMMMM-
/MMMMMMMm- -yNMMMm. .yMMM. dMMMMMMMMMMMMMMNh:` `..` yMMMMM-
/MMMMMMMMN+ .+hNMd. :hM: dMMMMMMMMMMMMMMMMNmo- .NMMMM-
/MMMMMMMMMMh- ./ss. `:: sMMMMMMMMMMMMMMMMMMMNms/. /MMMM-
/MMMMMMMMMMMNo. ` :MMMMMMMMMMMMMMMMMMMMMMMNdo:.` oMMM-
/MMMMMMMMMMMMMmo. `mMMMMMMMMMMMMMMMMMMMMMMMMMMNmh: .dMM-
/MMMMMMMMMMMMMMMNy:` +MMMMMMMMMMMMMMMMMMMMMMMMMMNh+::/+sdNMMM-
/MMMMMMMMMMMMMMMMMNdo- `dMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNMMMMMMMM-
/MMMMMMMMMMMMMMMMMMMMNd+-` -NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-
-NMMMMMMMMMMMMMMMMMMMMMMNdo:` /NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMd`
-ymNNNNNNNNNNNNNNNNNNNNNNNNdo-` +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNmy.
............................ .-...............................`
`````` ````````` `````````````` `````````` ```'''

53
plugins/recluse_plugin.py Normal file
View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
from collections import Counter
import irc3
import timeago
import dateutil.parser
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
return
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='staff')
def recluse(self, mask, target, args):
"""Display users whom have not been seen...
%%recluse
"""
# Need to improve this in future...
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using recluse plugins')
return
nick_list = []
channel = self.bot.channels[target]
for nick in list(channel):
if len(nick) == 0:
continue
key = "last_msg_for_{}".format(nick).lower()
message_list = self.bot.db.getlist(key)
if not message_list:
nick_list.append(nick)
msg = ", ".join(nick_list)
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)
return

126
plugins/remind_plugin.py Normal file
View File

@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
from datetime import datetime
from time import time
import re
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
REMIND_RE = re.compile('g1mp.remind\s(.+?)\s(.+)')
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
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):
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using url plugins')
return
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 g1mp remind ircnick in 2h15m to pet cat, or g1mp remind me in 1h to pet cat.".format(mask.nick)
self.bot.privmsg(target, self.__emoj(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 g1mp remind ircnick in 2h15m to pet cat, or g1mp remind me in 1h to pet cat.".format(mask.nick)
self.bot.privmsg(target, self.__emoj(irc_message))
return
iminutes = minutes * 60
except:
irc_message = "TCPDIRECT/REMIND: reminding {} to go and fuck themself err i mean, format is g1mp remind ircnick in 2h15m to pet cat, or g1mp remind me in 1h to pet cat.".format(mask.nick)
self.bot.privmsg(target, self.__emoj(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 g1mp remind ircnick in 2h15m to pet cat, or g1mp remind me in 1h to pet cat.".format(mask.nick)
self.bot.privmsg(target, self.__emoj(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.__emoj(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)

155
plugins/rip_plugin.py Normal file
View File

@ -0,0 +1,155 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import re
import sys
import requests
import pycurl
import random
from io import BytesIO
import ipdb
dir_path = os.path.dirname(os.path.realpath(__file__))
lok='X-RapidAPI-Key'
key='e0d6e2bc89msh93a93ad59d66ec6p1cbb1fjsn3ad71cc26a8b'
api="https://getvideo.p.rapidapi.com/?url={}"
ALPHANUM = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
SCRAMBLE = ''.join(random.sample(ALPHANUM,len(ALPHANUM)))
LOGFILE = '{}.txt'.format(SCRAMBLE)
URL_REGEX = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
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
def __space(self,s,n):
if(len(s)<n):
s = s + ' ' * int(n-len(s))
return s
def __write(self,s):
l = open(LOGFILE, 'a')
l.write("{}\n".format(s))
l.close()
@command(permission='view')
def rip(self, mask, target, args):
"""rip link
%%rip <url>
"""
#ipdb.set_trace()
url = args.get('<url>')
match_list = URL_REGEX.findall(url)
if match_list:
url = match_list[0]
else:
msg = self.__emoj('no valid url found to process')
self.bot.privmsg(target,msg)
return
l = []
l.append(match_list[0].find('youtube.com/'))
l.append(match_list[0].find('youtu.be/'))
l.append(match_list[0].find('soundcloud.com/'))
l.append(match_list[0].find('bandcamp.com/'))
if(l[0] <0 and l[1] <0 and l[2] <0 and l[3] <0 and l[4] <0):
msg = self.__emoj('not a validated domain/link. validated domain(s): youtube,youtu.be,soundcloud,bandcamp')
self.bot.privmsg(target,msg)
return
try:
os.remove(LOGFILE)
except:
pass
r = requests.get(api.format(url),headers={lok:key,"Accept": "text/plain"})
if not(r.json()['status']):
msg = self.__emoj(r.json()['message'])
self.bot.privmsg(target,msg)
return
if(r.json()['is_playlist']):
msg = self.__emoj('this is a playlist, not a song')
self.bot.privmsg(target,msg)
return
self.__write('R1P//G1MP')
self.__write('\n---------\n')
self.__write('__SOURCE: {}'.format(url))
self.__write('___TITLE: {}'.format(r.json()['title']))
m, s = divmod(r.json()['duration'],60)
self.__write('DURATION: {}m{}s'.format(m,s))
self.__write('\n---------\n')
for i in r.json()['streams']:
urlz = i['url']
u = self.__get_tiny_url(urlz)
f = i['format'] #format e.g. 640x360 (medium)
e = i['extension'] #extension e.g. mp4
v = i['video_codec'] #video_codec e.g. avc1.42001E
try:
a = i['audio_codec'] #audio_codec e.g. mp4a.40.2
except:
a = '?????'
s = i['filesize_pretty'] #filesize e.g. 17.89 MB
if(s=='-'):
s = '?????'
ba = i['has_audio'] #has_audio e.g. True
bv = i['has_video'] #has_video e.g. False
f = self.__space(f,17)
e = self.__space(e,4)
v = self.__space(v,13)
a = self.__space(a,9)
s = self.__space(s,10)
ba = self.__space(str(ba),5)
bv = self.__space(str(ba),5)
msg = "URL: {} FORMAT: {} EXTENSION: {} VCODEC: {} ACODEC: {} FILESIZE: {} HAS_AUDIO: {} HAS_VIDEO: {}"
msg = msg.format(u,f,e,v,a,s,ba,bv)
self.__write(msg)
try:
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL,'https://0x0.st')
c.setopt(c.POST, 1)
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.HTTPPOST, [('file', (c.FORM_FILE, LOGFILE))])
c.perform()
c.close()
body = buffer.getvalue()
except:
pass
try:
os.remove(LOGFILE)
except:
pass
msg = self.__emoj(body.decode('ascii').replace('\n',''))
self.bot.privmsg(target,msg)

105
plugins/sed_plugin.py Normal file
View File

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import os
import random
import ipdb
from string import ascii_lowercase as alpha
dir_path = os.path.dirname(os.path.realpath(__file__))
SED1_RE = "sed s/"
SED2_RE = "s/"
import ipdb
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
def __emoj(self,s):
emote_db = '%s/../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
@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
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using sed plugins')
return
flag=0
offset = -1
offset = data.find(SED1_RE)
if not offset == 0:
offset = data.find(SED2_RE)
if offset == 0:
flag=1
if flag==0:
self.d.push(data,mask.nick)
return
_data=data.split('/')
_from=''
_to=''
_mode=''
try:
_from=_data[1]
_to=_data[2]
if len(_data) == 4:
if _data[3].lower() == 'g': _mode='g'
except Exception as e:
irc_message = f'TCPDIRECT/SED - Error: {e}'
self.bot.privmsg(target, self.__emoj(irc_message))
return
itwist=-1
count=0
for i,_ in enumerate(self.d.buffer_text):
if not _ == '':
itwist=i
count = len([_i for _i in range(len(_)) if _.startswith(_from, _i)])
if count == 1:
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to)
break
elif count > 1:
if _mode == 'g':
for y in range(count):
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to)
break
else:
self.d.buffer_text[i] = self.d.buffer_text[i].replace(_from,_to,1)
break
if count != 0:
irc_message = "{}: {}".format(self.d.buffer_nick[itwist],self.d.buffer_text[itwist])
else:
irc_message = f"TCPDIRECT/SED - Error: no result for: {data}"
self.bot.privmsg(target, self.__emoj(irc_message))

107
plugins/seen_plugin.py Normal file
View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
from collections import Counter
import operator
import irc3
import timeago
import dateutil.parser
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
return
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@irc3.event(irc3.rfc.NEW_NICK)
def on_nick_change_for_seen(self, nick, new_nick):
new_key = "last_msg_for_{}".format(new_nick).lower()
msg_list = self.bot.db.getlist(new_key)
if not msg_list:
msg_list = []
seen_msg = { "type": "newnick",
"time": datetime.now().isoformat(),
"msg": "{} changed nick to {}".format(nick.nick, new_nick)}
msg_list.append(seen_msg)
self.bot.db.setlist(new_key, msg_list)
return
@irc3.event(irc3.rfc.PRIVMSG)
def on_privmsg_for_seen(self, mask=None, target=None, data=None, **kw):
if data.startswith("?"): return # no ?
if mask.lnick == self.bot.get_nick().lower(): return # Ignore ourseves
key = "last_msg_for_{}".format(mask.nick).lower()
priv_msg = { "type": "privmsg",
"time": datetime.now().isoformat(),
"msg": data }
messages = self.bot.db.getlist(key)
if not messages:
messages = []
else:
# May be slow
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>")
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using seen plugins')
return
if nick.lower() == self.bot.get_nick().lower():
msg = "please don't spy on me..."
msg = self.__emoj(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.__emoj(msg)
self.bot.privmsg(target, msg)
else:
msg = "{} Has Not Been Seen".format(nick)
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)
return

55
plugins/shodan_plugin.py Normal file
View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import datetime
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import ipdb
import lxml
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def shodan(self, mask, target, args):
"""Show SHODAN Open Ports
%%shodan <ip>
"""
ip = args.get("<ip>")
try:
ipaddress.ip_address(ip)
except:
self.bot.privmsg(target,'invalid ip address')
exit
async def fetch(session, url):
async with async_timeout.timeout(10):
async with session.get(url) as response:
return await response.text()
async def grab_url(url):
async with aiohttp.ClientSession() as session:
response = await fetch(session, url)
return response # it's still in this await so i think we gotta access it after it runs the tasks
def process_lookups(response):
html = response.result()
dom = lxml.html.fromstring(html)
dns = dom.xpath('/html/body/div[3]/div/div[2]/div/div[1]/div[1]/h2/small')[0].text
ports = [ item.text_content() for item in dom.xpath('/html/body/div[3]/div/div[2]/div/div[2]/ul[1]')[0].getchildren() if item]
for i in range(0,len(ports)):
ports[i] = ports[i].replace('\n','')
# ipdb.set_trace()
self.bot.privmsg(target,"ip: {} ::: dns: {} ::: ports: {}".format(ip,dns,",".join(ports)))
# task_result, fu = response.result()
# self.bot.privmsg(target,"URL: {}".format(____URL))
url = "https://www.shodan.io/host/{}".format(ip) # shodan.io/host/1.1.1.1
asyncio.ensure_future(grab_url(url), loop=self.bot.loop).add_done_callback(process_lookups)

View File

@ -0,0 +1,97 @@
# Pastebin lzlssqMI
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
from urllib.parse import quote_plus
import os
import sys
import random
import html
import requests
from lxml.html import fromstring
dir_path = os.path.dirname(os.path.realpath(__file__))
import ipdb
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
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>...
"""
query = ' '.join(args['<query>'])
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using sc plugins')
return
result=self.__soundcloud__request('search',query)
pop=[]; _path=[];_name=[];
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])
title=''
try:
url=f'https://soundcloud.com/{_path[0]}'
try:
read_size = 0
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
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
title = title.split('|')[0].split('by')[-1].strip()
msg="\x02\x0302{NICK}\x0F\x02\x0304 ▶ \x0F\x02\x0313{NAME}\x0F\x02\x0304 ▶ \x0F\x02\x0312https://soundcloud.com/{PATH}\x0F\x02\x0313\x0F\x02\x0304 ▶ \x0F\x1D\x0314{TITLE}\x0F\x02\x0304 ".format(NICK=mask.nick,NAME=html.unescape(_name[0]),PATH=_path[0],TITLE=title)
except:
msg="\x02\x0302{NICK}\x0F\x02\x0304 ▶ \x0F\x02\x0313no result\x0F\x02\x0304 ".format(NICK=mask.nick,)
self.bot.privmsg(target,self.__emoj(f"{msg}"))

51
plugins/stalk_plugin.py Normal file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import twitter
import irc3
import os
import random
import ipdb
dir_path = os.path.dirname(os.path.realpath(__file__))
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']
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
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
def __stalk(self,screen_name):
try:
id = twitter.GetUser(screen_name=screen_name).id
statuses = twitter.GetUserTimeline(id)
return statuses
except Exception as e:
return 'error: %s' % e.message[0]['message']
@command(permission='admin')
def stalk(self, mask, target, args):
"""stalk screen_name
%%stalk <screen_name> <msg_index>
"""
screen_name = args.get('<screen_name>')
msg_index = args.get('<msg_index>')
statuses = self.__stalk(screen_name)
msg = self.__emoj(str(statuses[int(msg_index)]))
self.bot.privmsg(target,msg)

104
plugins/strain_plugin.py Normal file
View File

@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import requests
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def _get_weed(self,t,s):
try:
url=""
if t == "search":
s = s.lower().replace(' ','-')
url = 'https://api.wikileaf.com/api/v7/search/all/?type=S&num=24&offset=0&sort=popular&query={}'.format(s)
if t == "review":
url = 'https://api.wikileaf.com/api/v6/reviews/?content_type__model=strain&object_id={}'.format(s)
r = requests.get(url)
try:
if r.json()['detail'] == 'Not found.':
return 'Not Found.'
except:
return r.json()
except:
return -1
@command(permission='view')
def strain(self, mask, target, args):
"""strain
%%strain <message>...
"""
try:
msg = ' '.join(args['<message>'])
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using strain plugins')
return
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)
# r = requests.get(url)
# x = r.text.find('"description":')+16
# y = r.text.find('"aggregateRating":')
# a = r.text[x:y].replace('<p>','').replace('</p>','').replace('\\r','').replace('\\n','').replace('\n','').strip()
# b = a[:a.find("<a href")]
# c = a[a.find("</a>")+4:]
# msg = b + c
# width = 444
# chunks = [msg[i:i+width] for i in range(0, len(msg), width)]
# for _ in chunks:
# self.bot.privmsg(target, _)
except:
pass
except:
msg = "strain: not found"
self.bot.privmsg(target, msg)

221
plugins/sw33t_plugin.py Normal file
View File

@ -0,0 +1,221 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# sweet_plugin
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import os
import re
import irc3
import random
import requests
import twitter
import twitter
from lxml.html import fromstring
from difflib import SequenceMatcher
import ipdb
dir_path = os.path.dirname(os.path.realpath(__file__))
URL_REGEX = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
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']
twitter = twitter.Api(consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET,
access_token_key=ACCESS_TOKEN_KEY, access_token_secret=ACCESS_TOKEN_SECRET)
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
TARGET = '#b0ts3x'
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
@irc3.plugin
class Plugin:
def __init__(self,bot):
self.bot = bot
@irc3.extend
def _emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@irc3.extend
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
@irc3.extend
def _similar(self, a, b):
return SequenceMatcher(None, a, b).ratio()
@irc3.extend
def _check_for_url(self, msg, unrolled, twext, target):
match_list = URL_REGEX.findall(msg)
read_size = 0
if match_list:
url = match_list.pop()
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
# Ignore Non text/html
if not content_type.startswith("text/html"):
return
# Ignore Large Content
if int(content_length) > 200000:
self.bot.privmsg(target, "Fuck your large ass content")
# 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:
#ipdb.set_trace()
title = title.text.strip()[:100]
similarity = self.bot._similar(title,twext)
#ipdb.set_trace()
if( not unrolled.find('https://twitter.com/') == -1 ):
return
if( similarity > 0.4):
#self-reference escape
#self.bot.privmsg(target, self.__emoj('trapped self-reference escape // similarity ratio: {}'.format(similarity)) )
return
#if( title.find(twext[0:70]) > 0 ):
#self-reference escape
# return
# Comment out Tiny URL
#url = archiveis.capture(url)
msg = "\x02{nick:}\x0F\x02\x0303 ▶ \x0F\x02\x0312{url:}\x0F\x0303 ▶ {unrolled:}\x0F\x1D\x0314{title:}\x0F".format(nick='UNROLLED',url=url,unrolled=unrolled,title=title)
msg = self.bot._emoj(msg)
self.bot.privmsg(target, msg)
return
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass
@cron('* * * * *')
def _phuq(bot):
self = bot
users = [
's3kur1ty',
'notdan',
'_mg_',
'thugcrowd'
]
# get tweets
statuses = []
sdb = {}
for i in users:
statuses.append( twitter.GetUserTimeline( twitter.GetUser(screen_name=i).id, exclude_replies=True ) )
for i in range(len(statuses)):
sdb.update({ statuses[i][0].user.screen_name:statuses[i][0].text })
# check db for previous smeets
try:
#ipdb.set_trace()
smeet_list_original = bot.db.getlist("smeets")
if not smeet_list_original:
smeet_list_original = []
smeet_list_original.append("")
smeet_list = []
bot.db.setlist('smeets',[])
id = twitter.VerifyCredentials()
t = twitter.GetMentions(id.id)
t = twitter.GetStatus(t[0].in_reply_to_status_id)
_tag = t.in_reply_to_screen_name
_tid = t.id
_txt = t.text
while t.in_reply_to_status_id:
tid = t.in_reply_to_status_id
t = twitter.GetStatus(tid)
smeet = { 'tag' : _tag, # original tagger
'txt': _txt, # original tagger text
'tid': _tid, # status id to original tagger
'bxt': t.text, # text of base tweet from recursion
'bag': t.user.screen_name, # screen_name of base tweet from recursion
'bid': t.id } # status id of base tweet from recursion
if(smeet_list_original[0] == smeet):
smeet_list.append(smeet_list_original[0])
else:
smeet_list.append(smeet)
turl = 'https://twitter.com/{}/status/{}'.format(t.user.screen_name,t.id)
if _txt:
msg = "@{}{} ▶ @{}{}{}".format( _tag, _txt, t.user.screen_name, t.text, turl )
else:
msg = "@{} ▶ @{}{}{}".format( _tag, t.user.screen_name, t.text, turl )
msg = bot._emoj(msg)
bot.privmsg(TARGET,msg)
match_list = URL_REGEX.findall(t.text)
try:
if(match_list):
for m in match_list:
url = irc3.urlopen(m)
bot._check_for_url(m, url.url, t.text, TARGET)
except:
pass
bot.db.setlist("smeets", smeet_list)
except:
pass
# check db for previous tweets
try:
sweet_list_original = bot.db.getlist("sweets")
if not sweet_list_original:
sweet_list_original = []
for i in users:
sweet_list_original.append("")
sweet_list = []
bot.db.setlist('sweets',[])
for i in range(len(statuses)):
sweet = { 'screen_name' : statuses[i][0].user.screen_name,
'text': statuses[i][0].text,
'created_at_in_seconds': statuses[i][0].created_at_in_seconds }
if(sweet_list_original[i] == sweet):
sweet_list.append(sweet_list_original[i])
else:
sweet_list.append(sweet)
source = statuses[i][0].source[statuses[i][0].source.find('>')+1:statuses[i][0].source.rfind('<')]
screen_name = statuses[i][0].user.screen_name
text = statuses[i][0].text
text = statuses[i][0].text.replace('&amp;','&').replace('&lt;','<').replace('&gt;','>')
sext = text[:text.find('https:')]
sext = sext.rstrip()
turl = 'https://twitter.com/{}/status/{}'.format(statuses[i][0].user.screen_name,statuses[i][0].id_str)
# turl = bot._get_tiny_url(turl)
#ipdb.set_trace()
msg = '@{} via {}{}{}'.format(screen_name,source,sext,turl)
msg = bot._emoj(msg)
bot.privmsg(TARGET,msg)
match_list = URL_REGEX.findall(text)
try:
if(match_list):
for m in match_list:
url = irc3.urlopen(m)
bot._check_for_url(m, url.url, text, target)
except Exception as e:
pass
#bot.privmsg(target,'wu/tang: {}'.format(e))
bot.db.setlist("sweets", sweet_list)
except:
bot.privmsg(TARGET,'sweet error')

318
plugins/sweet_plugin.py Normal file
View File

@ -0,0 +1,318 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# sweet_plugin
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import os
import re
import irc3
import random
import requests
import twitter
from lxml.html import fromstring
from difflib import SequenceMatcher
import urllib.request
import pycurl
from io import BytesIO
from random import choices
dir_path = os.path.dirname(os.path.realpath(__file__))
URL_REGEX = re.compile('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE)
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']
twitter = twitter.Api(consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET,
access_token_key=ACCESS_TOKEN_KEY, access_token_secret=ACCESS_TOKEN_SECRET)
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
TARGET = '#tcpdirect'
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
@irc3.plugin
class Plugin:
def __init__(self,bot):
self.bot = bot
@irc3.extend
def _emoj(self,s):
emote_db = '%s/../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 + ' \x02\x0303▶\x0F ' + emoj
return s
@irc3.extend
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
@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{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)
#try:
# _mask = irc3.utils.IrcString
# _mask.nick = d_nick
# self.bot.asciimg(_mask,d_target,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(m_murl), '<x>': '100', 'asciimg': True})
#except:
# pass
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._emoj(msg)
self.bot.privmsg(d_target, msg)
return
except Exception as e:
msg = "wu/tang >>>>>>>>>>> sub-unrolling: {}".format(e)
msg = self.bot._emoj(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{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ [media] {media:} \x0F".format(nick1=d_nick,nick2='UNROLLED',media=d_unrolled)
msg = self.bot._emoj(msg)
self.bot.privmsg(d_target, msg)
#try:
# _mask = irc3.utils.IrcString
# _mask.nick = d_nick
# self.bot.asciimg(_mask,d_target,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(m_murl), '<x>': '100', 'asciimg': True})
#except:
# pass
return
# Ignore Non text/html
if not content_type.startswith("text/html"):
return
# Ignore Large Content
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{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ \x0F\x02\x0312{url:}\x0F\x0303 ▶▶ {unrolled:} ▶▶ \x0F\x1D\x0314{title:}\x0F".format(nick1=d_nick,nick2='UNROLLED',url=d_url,unrolled=d_unrolled,title=title)
msg = self.bot._emoj(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
@cron('* * * * *')
def _phuq(bot):
self = bot
users = [
'tcpdirect',
'yunginnanet',
'vxunderground',
'ircdchat'
]
# get tweets
statuses = []
sdb = {}
try:
for i in users:
try:
statuses.append( twitter.GetUserTimeline( twitter.GetUser(screen_name=i).id, exclude_replies=True ) )
except:
bot.privmsg(TARGET,'sweet_1: error: {} -> skip'.format(i))
pass
for i in range(len(statuses)):
try:
sdb.update({ statuses[i][0].user.screen_name:statuses[i][0].text })
except:
bot.privmsg(TARGET,'sweet_2: error: {} -> skip'.format(i))
except Exception as e:
bot.privmsg(TARGET,'sweet_0: error: {}'.format(e))
return
# check db for previous smeets
try:
smeet_list_original = bot.db.getlist("smeets")
if not smeet_list_original:
smeet_list_original = []
smeet_list_original.append("")
smeet_list = []
bot.db.setlist('smeets',[])
id = twitter.VerifyCredentials()
t = twitter.GetMentions(id.id)
_t = t[0]
t = twitter.GetStatus(t[0].in_reply_to_status_id)
_tag = _t.user.screen_name
_tid = _t.id
_txt = _t.text[_t.text.find('@s3kur1ty')+10:]
while t.in_reply_to_status_id:
tid = t.in_reply_to_status_id
t = twitter.GetStatus(tid)
smeet = { 'tag' : _tag, # original tagger
'txt': _txt, # original tagger text
'tid': _tid, # status id to original tagger
'bxt': t.text, # text of base tweet from recursion
'bag': t.user.screen_name, # screen_name of base tweet from recursion
'bid': t.id } # status id of base tweet from recursion
if(smeet_list_original[0] == smeet):
smeet_list.append(smeet_list_original[0])
bot.privmsg(TARGET,'sweet: no variance')
else:
bot.privmsg(TARGET,'sweet: variance')
smeet_list.append(smeet)
text = text.replace('&amp;','&').replace('&lt;','<').replace('&gt;','>')
for y,_ in enumerate(users):
if _ == screen_name:
break
turl = "https://twitter.com/i/web/status/{}".format(statuses[y][0].id)
if _txt:
msg = "\x02@{}\x0F\x02\x0303 ▶ \x02\x0302\x1D\x1F{}\x0F \x02\x0303▶\x0F @{} \x02\x0303▶\x0F {} \x0F\x02\x0303◀-◀-◀-◀\x0f \x0F\x02\x0312\x1D\x1F\x0F{}\x0F".format( _tag, _txt, t.user.screen_name, text, turl )
else:
msg = "\x02@{} \x0F\x02\x0303▶\x0F \x02\x0302\x1D\x1F{}\x0F \x0F\x02\x0303◀◀◀◀◀◀\x0f \x02\x0312\x1D\x1F\x0F{}\x0F".format( t.user.screen_name, text, turl )
msg = bot._emoj(msg)
bot.privmsg(TARGET, msg)
match_list = URL_REGEX.findall(t.text)
try:
if(match_list):
for m in match_list:
try:
if len(statuses[i][0].urls) == 0:
if statuses[i][0].media:
for y in range(len(statuses[i][0].media)):
m_turl = statuses[i][0].media[y].url
m_murl = statuses[i][0].media[y].media_url
m_eurl = statuses[i][0].media[y].expanded_url
msg = "\x02{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ [media] \x0F\x02\x0312{m_turl:}\x0F\x0303 ▶▶ {m_murl:} ▶▶ \x0F\x1D\x0314{m_eurl:}\x0F".format(nick1=users[i],nick2='UNROLLED',m_turl=m_turl,m_murl=m_murl,m_eurl=m_eurl)
#try:
# #_mask = irc3.utils.IrcString
# #_mask.nick = users[i]
# #bot.asciimg(_mask,TARGET,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(m_murl), '<x>': '100', 'asciimg': True})
#except:
# pass
msg = bot._emoj(msg)
bot.privmsg(TARGET, msg)
else:
for y in range(len(statuses[i][0].urls)):
t_turl = statuses[i][0].urls[y].url
t_eurl = statuses[i][0].urls[y].expanded_url
bot._check_for_url(statuses[i][0],users[i],t_turl,t_eurl,text,TARGET)
except:
bot.privmsg(TARGET, ".▶++▶++▶ wu/tang: error")
except:
pass
bot.db.setlist("smeets", smeet_list)
except:
pass
# check db for previous tweets
try:
sweet_list_original = bot.db.getlist("sweets")
if not sweet_list_original:
sweet_list_original = []
for i in users:
sweet_list_original.append("")
sweet_list = []
bot.db.setlist('sweets',[])
for i in range(len(statuses)):
sweet = { 'screen_name' : statuses[i][0].user.screen_name,
'text': statuses[i][0].text,
'created_at_in_seconds': statuses[i][0].created_at_in_seconds }
if(sweet_list_original[i] == sweet):
sweet_list.append(sweet_list_original[i])
else:
sweet_list.append(sweet)
screen_name = statuses[i][0].user.screen_name
rext = statuses[i][0].text
text = statuses[i][0].text.replace('&amp;','&').replace('&lt;','<').replace('&gt;','>')
turl = "https://twitter.com/i/web/status/{}".format(statuses[i][0].id)
msg = '\x02@{}\x0f \x02\x0303<<<▶\x0F \x02\x0302\x1D\x1F{}\x0F \x0F\x02\x0303◀\x0F\x02\x0302\x1D\x1F\x0F {}\x0F'.format(screen_name,text,turl)
msg = bot._emoj(msg)
bot.privmsg(TARGET,msg)
match_list = URL_REGEX.findall(text)
try:
if(match_list):
for m in match_list:
try:
if len(statuses[i][0].urls) == 0:
if statuses[i][0].media:
for y in range(len(statuses[i][0].media)):
m_turl = statuses[i][0].media[y].url
m_murl = statuses[i][0].media[y].media_url
m_eurl = statuses[i][0].media[y].expanded_url
msg = "\x02{nick1:}:{nick2:}\x0F\x02\x0303 ▶▶ [media] \x0F\x02\x0312{m_turl:}\x0F\x0303 ▶▶ {m_murl:} ▶▶ \x0F\x1D\x0314{m_eurl:}\x0F".format(nick1=users[i],nick2='UNROLLED',m_turl=m_turl,m_murl=m_murl,m_eurl=m_eurl)
#try:
# _mask = irc3.utils.IrcString
# _mask.nick = users[i]
# bot.asciimg(_mask,TARGET,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(m_murl), '<x>': '100', 'asciimg': True})
#except:
# pass
msg = bot._emoj(msg)
bot.privmsg(TARGET, msg)
else:
for y in range(len(statuses[i][0].urls)):
t_turl = statuses[i][0].urls[y].url
t_eurl = statuses[i][0].urls[y].expanded_url
bot._check_for_url(statuses[i][0],users[i],t_turl,t_eurl,text,TARGET)
except:
bot.privmsg(TARGET,'.<><><>[[[]]] wu/tang: error ')
except Exception as e:
bot.privmsg(TARGET,'wu/tang/tang/tang: {}'.format(e))
pass
bot.db.setlist("sweets", sweet_list)
except:
bot.privmsg(TARGET,'sweet error')

56
plugins/tell_plugin.py Normal file
View File

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
import irc3
import re
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
TELL_RE = re.compile('g1mp.tell\s(.+?)\s(.+)')
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@irc3.event(irc3.rfc.PRIVMSG)
def on_privmsg_search_to_tell(self, mask=None, target=None, data=None, **kw):
if mask.nick.lower() == "g1mp": # Read nick from config in future...
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/TELL: {} <{}> {}".format(msg.get("time"), msg.get("from"),msg.get("message"))
self.bot.privmsg(target, self.__emoj(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):
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using url plugins')
return
match_list = TELL_RE.findall(data)
if len(match_list) > 0:
tell_nick, message = match_list[0]
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: {} <{}> {}".format(new_message.get("time"),new_message.get("from"),new_message.get("message"))
self.bot.privmsg(target, self.__emoj(irc_message))

28
plugins/time_plugin.py Normal file
View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
from datetime import datetime
from pytz import timezone
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def time(self, mask, target, args):
"""time
%%time
"""
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using time plugins')
return
shanghai = timezone('Asia/Shanghai')
shanghai_time = datetime.now(shanghai)
msg = shanghai_time.strftime('%H:%M:%S - %m/%d/%Y')
msg = 'shanghai: {}'.format(msg)
self.bot.privmsg(target, msg)

88
plugins/trivia_plugin.py Normal file
View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
from base64 import b64decode
import requests
import irc3
import uuid
import time
import asyncio
import operator
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
self.trivia_started = False
self.trivia_unanswered = True
self.trivia_question_list = []
self.trivia_user_points = {}
self.trivia_question = ""
self.trivia_correct_answer = ""
@command(permission='staff', public=True, show_in_help_list=True)
def trivia_answer(self, mask, target, args):
"""Show Triva Answer
%%trivia_answer
"""
if self.trivia_started:
self.bot.privmsg(target, self.trivia_correct_answer)
else:
self.bot.privmsg(target, "Trivia has not been started")
@irc3.event(irc3.rfc.PRIVMSG)
def _on_privmsg_trivia(self, mask=None, target=None, data=None, **kw):
# Don't parse commands
if self.trivia_started == False:
return
if data.startswith("?"):
return
if mask.nick.lower() in self.bot.ignore_list:
return
if self.trivia_unanswered:
if data.lower() == self.trivia_correct_answer.lower():
current = self.trivia_user_points.get(mask.nick, 0) + 1
self.trivia_user_points[mask.nick] = current
self.bot.privmsg(target, "<{}> {} Got it correct!".format(mask.nick, current))
self.bot.loop.call_later(1, self.__trivia_run, target)
else:
print("WRONG: {} | Answer: {}".format(data, self.trivia_answer))
def __trivia_run(self, channel):
if self.trivia_question_list:
q = self.trivia_question_list.pop()
self.trivia_question = q.get("question")
self.trivia_correct_answer = q.get("correct_answer")
self.bot.privmsg(channel, "Question: {}".format(self.trivia_question))
else:
self.trivia_started = False
winner = max(self.trivia_user_points.items(), key=operator.itemgetter(1))[0]
self.bot.privmsg(channel, "Trivia Finished!")
self.bot.privmsg(channel, "{} Is the winner".format(winner))
def __build_trivia(self, channel, amount):
url = "https://opentdb.com/api.php?amount={}&category=18&type=multiple&encode=base64".format(amount)
results = requests.get(url).json().get('results')
for q in results:
question = {"question": b64decode(q.get("question")).decode("utf-8"),
"correct_answer": b64decode(q.get("correct_answer")).decode("utf-8")}
self.trivia_question_list.append(question)
print(self.trivia_question_list)
self.bot.loop.call_later(1, self.__trivia_run, channel)
@command(permission='staff', public=True, show_in_help_list=True)
def trivia_start(self, mask, target, args):
"""Clear all notes
%%trivia_start [<amount>]
"""
if self.trivia_started:
self.bot.privmsg(target, "Trivia Already Started")
else:
amount = args.get("<amount>")
if not amount: amount = 7 # Default to 7
self.bot.privmsg(target, "Starting Trivia with {} Questions".format(amount))
self.trivia_started = True
self.__build_trivia(target, amount)

98
plugins/tw1tch_plugin.py Normal file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# tw1tch_plugin
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import irc3
from twitch import TwitchHelix
import random
import os
import pdb
dir_path = os.path.dirname(os.path.realpath(__file__))
TWITCH_ID = os.environ['TWITCH_ID']
TWITCH_SECRET = os.environ['TWITCH_SECRET']
client = TwitchHelix(client_id=TWITCH_ID,oauth_token=TWITCH_SECRET)
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
TARGET = '#Security'
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
# TARGET TARGET TARGET TARGET TARGET TARGET TARGET TARGET #
###########################################################
@irc3.plugin
class Plugin:
def __init__(self,bot):
self.bot = bot
@irc3.extend
def _emoj(self,s):
emote_db = '%s/../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 + ' \x02\x0303▶\x0F ' + emoj
return s
@cron('* * * * *')
def _tw1tch_str34ms(bot):
self = bot
# usernames
users = ['hardchat','vikingsec','thuggary137']
# get stream statuses
statuses = []
for user in users:
statuses.append(client.get_streams(user_logins=user))
# check db for previous streams
try:
stream_list_original = bot.db.getlist("streams")
if not stream_list_original:
stream_list_original = []
for user in users:
stream_list_original.append("")
stream_list = []
bot.db.setlist('streams',[])
for i in range(len(statuses)):
try:
assert statuses[i][0]['user_name']
assert statuses[i][0]['user_id']
assert statuses[i][0]['type']
assert statuses[i][0]['title']
stream = { 'user_name': statuses[i][0]['user_name'],
'user_id' : statuses[i][0]['user_id'],
'type': statuses[i][0]['type'],
'title': statuses[i][0]['title'] }
bTrap = False
sStream = ''
for slo in stream_list_original:
if stream == slo:
bTrap = True
sStream = slo
if bTrap == False:
stream_list.append(stream)
_user_name = stream['user_name']
_user_id = stream['user_id']
_type = stream['type']
_title = stream['title']
_url = 'https://www.twitch.tv/{}'.format(_user_name).lower()
msg = '\x02{}\x0f \x02\x0303◀[\x0F \x0304{}\x0f \x02\x0303]▶\x0F \x02\x0302\x1D\x1F{}\x0f \x02\x0303▶\x0F \x0F\x02\x0313\x1D{}\x0f'.format(_user_name, _type.upper(), _title, _url)
msg = bot._emoj(msg)
bot.privmsg(TARGET,msg)
else:
stream_list.append(sStream)
except:
pass
bot.db.setlist("streams", stream_list)
except:
pass

58
plugins/tweet_plugin.py Normal file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from irc3.plugins.cron import cron
from irc3.plugins.command import command
import twitter
import irc3
import os
import random
import ipdb
dir_path = os.path.dirname(os.path.realpath(__file__))
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']
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
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
def __tweet(self,message):
try:
status = twitter.PostUpdate(message)
return '\x0F\x1D\x0314https://twitter.com/{}/status/{} \x02\x0304▶ \x0F\x1D\x0314{}'.format(status.user.screen_name,status.id,status.text)
except Exception as e:
return 'error: %s' % e.message[0]['message']
@command(permission='admin')
def tweet(self, mask, target, args):
"""tweet message
%%tweet <message>...
"""
message = ' '.join(args['<message>'])
status = self.__tweet(message)
msg = "\x02\x0302{nick:\x0F\x02\x0304 ▶ \x02\x0303POSTED \x02\x0304▶ {status:}\x0F".format(nick=mask.nick,status=status)
msg = self.__emoj(msg)
self.bot.privmsg(target,msg)
#@cron('* * * * *')
#def _phuq(bot):
# target = "#Security"
# msg = 'ninja flipz'
# bot.privmsg(target, msg)
# return

230
plugins/twitter_plugin.py Normal file
View File

@ -0,0 +1,230 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from datetime import datetime
import twitter
import re
import os
import irc3
import time
import timeago
import random
import os
import sys
import requests
from lxml.html import fromstring
from difflib import SequenceMatcher
dir_path = os.path.dirname(os.path.realpath(__file__))
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 _emoj(self,s):
emote_db = '%s/../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 + ' \x02\x0303▶\x0F ' + emoj
return s
@irc3.extend
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
@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)
#try:
# _mask = irc3.utils.IrcString
# _mask.nick = d_nick
# self.bot.asciimg(_mask,d_target,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(m_murl), '<x>': '100', 'asciimg': True})
#except:
# pass
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._emoj(msg)
self.bot.privmsg(d_target, msg)
return
except Exception as e:
msg = "wu/tang >>>>>>>>>>> sub-unrolling: {}".format(e)
msg = self.bot._emoj(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._emoj(msg)
self.bot.privmsg(d_target, msg)
return
# Ignore Non text/html
if not content_type.startswith("text/html"):
return
# Ignore Large Content
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._emoj(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._emoj(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._emoj(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._emoj(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):
# Don't parse commands
if data.startswith("?"): return
if mask.nick.lower() not in self.bot.ignore_list:
self._check_for_twitter(mask, data, target)

34
plugins/ud_plugin.py Normal file
View File

@ -0,0 +1,34 @@
# Pastebin lzlssqMI
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import requests
import urllib.parse
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def ud(self, mask, target, args):
"""Urban Dictonary A Term
%%ud <term>...
"""
term = ' '.join(args['<term>'])
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using ud plugins')
return
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)

View File

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
import irc3
import re
import sys
import os
import random
import requests
from lxml.html import fromstring
import archiveis
from random import choices
import ipdb
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)
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@irc3.event(irc3.rfc.PRIVMSG)
def on_privmsg(self, mask=None, target=None, data=None, **kw):
# Don't parse commands
for _ in self.bot.phuq.USER:
if mask.nick.lower() == _:
print(f'{mask.nick} denied using url plugins')
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 __get_tiny_url(self, url):
tiny_url = 'http://tinyurl.com/api-create.php?url=%s' % url
r = requests.get(tiny_url)
return r.text
def __check_for_url(self, msg, target, mask):
match_list = URL_REGEX.findall(msg)
read_size = 0
if match_list:
url = match_list.pop()
# Ignore Youtube
y_match = YOUTUBE_REGEX.findall(url)
if y_match:
y_match = y_match.pop()
if len(y_match) == 3:
return
# Ignore Twitter
t_match = TWITTER_REGEX.findall(url)
if t_match:
t_match = t_match.pop()
if len(t_match) == 3:
return
# End Ignore Twitter
# End Ignore Youtube
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.__emoj(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.__emoj(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
# Ignore Non text/html but report content/size
if not content_type.startswith("text/html"):
try:
msg = "\x02\x0302{nick1:}\x0F\x02\x0304 ▶▶ \x0304[content_type]:\x0F \x0305{con_type:}\x0F \x02\x0304▶▶\x0F \x0304[content_length]:\x0F \x0305{con_length:}\x0F \x02\x0304▶▶\x0F \x0F\x02\x0303{d_url:}\x0F\x0303".format(nick1=mask.nick,con_type=content_type,con_length=content_length,d_url=url)
try:
if content_type.startswith("image"):
try:
self.bot.asciimg(mask,target,{'<c0l0r>': choices("cdefgjklmn")[0], '<charset>': '.oO0_,#=+-%', '<intensity>': '26', '<url>': '{}'.format(url), '<x>': '100', 'asciimg': True})
except:
pass
except:
pass
except:
msg = "wu/tang: pre-fetch of non text/html failed"
msg = self.bot._emoj(msg)
self.bot.privmsg(target, msg)
return
# Ignore Large Content
if int(content_length) > 200000:
msg = 'pre-fetch aborted -> fuck your large ass content'
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)
# 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]
# Comment out Tiny URL
if len(url) >= 60:
url = self.__get_tiny_url(url)
#url = archiveis.capture(url)
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶ \x0F\x02\x0303{url:}\x0F\x02\x0304 ▶▶▶▶▶ \x0F\x1D\x0314{title:}\x0F".format(nick=mask.nick,url=url,title=title)
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)
return
read_size = read_size + 2000
except Exception as e:
print("%s" % e)
pass

206
plugins/userlist.py Normal file
View File

@ -0,0 +1,206 @@
# -*- coding: utf-8 -*-
from irc3 import plugin
from irc3 import utils
from irc3 import rfc
from irc3.dec import event
from irc3.utils import IrcString
from collections import defaultdict
__doc__ = '''
==============================================
:mod:`irc3.plugins.userlist` User list plugin
==============================================
This plugin maintain a known user list and a channel list.
..
>>> from irc3.testing import IrcBot
Usage::
>>> bot = IrcBot()
>>> bot.include('irc3.plugins.userlist')
>>> bot.test(':gawel!user@host JOIN #chan')
>>> print(list(bot.channels['#chan'])[0])
gawel
>>> print(list(bot.nicks.keys())[0])
gawel
>>> bot.test(':gawel!user@host MODE #chan +o gawel')
>>> print(list(bot.channels['#chan'].modes['@'])[0])
gawel
Api
===
.. autoclass:: Channel
'''
class Channel(set):
"""A set like object which contains nicknames that are on the channel and
user modes:
.. code-block:: python
>>> channel = Channel()
>>> channel.add('gawel', modes='@')
>>> 'gawel' in channel
True
>>> 'gawel' in channel.modes['@']
True
>>> channel.remove('gawel')
>>> 'gawel' in channel
False
>>> 'gawel' in channel.modes['@']
False
"""
def __init__(self):
set.__init__(self)
self.modes = defaultdict(set)
self.topic = None
def add(self, item, modes=''):
set.add(self, item)
for mode in modes:
self.modes[mode].add(item)
def remove(self, item):
set.remove(self, item)
for items in self.modes.values():
if item in items:
items.remove(item)
def __repr__(self):
return repr(sorted(self))
@plugin
class Userlist:
def __init__(self, context):
self.context = context
self.connection_lost()
def connection_lost(self, client=None):
self.channels = defaultdict(Channel)
self.context.channels = self.channels
self.nicks = {}
self.context.nicks = self.nicks
def broadcast(self, *args, **kwargs):
# only usefull for servers
pass
@event(rfc.JOIN_PART_QUIT)
def on_join_part_quit(self, mask=None, event=None, **kwargs):
getattr(self, event.lower())(mask.nick, mask, **kwargs)
@event(rfc.KICK)
def on_kick(self, mask=None, event=None, target=None, **kwargs):
self.part(target.nick, mask=None, **kwargs)
def join(self, nick, mask, client=None, **kwargs):
channel = self.channels[kwargs['channel']]
if nick != self.context.nick:
channel.add(mask.nick)
self.nicks[mask.nick] = client or mask
if client:
self.broadcast(client=client, clients=channel, **kwargs)
def part(self, nick, mask=None, channel=None, client=None, **kwargs):
if nick == self.context.nick:
del self.channels[channel]
else:
channel = self.channels[channel]
self.broadcast(client=client, clients=channel, **kwargs)
channel.remove(nick)
if client is None and all(
nick not in c for c in self.channels.values()):
del self.nicks[nick]
def quit(self, nick, mask, channel=None, client=None, **kwargs):
if nick == self.context.nick:
self.connection_lost()
else:
clients = set()
for channel in self.channels.values():
if nick in channel:
clients.update(channel)
channel.remove(nick)
self.broadcast(client=client, clients=clients, **kwargs)
del self.nicks[nick]
@event(rfc.NEW_NICK)
def new_nick(self, nick=None, new_nick=None, client=None, **kwargs):
"""update list on new nick"""
if client is None:
self.nicks[new_nick] = new_nick + '!' + nick.host
nick = nick.nick
clients = {new_nick}
for channel in self.channels.values():
if nick in channel:
for nicknames in channel.modes.values():
if nick in nicknames:
nicknames.add(new_nick)
channel.remove(nick)
clients.update(channel)
channel.add(new_nick)
del self.nicks[nick]
self.broadcast(client=client, clients=clients, **kwargs)
@event(rfc.RPL_NAMREPLY)
def names(self, channel=None, data=None, **kwargs):
"""Initialise channel list and channel.modes"""
statusmsg = self.context.server_config['STATUSMSG']
nicknames = data.split(' ')
channel = self.channels[channel]
for item in nicknames:
nick = item.strip(statusmsg)
channel.add(nick, modes=item[:-len(nick)])
self.nicks[nick] = nick
@event(rfc.RPL_WHOREPLY)
def who(self, channel=None, nick=None, username=None, server=None, **kw):
"""Set nick mask"""
self.channels[channel].add(nick)
mask = IrcString(nick + '!' + username + '@' + server)
self.nicks[nick] = mask
@event(rfc.MODE)
def mode(self, target=None, modes=None, data=None, client=None, **kw):
"""Add nicknames to channel.modes"""
if target[0] not in self.context.server_config['CHANTYPES'] \
or not data:
# not a channel or no user target
return
noargs = self.context.server_config['CHANMODES'].split(',')[-1]
if not isinstance(data, list):
data = [d for d in data.split(' ') if d]
if not modes.startswith(('+', '-')):
modes = '+' + modes
modes = utils.parse_modes(modes, data, noargs)
prefix = self.context.server_config['PREFIX']
prefix = dict(zip(*prefix.strip('(').split(')')))
channel = self.channels[target]
for char, mode, tgt in modes:
if mode in prefix:
nicknames = channel.modes[prefix[mode]]
if char == '+':
nicknames.add(tgt)
elif tgt in nicknames:
nicknames.remove(tgt)
if client is not None:
broadcast = (
':{mask} MODE {target} {char}{mode} {tgt}').format(
char=char, mode=mode, target=target, tgt=tgt,
**client.data)
self.broadcast(client=client, broadcast=broadcast,
clients=channel)
@event(rfc.RPL_TOPIC)
def topic(self, channel=None, data=None, client=None, **kwargs):
self.channels[channel].topic = data

62
plugins/vimeo_plugin.py Normal file
View File

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import vimeo
import irc3
import random
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
ci = 'b909632e42bece3757fa46d38da6121737fd18a1'
cs = 'pt1VzEIEJhC4VVQc/FV4ewJSnoN3JzT1KYKwuhUxCAlNmNKM6m95cwYkIOk3K8E9IrtMRD1PpCLHplNg+xAZQebscyHdm8sTlXL4ioy4bpZI5FXBX9ZVCN5u0OI/1nEh'
at = '6ef83a3b7adcf426b9d3f3ea2dc9fa3e'
aurl = 'https://api.vimeo.com/oauth/authorize'
aturl = 'https://api.vimeo.com/oauth/access_token'
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
self.bot._youtube_live = False
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def vimeo(self, mask, target, args):
"""Search for vimeo video
%%vimeo <keyword>
"""
keyword = args['<keyword>']
client = vimeo.VimeoClient(token=at,key=ci,secret=cs)
try:
response = client.get('/videos?query={}'.format(keyword))
tally = response.json()['total']
if(tally==0):
msg = 'vimeo returned no results or error'
else:
name = response.json()['data'][0]['name']
link = response.json()['data'][0]['link']
released = response.json()['data'][0]['release_time']
seconds = response.json()['data'][0]['duration']
minutes,seconds = divmod(seconds,60)
duration = '{}m{}s'.format(str(minutes),str(seconds))
msg = 'name: {} > released: {} > duration: {} > link: {}'.format(name,released,duration,link)
except:
tally = 0
msg = 'vimeo returned no results or error'
if(tally>0):
msg = "\x02{nick:}\x0F\x02\x1D\x0303 ▶ \x0F\x02\x0306\x1D{title:}\x0F\x0308 ⑆ \x1f{elapsed:}\x0f\x0304 ⑆ \x0F\x0314Released: \x1F{published:}\x0F\x0304 ▶ \x1f{url:}\x0f\x0304\x0F".format(nick=mask.nick, title=name, elapsed=duration, published=released, url=link)
else:
msg = "\x02{nick:}\x0F\x02\x1D\x0303 ▶ \x0F\x02\x0306\x1D{msg_error:}\x0F\x0308".format(nick=mask.nick, msg_error=msg)
msg = self.__emoj(msg)
self.bot.privmsg(target, msg)

63
plugins/whois_plugin.py Normal file
View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import ipdb
import aiodns
import socket
import random
import os
import whois
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
@command(permission='view')
def whois(self, mask, target, args):
"""Show WHOIS query
%%whois <domain>
"""
domain = args.get('<domain>')
bad = False
try:
socket.gethostbyname(domain)
bad = True
except:
bad = False
if(bad==False):
msg = 'invalid domain'
self.bot.privmsg(target,'invalid domain')
else:
if(bad):
try:
w = whois.whois(domain)
except:
w = 'error'
msg = "WHOIS:['{}']".format(w)
msg = self.__emoj(msg)
self.bot.privmsg(target,msg)

160
plugins/why_plugin.py Normal file
View File

@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
import irc3
import aiohttp
import asyncio
import async_timeout
from functools import partial
from io import StringIO
import ipaddress
import aiodns
import socket
import random
import os
import whois
dir_path = os.path.dirname(os.path.realpath(__file__))
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
def __emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
def what(self):
r = [
'because',
'sometimes',
"like",
"what if",
"oddly enough",
"so like",
"you wouldn't believe me but",
'and']
s = [
'all these',
'all of these',
'they say',
'they said',
"that is how",
"that is when",
"that is why",
'back in my day']
t = [
'penises',
'dildos',
'low-battery-dildos',
'politicians',
'magic tricks',
'smurfs',
'doorknobs',
'teledildonics',
'punks',
'wizards',
'ninjas',
'conspiracies',
"exes",
'russians',
'ramen noodles',
'pokemon',
'0dayz',
'drugz',
'pillz',
'lost and found drugz',
'alex jones types']
u = [
'became',
'tasted like',
'were into',
'were not',
'were really not',
'were really not into',
'transcended into',
'transmutated',
'were mostly',
"could be",
"could have been",
"could actually be",
"could not be",
"could not possibly be",
'never were',
'never were really',
'really meant']
v = [
'satanic cultists',
'gremlins',
'dingle berries',
'porno stars',
'sloppy alien snatches',
'hard chatters',
'christian propaganda',
'camgurlz',
'gingerz',
'boogers',
'transgingerz',
'nazis',
'uber drivers',
'hallucinogens',
'oompa loompas',
'communists',
'social justice warriors',
'a good reason',
'hiphop mixtapes',
'harry potter',
'free pizza',
'mcdonalds',
'illuminati']
w = [
'bitch',
'after all',
'so praise bob',
'and praise be to bob',
'praise bob',
'so hail satan',
'and hail satan',
'hail satan',
'is fakenews',
'is not fakenews',
'tonight on the faux news network',
'tonight on the counterfeit news network',
'dude',
'right',
'duh',
'my nigga',
'hmm',
'lol']
p = [
'!',
'?',
'.']
rr = r[random.randint(0,len(r)-1)]
ss = s[random.randint(0,len(s)-1)]
tt = t[random.randint(0,len(t)-1)]
uu = u[random.randint(0,len(u)-1)]
vv = v[random.randint(0,len(v)-1)]
ww = w[random.randint(0,len(w)-1)]
pp=''
x = random.randint(1,10)
for i in range(x):
y = random.randint(1,5)
pp += p[random.randint(0,len(p)-1)] * y
return rr + ' ' + ss + ' ' + tt + ' ' + uu + ' ' + vv + ' ' + ww + pp
@command(permission='view')
def why(self, mask, target, args):
"""why?
%%why
"""
msg = self.what()
msg = self.__emoj(msg)
self.bot.privmsg(target,msg)

262
plugins/youtube_plugin.py Normal file
View File

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
from irc3.plugins.command import command
from irc3.plugins.cron import cron
import irc3
import datetime
import dateutil.parser
import random
import os
import re
import timeago
import isodate
import requests
#import ipdb
# Youtube API
from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.tools import argparser
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 = []
def _emoj(self,s):
emote_db = '%s/../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 + '' + emoj
return s
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
@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):
# Don't parse commands
if data.startswith("?"): return
if self.bot.check_if_ignored(mask): return
self.__check_for_youtube(mask, data, target)
def __check_for_youtube(self, mask, msg, target):
match_list = YOUTUBE_REGEX.findall(msg)
if match_list:
video_id = match_list.pop()
if int(len(video_id)) == 3:
video_id = video_id[0]
video_info = self.videos_list_by_id(id=video_id)
title = video_info.get("snippet",{}).get("title")
published_at = video_info.get("snippet",{}).get("publishedAt")
view_count = int(video_info.get("statistics").get("viewCount"))
if published_at:
published_at = dateutil.parser.parse(published_at)
published_at = timeago.format(published_at.replace(tzinfo=None), datetime.datetime.now())
try:
topics = video_info.get("topicDetails",{}).get("topicCategories")
topics[:] = [i.replace("https://en.wikipedia.org/wiki/", "").replace("_"," ").title() for i in topics]
except:
topics = []
#YOUPAK
#try:
# _url = 'https://www.youpak.com/watch?v={}'.format(video_id)
# r = requests.get(_url)
# lines = r.text.splitlines()
# for i,line in enumerate(lines):
# if not line.find('downloadtoggle') == -1:
# bingo = i
# for line in range(bingo,len(lines)):
# if not lines[line].find('mp4') == -1:
# bingo = line
# break
# bCheck = False
# if bingo > 0:
# try:
# _url = lines[bingo].split('"')[1]
# _url = self.__get_tiny_url(_url)
# if len(_url) <= 27 and _url[:18] == 'http://tinyurl.com':
# url = " \x0303▶\x0f \x02\x0312{}\x0f\x0303".format(_url)
# bCheck = True
# except:
# pass
#except:
# bCheck = False
#YOUPAK
bCheck = False
duration = isodate.parse_duration(video_info.get("contentDetails").get("duration"))
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶▶ \x02\x0303\x1D\x1F{title:}\x0F".format(nick=mask.nick, title=title)
msg = msg + "\x02\x1D\x0304 ▶ \x0F\x1D\x0314Duration: \x0F\x1D{duration:} \x0F".format(duration=duration)
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,}\x0F".format(published=published_at, views=view_count)
msg = msg + "\x0F\x02\x0312 ♫ \x0F\x02\x0313\x1D{topics:}\x0F\x02\x0312".format(topics=", ".join(topics))
#if bCheck == True:
msg = msg
msg = self._emoj(msg)
self.bot.privmsg(target,msg)
@irc3.extend
def videos_list_by_id(self, id):
# See full sample for function
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 dyt(self, mask, target, args):
# """youtube debug hook to ipdb.set_trace()
# %%dyt <keyword>...
# """
# keyword = ' '.join(args['<keyword>'])
# ipdb.set_trace()
# ipdb.set_trace()
# ipdb.set_trace()
@irc3.extend
@command(permission='view')
def yt(self, mask, target, args):
"""Search for youtube video
%%yt <keyword>...
"""
#keyword = args['<keyword>']
keyword = ' '.join(args['<keyword>'])
video = self.youtube_search(q=keyword)
if video:
video_id = video.get("id",{}).get("videoId")
video = video.get("snippet")
video_info = self.videos_list_by_id(id=video_id)
title = video_info.get("snippet",{}).get("title")
published_at = video_info.get("snippet",{}).get("publishedAt")
view_count = int(video_info.get("statistics").get("viewCount"))
if published_at:
published_at = dateutil.parser.parse(published_at)
published_at = timeago.format(published_at.replace(tzinfo=None), datetime.datetime.now())
try:
topics = video_info.get("topicDetails",{}).get("topicCategories")
topics[:] = [i.replace("https://en.wikipedia.org/wiki/", "").replace("_"," ").title() for i in topics]
except:
topics = []
duration = isodate.parse_duration(video_info.get("contentDetails").get("duration"))
#YOUPAK
#try:
# _url = 'https://www.youpak.com/watch?v={}'.format(video_id)
# r = requests.get(_url)
# lines = r.text.splitlines()
# for i,line in enumerate(lines):
# if not line.find('downloadtoggle') == -1:
# bingo = i
# for line in range(bingo,len(lines)):
# if not lines[line].find('mp4') == -1:
# bingo = line
# break
# bCheck = False
# if bingo > 0:
# try:
# _url = lines[bingo].split('"')[1]
# _url = self._get_tiny_url(_url)
# if len(_url) <= 27 and _url[:18] == 'http://tinyurl.com':
# bCheck = True
# except:
# pass
#except:
# bCheck = False
#YOUPAK
bCheck = False
#_url = ""
#ipdb.set_trace()
url = "https://youtu.be/{}".format(video_id)
_nick = ""
try:
if len(self.bot.madjust) > 0:
_nick = self.bot.madjust
else:
_nick = mask.nick
except:
_nick = mask.nick
msg = "\x02\x0302{nick:}\x0F\x02\x0304 ▶▶ \x02\x0303\x1D\x1F{title:}\x0F".format(nick=_nick, title=title)
msg = msg + "\x02\x1D\x0304 ▶ \x0F\x1D\x0314Duration: \x0F\x1D{duration:} \x0F".format(duration=duration)
msg = msg + "\x0F\x1D\x0314Published: \x0F\x1D{published:} \x0F\x1D\x0314Views: \x0F\x1D{views:,}\x0F".format(published=published_at, views=view_count)
msg = msg + "\x0F\x02\x0312 ♫ \x0F\x02\x0313\x1D{topics:}\x0F\x02\x0312 ".format(topics=", ".join(topics))
#if bCheck == True:
msg = msg + url
msg = self._emoj(msg)
self.bot.privmsg(target, msg)
#@cron('* * * * *')
#def _check_for_live_video(bot):
# TARGET = "#Security"
# channels = []
# channels.append('UC_waCFCtUJpkkUxftNCbOBA') # l0de radio hour
# for iCount, channel in enumerate(channels):
# try:
# assert bot.channel_live[iCount]
# except IndexError:
# bot.channel_live.append(False)
# except AssertionError:
# pass
# stream = bot.youtube_search(channelId=channel,eventType='live')
# if stream and bot.channel_live[iCount] == False:
# bot.channel_live[iCount] = True
# try:
# assert stream['snippet']['channelTitle']
# assert stream['snippet']['title']
# assert stream['snippet']['description']
# assert stream['id']['videoId']
# _channel = stream['snippet']['channelTitle']
# _title = stream['snippet']['title']
# _desc = stream['snippet']['description']
# _video_id = stream['id']['videoId']
# _url = 'https://youtu.be/{}'.format(_video_id)
# msg = '\x02༺{}༻\x0f \x02\x0303◀[\x0F \x0304{}\x0f \x02\x0303]▶\x0F \x02\x0302\x1D\x1F{}\x0f \x02\x0303▶\x0F \x0F\x02\x0313\x1D{}\x0f'.format(_channel, _title, _desc, _url)
# msg = bot._emoj(msg)
# bot.privmsg(TARGET,msg)
# except:
# pass
# elif not stream:
# bot.channel_live[iCount] = False

41
requirements.txt Normal file
View File

@ -0,0 +1,41 @@
astroid==1.6.1
certifi==2018.1.18
chardet==3.0.4
docopt==0.6.2
idna==2.6
irc3
isort==4.3.4
lazy-object-proxy==1.3.1
mccabe==0.6.1
pylint==1.8.2
requests
requests-cache==0.4.13
six==1.11.0
urllib3==1.22
venusian
wrapt==1.10.11
google-api-python-client
timeago
aiodns
aiohttp
cchardet
isodate
python-twitter
aiocron
feedparser
pyfiglet
cssselect
archiveis
safygiphy
bs4
selenium
ipdb
oauth2client
lxml
google
#vimeo
#urlparse2
setuptools
pycurl
pyping

34
run_d_d3vg1mp Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash
while :
do
touch _d_d3vg1mp.pids
if [ $(wc -c _d_d3vg1mp.pids|cut -d' ' -f1) -ne 0 ]; then
cat _d_d3vg1mp.pids|xargs -n 1 kill
fi
echo $$ > _d_d3vg1mp.pids
echo "echo \$$ > _d_d3vg1mp.pids" > _d_d3vg1mp_sh
echo "killall -9 irc3 > /dev/null 2>&1" >> _d_d3vg1mp_sh
echo "rm -f _d_d3vg1mp_db.json" >> _d_d3vg1mp_sh
echo "git pull" >> _d_d3vg1mp_sh
echo "irc3 -v _d_d3vg1mp.ini" >> _d_d3vg1mp_sh
chmod +x _d_d3vg1mp_sh
# EXAMPE OF DEVELOPMENT WORKFLOW
# if you were working on a soundcloud plugin
# 1) add plugins.d3v_soundcloud_plugin to _d_d3vg1mp.ini
# we will be editing our plugin so we will want to maybe remove the plugin, paste new code
# and then restart the bot over and over again until we are done so
# rm plugins/d3v_soundcloud_plugin.py && nano plugins/d3v_soundcloud_plugin.py && irc3 _d_d3vg1mp.ini
rm plugins/d3v_soundcloud_plugin.py && nano plugins/d3v_soundcloud_plugin.py
bash _d_d3vg1mp_sh && rm -f _d_d3vg1mp.pids && rm -f _d_d3vg1mp_sh
done
# when we done with development, we either rename or copy the code from plugins/d3v_soundcloud_plugin.py into
# plugins/soundcloud_plugin.py and then add our plugin into the real _d_g1mp.ini.. then run irc3 _d_g1mp.ini