Compare commits

..

No commits in common. "ChaosChemnitz" and "testing!" have entirely different histories.

186 changed files with 2050 additions and 4155 deletions

1
.gitignore vendored Normal file → Executable file
View file

@ -1,6 +1,5 @@
persist
config
config.ssl
gitflow
*.db
*.log

View file

@ -22,7 +22,6 @@ frdmn
We are using code from the following projects:
./plugins/mlia.py - https://github.com/infinitylabs/UguuBot
./plugins/horoscope.py - https://github.com/infinitylabs/UguuBot
color section in ./plugins/utility.py - https://github.com/hitzler/homero
Special Thanks:
Rmmh (created skybot!)

0
LICENSE Normal file → Executable file
View file

5
README.md Normal file → Executable file
View file

@ -6,7 +6,7 @@ CloudBot is a Python IRC bot based on [Skybot](http://git.io/skybot) by [rmmh](h
## Getting and using CloudBot
### Download
### Download
Get CloudBot at [https://github.com/ClouDev/CloudBot/zipball/develop](https://github.com/ClouDev/CloudBot/zipball/develop "Get CloudBot from Github!").
@ -20,9 +20,6 @@ Before you can run the bot, you need to install a few Python dependencies. LXML
These can be installed with `pip` (The Python package manager):
[sudo] pip install -r requirements.txt
If you use `pip`, you will also need the following packages on linux or `pip` will fail to install the requirements.
```python, python-dev, libenchant-dev, libenchant1c2a, libxslt-dev, libxml2-dev.```
#### How to install `pip`

View file

@ -1,28 +1,47 @@
#!/usr/bin/env python
__author__ = "ClouDev"
__authors__ = ["Lukeroge", "neersighted"]
__copyright__ = "Copyright 2012-2013, ClouDev"
__credits__ = ["thenoodle", "_frozen", "rmmh"]
__license__ = "GPL v3"
__version__ = "DEV"
__maintainer__ = "ClouDev"
__email__ = "cloudev@neersighted.com"
__status__ = "Development"
import os
import Queue
import sys
import time
import platform
import re
sys.path += ['plugins', 'lib'] # add stuff to the sys.path for easy imports
sys.path += ['plugins', 'lib'] # so 'import hook' works without duplication
os.chdir(sys.path[0] or '.') # do stuff relative to the install directory
class Bot(object):
pass
print 'CloudBot DEV <http://git.io/cloudbotirc>'
# create new bot object
print 'CloudBot %s (%s) <http://git.io/cloudbotirc>' % (__version__, __status__)
# print debug info
opsys = platform.platform()
python_imp = platform.python_implementation()
python_ver = platform.python_version()
architecture = ' '.join(platform.architecture())
print "Operating System: %s, Python " \
"Version: %s %s, Architecture: %s" \
"" % (opsys, python_imp, python_ver, architecture)
bot = Bot()
bot.vars = {}
# record start time for the uptime command
bot.start_time = time.time()
print 'Begin Plugin Loading.'
print 'Loading plugins...'
# bootstrap the reloader
eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(),

View file

@ -1,77 +1,65 @@
{
"connections": {
"hackint": {
"server": "irc.hackint.eu",
"nick": "antibot",
"user": "antibot",
"realname": "CloudBot - http://git.io/cloudbotirc",
"mode": "",
"_nickserv_password": "",
"-nickserv_user": "",
"channels": [
"#ChaosChemnitz",
"#logbot"
],
"invite_join": true,
"auto_rejoin": false,
"command_prefix": "."
}
"connections":
{
"esper":
{
"server": "irc.esper.net",
"nick": "MyCloudBot",
"user": "cloudbot",
"realname": "CloudBot - http://git.io/cloudbotirc",
"mode": "",
"nickserv_password": "",
"nickserv_user": "",
"channels": ["#cloudbot", "#cloudbot2"],
"invite_join": true,
"auto_rejoin": false,
"command_prefix": "."
}
},
"disabled_plugins": [],
"disabled_commands": [],
"acls": {},
"api_keys":
{
"tvdb": "",
"wolframalpha": "",
"lastfm": "",
"rottentomatoes": "",
"soundcloud": "",
"twitter_consumer_key": "",
"twitter_consumer_secret": "",
"twitter_access_token": "",
"twitter_access_secret": "",
"wunderground": "",
"googletranslate": "",
"rdio_key": "",
"rdio_secret": "",
"steam_key": ""
},
"permissions": {
"admins": {
"perms": ["adminonly", "addfactoid", "delfactoid", "ignore", "botcontrol", "permissions_users", "op"],
"users": ["examplea!user@example.com", "exampleb!user@example.com"]
},
"disabled_plugins": [],
"disabled_commands": [],
"acls": {},
"api_keys": {
"tvdb": "",
"wolframalpha": "",
"lastfm": "",
"rottentomatoes": "",
"soundcloud": "",
"twitter_consumer_key": "",
"twitter_consumer_secret": "",
"twitter_access_token": "",
"twitter_access_secret": "",
"wunderground": "",
"googletranslate": "",
"rdio_key": "",
"rdio_secret": ""
"moderators": {
"perms": ["addfactoid", "delfactoid", "ignore"],
"users": ["examplec!user@example.com"]
}
},
"plugins":
{
"factoids":
{
"prefix": false
},
"permissions": {
"admins": {
"perms": [
"adminonly",
"addfactoid",
"delfactoid",
"ignore",
"botcontrol",
"permissions_users",
"op"
],
"users": [
"examplea!user@example.com",
"exampleb!user@example.com"
]
},
"moderators": {
"perms": [
"addfactoid",
"delfactoid",
"ignore"
],
"users": [
"stummi!~Stummi@stummi.org"
]
}
},
"plugins": {
"factoids": {
"prefix": false
},
"ignore": {
"ignored": []
}
},
"censored_strings": [
"mypass",
"mysecret"
]
"ignore":
{
"ignored": []
}
},
"censored_strings":
[
"mypass",
"mysecret"
]
}

2
core/config.py Normal file → Executable file
View file

@ -24,4 +24,4 @@ def config():
print 'error: malformed config', e
bot._config_mtime = 0
bot._config_mtime = 0

0
core/db.py Normal file → Executable file
View file

60
core/irc.py Normal file → Executable file
View file

@ -44,16 +44,7 @@ class crlf_tcp(object):
return socket.socket(socket.AF_INET, socket.TCP_NODELAY)
def run(self):
noerror = 0
while 1:
try:
self.socket.connect((self.host, self.port))
break
except socket.gaierror as e:
time.sleep(5)
except socket.timeout as e:
time.sleep(5)
self.socket.connect((self.host, self.port))
thread.start_new_thread(self.recv_loop, ())
thread.start_new_thread(self.send_loop, ())
@ -64,25 +55,17 @@ class crlf_tcp(object):
return socket.timeout
def handle_receive_exception(self, error, last_timestamp):
print("Receive exception: %s" % (error))
if time.time() - last_timestamp > self.timeout:
print("Receive timeout. Restart connection.")
self.iqueue.put(StopIteration)
self.socket.close()
return True
return False
def handle_send_exception(self, error):
print("Send exception: %s" % (error))
self.iqueue.put(StopIteration)
self.socket.close()
return True
def recv_loop(self):
last_timestamp = time.time()
while True:
try:
data = self.recv_from_socket(4096)
data = self.recv_from_socket(4096)
self.ibuffer += data
if data:
last_timestamp = time.time()
@ -96,8 +79,6 @@ class crlf_tcp(object):
if self.handle_receive_exception(e, last_timestamp):
return
continue
except AttributeError:
return
while '\r\n' in self.ibuffer:
line, self.ibuffer = self.ibuffer.split('\r\n', 1)
@ -105,19 +86,13 @@ class crlf_tcp(object):
def send_loop(self):
while True:
try:
line = self.oqueue.get().splitlines()[0][:500]
if line == StopIteration:
return
print ">>> %r" % line
self.obuffer += line.encode('utf-8', 'replace') + '\r\n'
while self.obuffer:
sent = self.socket.send(self.obuffer)
self.obuffer = self.obuffer[sent:]
line = self.oqueue.get().splitlines()[0][:500]
print ">>> %r" % line
self.obuffer += line.encode('utf-8', 'replace') + '\r\n'
while self.obuffer:
sent = self.socket.send(self.obuffer)
self.obuffer = self.obuffer[sent:]
except socket.error as e:
self.handle_send_exception(e)
return
class crlf_ssl_tcp(crlf_tcp):
"""Handles ssl tcp connetions that consist of utf-8 lines ending with crlf"""
@ -139,13 +114,10 @@ class crlf_ssl_tcp(crlf_tcp):
def handle_receive_exception(self, error, last_timestamp):
# this is terrible
#if not "timed out" in error.args[0]:
# raise
if not "timed out" in error.args[0]:
raise
return crlf_tcp.handle_receive_exception(self, error, last_timestamp)
def handle_send_exception(self, error):
return crlf_tcp.handle_send_exception(self, error)
irc_prefix_rem = re.compile(r'(.*?) (.*?) (.*)').match
irc_noprefix_rem = re.compile(r'()(.*?) (.*)').match
@ -163,7 +135,6 @@ class IRC(object):
self.server = server
self.port = port
self.nick = nick
self.history = {}
self.vars = {}
self.out = Queue.Queue() # responses from the server are placed here
@ -234,18 +205,13 @@ class IRC(object):
self.channels.remove(channel)
def msg(self, target, text):
""" makes the bot send a PRIVMSG to a target """
""" makes the bot send a message to a user """
self.cmd("PRIVMSG", [target, text])
def ctcp(self, target, ctcp_type, text):
""" makes the bot send a PRIVMSG CTCP to a target """
out = u"\x01{} {}\x01".format(ctcp_type, text)
self.cmd("PRIVMSG", [target, out])
def cmd(self, command, params=None):
if params:
params[-1] = u':' + params[-1]
self.send(u"{} {}".format(command, ' '.join(params)))
params[-1] = ':' + params[-1]
self.send(command + ' ' + ' '.join(map(censor, params)))
else:
self.send(command)

35
core/main.py Normal file → Executable file
View file

@ -13,34 +13,29 @@ class Input(dict):
if chan == conn.nick.lower(): # is a PM
chan = nick
def message(message, target=chan):
"""sends a message to a specific or current channel/user"""
conn.msg(target, message)
def say(msg, chan=chan):
conn.msg(chan, msg)
def reply(message, target=chan):
"""sends a message to the current channel/user with a prefix"""
if target == nick:
conn.msg(target, message)
def pm(msg, nick=nick):
conn.msg(nick, msg)
def reply(msg, chan=chan):
if chan == nick: # PMs don't need prefixes
conn.msg(chan, msg)
else:
conn.msg(target, u"({}) {}".format(nick, message))
conn.msg(chan, '(' + nick + ') ' + msg)
def action(message, target=chan):
"""sends an action to the current channel/user or a specific channel/user"""
conn.ctcp(target, "ACTION", message)
def me(msg, chan=chan):
conn.msg(chan, "\x01{} {}\x01".format("ACTION", msg))
def ctcp(message, ctcp_type, target=chan):
"""sends an ctcp to the current channel/user or a specific channel/user"""
conn.ctcp(target, ctcp_type, message)
def notice(message, target=nick):
"""sends a notice to the current channel/user or a specific channel/user"""
conn.cmd('NOTICE', [target, message])
def notice(msg, nick=nick):
conn.cmd('NOTICE', [nick, msg])
dict.__init__(self, conn=conn, raw=raw, prefix=prefix, command=command,
params=params, nick=nick, user=user, host=host, mask=mask,
paraml=paraml, msg=msg, server=conn.server, chan=chan,
notice=notice, message=message, reply=reply, bot=bot,
action=action, ctcp=ctcp, lastparam=paraml[-1])
notice=notice, say=say, reply=reply, pm=pm, bot=bot,
me=me, lastparam=paraml[-1])
# make dict keys accessible as attributes
def __getattr__(self, key):

0
core/reload.py Normal file → Executable file
View file

View file

@ -1,37 +0,0 @@
from util import hook
import re
CORRECTION_RE = r'^(s|S)/.*/.*/?\S*$'
@hook.regex(CORRECTION_RE)
def correction(match, input=None, conn=None, message=None):
split = input.msg.split("/")
if len(split) == 4:
nick = split[3].lower()
else:
nick = None
find = split[1]
replace = split[2]
for item in conn.history[input.chan].__reversed__():
name, timestamp, msg = item
if msg.startswith("s/"):
# don't correct corrections, it gets really confusing
continue
if nick:
if nick != name.lower():
continue
if find in msg:
if "\x01ACTION" in msg:
msg = msg.replace("\x01ACTION ", "/me ").replace("\x01", "")
message(u"Correction, <{}> {}".format(name, msg.replace(find, "\x02" + replace + "\x02")))
return
else:
continue
return u"Did not find {} in any recent messages.".format(find)

View file

@ -1,60 +0,0 @@
from util import http, hook
## CONSTANTS
exchanges = {
"blockchain": {
"api_url": "https://blockchain.info/ticker",
"func": lambda data: u"Blockchain // Buy: \x0307${:,.2f}\x0f -"
u" Sell: \x0307${:,.2f}\x0f".format(data["USD"]["buy"], data["USD"]["sell"])
},
"coinbase": {
"api_url": "https://coinbase.com/api/v1/prices/spot_rate",
"func": lambda data: u"Coinbase // Current: \x0307${:,.2f}\x0f".format(float(data['amount']))
},
"bitpay": {
"api_url": "https://bitpay.com/api/rates",
"func": lambda data: u"Bitpay // Current: \x0307${:,.2f}\x0f".format(data[0]['rate'])
},
"bitstamp": {
"api_url": "https://www.bitstamp.net/api/ticker/",
"func": lambda data: u"BitStamp // Current: \x0307${:,.2f}\x0f - High: \x0307${:,.2f}\x0f -"
u" Low: \x0307${:,.2f}\x0f - Volume: {:,.2f} BTC".format(float(data['last']),
float(data['high']),
float(data['low']),
float(data['volume']))
}
}
## HOOK FUNCTIONS
@hook.command("btc", autohelp=False)
@hook.command(autohelp=False)
def bitcoin(inp):
"""bitcoin <exchange> -- Gets current exchange rate for bitcoins from several exchanges, default is Blockchain.
Supports MtGox, Bitpay, Coinbase and BitStamp."""
inp = inp.lower()
if inp:
if inp in exchanges:
exchange = exchanges[inp]
else:
return "Invalid Exchange"
else:
exchange = exchanges["blockchain"]
data = http.get_json(exchange["api_url"])
func = exchange["func"]
return func(data)
@hook.command("ltc", autohelp=False)
@hook.command(autohelp=False)
def litecoin(inp, message=None):
"""litecoin -- gets current exchange rate for litecoins from BTC-E"""
data = http.get_json("https://btc-e.com/api/2/ltc_usd/ticker")
ticker = data['ticker']
message("Current: \x0307${:,.2f}\x0f - High: \x0307${:,.2f}\x0f"
" - Low: \x0307${:,.2f}\x0f - Volume: {:,.2f} LTC".format(ticker['buy'], ticker['high'], ticker['low'],
ticker['vol_cur']))

Binary file not shown.

View file

@ -1,620 +0,0 @@
1 Stone
1:1 Granite
1:2 Polished Granite
1:3 Diorite
1:4 Polished Diorite
1:5 Andesite
1:6 Polished Andesite
2 Grass
3 Dirt
3:1 Dirt (No Grass)
3:2 Podzol
4 Cobblestone
5 Wooden Plank (Oak)
5:1 Wooden Plank (Spruce)
5:2 Wooden Plank (Birch)
5:3 Wooden Plank (Jungle)
5:4 Wooden Plank (Acacia)
5:5 Wooden Plank (Dark Oak)
6 Sapling (Oak)
6:1 Sapling (Spruce)
6:2 Sapling (Birch)
6:3 Sapling (Jungle)
6:4 Sapling (Acacia)
6:5 Sapling (Dark Oak)
7 Bedrock
8 Water
9 Water (No Spread)
10 Lava
11 Lava (No Spread)
12 Sand
12:1 Red Sand
13 Gravel
14 Gold Ore
15 Iron Ore
16 Coal Ore
17 Wood (Oak)
17:1 Wood (Spruce)
17:2 Wood (Birch)
17:3 Wood (Jungle)
17:4 Wood (Oak 4)
17:5 Wood (Oak 5)
18 Leaves (Oak)
18:1 Leaves (Spruce)
18:2 Leaves (Birch)
18:3 Leaves (Jungle)
19 Sponge
20 Glass
21 Lapis Lazuli Ore
22 Lapis Lazuli Block
23 Dispenser
24 Sandstone
24:1 Sandstone (Chiseled)
24:2 Sandstone (Smooth)
25 Note Block
26 Bed (Block)
27 Rail (Powered)
28 Rail (Detector)
29 Sticky Piston
30 Cobweb
31 Tall Grass (Dead Shrub)
31:1 Tall Grass
31:2 Tall Grass (Fern)
32 Dead Shrub
33 Piston
34 Piston (Head)
35 Wool
35:1 Orange Wool
35:2 Magenta Wool
35:3 Light Blue Wool
35:4 Yellow Wool
35:5 Lime Wool
35:6 Pink Wool
35:7 Gray Wool
35:8 Light Gray Wool
35:9 Cyan Wool
35:10 Purple Wool
35:11 Blue Wool
35:12 Brown Wool
35:13 Green Wool
35:14 Red Wool
35:15 Black Wool
36 Piston (Moving)
37 Dandelion
38 Poppy
38:1 Blue Orchid
38:2 Allium
38:4 Red Tulip
38:5 Orange Tulip
38:6 White Tulip
38:7 Pink Tulip
38:8 Oxeye Daisy
39 Brown Mushroom
40 Red Mushroom
41 Block of Gold
42 Block of Iron
43 Stone Slab (Double)
43:1 Sandstone Slab (Double)
43:2 Wooden Slab (Double)
43:3 Cobblestone Slab (Double)
43:4 Brick Slab (Double)
43:5 Stone Brick Slab (Double)
43:6 Nether Brick Slab (Double)
43:7 Quartz Slab (Double)
43:8 Smooth Stone Slab (Double)
43:9 Smooth Sandstone Slab (Double)
44 Stone Slab
44:1 Sandstone Slab
44:2 Wooden Slab
44:3 Cobblestone Slab
44:4 Brick Slab
44:5 Stone Brick Slab
44:6 Nether Brick Slab
44:7 Quartz Slab
45 Brick
46 TNT
47 Bookshelf
48 Moss Stone
49 Obsidian
50 Torch
51 Fire
52 Mob Spawner
53 Wooden Stairs (Oak)
54 Chest
55 Redstone Wire
56 Diamond Ore
57 Block of Diamond
58 Workbench
59 Wheat (Crop)
60 Farmland
61 Furnace
62 Furnace (Smelting)
63 Sign (Block)
64 Wood Door (Block)
65 Ladder
66 Rail
67 Cobblestone Stairs
68 Sign (Wall Block)
69 Lever
70 Stone Pressure Plate
71 Iron Door (Block)
72 Wooden Pressure Plate
73 Redstone Ore
74 Redstone Ore (Glowing)
75 Redstone Torch (Off)
76 Redstone Torch
77 Button (Stone)
78 Snow
79 Ice
80 Snow Block
81 Cactus
82 Clay Block
83 Sugar Cane (Block)
84 Jukebox
85 Fence
86 Pumpkin
87 Netherrack
88 Soul Sand
89 Glowstone
90 Portal
91 Jack-O-Lantern
92 Cake (Block)
93 Redstone Repeater (Block Off)
94 Redstone Repeater (Block On)
95 Stained Glass (White)
95:1 Stained Glass (Orange)
95:2 Stained Glass (Magenta)
95:3 Stained Glass (Light Blue)
95:4 Stained Glass (Yellow)
95:5 Stained Glass (Lime)
95:6 Stained Glass (Pink)
95:7 Stained Glass (Gray)
95:8 Stained Glass (Light Grey)
95:9 Stained Glass (Cyan)
95:10 Stained Glass (Purple)
95:11 Stained Glass (Blue)
95:12 Stained Glass (Brown)
95:13 Stained Glass (Green)
95:14 Stained Glass (Red)
95:15 Stained Glass (Black)
96 Trapdoor
97 Monster Egg (Stone)
97:1 Monster Egg (Cobblestone)
97:2 Monster Egg (Stone Brick)
97:3 Monster Egg (Mossy Stone Brick)
97:4 Monster Egg (Cracked Stone)
97:5 Monster Egg (Chiseled Stone)
98 Stone Bricks
98:1 Mossy Stone Bricks
98:2 Cracked Stone Bricks
98:3 Chiseled Stone Brick
99 Brown Mushroom (Block)
100 Red Mushroom (Block)
101 Iron Bars
102 Glass Pane
103 Melon (Block)
104 Pumpkin Vine
105 Melon Vine
106 Vines
107 Fence Gate
108 Brick Stairs
109 Stone Brick Stairs
110 Mycelium
111 Lily Pad
112 Nether Brick
113 Nether Brick Fence
114 Nether Brick Stairs
115 Nether Wart
116 Enchantment Table
117 Brewing Stand (Block)
118 Cauldron (Block)
119 End Portal
120 End Portal Frame
121 End Stone
122 Dragon Egg
123 Redstone Lamp
124 Redstone Lamp (On)
125 Oak-Wood Slab (Double)
125:1 Spruce-Wood Slab (Double)
125:2 Birch-Wood Slab (Double)
125:3 Jungle-Wood Slab (Double)
125:4 Acacia Wood Slab (Double)
125:5 Dark Oak Wood Slab (Double)
126 Oak-Wood Slab
126:1 Spruce-Wood Slab
126:2 Birch-Wood Slab
126:3 Jungle-Wood Slab
126:4 Acacia Wood Slab
126:5 Dark Oak Wood Slab
127 Cocoa Plant
128 Sandstone Stairs
129 Emerald Ore
130 Ender Chest
131 Tripwire Hook
132 Tripwire
133 Block of Emerald
134 Wooden Stairs (Spruce)
135 Wooden Stairs (Birch)
136 Wooden Stairs (Jungle)
137 Command Block
138 Beacon
139 Cobblestone Wall
139:1 Mossy Cobblestone Wall
140 Flower Pot (Block)
141 Carrot (Crop)
142 Potatoes (Crop)
143 Button (Wood)
144 Head Block (Skeleton)
144:1 Head Block (Wither)
144:2 Head Block (Zombie)
144:3 Head Block (Steve)
144:4 Head Block (Creeper)
145 Anvil
145:1 Anvil (Slightly Damaged)
145:2 Anvil (Very Damaged)
146 Trapped Chest
147 Weighted Pressure Plate (Light)
148 Weighted Pressure Plate (Heavy)
149 Redstone Comparator (Off)
150 Redstone Comparator (On)
151 Daylight Sensor
152 Block of Redstone
153 Nether Quartz Ore
154 Hopper
155 Quartz Block
155:1 Chiseled Quartz Block
155:2 Pillar Quartz Block
156 Quartz Stairs
157 Rail (Activator)
158 Dropper
159 Stained Clay (White)
159:1 Stained Clay (Orange)
159:2 Stained Clay (Magenta)
159:3 Stained Clay (Light Blue)
159:4 Stained Clay (Yellow)
159:5 Stained Clay (Lime)
159:6 Stained Clay (Pink)
159:7 Stained Clay (Gray)
159:8 Stained Clay (Light Gray)
159:9 Stained Clay (Cyan)
159:10 Stained Clay (Purple)
159:11 Stained Clay (Blue)
159:12 Stained Clay (Brown)
159:13 Stained Clay (Green)
159:14 Stained Clay (Red)
159:15 Stained Clay (Black)
160 Stained Glass Pane (White)
160:1 Stained Glass Pane (Orange)
160:2 Stained Glass Pane (Magenta)
160:3 Stained Glass Pane (Light Blue)
160:4 Stained Glass Pane (Yellow)
160:5 Stained Glass Pane (Lime)
160:6 Stained Glass Pane (Pink)
160:7 Stained Glass Pane (Gray)
160:8 Stained Glass Pane (Light Gray)
160:9 Stained Glass Pane (Cyan)
160:10 Stained Glass Pane (Purple)
160:11 Stained Glass Pane (Blue)
160:12 Stained Glass Pane (Brown)
160:13 Stained Glass Pane (Green)
160:14 Stained Glass Pane (Red)
160:15 Stained Glass Pane (Black)
162 Wood (Acacia Oak)
162:1 Wood (Dark Oak)
163 Wooden Stairs (Acacia)
164 Wooden Stairs (Dark Oak)
165 Slime Block
170 Hay Bale
171 Carpet (White)
171:1 Carpet (Orange)
171:2 Carpet (Magenta)
171:3 Carpet (Light Blue)
171:4 Carpet (Yellow)
171:5 Carpet (Lime)
171:6 Carpet (Pink)
171:7 Carpet (Grey)
171:8 Carpet (Light Gray)
171:9 Carpet (Cyan)
171:10 Carpet (Purple)
171:11 Carpet (Blue)
171:12 Carpet (Brown)
171:13 Carpet (Green)
171:14 Carpet (Red)
171:15 Carpet (Black)
172 Hardened Clay
173 Block of Coal
174 Packed Ice
175 Sunflower
175:1 Lilac
175:2 Double Tallgrass
175:3 Large Fern
175:4 Rose Bush
175:5 Peony
256 Iron Shovel
257 Iron Pickaxe
258 Iron Axe
259 Flint and Steel
260 Apple
261 Bow
262 Arrow
263 Coal
263:1 Charcoal
264 Diamond Gem
265 Iron Ingot
266 Gold Ingot
267 Iron Sword
268 Wooden Sword
269 Wooden Shovel
270 Wooden Pickaxe
271 Wooden Axe
272 Stone Sword
273 Stone Shovel
274 Stone Pickaxe
275 Stone Axe
276 Diamond Sword
277 Diamond Shovel
278 Diamond Pickaxe
279 Diamond Axe
280 Stick
281 Bowl
282 Mushroom Stew
283 Gold Sword
284 Gold Shovel
285 Gold Pickaxe
286 Gold Axe
287 String
288 Feather
289 Gunpowder
290 Wooden Hoe
291 Stone Hoe
292 Iron Hoe
293 Diamond Hoe
294 Gold Hoe
295 Wheat Seeds
296 Wheat
297 Bread
298 Leather Helmet
299 Leather Chestplate
300 Leather Leggings
301 Leather Boots
302 Chainmail Helmet
303 Chainmail Chestplate
304 Chainmail Leggings
305 Chainmail Boots
306 Iron Helmet
307 Iron Chestplate
308 Iron Leggings
309 Iron Boots
310 Diamond Helmet
311 Diamond Chestplate
312 Diamond Leggings
313 Diamond Boots
314 Gold Helmet
315 Gold Chestplate
316 Gold Leggings
317 Gold Boots
318 Flint
319 Raw Porkchop
320 Cooked Porkchop
321 Painting
322 Golden Apple
322:1 Enchanted Golden Apple
323 Sign
324 Wooden Door
325 Bucket
326 Bucket (Water)
327 Bucket (Lava)
328 Minecart
329 Saddle
330 Iron Door
331 Redstone Dust
332 Snowball
333 Boat
334 Leather
335 Bucket (Milk)
336 Clay Brick
337 Clay
338 Sugar Cane
339 Paper
340 Book
341 Slime Ball
342 Minecart (Storage)
343 Minecart (Powered)
344 Egg
345 Compass
346 Fishing Rod
347 Watch
348 Glowstone Dust
349 Raw Fish
349:1 Raw Salmon
349:2 Clownfish
349:3 Pufferfish
350 Cooked Fish
350:1 Cooked Salmon
350:2 Clownfish
350:3 Pufferfish
351 Ink Sack
351:1 Rose Red Dye
351:2 Cactus Green Dye
351:3 Cocoa Bean
351:4 Lapis Lazuli
351:5 Purple Dye
351:6 Cyan Dye
351:7 Light Gray Dye
351:8 Gray Dye
351:9 Pink Dye
351:10 Lime Dye
351:11 Dandelion Yellow Dye
351:12 Light Blue Dye
351:13 Magenta Dye
351:14 Orange Dye
351:15 Bone Meal
352 Bone
353 Sugar
354 Cake
355 Bed
356 Redstone Repeater
357 Cookie
358 Map
359 Shears
360 Melon (Slice)
361 Pumpkin Seeds
362 Melon Seeds
363 Raw Beef
364 Steak
365 Raw Chicken
366 Cooked Chicken
367 Rotten Flesh
368 Ender Pearl
369 Blaze Rod
370 Ghast Tear
371 Gold Nugget
372 Nether Wart Seeds
373 Water Bottle
373:16 Awkward Potion
373:32 Thick Potion
373:64 Mundane Potion
373:8193 Regeneration Potion (0:45)
373:8194 Swiftness Potion (3:00)
373:8195 Fire Resistance Potion (3:00)
373:8196 Poison Potion (0:45)
373:8197 Healing Potion
373:8198 Night Vision Potion (3:00)
373:8200 Weakness Potion (1:30)
373:8201 Strength Potion (3:00)
373:8202 Slowness Potion (1:30)
373:8204 Harming Potion
373:8205 Water Breathing Potion (3:00)
373:8206 Invisibility Potion (3:00)
373:8225 Regeneration Potion II (0:22)
373:8226 Swiftness Potion II (1:30)
373:8228 Poison Potion II (0:22)
373:8229 Healing Potion II
373:8233 Strength Potion II (1:30)
373:8236 Harming Potion II
373:8257 Regeneration Potion (2:00)
373:8258 Swiftness Potion (8:00)
373:8259 Fire Resistance Potion (8:00)
373:8260 Poison Potion (2:00)
373:8262 Night Vision Potion (8:00)
373:8264 Weakness Potion (4:00)
373:8265 Strength Potion (8:00)
373:8266 Slowness Potion (4:00)
373:8269 Water Breathing Potion (8:00)
373:8270 Invisibility Potion (8:00)
373:8289 Regeneration Potion II (1:00)
373:8290 Swiftness Potion II (4:00)
373:8292 Poison Potion II (1:00)
373:8297 Strength Potion II (4:00)
373:16385 Regeneration Splash (0:33)
373:16386 Swiftness Splash (2:15)
373:16387 Fire Resistance Splash (2:15)
373:16388 Poison Splash (0:33)
373:16389 Healing Splash
373:16390 Night Vision Splash (2:15)
373:16392 Weakness Splash (1:07)
373:16393 Strength Splash (2:15)
373:16394 Slowness Splash (1:07)
373:16396 Harming Splash
373:16397 Breathing Splash (2:15)
373:16398 Invisibility Splash (2:15)
373:16417 Regeneration Splash II (0:16)
373:16418 Swiftness Splash II (1:07)
373:16420 Poison Splash II (0:16)
373:16421 Healing Splash II
373:16425 Strength Splash II (1:07)
373:16428 Harming Splash II
373:16449 Regeneration Splash (1:30)
373:16450 Swiftness Splash (6:00)
373:16451 Fire Resistance Splash (6:00)
373:16452 Poison Splash (1:30)
373:16454 Night Vision Splash (6:00)
373:16456 Weakness Splash (3:00)
373:16457 Strength Splash (6:00)
373:16458 Slowness Splash (3:00)
373:16461 Breathing Splash (6:00)
373:16462 Invisibility Splash (6:00)
373:16481 Regeneration Splash II (0:45)
373:16482 Swiftness Splash II (3:00)
373:16484 Poison Splash II (0:45)
373:16489 Strength Splash II (3:00)
374 Glass Bottle
375 Spider Eye
376 Fermented Spider Eye
377 Blaze Powder
378 Magma Cream
379 Brewing Stand
380 Cauldron
381 Eye of Ender
382 Glistering Melon (Slice)
383:50 Spawn Egg (Creeper)
383:51 Spawn Egg (Skeleton)
383:52 Spawn Egg (Spider)
383:54 Spawn Egg (Zombie)
383:55 Spawn Egg (Slime)
383:56 Spawn Egg (Ghast)
383:57 Spawn Egg (Zombie Pigmen)
383:58 Spawn Egg (Endermen)
383:59 Spawn Egg (Cave Spider)
383:60 Spawn Egg (Silverfish)
383:61 Spawn Egg (Blaze)
383:62 Spawn Egg (Magma Cube)
383:65 Spawn Egg (Bat)
383:66 Spawn Egg (Witch)
383:90 Spawn Egg (Pig)
383:91 Spawn Egg (Sheep)
383:92 Spawn Egg (Cow)
383:93 Spawn Egg (Chicken)
383:94 Spawn Egg (Squid)
383:95 Spawn Egg (Wolf)
383:96 Spawn Egg (Mooshroom)
383:98 Spawn Egg (Ocelot)
383:100 Spawn Egg (Horse)
383:120 Spawn Egg (Villager)
384 Bottle of Enchanting
385 Fire Charge
386 Book and Quill
387 Written Book
388 Emerald
389 Item Frame
390 Flower Pot
391 Carrot
392 Potato
393 Baked Potato
394 Poisonous Potato
395 Empty Map
396 Golden Carrot
397 Head (Skeleton)
397:1 Head (Wither)
397:2 Head (Zombie)
397:3 Head (Steve)
397:4 Head (Creeper)
398 Carrot on a Stick
399 Nether Star
400 Pumpkin Pie
401 Firework Rocket
402 Firework Star
403 Enchanted Book
404 Redstone Comparator
405 Nether Brick (Item)
406 Nether Quartz
407 Minecart (TNT)
408 Minecart (Hopper)
417 Iron Horse Armor
418 Gold Horse Armor
419 Diamond Horse Armor
420 Lead
421 Name Tag
422 Minecart (Command Block)
2256 Music Disk (13)
2257 Music Disk (Cat)
2258 Music Disk (Blocks)
2259 Music Disk (Chirp)
2260 Music Disk (Far)
2261 Music Disk (Mall)
2262 Music Disk (Mellohi)
2263 Music Disk (Stal)
2264 Music Disk (Strad)
2265 Music Disk (Ward)
2266 Music Disk (11)
2267 Music Disk (Wait)

View file

@ -1,79 +0,0 @@
{
"templates": [
"rips off {user}'s {limbs} and leaves them to die.",
"grabs {user}'s head and rips it clean off their body.",
"grabs a {gun} and riddles {user}'s body with bullets.",
"gags and ties {user} then throws them off a {tall_thing}.",
"crushes {user} with a huge spiked {spiked_thing}.",
"glares at {user} until they die of boredom.",
"stabs {user} in the heart a few times with a {weapon_stab}.",
"rams a {weapon_explosive} up {user}'s ass and lets off a few rounds.",
"crushes {user}'s skull in with a {weapon_crush}.",
"unleashes the armies of Isengard on {user}.",
"gags and ties {user} then throws them off a {tall_thing} to their death.",
"reaches out and punches right through {user}'s chest.",
"slices {user}'s limbs off with a {weapon_slice}.",
"throws {user} to Cthulu and watches them get ripped to shreds.",
"feeds {user} to an owlbear who then proceeds to maul them violently.",
"turns {user} into a snail and covers then in salt.",
"snacks on {user}'s dismembered body.",
"stuffs {bomb} up {user}'s ass and waits for it to go off.",
"puts {user} into a sack, throws the sack in the river, and hurls the river into space.",
"goes bowling with {user}'s bloody disembodied head.",
"sends {user} to /dev/null!",
"feeds {user} coke and mentos till they violently explode."
],
"parts": {
"gun": [
"AK47",
"machine gun",
"automatic pistol",
"Uzi"
],
"limbs": [
"legs",
"arms",
"limbs"
],
"weapon_stab": [
"knife",
"shard of glass",
"sword blade",
"butchers knife",
"corkscrew"
],
"weapon_slice": [
"sharpened katana",
"chainsaw",
"polished axe"
],
"weapon_crush": [
"spiked mace",
"baseball bat",
"wooden club",
"massive steel ball",
"heavy iron rod"
],
"weapon_explosive": [
"rocket launcher",
"grenade launcher",
"napalm launcher"
],
"tall_thing": [
"bridge",
"tall building",
"cliff",
"mountain"
],
"spiked_thing": [
"boulder",
"rock",
"barrel of rocks"
],
"bomb": [
"a bomb",
"some TNT",
"a bunch of C4"
]
}
}

View file

@ -1,105 +0,0 @@
import os
import base64
import json
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from util import hook
# helper functions to pad and unpad a string to a specified block size
# <http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256>
BS = AES.block_size
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s: s[0:-ord(s[-1])]
# helper functions to encrypt and encode a string with AES and base64
encode_aes = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
decode_aes = lambda c, s: unpad(c.decrypt(base64.b64decode(s)))
db_ready = False
def db_init(db):
"""check to see that our db has the the encryption table."""
global db_ready
if not db_ready:
db.execute("create table if not exists encryption(encrypted, iv, "
"primary key(encrypted))")
db.commit()
db_ready = True
def get_salt(bot):
"""generate an encryption salt if none exists, then returns the salt"""
if not bot.config.get("random_salt", False):
bot.config["random_salt"] = hashlib.md5(os.urandom(16)).hexdigest()
json.dump(bot.config, open('config', 'w'), sort_keys=True, indent=2)
return bot.config["random_salt"]
@hook.command
def encrypt(inp, bot=None, db=None, notice=None):
"""encrypt <pass> <string> -- Encrypts <string> with <pass>. (<string> can only be decrypted using this bot)"""
db_init(db)
split = inp.split(" ")
# if there is only one argument, return the help message
if len(split) == 1:
notice(encrypt.__doc__)
return
# generate the key from the password and salt
password = split[0]
salt = get_salt(bot)
key = PBKDF2(password, salt)
# generate the IV and encode it to store in the database
iv = Random.new().read(AES.block_size)
iv_encoded = base64.b64encode(iv)
# create the AES cipher and encrypt/encode the text with it
text = " ".join(split[1:])
cipher = AES.new(key, AES.MODE_CBC, iv)
encoded = encode_aes(cipher, text)
# store the encoded text and IV in the DB for decoding later
db.execute("insert or replace into encryption(encrypted, iv)"
"values(?,?)", (encoded, iv_encoded))
db.commit()
return encoded
@hook.command
def decrypt(inp, bot=None, db=None, notice=None):
"""decrypt <pass> <string> -- Decrypts <string> with <pass>. (can only decrypt strings encrypted on this bot)"""
if not db_ready:
db_init(db)
split = inp.split(" ")
# if there is only one argument, return the help message
if len(split) == 1:
notice(decrypt.__doc__)
return
# generate the key from the password and salt
password = split[0]
salt = get_salt(bot)
key = PBKDF2(password, salt)
text = " ".join(split[1:])
# get the encoded IV from the database and decode it
iv_encoded = db.execute("select iv from encryption where"
" encrypted=?", (text,)).fetchone()[0]
iv = base64.b64decode(iv_encoded)
# create AES cipher, decode text, decrypt text, and unpad it
cipher = AES.new(key, AES.MODE_CBC, iv)
return decode_aes(cipher, text)

View file

@ -1,13 +0,0 @@
from util import hook, http, web
from subprocess import check_output, CalledProcessError
@hook.command
def freddycode(inp):
"""freddycode <code> - Check if the Freddy Fresh code is correct."""
try:
return "Freddy: '%s' ist %s" % (inp, \
check_output(["/bin/freddycheck", inp]))
except CalledProcessError as err:
return "Freddy: Skript returned %s" % (str(err))

View file

@ -1,22 +0,0 @@
from util import hook
from urllib import unquote
@hook.command(autohelp=False)
def googleurl(inp, db=None, nick=None):
"""googleurl [nickname] - Converts Google urls (google.com/url) to normal urls
where possible, in the specified nickname's last message. If nickname isn't provided,
action will be performed on user's last message"""
if not inp:
inp = nick
last_message = db.execute("select name, quote from seen_user where name"
" like ? and chan = ?", (inp.lower(), input.chan.lower())).fetchone()
if last_message:
msg = last_message[1]
out = ", ".join([(unquote(a[4:]) if a[:4] == "url=" else "") for a in msg.split("&")])\
.replace(", ,", "").strip()
return out if out else "No matches in your last message."
else:
if inp == nick:
return "You haven't said anything in this channel yet!"
else:
return "That user hasn't said anything in this channel yet!"

View file

@ -1,89 +0,0 @@
from collections import deque
from util import hook, timesince
import time
import re
db_ready = []
def db_init(db, conn_name):
"""check to see that our db has the the seen table (connection name is for caching the result per connection)"""
global db_ready
if db_ready.count(conn_name) < 1:
db.execute("create table if not exists seen_user(name, time, quote, chan, host, "
"primary key(name, chan))")
db.commit()
db_ready.append(conn_name)
def track_seen(input, message_time, db, conn):
""" Tracks messages for the .seen command """
db_init(db, conn)
# keep private messages private
if input.chan[:1] == "#" and not re.findall('^s/.*/.*/$', input.msg.lower()):
db.execute("insert or replace into seen_user(name, time, quote, chan, host)"
"values(?,?,?,?,?)", (input.nick.lower(), message_time, input.msg,
input.chan, input.mask))
db.commit()
def track_history(input, message_time, conn):
try:
history = conn.history[input.chan]
except KeyError:
conn.history[input.chan] = deque(maxlen=100)
history = conn.history[input.chan]
data = (input.nick, message_time, input.msg)
history.append(data)
@hook.singlethread
@hook.event('PRIVMSG', ignorebots=False)
def chat_tracker(paraml, input=None, db=None, conn=None):
message_time = time.time()
track_seen(input, message_time, db, conn)
track_history(input, message_time, conn)
@hook.command(autohelp=False)
def resethistory(inp, input=None, conn=None):
"""resethistory - Resets chat history for the current channel"""
try:
conn.history[input.chan].clear()
return "Reset chat history for current channel."
except KeyError:
# wat
return "There is no history for this channel."
"""seen.py: written by sklnd in about two beers July 2009"""
@hook.command
def seen(inp, nick='', chan='', db=None, input=None, conn=None):
"""seen <nick> <channel> -- Tell when a nickname was last in active in one of this bot's channels."""
if input.conn.nick.lower() == inp.lower():
return "You need to get your eyes checked."
if inp.lower() == nick.lower():
return "Have you looked in a mirror lately?"
if not re.match("^[A-Za-z0-9_|.\-\]\[]*$", inp.lower()):
return "I can't look up that name, its impossible to use!"
db_init(db, conn.name)
last_seen = db.execute("select name, time, quote from seen_user where name"
" like ? and chan = ?", (inp, chan)).fetchone()
if last_seen:
reltime = timesince.timesince(last_seen[1])
if last_seen[0] != inp.lower(): # for glob matching
inp = last_seen[0]
if last_seen[2][0:1] == "\x01":
return '{} was last seen {} ago: * {} {}'.format(inp, reltime, inp,
last_seen[2][8:-1])
else:
return '{} was last seen {} ago saying: {}'.format(inp, reltime, last_seen[2])
else:
return "I've never seen {} talking in this channel.".format(inp)

View file

@ -1,82 +0,0 @@
import re
import random
from util import hook, http, web
base_url = "http://reddit.com/r/{}/.json"
imgur_re = re.compile(r'http://(?:i\.)?imgur\.com/(a/)?(\w+\b(?!/))\.?\w?')
album_api = "https://api.imgur.com/3/album/{}/images.json"
def is_valid(data):
if data["domain"] in ["i.imgur.com", "imgur.com"]:
return True
else:
return False
@hook.command(autohelp=False)
def imgur(inp):
"""imgur [subreddit] -- Gets the first page of imgur images from [subreddit] and returns a link to them.
If [subreddit] is undefined, return any imgur images"""
if inp:
# see if the input ends with "nsfw"
show_nsfw = inp.endswith(" nsfw")
# remove "nsfw" from the input string after checking for it
if show_nsfw:
inp = inp[:-5].strip().lower()
url = base_url.format(inp.strip())
else:
url = "http://www.reddit.com/domain/imgur.com/.json"
show_nsfw = False
try:
data = http.get_json(url, user_agent=http.ua_chrome)
except Exception as e:
return "Error: " + str(e)
data = data["data"]["children"]
random.shuffle(data)
# filter list to only have imgur links
filtered_posts = [i["data"] for i in data if is_valid(i["data"])]
if not filtered_posts:
return "No images found."
items = []
headers = {
"Authorization": "Client-ID b5d127e6941b07a"
}
# loop over the list of posts
for post in filtered_posts:
if post["over_18"] and not show_nsfw:
continue
match = imgur_re.search(post["url"])
if match.group(1) == 'a/':
# post is an album
url = album_api.format(match.group(2))
images = http.get_json(url, headers=headers)["data"]
# loop over the images in the album and add to the list
for image in images:
items.append(image["id"])
elif match.group(2) is not None:
# post is an image
items.append(match.group(2))
if not items:
return "No images found (use .imgur <subreddit> nsfw to show explicit content)"
if show_nsfw:
return "{} \x02NSFW\x02".format(web.isgd("http://imgur.com/" + ','.join(items)))
else:
return web.isgd("http://imgur.com/" + ','.join(items))

View file

@ -1,33 +0,0 @@
import json
from util import hook, textgen
def get_generator(_json, variables):
data = json.loads(_json)
return textgen.TextGenerator(data["templates"],
data["parts"], variables=variables)
@hook.command
def kill(inp, action=None, nick=None, conn=None, notice=None):
"""kill <user> -- Makes the bot kill <user>."""
target = inp.strip()
if " " in target:
notice("Invalid username!")
return
# if the user is trying to make the bot kill itself, kill them
if target.lower() == conn.nick.lower() or target.lower() == "itself":
target = nick
variables = {
"user": target
}
with open("plugins/data/kills.json") as f:
generator = get_generator(f.read(), variables)
# act out the message
action(generator.generate_string())

View file

@ -1,154 +0,0 @@
import time
import random
from util import hook, http, web, text
## CONSTANTS
base_url = "http://api.bukget.org/3/"
search_url = base_url + "search/plugin_name/like/{}"
random_url = base_url + "plugins/bukkit/?start={}&size=1"
details_url = base_url + "plugins/bukkit/{}"
categories = http.get_json("http://api.bukget.org/3/categories")
count_total = sum([cat["count"] for cat in categories])
count_categories = {cat["name"].lower(): int(cat["count"]) for cat in categories} # dict comps!
class BukgetError(Exception):
def __init__(self, code, text):
self.code = code
self.text = text
def __str__(self):
return self.text
## DATA FUNCTIONS
def plugin_search(term):
""" searches for a plugin with the bukget API and returns the slug """
term = term.lower().strip()
search_term = http.quote_plus(term)
try:
results = http.get_json(search_url.format(search_term))
except (http.HTTPError, http.URLError) as e:
raise BukgetError(500, "Error Fetching Search Page: {}".format(e))
if not results:
raise BukgetError(404, "No Results Found")
for result in results:
if result["slug"] == term:
return result["slug"]
return results[0]["slug"]
def plugin_random():
""" gets a random plugin from the bukget API and returns the slug """
results = None
while not results:
plugin_number = random.randint(1, count_total)
print "trying {}".format(plugin_number)
try:
results = http.get_json(random_url.format(plugin_number))
except (http.HTTPError, http.URLError) as e:
raise BukgetError(500, "Error Fetching Search Page: {}".format(e))
return results[0]["slug"]
def plugin_details(slug):
""" takes a plugin slug and returns details from the bukget API """
slug = slug.lower().strip()
try:
details = http.get_json(details_url.format(slug))
except (http.HTTPError, http.URLError) as e:
raise BukgetError(500, "Error Fetching Details: {}".format(e))
return details
## OTHER FUNCTIONS
def format_output(data):
""" takes plugin data and returns two strings representing information about that plugin """
name = data["plugin_name"]
description = text.truncate_str(data['description'], 30)
url = data['website']
authors = data['authors'][0]
authors = authors[0] + u"\u200b" + authors[1:]
stage = data['stage']
current_version = data['versions'][0]
last_update = time.strftime('%d %B %Y %H:%M',
time.gmtime(current_version['date']))
version_number = data['versions'][0]['version']
bukkit_versions = ", ".join(current_version['game_versions'])
link = web.try_isgd(current_version['link'])
if description:
line_a = u"\x02{}\x02, by \x02{}\x02 - {} - ({}) \x02{}".format(name, authors, description, stage, url)
else:
line_a = u"\x02{}\x02, by \x02{}\x02 ({}) \x02{}".format(name, authors, stage, url)
line_b = u"Last release: \x02v{}\x02 for \x02{}\x02 at {} \x02{}\x02".format(version_number, bukkit_versions,
last_update, link)
return line_a, line_b
## HOOK FUNCTIONS
@hook.command('plugin')
@hook.command
def bukget(inp, reply=None, message=None):
"""bukget <slug/name> - Look up a plugin on dev.bukkit.org"""
# get the plugin slug using search
try:
slug = plugin_search(inp)
except BukgetError as e:
return e
# get the plugin info using the slug
try:
data = plugin_details(slug)
except BukgetError as e:
return e
# format the final message and send it to IRC
line_a, line_b = format_output(data)
reply(line_a)
message(line_b)
@hook.command(autohelp=None)
def randomplugin(inp, reply=None, message=None):
"""randomplugin - Gets a random plugin from dev.bukkit.org"""
# get a random plugin slug
try:
slug = plugin_random()
except BukgetError as e:
return e
# get the plugin info using the slug
try:
data = plugin_details(slug)
except BukgetError as e:
return e
# format the final message and send it to IRC
line_a, line_b = format_output(data)
reply(line_a)
message(line_b)

View file

@ -1,232 +0,0 @@
import socket
import struct
import json
import traceback
from util import hook
try:
import DNS
has_dns = True
except ImportError:
has_dns = False
mc_colors = [(u'\xa7f', u'\x0300'), (u'\xa70', u'\x0301'), (u'\xa71', u'\x0302'), (u'\xa72', u'\x0303'),
(u'\xa7c', u'\x0304'), (u'\xa74', u'\x0305'), (u'\xa75', u'\x0306'), (u'\xa76', u'\x0307'),
(u'\xa7e', u'\x0308'), (u'\xa7a', u'\x0309'), (u'\xa73', u'\x0310'), (u'\xa7b', u'\x0311'),
(u'\xa71', u'\x0312'), (u'\xa7d', u'\x0313'), (u'\xa78', u'\x0314'), (u'\xa77', u'\x0315'),
(u'\xa7l', u'\x02'), (u'\xa79', u'\x0310'), (u'\xa7o', u'\t'), (u'\xa7m', u'\x13'),
(u'\xa7r', u'\x0f'), (u'\xa7n', u'\x15')]
## EXCEPTIONS
class PingError(Exception):
def __init__(self, text):
self.text = text
def __str__(self):
return self.text
class ParseError(Exception):
def __init__(self, text):
self.text = text
def __str__(self):
return self.text
## MISC
def unpack_varint(s):
d = 0
i = 0
while True:
b = ord(s.recv(1))
d |= (b & 0x7F) << 7 * i
i += 1
if not b & 0x80:
return d
pack_data = lambda d: struct.pack('>b', len(d)) + d
pack_port = lambda i: struct.pack('>H', i)
## DATA FUNCTIONS
def mcping_modern(host, port):
""" pings a server using the modern (1.7+) protocol and returns data """
try:
# connect to the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
except socket.gaierror:
raise PingError("Invalid hostname")
except socket.timeout:
raise PingError("Request timed out")
# send handshake + status request
s.send(pack_data("\x00\x00" + pack_data(host.encode('utf8')) + pack_port(port) + "\x01"))
s.send(pack_data("\x00"))
# read response
unpack_varint(s) # Packet length
unpack_varint(s) # Packet ID
l = unpack_varint(s) # String length
if not l > 1:
raise PingError("Invalid response")
d = ""
while len(d) < l:
d += s.recv(1024)
# Close our socket
s.close()
except socket.error:
raise PingError("Socket Error")
# Load json and return
data = json.loads(d.decode('utf8'))
try:
version = data["version"]["name"]
try:
desc = u" ".join(data["description"]["text"].split())
except TypeError:
desc = u" ".join(data["description"].split())
max_players = data["players"]["max"]
online = data["players"]["online"]
except Exception as e:
# TODO: except Exception is bad
traceback.print_exc(e)
raise PingError("Unknown Error: {}".format(e))
output = {
"motd": format_colors(desc),
"motd_raw": desc,
"version": version,
"players": online,
"players_max": max_players
}
return output
def mcping_legacy(host, port):
""" pings a server using the legacy (1.6 and older) protocol and returns data """
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
sock.send('\xfe\x01')
response = sock.recv(1)
except socket.gaierror:
raise PingError("Invalid hostname")
except socket.timeout:
raise PingError("Request timed out")
if response[0] != '\xff':
raise PingError("Invalid response")
length = struct.unpack('!h', sock.recv(2))[0]
values = sock.recv(length * 2).decode('utf-16be')
data = values.split(u'\x00') # try to decode data using new format
if len(data) == 1:
# failed to decode data, server is using old format
data = values.split(u'\xa7')
output = {
"motd": format_colors(" ".join(data[0].split())),
"motd_raw": data[0],
"version": None,
"players": data[1],
"players_max": data[2]
}
else:
# decoded data, server is using new format
output = {
"motd": format_colors(" ".join(data[3].split())),
"motd_raw": data[3],
"version": data[2],
"players": data[4],
"players_max": data[5]
}
sock.close()
return output
## FORMATTING/PARSING FUNCTIONS
def check_srv(domain):
""" takes a domain and finds minecraft SRV records """
DNS.DiscoverNameServers()
srv_req = DNS.Request(qtype='srv')
srv_result = srv_req.req('_minecraft._tcp.{}'.format(domain))
for getsrv in srv_result.answers:
if getsrv['typename'] == 'SRV':
data = [getsrv['data'][2], getsrv['data'][3]]
return data
def parse_input(inp):
""" takes the input from the mcping command and returns the host and port """
inp = inp.strip().split(" ")[0]
if ":" in inp:
# the port is defined in the input string
host, port = inp.split(":", 1)
try:
port = int(port)
if port > 65535 or port < 0:
raise ParseError("The port '{}' is invalid.".format(port))
except ValueError:
raise ParseError("The port '{}' is invalid.".format(port))
return host, port
if has_dns:
# the port is not in the input string, but we have PyDNS so look for a SRV record
srv_data = check_srv(inp)
if srv_data:
return str(srv_data[1]), int(srv_data[0])
# return default port
return inp, 25565
def format_colors(motd):
for original, replacement in mc_colors:
motd = motd.replace(original, replacement)
motd = motd.replace(u"\xa7k", "")
return motd
def format_output(data):
if data["version"]:
return u"{motd}\x0f - {version}\x0f - {players}/{players_max}" \
u" players.".format(**data).replace("\n", u"\x0f - ")
else:
return u"{motd}\x0f - {players}/{players_max}" \
u" players.".format(**data).replace("\n", u"\x0f - ")
@hook.command
@hook.command("mcp")
def mcping(inp):
"""mcping <server>[:port] - Ping a Minecraft server to check status."""
try:
host, port = parse_input(inp)
except ParseError as e:
return "Could not parse input ({})".format(e)
try:
data = mcping_modern(host, port)
except PingError:
try:
data = mcping_legacy(host, port)
except PingError as e:
return "Could not ping server, is it offline? ({})".format(e)
return format_output(data)

View file

@ -1,101 +0,0 @@
import json
from util import hook, http
NAME_URL = "https://account.minecraft.net/buy/frame/checkName/{}"
PAID_URL = "http://www.minecraft.net/haspaid.jsp"
class McuError(Exception):
pass
def get_status(name):
""" takes a name and returns status """
try:
name_encoded = http.quote_plus(name)
response = http.get(NAME_URL.format(name_encoded))
except (http.URLError, http.HTTPError) as e:
raise McuError("Could not get name status: {}".format(e))
if "OK" in response:
return "free"
elif "TAKEN" in response:
return "taken"
elif "invalid characters" in response:
return "invalid"
def get_profile(name):
profile = {}
# form the profile request
request = {
"name": name,
"agent": "minecraft"
}
# submit the profile request
try:
headers = {"Content-Type": "application/json"}
r = http.get_json(
'https://api.mojang.com/profiles/page/1',
post_data=json.dumps(request),
headers=headers
)
except (http.URLError, http.HTTPError) as e:
raise McuError("Could not get profile status: {}".format(e))
user = r["profiles"][0]
profile["name"] = user["name"]
profile["id"] = user["id"]
profile["legacy"] = user.get("legacy", False)
try:
response = http.get(PAID_URL, user=name)
except (http.URLError, http.HTTPError) as e:
raise McuError("Could not get payment status: {}".format(e))
if "true" in response:
profile["paid"] = True
else:
profile["paid"] = False
return profile
@hook.command("haspaid")
@hook.command("mcpaid")
@hook.command
def mcuser(inp):
"""mcpaid <username> -- Gets information about the Minecraft user <account>."""
user = inp.strip()
try:
# get status of name (does it exist?)
name_status = get_status(user)
except McuError as e:
return e
if name_status == "taken":
try:
# get information about user
profile = get_profile(user)
except McuError as e:
return "Error: {}".format(e)
profile["lt"] = ", legacy" if profile["legacy"] else ""
if profile["paid"]:
return u"The account \x02{name}\x02 ({id}{lt}) exists. It is a \x02paid\x02" \
u" account.".format(**profile)
else:
return u"The account \x02{name}\x02 ({id}{lt}) exists. It \x034\x02is NOT\x02\x0f a paid" \
u" account.".format(**profile)
elif name_status == "free":
return u"The account \x02{}\x02 does not exist.".format(user)
elif name_status == "invalid":
return u"The name \x02{}\x02 contains invalid characters.".format(user)
else:
# if you see this, panic
return "Unknown Error."

View file

@ -1,51 +0,0 @@
import re
from util import hook, http, text
api_url = "http://minecraft.gamepedia.com/api.php?action=opensearch"
mc_url = "http://minecraft.gamepedia.com/"
@hook.command
def mcwiki(inp):
"""mcwiki <phrase> -- Gets the first paragraph of
the Minecraft Wiki article on <phrase>."""
try:
j = http.get_json(api_url, search=inp)
except (http.HTTPError, http.URLError) as e:
return "Error fetching search results: {}".format(e)
except ValueError as e:
return "Error reading search results: {}".format(e)
if not j[1]:
return "No results found."
# we remove items with a '/' in the name, because
# gamepedia uses sub-pages for different languages
# for some stupid reason
items = [item for item in j[1] if not "/" in item]
if items:
article_name = items[0].replace(' ', '_').encode('utf8')
else:
# there are no items without /, just return a / one
article_name = j[1][0].replace(' ', '_').encode('utf8')
url = mc_url + http.quote(article_name, '')
try:
page = http.get_html(url)
except (http.HTTPError, http.URLError) as e:
return "Error fetching wiki page: {}".format(e)
for p in page.xpath('//div[@class="mw-content-ltr"]/p'):
if p.text_content():
summary = " ".join(p.text_content().splitlines())
summary = re.sub("\[\d+\]", "", summary)
summary = text.truncate_str(summary, 200)
return u"{} :: {}".format(summary, url)
# this shouldn't happen
return "Unknown Error."

0
disabled_stuff/mtg.py Normal file → Executable file
View file

2
disabled_stuff/mygengo_translate.py Normal file → Executable file
View file

@ -1,7 +1,7 @@
# BING translation plugin by Lukeroge and neersighted
from util import hook
from util import http
import re
import re
import htmlentitydefs
import mygengo

View file

@ -1,95 +0,0 @@
import json
import re
from util import hook, http, text, web
## CONSTANTS
ITEM_URL = "http://www.newegg.com/Product/Product.aspx?Item={}"
API_PRODUCT = "http://www.ows.newegg.com/Products.egg/{}/ProductDetails"
API_SEARCH = "http://www.ows.newegg.com/Search.egg/Advanced"
NEWEGG_RE = (r"(?:(?:www.newegg.com|newegg.com)/Product/Product\.aspx\?Item=)([-_a-zA-Z0-9]+)", re.I)
## OTHER FUNCTIONS
def format_item(item, show_url=True):
""" takes a newegg API item object and returns a description """
title = text.truncate_str(item["Title"], 50)
# format the rating nicely if it exists
if not item["ReviewSummary"]["TotalReviews"] == "[]":
rating = "Rated {}/5 ({} ratings)".format(item["ReviewSummary"]["Rating"],
item["ReviewSummary"]["TotalReviews"][1:-1])
else:
rating = "No Ratings"
if not item["FinalPrice"] == item["OriginalPrice"]:
price = "{FinalPrice}, was {OriginalPrice}".format(**item)
else:
price = item["FinalPrice"]
tags = []
if item["Instock"]:
tags.append("\x02Stock Available\x02")
else:
tags.append("\x02Out Of Stock\x02")
if item["FreeShippingFlag"]:
tags.append("\x02Free Shipping\x02")
if item["IsFeaturedItem"]:
tags.append("\x02Featured\x02")
if item["IsShellShockerItem"]:
tags.append(u"\x02SHELL SHOCKER\u00AE\x02")
# join all the tags together in a comma separated string ("tag1, tag2, tag3")
tag_text = u", ".join(tags)
if show_url:
# create the item URL and shorten it
url = web.try_isgd(ITEM_URL.format(item["NeweggItemNumber"]))
return u"\x02{}\x02 ({}) - {} - {} - {}".format(title, price, rating,
tag_text, url)
else:
return u"\x02{}\x02 ({}) - {} - {}".format(title, price, rating,
tag_text)
## HOOK FUNCTIONS
@hook.regex(*NEWEGG_RE)
def newegg_url(match):
item_id = match.group(1)
item = http.get_json(API_PRODUCT.format(item_id))
return format_item(item, show_url=False)
@hook.command
def newegg(inp):
"""newegg <item name> -- Searches newegg.com for <item name>"""
# form the search request
request = {
"Keyword": inp,
"Sort": "FEATURED"
}
# submit the search request
r = http.get_json(
'http://www.ows.newegg.com/Search.egg/Advanced',
post_data=json.dumps(request)
)
# get the first result
if r["ProductListItems"]:
return format_item(r["ProductListItems"][0])
else:
return "No results found."

View file

@ -1,29 +0,0 @@
from bs4 import BeautifulSoup
from util import hook, http, web
user_url = "http://osrc.dfm.io/{}"
@hook.command
def osrc(inp):
"""osrc <github user> -- Gets an Open Source Report Card for <github user>"""
user_nick = inp.strip()
url = user_url.format(user_nick)
try:
soup = http.get_soup(url)
except (http.HTTPError, http.URLError):
return "Couldn't find any stats for this user."
report = soup.find("div", {"id": "description"}).find("p").get_text()
# Split and join to remove all the excess whitespace, slice the
# string to remove the trailing full stop.
report = " ".join(report.split())[:-1]
short_url = web.try_isgd(url)
return "{} - {}".format(report, short_url)

View file

@ -1,38 +0,0 @@
import datetime
from util import hook, http, timesince
@hook.command("scene")
@hook.command
def pre(inp):
"""pre <query> -- searches scene releases using orlydb.com"""
try:
h = http.get_html("http://orlydb.com/", q=inp)
except http.HTTPError as e:
return 'Unable to fetch results: {}'.format(e)
results = h.xpath("//div[@id='releases']/div/span[@class='release']/..")
if not results:
return "No results found."
result = results[0]
date = result.xpath("span[@class='timestamp']/text()")[0]
section = result.xpath("span[@class='section']//text()")[0]
name = result.xpath("span[@class='release']/text()")[0]
# parse date/time
date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
date_string = date.strftime("%d %b %Y")
since = timesince.timesince(date)
size = result.xpath("span[@class='inforight']//text()")
if size:
size = ' - ' + size[0].split()[0]
else:
size = ''
return '{} - {}{} - {} ({} ago)'.format(section, name, size, date_string, since)

View file

@ -1,106 +0,0 @@
import random
from util import hook, http, web
metadata_url = "http://omnidator.appspot.com/microdata/json/?url={}"
base_url = "http://www.cookstr.com"
search_url = base_url + "/searches"
random_url = search_url + "/surprise"
# set this to true to censor this plugin!
censor = True
phrases = [
u"EAT SOME FUCKING \x02{}\x02",
u"YOU WON'T NOT MAKE SOME FUCKING \x02{}\x02",
u"HOW ABOUT SOME FUCKING \x02{}?\x02",
u"WHY DON'T YOU EAT SOME FUCKING \x02{}?\x02",
u"MAKE SOME FUCKING \x02{}\x02",
u"INDUCE FOOD COMA WITH SOME FUCKING \x02{}\x02"
]
clean_key = lambda i: i.split("#")[1]
class ParseError(Exception):
pass
def get_data(url):
""" Uses the omnidator API to parse the metadata from the provided URL """
try:
omni = http.get_json(metadata_url.format(url))
except (http.HTTPError, http.URLError) as e:
raise ParseError(e)
schemas = omni["@"]
for d in schemas:
if d["a"] == "<http://schema.org/Recipe>":
data = {clean_key(key): value for (key, value) in d.iteritems()
if key.startswith("http://schema.org/Recipe")}
return data
raise ParseError("No recipe data found")
@hook.command(autohelp=False)
def recipe(inp):
"""recipe [term] - Gets a recipe for [term], or ets a random recipe if [term] is not provided"""
if inp:
# get the recipe URL by searching
try:
search = http.get_soup(search_url, query=inp.strip())
except (http.HTTPError, http.URLError) as e:
return "Could not get recipe: {}".format(e)
# find the list of results
result_list = search.find('div', {'class': 'found_results'})
if result_list:
results = result_list.find_all('div', {'class': 'recipe_result'})
else:
return "No results"
# pick a random front page result
result = random.choice(results)
# extract the URL from the result
url = base_url + result.find('div', {'class': 'image-wrapper'}).find('a')['href']
else:
# get a random recipe URL
try:
page = http.open(random_url)
except (http.HTTPError, http.URLError) as e:
return "Could not get recipe: {}".format(e)
url = page.geturl()
# use get_data() to get the recipe info from the URL
try:
data = get_data(url)
except ParseError as e:
return "Could not parse recipe: {}".format(e)
name = data["name"].strip()
return u"Try eating \x02{}!\x02 - {}".format(name, web.try_isgd(url))
@hook.command(autohelp=False)
def dinner(inp):
"""dinner - WTF IS FOR DINNER"""
try:
page = http.open(random_url)
except (http.HTTPError, http.URLError) as e:
return "Could not get recipe: {}".format(e)
url = page.geturl()
try:
data = get_data(url)
except ParseError as e:
return "Could not parse recipe: {}".format(e)
name = data["name"].strip().upper()
text = random.choice(phrases).format(name)
if censor:
text = text.replace("FUCK", "F**K")
return u"{} - {}".format(text, web.try_isgd(url))

View file

@ -1,79 +0,0 @@
from datetime import datetime
import re
import random
from util import hook, http, text, timesince
reddit_re = (r'.*(((www\.)?reddit\.com/r|redd\.it)[^ ]+)', re.I)
base_url = "http://reddit.com/r/{}/.json"
short_url = "http://redd.it/{}"
@hook.regex(*reddit_re)
def reddit_url(match):
thread = http.get_html(match.group(0))
title = thread.xpath('//title/text()')[0]
upvotes = thread.xpath("//span[@class='upvotes']/span[@class='number']/text()")[0]
downvotes = thread.xpath("//span[@class='downvotes']/span[@class='number']/text()")[0]
author = thread.xpath("//div[@id='siteTable']//a[contains(@class,'author')]/text()")[0]
timeago = thread.xpath("//div[@id='siteTable']//p[@class='tagline']/time/text()")[0]
comments = thread.xpath("//div[@id='siteTable']//a[@class='comments']/text()")[0]
return u'\x02{}\x02 - posted by \x02{}\x02 {} ago - {} upvotes, {} downvotes - {}'.format(
title, author, timeago, upvotes, downvotes, comments)
@hook.command(autohelp=False)
def reddit(inp):
"""reddit <subreddit> [n] -- Gets a random post from <subreddit>, or gets the [n]th post in the subreddit."""
id_num = None
if inp:
# clean and split the input
parts = inp.lower().strip().split()
# find the requested post number (if any)
if len(parts) > 1:
url = base_url.format(parts[0].strip())
try:
id_num = int(parts[1]) - 1
except ValueError:
return "Invalid post number."
else:
url = base_url.format(parts[0].strip())
else:
url = "http://reddit.com/.json"
try:
data = http.get_json(url, user_agent=http.ua_chrome)
except Exception as e:
return "Error: " + str(e)
data = data["data"]["children"]
# get the requested/random post
if id_num is not None:
try:
item = data[id_num]["data"]
except IndexError:
length = len(data)
return "Invalid post number. Number must be between 1 and {}.".format(length)
else:
item = random.choice(data)["data"]
item["title"] = text.truncate_str(item["title"], 50)
item["link"] = short_url.format(item["id"])
raw_time = datetime.fromtimestamp(int(item["created_utc"]))
item["timesince"] = timesince.timesince(raw_time)
if item["over_18"]:
item["warning"] = " \x02NSFW\x02"
else:
item["warning"] = ""
return u"\x02{title} : {subreddit}\x02 - posted by \x02{author}\x02" \
" {timesince} ago - {ups} upvotes, {downs} downvotes -" \
" {link}{warning}".format(**item)

View file

@ -1,128 +0,0 @@
from util import hook
# Default value.
# If True, all channels without a setting will have regex enabled
# If False, all channels without a setting will have regex disabled
default_enabled = True
db_ready = False
def db_init(db):
global db_ready
if not db_ready:
db.execute("CREATE TABLE IF NOT EXISTS regexchans(channel PRIMARY KEY, status)")
db.commit()
db_ready = True
def get_status(db, channel):
row = db.execute("SELECT status FROM regexchans WHERE channel = ?", [channel]).fetchone()
if row:
return row[0]
else:
return None
def set_status(db, channel, status):
row = db.execute("REPLACE INTO regexchans (channel, status) VALUES(?, ?)", [channel, status])
db.commit()
def delete_status(db, channel):
row = db.execute("DELETE FROM regexchans WHERE channel = ?", [channel])
db.commit()
def list_status(db):
row = db.execute("SELECT * FROM regexchans").fetchall()
result = None
for values in row:
if result:
result += u", {}: {}".format(values[0], values[1])
else:
result = u"{}: {}".format(values[0], values[1])
return result
@hook.sieve
def sieve_regex(bot, inp, func, kind, args):
db = bot.get_db_connection(inp.conn)
db_init(db)
if kind == 'regex' and inp.chan.startswith("#") and func.__name__ != 'factoid':
chanstatus = get_status(db, inp.chan)
if chanstatus != "ENABLED" and (chanstatus == "DISABLED" or not default_enabled):
print u"Denying input.raw={}, kind={}, args={} from {}".format(inp.raw, kind, args, inp.chan)
return None
print u"Allowing input.raw={}, kind={}, args={} from {}".format(inp.raw, kind, args, inp.chan)
return inp
@hook.command(permissions=["botcontrol"])
def enableregex(inp, db=None, message=None, notice=None, chan=None, nick=None):
db_init(db)
inp = inp.strip().lower()
if not inp:
channel = chan
elif inp.startswith("#"):
channel = inp
else:
channel = u"#{}".format(inp)
message(u"Enabling regex matching (youtube, etc) (issued by {})".format(nick), target=channel)
notice(u"Enabling regex matching (youtube, etc) in channel {}".format(channel))
set_status(db, channel, "ENABLED")
@hook.command(permissions=["botcontrol"])
def disableregex(inp, db=None, message=None, notice=None, chan=None, nick=None):
db_init(db)
inp = inp.strip().lower()
if not inp:
channel = chan
elif inp.startswith("#"):
channel = inp
else:
channel = u"#{}".format(inp)
message(u"Disabling regex matching (youtube, etc) (issued by {})".format(nick), target=channel)
notice(u"Disabling regex matching (youtube, etc) in channel {}".format(channel))
set_status(db, channel, "DISABLED")
@hook.command(permissions=["botcontrol"])
def resetregex(inp, db=None, message=None, notice=None, chan=None, nick=None):
db_init(db)
inp = inp.strip().lower()
if not inp:
channel = chan
elif inp.startswith("#"):
channel = inp
else:
channel = u"#{}".format(inp)
message(u"Resetting regex matching setting (youtube, etc) (issued by {})".format(nick), target=channel)
notice(u"Resetting regex matching setting (youtube, etc) in channel {}".format(channel))
delete_status(db, channel)
@hook.command(permissions=["botcontrol"])
def regexstatus(inp, db=None, chan=None):
db_init(db)
inp = inp.strip().lower()
if not inp:
channel = chan
elif inp.startswith("#"):
channel = inp
else:
channel = u"#{}".format(inp)
return u"Regex status for {}: {}".format(channel, get_status(db, channel))
@hook.command(permissions=["botcontrol"])
def listregex(inp, db=None):
db_init(db)
return list_status(db)

View file

@ -1,38 +0,0 @@
from util import hook, http
@hook.command('god')
@hook.command
def bible(inp):
""".bible <passage> -- gets <passage> from the Bible (ESV)"""
base_url = ('http://www.esvapi.org/v2/rest/passageQuery?key=IP&'
'output-format=plain-text&include-heading-horizontal-lines&'
'include-headings=false&include-passage-horizontal-lines=false&'
'include-passage-references=false&include-short-copyright=false&'
'include-footnotes=false&line-length=0&'
'include-heading-horizontal-lines=false')
text = http.get(base_url, passage=inp)
text = ' '.join(text.split())
if len(text) > 400:
text = text[:text.rfind(' ', 0, 400)] + '...'
return text
@hook.command('allah')
@hook.command
def koran(inp): # Koran look-up plugin by Ghetto Wizard
""".koran <chapter.verse> -- gets <chapter.verse> from the Koran"""
url = 'http://quod.lib.umich.edu/cgi/k/koran/koran-idx?type=simple'
results = http.get_html(url, q1=inp).xpath('//li')
if not results:
return 'No results for ' + inp
return results[0].text_content()

0
disabled_stuff/repaste.py Normal file → Executable file
View file

View file

@ -1,53 +0,0 @@
from util import hook
import re
import time
from subprocess import check_output
def getstatus():
try:
return check_output("sudo /bin/chch-status", shell=True).strip("\n").decode("utf-8")
except:
return "unbekannt"
@hook.command("status", autohelp=False)
def cmd_status(inp, reply=None):
"""status - Return the door status"""
reply("Chaostreff Status: %s" % (getstatus()))
@hook.event("TOPIC")
def topic_update(info, conn=None, chan=None):
"""topic_update -- Update the topic on TOPIC command"""
status = getstatus()
topic = info[-1]
sstr = "Status: %s" % (status)
if sstr in topic:
return
if 'Status: ' in topic:
new_topic = re.sub("Status: [^ ]*", sstr, topic)
else:
new_topic = "%s | %s" % (topic.rstrip(' |'), sstr)
if new_topic != topic:
conn.send("TOPIC %s :%s" % (chan, new_topic))
@hook.event("332")
def e332_update(info, conn=None, chan=None):
"""e332_update -- run after current topic was requested"""
chan = info[1]
topic_update(info, conn=conn, chan=chan)
@hook.singlethread
@hook.event("353")
def e353_update(info, conn=None, chan=None):
"""e353_update -- runs after a channel was joined"""
chan = info[2]
if chan.lower() == "#chaoschemnitz":
conn.send("PRIVMSG Chanserv :op #chaoschemnitz")
while True:
conn.send("TOPIC %s" % (chan))
time.sleep(60)

View file

@ -1,75 +0,0 @@
import re
from bs4 import BeautifulSoup, NavigableString, Tag
from util import hook, http, web
from util.text import truncate_str
steam_re = (r'(.*:)//(store.steampowered.com)(:[0-9]+)?(.*)', re.I)
def get_steam_info(url):
page = http.get(url)
soup = BeautifulSoup(page, 'lxml', from_encoding="utf-8")
data = {}
data["name"] = soup.find('div', {'class': 'apphub_AppName'}).text
data["desc"] = truncate_str(soup.find('meta', {'name': 'description'})['content'].strip(), 80)
# get the element details_block
details = soup.find('div', {'class': 'details_block'})
# loop over every <b></b> tag in details_block
for b in details.findAll('b'):
# get the contents of the <b></b> tag, which is our title
title = b.text.lower().replace(":", "")
if title == "languages":
# we have all we need!
break
# find the next element directly after the <b></b> tag
next_element = b.nextSibling
if next_element:
# if the element is some text
if isinstance(next_element, NavigableString):
text = next_element.string.strip()
if text:
# we found valid text, save it and continue the loop
data[title] = text
continue
else:
# the text is blank - sometimes this means there are
# useless spaces or tabs between the <b> and <a> tags.
# so we find the next <a> tag and carry on to the next
# bit of code below
next_element = next_element.find_next('a', href=True)
# if the element is an <a></a> tag
if isinstance(next_element, Tag) and next_element.name == 'a':
text = next_element.string.strip()
if text:
# we found valid text (in the <a></a> tag),
# save it and continue the loop
data[title] = text
continue
data["price"] = soup.find('div', {'class': 'game_purchase_price price'}).text.strip()
return u"\x02{name}\x02: {desc}, \x02Genre\x02: {genre}, \x02Release Date\x02: {release date}," \
u" \x02Price\x02: {price}".format(**data)
@hook.regex(*steam_re)
def steam_url(match):
return get_steam_info("http://store.steampowered.com" + match.group(4))
@hook.command
def steam(inp):
"""steam [search] - Search for specified game/trailer/DLC"""
page = http.get("http://store.steampowered.com/search/?term=" + inp)
soup = BeautifulSoup(page, 'lxml', from_encoding="utf-8")
result = soup.find('a', {'class': 'search_result_row'})
return get_steam_info(result['href']) + " - " + web.isgd(result['href'])

View file

@ -1,30 +0,0 @@
from util import hook, web
@hook.command
def stock(inp):
"""stock <symbol> -- gets stock information"""
sym = inp.strip().lower()
query = "SELECT * FROM yahoo.finance.quote WHERE symbol=@symbol LIMIT 1"
quote = web.query(query, {"symbol": sym}).one()
# if we don't get a company name back, the symbol doesn't match a company
if quote['Change'] is None:
return "Unknown ticker symbol: {}".format(sym)
change = float(quote['Change'])
price = float(quote['LastTradePriceOnly'])
if change < 0:
quote['color'] = "5"
else:
quote['color'] = "3"
quote['PercentChange'] = 100 * change / (price - change)
print quote
return u"\x02{Name}\x02 (\x02{symbol}\x02) - {LastTradePriceOnly} " \
"\x03{color}{Change} ({PercentChange:.2f}%)\x03 " \
"Day Range: {DaysRange} " \
"MCAP: {MarketCapitalization}".format(**quote)

42
disabled_stuff/suggest.py Normal file → Executable file
View file

@ -1,19 +1,33 @@
from util import hook, http, text
from bs4 import BeautifulSoup
import json
import random
import re
from util import hook, http
@hook.command
def suggest(inp):
"""suggest <phrase> -- Gets suggested phrases for a google search"""
suggestions = http.get_json('http://suggestqueries.google.com/complete/search', client='firefox', q=inp)[1]
def suggest(inp, inp_unstripped=''):
".suggest [#n] <phrase> -- gets a random/the nth suggested google search"
inp = inp_unstripped
m = re.match('^#(\d+) (.+)$', inp)
if m:
num, inp = m.groups()
num = int(num)
if num > 10:
return 'I can only get the first ten suggestions.'
else:
num = 0
page = http.get('http://google.com/complete/search', output='json', client='hp', q=inp)
page_json = page.split('(', 1)[1][:-1]
suggestions = json.loads(page_json)[1]
if not suggestions:
return 'no suggestions found'
out = u", ".join(suggestions)
# defuckify text (might not be needed now, but I'll keep it)
soup = BeautifulSoup(out)
out = soup.get_text()
return text.truncate_str(out, 200)
return 'No suggestions found.'
if num:
if len(suggestions) + 1 <= num:
return 'I only got %d suggestions.' % len(suggestions)
out = suggestions[num - 1]
else:
out = random.choice(suggestions)
return '#%d: %s' % (int(out[2][0]) + 1, out[0].replace('<b>', '').replace('</b>', ''))

View file

@ -1,43 +0,0 @@
from git import Repo
from util import hook, web
@hook.command
def update(inp, bot=None):
repo = Repo()
git = repo.git
try:
pull = git.pull()
except Exception as e:
return e
if "\n" in pull:
return web.haste(pull)
else:
return pull
@hook.command
def version(inp, bot=None):
repo = Repo()
# get origin and fetch it
origin = repo.remotes.origin
info = origin.fetch()
# get objects
head = repo.head
origin_head = info[0]
current_commit = head.commit
remote_commit = origin_head.commit
if current_commit == remote_commit:
in_sync = True
else:
in_sync = False
# output
return "Local \x02{}\x02 is at commit \x02{}\x02, remote \x02{}\x02 is at commit \x02{}\x02." \
" You {} running the latest version.".format(head, current_commit.name_rev[:7],
origin_head, remote_commit.name_rev[:7],
"are" if in_sync else "are not")

View file

@ -1,66 +0,0 @@
import re
import random
from util import hook, http, text
base_url = 'http://api.urbandictionary.com/v0'
define_url = base_url + "/define"
random_url = base_url + "/random"
@hook.command('u', autohelp=False)
@hook.command(autohelp=False)
def urban(inp):
"""urban <phrase> [id] -- Looks up <phrase> on urbandictionary.com."""
if inp:
# clean and split the input
inp = inp.lower().strip()
parts = inp.split()
# if the last word is a number, set the ID to that number
if parts[-1].isdigit():
id_num = int(parts[-1])
# remove the ID from the input string
del parts[-1]
inp = " ".join(parts)
else:
id_num = 1
# fetch the definitions
page = http.get_json(define_url, term=inp, referer="http://m.urbandictionary.com")
if page['result_type'] == 'no_results':
return 'Not found.'
else:
# get a random definition!
page = http.get_json(random_url, referer="http://m.urbandictionary.com")
id_num = None
definitions = page['list']
if id_num:
# try getting the requested definition
try:
definition = definitions[id_num - 1]
def_text = " ".join(definition['definition'].split()) # remove excess spaces
def_text = text.truncate_str(def_text, 200)
except IndexError:
return 'Not found.'
url = definition['permalink']
output = u"[%i/%i] %s :: %s" % \
(id_num, len(definitions), def_text, url)
else:
definition = random.choice(definitions)
def_text = " ".join(definition['definition'].split()) # remove excess spaces
def_text = text.truncate_str(def_text, 200)
name = definition['word']
url = definition['permalink']
output = u"\x02{}\x02: {} :: {}".format(name, def_text, url)
return output

0
disabled_stuff/urlhistory.py Normal file → Executable file
View file

View file

@ -1,197 +0,0 @@
import hashlib
import collections
import re
from util import hook, text
# variables
colors = collections.OrderedDict([
('red', '\x0304'),
('orange', '\x0307'),
('yellow', '\x0308'),
('green', '\x0309'),
('cyan', '\x0303'),
('ltblue', '\x0310'),
('rylblue', '\x0312'),
('blue', '\x0302'),
('magenta', '\x0306'),
('pink', '\x0313'),
('maroon', '\x0305')
])
# helper functions
strip_re = re.compile("(\x03|\x02|\x1f)(?:,?\d{1,2}(?:,\d{1,2})?)?", re.UNICODE)
def strip(string):
return strip_re.sub('', string)
# basic text tools
## TODO: make this capitalize sentences correctly
@hook.command("capitalise")
@hook.command
def capitalize(inp):
"""capitalize <string> -- Capitalizes <string>."""
return inp.capitalize()
@hook.command
def upper(inp):
"""upper <string> -- Convert string to uppercase."""
return inp.upper()
@hook.command
def lower(inp):
"""lower <string> -- Convert string to lowercase."""
return inp.lower()
@hook.command
def titlecase(inp):
"""title <string> -- Convert string to title case."""
return inp.title()
@hook.command
def swapcase(inp):
"""swapcase <string> -- Swaps the capitalization of <string>."""
return inp.swapcase()
# encoding
@hook.command
def rot13(inp):
"""rot13 <string> -- Encode <string> with rot13."""
return inp.encode('rot13')
@hook.command
def base64(inp):
"""base64 <string> -- Encode <string> with base64."""
return inp.encode('base64')
@hook.command
def unbase64(inp):
"""unbase64 <string> -- Decode <string> with base64."""
return inp.decode('base64')
@hook.command
def checkbase64(inp):
try:
decoded = inp.decode('base64')
recoded = decoded.encode('base64').strip()
is_base64 = recoded == inp
except:
return '"{}" is not base64 encoded'.format(inp)
if is_base64:
return '"{}" is base64 encoded'.format(recoded)
else:
return '"{}" is not base64 encoded'.format(inp)
@hook.command
def unescape(inp):
"""unescape <string> -- Unescapes <string>."""
try:
return inp.decode('unicode-escape')
except Exception as e:
return "Error: {}".format(e)
@hook.command
def escape(inp):
"""escape <string> -- Escapes <string>."""
try:
return inp.encode('unicode-escape')
except Exception as e:
return "Error: {}".format(e)
# length
@hook.command
def length(inp):
"""length <string> -- gets the length of <string>"""
return "The length of that string is {} characters.".format(len(inp))
# reverse
@hook.command
def reverse(inp):
"""reverse <string> -- reverses <string>."""
return inp[::-1]
# hashing
@hook.command("hash")
def hash_command(inp):
"""hash <string> -- Returns hashes of <string>."""
return ', '.join(x + ": " + getattr(hashlib, x)(inp).hexdigest()
for x in ['md5', 'sha1', 'sha256'])
# novelty
@hook.command
def munge(inp):
"""munge <text> -- Munges up <text>."""
return text.munge(inp)
# colors - based on code by Reece Selwood - <https://github.com/hitzler/homero>
@hook.command
def rainbow(inp):
inp = unicode(inp)
inp = strip(inp)
col = colors.items()
out = ""
l = len(colors)
for i, t in enumerate(inp):
if t == " ":
out += t
else:
out += col[i % l][1] + t
return out
@hook.command
def wrainbow(inp):
inp = unicode(inp)
col = colors.items()
inp = strip(inp).split(' ')
out = []
l = len(colors)
for i, t in enumerate(inp):
out.append(col[i % l][1] + t)
return ' '.join(out)
@hook.command
def usa(inp):
inp = strip(inp)
c = [colors['red'], '\x0300', colors['blue']]
l = len(c)
out = ''
for i, t in enumerate(inp):
out += c[i % l] + t
return out

0
disabled_stuff/wordoftheday.py Normal file → Executable file
View file

0
disabled_stuff/wrapper.old Normal file → Executable file
View file

View file

@ -1,43 +0,0 @@
import re
from util import hook, http
xkcd_re = (r'(.*:)//(www.xkcd.com|xkcd.com)(.*)', re.I)
months = {1: 'January', 2: 'February', 3: 'March', 4: 'April', 5: 'May', 6: 'June', 7: 'July', 8: 'August',
9: 'September', 10: 'October', 11: 'November', 12: 'December'}
def xkcd_info(xkcd_id, url=False):
""" takes an XKCD entry ID and returns a formatted string """
data = http.get_json("http://www.xkcd.com/" + xkcd_id + "/info.0.json")
date = "%s %s %s" % (data['day'], months[int(data['month'])], data['year'])
if url:
url = " | http://xkcd.com/" + xkcd_id.replace("/", "")
return "xkcd: \x02%s\x02 (%s)%s" % (data['title'], date, url if url else "")
def xkcd_search(term):
search_term = http.quote_plus(term)
soup = http.get_soup("http://www.ohnorobot.com/index.pl?s={}&Search=Search&"
"comic=56&e=0&n=0&b=0&m=0&d=0&t=0".format(search_term))
result = soup.find('li')
if result:
url = result.find('div', {'class': 'tinylink'}).text
xkcd_id = url[:-1].split("/")[-1]
print xkcd_id
return xkcd_info(xkcd_id, url=True)
else:
return "No results found!"
@hook.regex(*xkcd_re)
def xkcd_url(match):
xkcd_id = match.group(3).split(" ")[0].split("/")[1]
return xkcd_info(xkcd_id)
@hook.command
def xkcd(inp):
"""xkcd <search term> - Search for xkcd comic matching <search term>"""
return xkcd_search(inp)

View file

@ -1,136 +0,0 @@
import re
import time
from util import hook, http, timeformat
youtube_re = (r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)'
'([-_a-zA-Z0-9]+)', re.I)
base_url = 'http://gdata.youtube.com/feeds/api/'
api_url = base_url + 'videos/{}?v=2&alt=jsonc'
search_api_url = base_url + 'videos?v=2&alt=jsonc&max-results=1'
video_url = "http://youtu.be/%s"
def plural(num=0, text=''):
return "{:,} {}{}".format(num, text, "s"[num == 1:])
def get_video_description(video_id):
request = http.get_json(api_url.format(video_id))
if request.get('error'):
return
data = request['data']
out = u'\x02{}\x02'.format(data['title'])
if not data.get('duration'):
return out
length = data['duration']
out += u' - length \x02{}\x02'.format(timeformat.format_time(length, simple=True))
if 'ratingCount' in data:
likes = plural(int(data['likeCount']), "like")
dislikes = plural(data['ratingCount'] - int(data['likeCount']), "dislike")
percent = 100 * float(data['likeCount']) / float(data['ratingCount'])
out += u' - {}, {} (\x02{:.1f}\x02%)'.format(likes,
dislikes, percent)
if 'viewCount' in data:
views = data['viewCount']
out += u' - \x02{:,}\x02 view{}'.format(views, "s"[views == 1:])
try:
uploader = http.get_json(base_url + "users/{}?alt=json".format(data["uploader"]))["entry"]["author"][0]["name"][
"$t"]
except:
uploader = data["uploader"]
upload_time = time.strptime(data['uploaded'], "%Y-%m-%dT%H:%M:%S.000Z")
out += u' - \x02{}\x02 on \x02{}\x02'.format(uploader,
time.strftime("%Y.%m.%d", upload_time))
if 'contentRating' in data:
out += u' - \x034NSFW\x02'
return out
@hook.regex(*youtube_re)
def youtube_url(match):
return get_video_description(match.group(1))
@hook.command('you')
@hook.command('yt')
@hook.command('y')
@hook.command
def youtube(inp):
"""youtube <query> -- Returns the first YouTube search result for <query>."""
request = http.get_json(search_api_url, q=inp)
if 'error' in request:
return 'error performing search'
if request['data']['totalItems'] == 0:
return 'no results found'
video_id = request['data']['items'][0]['id']
return get_video_description(video_id) + u" - " + video_url % video_id
@hook.command('ytime')
@hook.command
def youtime(inp):
"""youtime <query> -- Gets the total run time of the first YouTube search result for <query>."""
request = http.get_json(search_api_url, q=inp)
if 'error' in request:
return 'error performing search'
if request['data']['totalItems'] == 0:
return 'no results found'
video_id = request['data']['items'][0]['id']
request = http.get_json(api_url.format(video_id))
if request.get('error'):
return
data = request['data']
if not data.get('duration'):
return
length = data['duration']
views = data['viewCount']
total = int(length * views)
length_text = timeformat.format_time(length, simple=True)
total_text = timeformat.format_time(total, accuracy=8)
return u'The video \x02{}\x02 has a length of {} and has been viewed {:,} times for ' \
u'a total run time of {}!'.format(data['title'], length_text, views,
total_text)
ytpl_re = (r'(.*:)//(www.youtube.com/playlist|youtube.com/playlist)(:[0-9]+)?(.*)', re.I)
@hook.regex(*ytpl_re)
def ytplaylist_url(match):
location = match.group(4).split("=")[-1]
try:
soup = http.get_soup("https://www.youtube.com/playlist?list=" + location)
except Exception:
return "\x034\x02Invalid response."
title = soup.find('title').text.split('-')[0].strip()
author = soup.find('img', {'class': 'channel-header-profile-image'})['title']
num_videos = soup.find('ul', {'class': 'header-stats'}).findAll('li')[0].text.split(' ')[0]
views = soup.find('ul', {'class': 'header-stats'}).findAll('li')[1].text.split(' ')[0]
return u"\x02%s\x02 - \x02%s\x02 views - \x02%s\x02 videos - \x02%s\x02" % (title, views, num_videos, author)

50
plugins/admin.py Normal file → Executable file
View file

@ -1,12 +1,10 @@
from util import hook
import os
import sys
import re
import json
import time
import subprocess
from util import hook
@hook.command(autohelp=False, permissions=["permissions_users"])
def permissions(inp, bot=None, notice=None):
@ -116,18 +114,14 @@ def stop(inp, nick=None, conn=None):
@hook.command(autohelp=False, permissions=["botcontrol"])
def restart(inp, nick=None, conn=None, bot=None):
def restart(inp, nick=None, conn=None):
"""restart [reason] -- Restarts the bot with [reason] as its quit message."""
for botcon in bot.conns:
if inp:
bot.conns[botcon].cmd("QUIT", ["Restarted by {} ({})".format(nick, inp)])
else:
bot.conns[botcon].cmd("QUIT", ["Restarted by {}.".format(nick)])
if inp:
conn.cmd("QUIT", ["Restarted by {} ({})".format(nick, inp)])
else:
conn.cmd("QUIT", ["Restarted by {}.".format(nick)])
time.sleep(5)
#os.execl("./cloudbot", "cloudbot", "restart")
args = sys.argv[:]
args.insert(0, sys.executable)
os.execv(sys.executable, args)
os.execl("./cloudbot", "cloudbot", "restart")
@hook.command(autohelp=False, permissions=["botcontrol"])
@ -139,11 +133,8 @@ def clearlogs(inp, input=None):
@hook.command(permissions=["botcontrol"])
def join(inp, conn=None, notice=None):
"""join <channel> -- Joins <channel>."""
for target in inp.split(" "):
if not target.startswith("#"):
target = "#{}".format(target)
notice("Attempting to join {}...".format(target))
conn.join(target)
notice("Attempting to join {}...".format(inp))
conn.join(inp)
@hook.command(autohelp=False, permissions=["botcontrol"])
@ -152,14 +143,11 @@ def part(inp, conn=None, chan=None, notice=None):
If [channel] is blank the bot will leave the
channel the command was used in."""
if inp:
targets = inp
target = inp
else:
targets = chan
for target in targets.split(" "):
if not target.startswith("#"):
target = "#{}".format(target)
notice("Attempting to leave {}...".format(target))
conn.part(target)
target = chan
notice("Attempting to leave {}...".format(target))
conn.part(target)
@hook.command(autohelp=False, permissions=["botcontrol"])
@ -200,11 +188,11 @@ def say(inp, conn=None, chan=None):
the command was used in."""
inp = inp.split(" ")
if inp[0][0] == "#":
message = u" ".join(inp[1:])
out = u"PRIVMSG {} :{}".format(inp[0], message)
message = " ".join(inp[1:])
out = "PRIVMSG {} :{}".format(inp[0], message)
else:
message = u" ".join(inp[0:])
out = u"PRIVMSG {} :{}".format(chan, message)
message = " ".join(inp[0:])
out = "PRIVMSG {} :{}".format(chan, message)
conn.send(out)
@ -220,11 +208,11 @@ def me(inp, conn=None, chan=None):
for x in inp[1:]:
message = message + x + " "
message = message[:-1]
out = u"PRIVMSG {} :\x01ACTION {}\x01".format(inp[0], message)
out = "PRIVMSG {} :\x01ACTION {}\x01".format(inp[0], message)
else:
message = ""
for x in inp[0:]:
message = message + x + " "
message = message[:-1]
out = u"PRIVMSG {} :\x01ACTION {}\x01".format(chan, message)
out = "PRIVMSG {} :\x01ACTION {}\x01".format(chan, message)
conn.send(out)

View file

@ -1,12 +1,14 @@
import random
from util import hook
import random
with open("plugins/data/larts.txt") as f:
larts = [line.strip() for line in f.readlines()
if not line.startswith("//")]
with open("plugins/data/kills.txt") as f:
kills = [line.strip() for line in f.readlines()
if not line.startswith("//")]
with open("plugins/data/insults.txt") as f:
insults = [line.strip() for line in f.readlines()
if not line.startswith("//")]
@ -15,9 +17,8 @@ with open("plugins/data/flirts.txt") as f:
flirts = [line.strip() for line in f.readlines()
if not line.startswith("//")]
@hook.command
def lart(inp, action=None, nick=None, conn=None, notice=None):
def lart(inp, me=None, nick=None, conn=None, notice=None):
"""lart <user> -- LARTs <user>."""
target = inp.strip()
@ -33,11 +34,31 @@ def lart(inp, action=None, nick=None, conn=None, notice=None):
phrase = random.choice(larts)
# act out the message
action(phrase.format(**values))
me(phrase.format(**values))
@hook.command
def insult(inp, nick=None, action=None, conn=None, notice=None):
def kill(inp, me=None, nick=None, conn=None, notice=None):
"""kill <user> -- Makes the bot kill <user>."""
target = inp.strip()
if " " in target:
notice("Invalid username!")
return
# if the user is trying to make the bot slap itself, slap them
if target.lower() == conn.nick.lower() or target.lower() == "itself":
target = nick
values = {"user": target}
phrase = random.choice(kills)
# act out the message
me(phrase.format(**values))
@hook.command
def insult(inp, nick=None, me=None, conn=None, notice=None):
"""insult <user> -- Makes the bot insult <user>."""
target = inp.strip()
@ -51,11 +72,11 @@ def insult(inp, nick=None, action=None, conn=None, notice=None):
target = inp
out = 'insults {}... "{}"'.format(target, random.choice(insults))
action(out)
me(out)
@hook.command
def flirt(inp, action=None, conn=None, notice=None):
def flirt(inp, me=None, conn=None, notice=None):
"""flirt <user> -- Make the bot flirt with <user>."""
target = inp.strip()
@ -69,4 +90,4 @@ def flirt(inp, action=None, conn=None, notice=None):
target = inp
out = 'flirts with {}... "{}"'.format(target, random.choice(flirts))
action(out)
me(out)

View file

@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
from util import hook
from thread import start_new_thread
from time import sleep
def wait_and_send(conn, wait, msg):
sleep(wait)
conn.send(msg)
@hook.command("check")
def check_nick(inp, conn=None):
conn.send("PRIVMSG %s :\x01VERSION\x01" % inp)
@hook.event("JOIN")
def handle_join(info, input=None, conn=None):
start_new_thread(wait_and_send, (conn, 5, "PRIVMSG %s :\x01VERSION\x01" % input.nick))
@hook.event("NOTICE")
def handle_ctcp_rply(info, input=None, conn=None, nick=None):
print "notice..."
print "-%s-" % input.lastparam
if input.lastparam == ("\1VERSION %s\1" % "mIRC v7.22 Khaled Mardam-Bey"):
for chan in conn.channels:
if chan != "#logbot":
conn.send("KICK %s %s :bad version" % (chan, nick))
conn.send("MODE %s +b %s!*@*$#logbot" % (chan, nick))

View file

@ -1,21 +0,0 @@
from util import hook, http, web
from subprocess import check_output, CalledProcessError
from datetime import datetime
@hook.command("bw", autohelp=False)
def bw(inp):
"""bw - list last bandwidth measurement to the outside."""
try:
o = check_output("/bin/chch-bandwidth")
except CalledProcessError as err:
return "chch-bandwidth: returned %s" % (str(err))
os = o.split(",")
upl = int(os[-1])/1024.0/1024.0
dl = int(os[-2])/1024.0/1024.0
ts = os[0]
tsd = datetime.strptime(ts, "%Y%m%d%H%M%S")
return "%s: upl = %f Mbit/s; dl = %f Mbit/s;" % (tsd, upl, dl)

16
plugins/bitcoin.py Executable file
View file

@ -0,0 +1,16 @@
from util import http, hook
@hook.command(autohelp=False)
def bitcoin(inp, say=None):
"""bitcoin -- gets current exchange rate for bitcoins from mtgox"""
data = http.get_json("https://data.mtgox.com/api/2/BTCUSD/money/ticker")
data = data['data']
ticker = {
'buy': data['buy']['display_short'].encode('ascii','ignore'),
'high': data['high']['display_short'].encode('ascii','ignore'),
'low': data['low']['display_short'].encode('ascii','ignore'),
'vol': data['vol']['display_short'].encode('ascii','ignore'),
}
say("Current: \x0307{!s}\x0f - High: \x0307{!s}\x0f"
" - Low: \x0307{!s}\x0f - Volume: {!s}".format(ticker['buy'],ticker['high'],ticker['low'],ticker['vol']))

4
disabled_stuff/brainfuck.py → plugins/brainfuck.py Normal file → Executable file
View file

@ -1,5 +1,5 @@
"""brainfuck interpreter adapted from (public domain) code at
http://brainfuck.sourceforge.net/brain.py"""
'''brainfuck interpreter adapted from (public domain) code at
http://brainfuck.sourceforge.net/brain.py'''
import re
import random

View file

@ -1,310 +0,0 @@
# -*- coding: utf-8 -*-
from util import hook
import re
import time
import requests
import urllib
from subprocess import check_output
import json
import socket
import struct
#def run_ecmd(cmd):
## baseuri = "http://netio.chch.lan.ffc/ecmd?"
## baseuri = "http://10.8.128.35/ecmd?"
# baseuri = "http://127.0.0.1:4280/ecmd?"
# cmds = "%20".join(cmd)
# req = requests.get("%s%s" % (baseuri, cmds))
# return req.text.strip()
#def run_udp(cmd):
# ip="127.0.0.1"
# port=49152
# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# # 100 ms timeout
# s.settimeout(0.1)
# s.connect((ip, port))
# s.send(cmd)
# try:
# rec = s.recv(1024)
# except:
# rec = ""
# s.close()
# return rec
## lamp_lounge handling
#@hook.command("lamp_lounge", autohelp=True)
#def cmd_lamp_lounge(inp, reply=None):
# """lamp_lounge color - set the lamp color"""
# args = inp.split(" ")
# if len(args) < 1:
# reply("lamp_lounge color - set the lamp color")
# return
#
# if len(args[0]) != 6:
# reply("lamp_lounge color - set the lamp color")
# return
#
# c = "a\x00\x03" + struct.pack('BBB', int(args[0][2:4], 16), int(args[0][0:2], 16), int(args[0][4:6], 16))
#
# rep = run_tcp(c)
#
# if len(rep) < 3:
# reply("Error: no reply")
# return
#
# if rep[0] == 'a':
# reply("OK")
# elif rep[0] == 'e':
# reply("error: " + rep[3:])
# else:
# reply("fatal error")
@hook.command("corridor_light_toggle", autohelp=False)
def cmd_corridor_light_toggle(inp, reply=None):
"""toggle corridor light modes"""
reply(check_output("echo corridor_light_toggle | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
@hook.command("corridor_light", autohelp=False)
def cmd_corridor_light(inp, reply=None):
"""set corridor light color"""
args = inp.split(" ")
if len(args) < 1:
reply("corridor_light color - set the light color")
return
if len(args[0]) != 6:
reply("corridor_light color - set the light color")
return
reply(check_output("echo corridor_light " + args[0] + " | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
@hook.command("lounge_light_toggle", autohelp=False)
def cmd_lounge_light_toggle(inp, reply=None):
"""toggle lounge light modes"""
reply(check_output("echo lounge_light_toggle | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
@hook.command("lounge_light", autohelp=False)
def cmd_lounge_light(inp, reply=None):
"""set lounge light color"""
args = inp.split(" ")
if len(args) < 1:
reply("lounge_light color - set the light color")
return
if len(args[0]) != 6:
reply("lounge_light color - set the light color")
return
reply(check_output("echo lounge_light " + args[0] + " | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
@hook.command("elab_light_toggle", autohelp=False)
def cmd_elab_light_toggle(inp, reply=None):
"""toggle e-lab light modes"""
reply(check_output("echo e-lab_light_toggle | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
@hook.command("elab_light", autohelp=False)
def cmd_elab_light(inp, reply=None):
"""set e-lab light color"""
args = inp.split(" ")
if len(args) < 1:
reply("e-lab_light color - set the light color")
return
if len(args[0]) != 6:
reply("e-lab_light color - set the light color")
return
reply(check_output("echo e-lab_light " + args[0] + " | ssh -q -p 2322 command@127.0.0.1", shell=True).strip("\n").decode("utf-8"))
## Lamp handling
#@hook.command("lamp", autohelp=True)
#def cmd_lamp(inp, reply=None):
# """lamp color [mode] - set the lamp color"""
# args = inp.split(" ")
# if len(args) < 1:
# reply("""lamp color [mode] - set the lamp color""")
# return
#
# if len(args[0]) != 6:
# reply("""lamp color [mode] - set the lamp color""")
# return
#
# cmode = "s"
# if len(args) > 1:
# if args[1] == "s" or args[1] == "y" or args[1] == "f":
# cmode = args[1]
#
# c = []
# c.append([5, int(args[0][0:2], 16)])
# c.append([4, int(args[0][2:4], 16)])
# c.append([3, int(args[0][4:6], 16)])
#
# for ce in c:
# res = run_ecmd(["channel", str(ce[0]), str(ce[1]), cmode])
# if res != "OK":
# return
# reply("OK")
#@hook.command("lamp_fadestep", autohelp=True)
#def cmd_lamp_fadestep(inp, reply=None):
# """lamp_fadestep step - set the lamp fadestep"""
# args = inp.split(" ")
#
# if len(args) < 1:
# reply("""lamp_fadestep step - set the lamp fadestep""")
# return
#
# reply(run_ecmd(["fadestep", args[0]]))
#@hook.command("lamp_fadestep_get", autohelp=False)
#def cmd_lamp_fadestep_get(inp, reply=None):
# """lamp_fadestep_get - get the lamp fadestep"""
# reply(run_ecmd(["fadestep"]))
#
#@hook.command("lamp_channels", autohelp=False)
#def cmd_lamp_channels(inp, reply=None):
# """lamp_chanels - get the lamp channel count"""
# reply(run_ecmd(["channels"]))
# Wiki handling
def wiki_changes(cmd=False):
tmpfile = "/tmp/wikichanges.timestamp.txt"
basewikiuri = "https://www.chaoschemnitz.de/index.php?title=%s"
wikiapiuri = "https://www.chaoschemnitz.de/api.php?"\
"action=query&list=recentchanges&format=json&"\
"rcprop=user|userid|comment|parsedcomment|timestamp|"\
"title|sha1|sizes|redirect|loginfo|tags|flags"\
"&rclist=edit|external|new|log"
try:
fdch = open(tmpfile, "rw")
timestamp = fdch.read()
fdch.close()
except IOError:
timestamp = None
try:
r = requests.get(wikiapiuri, verify=False)
except:
return []
rarr = []
changes = r.json()["query"]["recentchanges"]
ntimestamp = changes[0]["timestamp"]
for change in changes:
if change["timestamp"] == timestamp:
break
uri = basewikiuri % (urllib.quote(change["title"].encode("utf-8"), safe=""))
rarr.append("wiki: %s changed '%s' ( %s ) comment: %s" %\
(change["user"], change["title"], uri,\
change["comment"].strip("\r\n\t")))
if cmd == False:
fdch = open(tmpfile, "w+")
fdch.write("%s" % (ntimestamp))
fdch.close()
return rarr
def print_wiki_changes(info, conn=None, chan=None):
"""print_wiki_changes - print wiki changes, when the worker calls"""
ch = wiki_changes(cmd=False)
if len(ch) == 0:
return
for c in ch[::-1]:
conn.msg("#chaoschemnitz", c)
time.sleep(0.5)
@hook.command("wikichanges", autohelp=False)
def cmd_wikichanges(inp, reply=None):
"""wikichanges - Return new recent wiki changes"""
ch = wiki_changes(cmd=True)
if len(ch) == 0:
reply("No changes since the last call were made to the wiki.")
else:
for c in ch[::-1][-4:]:
reply(c)
time.sleep(0.5)
# Status handling
def getstatus():
# try:
fd = requests.get('http://www.chaoschemnitz.de/chch.json')
chch_info = fd.json()
if 'message' in chch_info['state']:
message = chch_info['state']['message']
if " | " in message:
message = message.split(" | ", 1)[0]
else:
message = ""
if chch_info['state']['open']:
state = "geöffnet".decode("utf-8")
else:
state = "geschlossen"
return "%s (%s)" % (state, message)
# return check_output("sudo /bin/chch-status", shell=True).strip("\n").decode("utf-8")
# except:
# return "unbekannt"
@hook.command("status", autohelp=False)
def cmd_status(inp, reply=None):
"""status - Return the door status"""
reply("Chaostreff Status: %s" % (getstatus()))
@hook.event("TOPIC")
def topic_update(info, conn=None, chan=None):
print("topic update")
"""topic_update -- Update the topic on TOPIC command"""
if chan != "#ChaosChemnitz":
return
status = getstatus()
print("status: %s" % (status.encode('utf8')))
topic = info[-1].split(" | ")
print("topic: %s" % ([ elem.encode('utf8') for elem in topic ]))
sstr = "Status: %s" % (status)
print("sstr: %s" % (sstr.encode('utf8')))
didset = False
i = 0
while i < len(topic):
if sstr in topic[i]:
print("Found current status in topic.")
didset = True
break
if 'Status: ' in topic[i]:
print("Found Status field in topic.")
didset = True
topic[i] = sstr
i += 1
if didset == False:
print("No topic fiel was found, appending.")
topic.append(sstr)
newtopic = " | ".join(topic)
if newtopic != info[-1]:
conn.send("TOPIC %s :%s" % (chan, newtopic))
@hook.event("332")
def e332_update(info, conn=None, chan=None):
"""e332_update -- run after current topic was requested, runs worker tasks too"""
chan = info[1]
topic_update(info, conn=conn, chan=chan)
print_wiki_changes(info, conn=conn, chan=chan)
@hook.singlethread
@hook.event("353")
def e353_update(info, conn=None, chan=None):
"""e353_update -- runs after a channel (#chaoschemnitz) was joined"""
chan = info[2]
if chan.lower() == "#chaoschemnitz":
conn.send("PRIVMSG Chanserv :op #chaoschemnitz")
while True:
time.sleep(60)
conn.send("TOPIC %s" % (chan))

4
disabled_stuff/choose.py → plugins/choose.py Normal file → Executable file
View file

@ -6,7 +6,7 @@ from util import hook
@hook.command
def choose(inp):
"""choose <choice1>, [choice2], [choice3], [choice4], ... --
"""choose <choice1>, [choice2], [choice3], [choice4], ... --
Randomly picks one of the given choices."""
c = re.findall(r'([^,]+)', inp)
@ -15,4 +15,4 @@ def choose(inp):
if len(c) == 1:
return 'The decision is up to you!'
return random.choice(c).strip()
return random.choice(c).strip()

11
disabled_stuff/coin.py → plugins/coin.py Normal file → Executable file
View file

@ -1,10 +1,9 @@
import random
from util import hook
import random
@hook.command(autohelp=False)
def coin(inp, action=None):
def coin(inp, me=None):
"""coin [amount] -- Flips [amount] of coins."""
if inp:
@ -16,10 +15,10 @@ def coin(inp, action=None):
amount = 1
if amount == 1:
action("flips a coin and gets {}.".format(random.choice(["heads", "tails"])))
me("flips a coin and gets {}.".format(random.choice(["heads", "tails"])))
elif amount == 0:
action("makes a coin flipping motion with its hands.")
me("makes a coin flipping motion with its hands.")
else:
heads = int(random.normalvariate(.5 * amount, (.75 * amount) ** .5))
tails = amount - heads
action("flips {} coins and gets {} heads and {} tails.".format(amount, heads, tails))
me("flips {} coins and gets {} heads and {} tails.".format(amount, heads, tails))

1
plugins/core_ctcp.py Normal file → Executable file
View file

@ -1,5 +1,4 @@
import time
from util import hook

1
plugins/core_misc.py Normal file → Executable file
View file

@ -4,7 +4,6 @@ import re
from util import hook
socket.setdefaulttimeout(10)
nick_re = re.compile(":(.+?)!")

31
plugins/core_sieve.py Normal file → Executable file
View file

@ -1,7 +1,7 @@
import re
from fnmatch import fnmatch
from util import hook
from fnmatch import fnmatch
@hook.sieve
@ -38,21 +38,30 @@ def sieve_suite(bot, input, func, kind, args):
groups = bot.config.get("permissions", [])
allowed_permissions = args.get('permissions', [])
mask = input.mask.lower()
allowed_groups = []
# loop over every group
for key, group in groups.iteritems():
for key, value in groups.iteritems():
# loop over every permission the command allows
for permission in allowed_permissions:
# see if the group has that permission
if permission in group["perms"]:
# if so, check it
group_users = [_mask.lower() for _mask in group["users"]]
for pattern in group_users:
if fnmatch(mask, pattern):
print "Allowed group {}.".format(group)
return input
print value
if permission in value["perms"]:
# if so, add the group name to the allowed_groups list
allowed_groups.append(key)
if not allowed_groups:
print "Something is wrong. A hook requires {} but" \
" there are no groups with that permission!".format(str(allowed_permissions))
mask = input.mask.lower()
for group in allowed_groups:
group_users = bot.config.get("permissions", {}).get(group, [])["users"]
group_users = [_mask.lower() for _mask in group_users]
for pattern in group_users:
if fnmatch(mask, pattern):
return input
input.notice("Sorry, you are not allowed to use this command.")
return None

30
plugins/correction.py Normal file
View file

@ -0,0 +1,30 @@
from util import hook
@hook.regex(r'^(s|S)/.*/.*/\S*$')
def correction(inp, say=None, input=None, notice=None, db=None):
splitinput = input.msg.split("/")
if splitinput[3]:
nick = splitinput[3]
else:
nick = input.nick
last_message = db.execute("select name, quote from seen_user where name"
" like ? and chan = ?", (nick.lower(), input.chan.lower())).fetchone()
if last_message:
splitinput = input.msg.split("/")
find = splitinput[1]
replace = splitinput[2]
if find in last_message[1]:
if "\x01ACTION" in last_message[1]:
message = last_message[1].replace("\x01ACTION ", "/me ").replace("\x01", "")
else:
message = last_message[1]
say("{} meant to say: {}".format(nick, message.replace(find, "\x02" + replace + "\x02")))
else:
notice("{} can't be found in your last message".format(find))
else:
if nick == input.nick:
notice("I haven't seen you say anything here yet")
else:
notice("I haven't seen {} say anything here yet".format(nick))

8
disabled_stuff/cypher.py → plugins/cypher.py Normal file → Executable file
View file

@ -1,5 +1,4 @@
import base64
from util import hook
@ -11,10 +10,9 @@ def encode(key, clear):
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def decode(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc.encode('ascii', 'ignore'))
enc = base64.urlsafe_b64decode(enc.encode('ascii','ignore'))
for i in range(len(enc)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
@ -28,7 +26,7 @@ def cypher(inp):
passwd = inp.split(" ")[0]
inp = " ".join(inp.split(" ")[1:])
return encode(passwd, inp)
return encode(passwd,inp)
@hook.command
@ -36,4 +34,4 @@ def decypher(inp):
"""decypher <pass> <string> -- Decyphers <string> with <password>."""
passwd = inp.split(" ")[0]
inp = " ".join(inp.split(" ")[1:])
return decode(passwd, inp)
return decode(passwd,inp)

View file

@ -44,11 +44,4 @@ Do you live on a chicken farm? Because you sure know how to raise cocks.
Are you wearing space pants? Because your ass is out of this world.
Nice legs. What time do they open?
Are you lost? Because its so strange to see an angel so far from heaven.
Your daddy must have been a baker, because you've got a nice set of buns.
You're so beautiful that last night you made me forget my pickup line.
I've never seen such dark eyes with so much light in them.
I think we should just be friends with sexual tension.
Whenever I see you I feel like a dog dying to get out of the car.
If I'd have held you any closer I'd be in back of you.
I wish I were on Facebook so I could poke you.
I want you like JFK wanted a car with a roof.
Your daddy must have been a baker, because you've got a nice set of buns.

View file

View file

537
plugins/data/itemids.txt Executable file
View file

@ -0,0 +1,537 @@
1 Stone
2 Grass
3 Dirt
4 Cobblestone
5 Wooden Plank (Oak)
5:1 Wooden Plank (Spruce)
5:2 Wooden Plank (Birch)
5:3 Wooden Plank (Jungle)
6 Sapling (Oak)
6:1 Sapling (Spruce)
6:2 Sapling (Birch)
6:3 Sapling (Jungle)
7 Bedrock
8 Water
9 Water (No Spread)
10 Lava
11 Lava (No Spread)
12 Sand
13 Gravel
14 Gold Ore
15 Iron Ore
16 Coal Ore
17 Wood (Oak)
17:1 Wood (Spruce)
17:2 Wood (Birch)
17:3 Wood (Jungle)
18 Leaves (Oak)
18:1 Leaves (Spruce)
18:2 Leaves (Birch)
18:3 Leaves (Jungle)
19 Sponge
20 Glass
21 Lapis Lazuli Ore
22 Lapis Lazuli Block
23 Dispenser
24 Sandstone
24:1 Sandstone (Chiseled)
24:2 Sandstone (Smooth)
25 Note Block
26 Bed (Block)
27 Powered Rail
28 Detector Rail
29 Sticky Piston
30 Cobweb
31 Tall Grass (Dead Shrub)
31:1 Tall Grass
31:2 Tall Grass (Fern)
32 Dead Shrub
33 Piston
34 Piston (Head)
35 Wool
35:1 Orange Wool
35:2 Magenta Wool
35:3 Light Blue Wool
35:4 Yellow Wool
35:5 Lime Wool
35:6 Pink Wool
35:7 Gray Wool
35:8 Light Gray Wool
35:9 Cyan Wool
35:10 Purple Wool
35:11 Blue Wool
35:12 Brown Wool
35:13 Green Wool
35:14 Red Wool
35:15 Black Wool
36 Piston (Moving)
37 Dandelion
38 Rose
39 Brown Mushroom
40 Red Mushroom
41 Block of Gold
42 Block of Iron
43 Stone Slab (Double)
43:1 Sandstone Slab (Double)
43:2 Wooden Slab (Double)
43:3 Cobblestone Slab (Double)
43:4 Brick Slab (Double)
43:5 Stone Brick Slab (Double)
43:6 Nether Brick Slab (Double)
43:7 Quartz Slab (Double)
43:8 Smooth Stone Slab (Double)
43:9 Smooth Sandstone Slab (Double)
44 Stone Slab
44:1 Sandstone Slab
44:2 Wooden Slab
44:3 Cobblestone Slab
44:4 Brick Slab
44:5 Stone Brick Slab
44:6 Nether Brick Slab
44:7 Quartz Slab
45 Brick
46 TNT
47 Bookcase
48 Moss Stone
49 Obsidian
50 Torch
51 Fire
52 Mob Spawner
53 Wooden Stairs (Oak)
54 Chest
55 Redstone Wire
56 Diamond Ore
57 Block of Diamond
58 Workbench
59 Wheat (Crop)
60 Farmland
61 Furnace
62 Furnace (Smelting)
63 Sign (Block)
64 Wood Door (Block)
65 Ladder
66 Rail
67 Cobblestone Stairs
68 Sign (Wall Block)
69 Lever
70 Stone Pressure Plate
71 Iron Door (Block)
72 Wooden Pressure Plate
73 Redstone Ore
74 Redstone Ore (Glowing)
75 Redstone Torch (Off)
76 Redstone Torch
77 Button (Stone)
78 Snow
79 Ice
80 Snow Block
81 Cactus
82 Clay Block
83 Sugar Cane (Block)
84 Jukebox
85 Fence
86 Pumpkin
87 Netherrack
88 Soul Sand
89 Glowstone
90 Portal
91 Jack-O-Lantern
92 Cake (Block)
93 Redstone Repeater (Block Off)
94 Redstone Repeater (Block On)
95 Locked Chest
96 Trapdoor
97 Silverfish Stone
97:1 Silverfish Cobblestone
97:2 Silverfish Stone Brick
98 Stone Bricks
98:1 Mossy Stone Bricks
98:2 Cracked Stone Bricks
98:3 Chiseled Stone Brick
99 Brown Mushroom (Block)
100 Red Mushroom (Block)
101 Iron Bars
102 Glass Pane
103 Melon (Block)
104 Pumpkin Vine
105 Melon Vine
106 Vines
107 Fence Gate
108 Brick Stairs
109 Stone Brick Stairs
110 Mycelium
111 Lily Pad
112 Nether Brick
113 Nether Brick Fence
114 Nether Brick Stairs
115 Nether Wart
116 Enchantment Table
117 Brewing Stand (Block)
118 Cauldron (Block)
119 End Portal
120 End Portal Frame
121 End Stone
122 Dragon Egg
123 Redstone Lamp
124 Redstone Lamp (On)
125 Oak-Wood Slab (Double)
125:1 Spruce-Wood Slab (Double)
125:2 Birch-Wood Slab (Double)
125:3 Jungle-Wood Slab (Double)
126 Oak-Wood Slab
126:1 Spruce-Wood Slab
126:2 Birch-Wood Slab
126:3 Jungle-Wood Slab
127 Coca Plant
128 Sandstone Stairs
129 Emerald Ore
130 Ender Chest
131 Tripwire Hook
132 Tripwire
133 Block of Emerald
134 Wooden Stairs (Spruce)
135 Wooden Stairs (Birch)
136 Wooden Stairs (Jungle)
137 Command Block
138 Beacon
139 Cobblestone Wall
139:1 Mossy Cobblestone Wall
140 Flower Pot (Block)
141 Carrot (Crop)
142 Potatoes (Crop)
143 Button (Wood)
144 Head Block (Skeleton)
144:1 Head Block (Wither)
144:2 Head Block (Zombie)
144:3 Head Block (Steve)
144:4 Head Block (Creeper)
145 Anvil
145:1 Anvil (Slightly Damaged)
145:2 Anvil (Very Damaged)
146 Trapped Chest
147 Weighted Pressure Plate (Light)
148 Weighted Pressure Plate (Heavy)
149 Redstone Comparator (Off)
150 Redstone Comparator (On)
151 Daylight Sensor
152 Block of Redstone
153 Nether Quartz Ore
154 Hopper
155 Quartz Block
155:1 Chiseled Quartz Block
155:2 Pillar Quartz Block
156 Quartz Stairs
157 Activator Rail
158 Dropper
159 Stained Clay (White)
159:1 Stained Clay (Orange)
159:2 Stained Clay (Magenta)
159:3 Stained Clay (Light Blue)
159:4 Stained Clay (Yellow)
159:5 Stained Clay (Lime)
159:6 Stained Clay (Pink)
159:7 Stained Clay (Gray)
159:8 Stained Clay (Light Gray)
159:9 Stained Clay (Cyan)
159:10 Stained Clay (Purple)
159:11 Stained Clay (Blue)
159:12 Stained Clay (Brown)
159:13 Stained Clay (Green)
159:14 Stained Clay (Red)
159:15 Stained Clay (Black)
170 Hay Bale
171 Carpet (White)
171:1 Carpet (Orange)
171:2 Carpet (Magenta)
171:3 Carpet (Light Blue)
171:4 Carpet (Yellow)
171:5 Carpet (Lime)
171:6 Carpet (Pink)
171:7 Carpet (Grey)
171:8 Carpet (Light Gray)
171:9 Carpet (Cyan)
171:10 Carpet (Purple)
171:11 Carpet (Blue)
171:12 Carpet (Brown)
171:13 Carpet (Green)
171:14 Carpet (Red)
171:15 Carpet (Black)
172 Hardened Clay
173 Block of Coal
256 Iron Shovel
257 Iron Pickaxe
258 Iron Axe
259 Flint and Steel
260 Apple
261 Bow
262 Arrow
263 Coal
263:1 Charcoal
264 Diamond Gem
265 Iron Ingot
266 Gold Ingot
267 Iron Sword
268 Wooden Sword
269 Wooden Shovel
270 Wooden Pickaxe
271 Wooden Axe
272 Stone Sword
273 Stone Shovel
274 Stone Pickaxe
275 Stone Axe
276 Diamond Sword
277 Diamond Shovel
278 Diamond Pickaxe
279 Diamond Axe
280 Stick
281 Bowl
282 Mushroom Stew
283 Gold Sword
284 Gold Shovel
285 Gold Pickaxe
286 Gold Axe
287 String
288 Feather
289 Gunpowder
290 Wooden Hoe
291 Stone Hoe
292 Iron Hoe
293 Diamond Hoe
294 Gold Hoe
295 Wheat Seeds
296 Wheat
297 Bread
298 Leather Helmet
299 Leather Chestplate
300 Leather Leggings
301 Leather Boots
302 Chainmail Helmet
303 Chainmail Chestplate
304 Chainmail Leggings
305 Chainmail Boots
306 Iron Helmet
307 Iron Chestplate
308 Iron Leggings
309 Iron Boots
310 Diamond Helmet
311 Diamond Chestplate
312 Diamond Leggings
313 Diamond Boots
314 Gold Helmet
315 Gold Chestplate
316 Gold Leggings
317 Gold Boots
318 Flint
319 Raw Porkchop
320 Cooked Porkchop
321 Painting
322 Golden Apple
322:1 Enchanted Golden Apple
323 Sign
324 Wooden Door
325 Bucket
326 Bucket (Water)
327 Bucket (Lava)
328 Minecart
329 Saddle
330 Iron Door
331 Redstone Dust
332 Snowball
333 Boat
334 Leather
335 Bucket (Milk)
336 Clay Brick
337 Clay
338 Sugar Cane
339 Paper
340 Book
341 Slime Ball
342 Storage Minecart
343 Powered Minecart
344 Egg
345 Compass
346 Fishing Rod
347 Watch
348 Glowstone Dust
349 Raw Fish
350 Cooked Fish
351 Ink Sack
351:1 Rose Red Dye
351:2 Cactus Green Dye
351:3 Coca Bean
351:4 Lapis Lazuli
351:5 Purple Dye
351:6 Cyan Dye
351:7 Light Gray Dye
351:8 Gray Dye
351:9 Pink Dye
351:10 Lime Dye
351:11 Dandelion Yellow Dye
351:12 Light Blue Dye
351:13 Magenta Dye
351:14 Orange Dye
351:15 Bone Meal
352 Bone
353 Sugar
354 Cake
355 Bed
356 Redstone Repeater
357 Cookie
358 Map
359 Shears
360 Melon (Slice)
361 Pumpkin Seeds
362 Melon Seeds
363 Raw Beef
364 Steak
365 Raw Chicken
366 Cooked Chicken
367 Rotten Flesh
368 Ender Pearl
369 Blaze Rod
370 Ghast Tear
371 Gold Nugget
372 Nether Wart Seeds
373 Water Bottle
373:16 Awkward Potion
373:32 Thick Potion
373:64 Mundane Potion
373:8193 Regeneration Potion (0:45)
373:8194 Swiftness Potion (3:00)
373:8195 Fire Resistance Potion (3:00)
373:8196 Poison Potion (0:45)
373:8197 Healing Potion
373:8198 Night Vision Potion (3:00)
373:8200 Weakness Potion (1:30)
373:8201 Strength Potion (3:00)
373:8202 Slowness Potion (1:30)
373:8204 Harming Potion
373:8206 Invisibility Potion (3:00)
373:8225 Regeneration Potion II (0:22)
373:8226 Swiftness Potion II (1:30)
373:8228 Poison Potion II (0:22)
373:8229 Healing Potion II
373:8233 Strength Potion II (1:30)
373:8236 Harming Potion II
373:8257 Regeneration Potion (2:00)
373:8258 Swiftness Potion (8:00)
373:8259 Fire Resistance Potion (8:00)
373:8260 Poison Potion (2:00)
373:8262 Night Vision Potion (8:00)
373:8264 Weakness Potion (4:00)
373:8265 Strength Potion (8:00)
373:8266 Slowness Potion (4:00)
373:8270 Invisibility Potion (8:00)
373:8289 Regeneration Potion II (1:00)
373:8290 Swiftness Potion II (4:00)
373:8292 Poison Potion II (1:00)
373:8297 Strength Potion II (4:00)
373:16385 Regeneration Splash (0:33)
373:16386 Swiftness Splash (2:15)
373:16387 Fire Resistance Splash (2:15)
373:16388 Poison Splash (0:33)
373:16389 Healing Splash
373:16390 Night Vision Splash (2:15)
373:16392 Weakness Splash (1:07)
373:16393 Strength Splash (2:15)
373:16394 Slowness Splash (1:07)
373:16396 Harming Splash
373:16398 Invisibility Splash (2:15)
373:16417 Regeneration Splash II (0:16)
373:16418 Swiftness Splash II (1:07)
373:16420 Poison Splash II (0:16)
373:16421 Healing Splash II
373:16425 Strength Splash II (1:07)
373:16428 Harming Splash II
373:16449 Regeneration Splash (1:30)
373:16450 Swiftness Splash (6:00)
373:16451 Fire Resistance Splash (6:00)
373:16452 Poison Splash (1:30)
373:16454 Night Vision Splash (6:00)
373:16456 Weakness Splash (3:00)
373:16457 Strength Splash (6:00)
373:16458 Slowness Splash (3:00)
373:16462 Invisibility Splash (6:00)
373:16481 Regeneration Splash II (0:45)
373:16482 Swiftness Splash II (3:00)
373:16484 Poison Splash II (0:45)
373:16489 Strength Splash II (3:00)
374 Glass Bottle
375 Spider Eye
376 Fermented Spider Eye
377 Blaze Powder
378 Magma Cream
379 Brewing Stand
380 Cauldron
381 Eye of Ender
382 Glistering Melon (Slice)
383:50 Spawn Egg (Creeper)
383:51 Spawn Egg (Skeleton)
383:52 Spawn Egg (Spider)
383:54 Spawn Egg (Zombie)
383:55 Spawn Egg (Slime)
383:56 Spawn Egg (Ghast)
383:57 Spawn Egg (Zombie Pigmen)
383:58 Spawn Egg (Endermen)
383:59 Spawn Egg (Cave Spider)
383:60 Spawn Egg (Silverfish)
383:61 Spawn Egg (Blaze)
383:62 Spawn Egg (Magma Cube)
383:65 Spawn Egg (Bat)
383:66 Spawn Egg (Witch)
383:90 Spawn Egg (Pig)
383:91 Spawn Egg (Sheep)
383:92 Spawn Egg (Cow)
383:93 Spawn Egg (Chicken)
383:94 Spawn Egg (Squid)
383:95 Spawn Egg (Wolf)
383:96 Spawn Egg (Mooshroom)
383:98 Spawn Egg (Ocelot)
383:100 Spawn Egg (Horse)
383:120 Spawn Egg (Villager)
384 Bottle of Enchanting
385 Fire Charge
386 Book and Quill
387 Written Book
388 Emerald
389 Item Frame
390 Flower Pot
391 Carrot
392 Potato
393 Baked Potato
394 Poisonous Potato
395 Empty Map
396 Golden Carrot
397 Head (Skeleton)
397:1 Head (Wither)
397:2 Head (Zombie)
397:3 Head (Steve)
397:4 Head (Creeper)
398 Carrot on a Stick
399 Nether Star
400 Pumpkin Pie
401 Firework Rocket
402 Firework Star
403 Enchanted Book
404 Redstone Comparator
405 Nether Brick (Item)
406 Nether Quartz
407 TNT Minecart
408 Hopper Minecart
417 Iron Horse Armor
418 Gold Horse Armor
419 Diamond Horse Armor
420 Lead
421 Name Tag
2256 Music Disk (13)
2257 Music Disk (Cat)
2258 Music Disk (Blocks)
2259 Music Disk (Chirp)
2260 Music Disk (Far)
2261 Music Disk (Mall)
2262 Music Disk (Mellohi)
2263 Music Disk (Stal)
2264 Music Disk (Strad)
2265 Music Disk (Ward)
2266 Music Disk (11)
2267 Music Disk (Wait)

View file

View file

View file

@ -1,7 +1,7 @@
//Minecraft Recipes List
//Created by _303
//Obtained from https://github.com/ClouDev/CloudBot/blob/develop/plugins/data/recipes.txt
//Edited by CHCMATT for Minecraft version: 1.7.4
//Edited by _frozen
//
//Summary of Use: Each column is seperated by a comma (,) and rows by a vertical bar (|). Order of Recipes & Categories taken from
//www.minecraftwiki.net/wiki/Crafting for easier updating in the future (The Future!)
@ -21,10 +21,7 @@
1x Block of Gold: Gold Ingot, Gold Ingot, Gold Ingot | Gold Ingot, Gold Ingot, Gold Ingot | Gold Ingot, Gold Ingot, Gold Ingot
1x Block of Iron: Iron Ingot, Iron Ingot, Iron Ingot | Iron Ingot, Iron Ingot, Iron Ingot | Iron Ingot, Iron Ingot, Iron Ingot
1x Block of Diamond: Diamond, Diamond, Diamond | Diamond, Diamond, Diamond | Diamond, Diamond, Diamond
1x Block of Coal: Coal, Coal, Coal | Coal, Coal, Coal | Coal, Coal, Coal
1x Block of Redstone: Redstone Dust, Redstone Dust, Redstone Dust | Redstone Dust, Redstone Dust, Redstone Dust | Redstone Dust, Redstone Dust, Redstone Dust
1x Lapis Lazuli Block: Lapis Lazuli, Lapis Lazuli, Lapis Lazuli | Lapis Lazuli, Lapis Lazuli, Lapis Lazuli | Lapis Lazuli, Lapis Lazuli, Lapis Lazuli
1x Emerald Block: Emerald, Emerald, Emerald | Emerald, Emerald, Emerald | Emerald, Emerald, Emerald
1x Glowstone: Glowstone Dust, Glowstone Dust | Glowstone Dust, Glowstone Dust
1x Wool: String, String | String, String
1x TNT: Gunpowder, Sand, Gunpowder | Sand, Gunpowder, Sand | Gunpowder, Sand, Gunpowder
@ -120,7 +117,6 @@
6x Powered Rail: Gold Ingot, None, Gold Ingot | Gold Ingot, Stick, Gold Ingot | Gold Ingot, Redstone, Gold Ingot
6x Detector Rail: Iron Ingot, None, Iron Ingot | Iron Ingot, Pressure Plate, Iron Ingot | Iron Ingot, Redstone, Iron Ingot
1x Boat: Wooden Planks, None, Wooden Planks | Wooden Planks, Wooden Planks, Wooden Planks
1x Carrot On A Stick: Fishing Rod | None, Carrot
//
//Mechanism Recipes
//
@ -129,8 +125,7 @@
2x Trapdoor: Wooden Planks, Wooden Planks, Wooden Planks | Wooden Planks, Wooden Planks, Wooden Planks
1x Stone Pressure Plate: Stone, Stone
1x Wooden Pressure Plate: Wooden Planks, Wooden Planks
1x Stone Button: Stone
1x Wooden Button: Wooden Planks
1x Button: Stone | Stone
1x Redstone Torch: Redstone | Stick
1x Lever: Stick | Cobblestone
1x Note Block: Wooden Planks, Wooden Planks, Wooden Planks | Wooden Planks, Redstone, Wooden Planks | Wooden Planks, Wooden Planks, Wooden Planks
@ -138,13 +133,8 @@
1x Dispenser: Cobblestone, Cobblestone, Cobblestone | Cobblestone, Bow, Cobblestone | Cobblestone, Redstone, Cobblestone
1x Redstone Repeater: Redstone Torch, Redstone, Redstone Torch | Stone, Stone, Stone
1x Piston: Wooden Planks, Wooden Planks, Wooden Planks | Cobblestone, Iron Ingot, Cobblestone | Cobblestone, Redstone, Cobblestone
1x Sticky Piston: Slime Ball | Piston
1x Redstone Lamp: None, Redstone Dust, None | Redstone Dust, Glowstone Block, Redstone Dust | None, Redstone Dust, None
1x Trapped Chest: Chest, Tripwire Hook
1x Dropper: Cobblestone, Cobblestone, Cobblestone | Cobblestone, None, Cobblestone | Cobblestone, Redstone Dust, Cobblestone
1x Weighted Pressure Plate (Heavy): Iron Ingot, Iron Ingot
1x Weighted Pressure Plate (Light): Gold Ingot, Gold Ingot
2x Tripwire Hook: Iron Ingot | Stick | Wooden Planks
1x Sticky Piston: none, slime ball, none | none, piston, none
1x Redstone Lamp: none, redstone dust, none | redstone dust, glowstone block, redstone | none, redstone dust, none
//
//Food Recipes
//
@ -179,11 +169,6 @@
9x Gold Nugget: Gold Ingot
1x Gold Ingot: Gold Nugget, Gold Nugget, Gold Nugget | Gold Nugget, Gold Nugget, Gold Nugget | Gold Nugget, Gold Nugget, Gold Nugget
1x Eye of Ender: Ender Pearl | Blaze Powder
1x Item Frame: Stick, Stick, Stick | Stick, Leather, Stick | Stick, Stick, Stick
1x Anvil: Block of Iron, Block of Iron, Block of Iron | None, Iron Ingot, None | Iron Ingot, Iron Ingot, Iron Ingot
1x Ender Chest: Obsidian, Obsidian, Obsidian | Osbidian, Eye of Ender, Obsidian | Obsidian, Obsidian, Obsidian
1x Flower Pot: Brick, None, Brick | None, Brick, None
2x Lead: None, String, String | None, Slime Ball, String | String, None, None
//
//Dye Recipes
//
@ -229,41 +214,4 @@
1x Fermented Spider Eye: Spider Eye | Brown Mushroom, Sugar
1x Glistering Melon: Melon Slice, Gold Nugget
9x Gold Nugget: Gold Ingot
1x Enchantment Table: None, Book, None | Diamond, Obsidian, Diamond | Obsidian, Obsidian, Obsidian
//
//Stained Glass Recipes
//
8x White Stained Glass: Glass, Glass, Glass | Glass, Bone Meal, Glass | Glass, Glass, Glass
8x Orange Stained Glass: Glass, Glass, Glass | Glass, Orange Dye, Glass | Glass, Glass, Glass
8x Magenta Stained Glass: Glass, Glass, Glass | Glass, Magenta Dye, Glass | Glass, Glass, Glass
8x Light Blue Stained Glass: Glass, Glass, Glass | Glass, Light Blue Dye, Glass | Glass, Glass, Glass
8x Yellow Stained Glass: Glass, Glass, Glass | Glass, Dandelion Yellow, Glass | Glass, Glass, Glass
8x Lime Stained Glass: Glass, Glass, Glass | Glass, Lime Dye, Glass | Glass, Glass, Glass
8x Pink Stained Glass: Glass, Glass, Glass | Glass, Pink Dye, Glass | Glass, Glass, Glass
8x Gray Stained Glass: Glass, Glass, Glass | Glass, Gray Dye, Glass | Glass, Glass, Glass
8x Light Gray Stained Glass: Glass, Glass, Glass | Glass, Light Gray Dye, Glass | Glass, Glass, Glass
8x Cyan Stained Glass: Glass, Glass, Glass | Glass, Cyan Dye, Glass | Glass, Glass, Glass
8x Purple Stained Glass: Glass, Glass, Glass | Glass, Purple Dye, Glass | Glass, Glass, Glass
8x Blue Stained Glass: Glass, Glass, Glass | Glass, Lapis Lazuli, Glass | Glass, Glass, Glass
8x Brown Stained Glass: Glass, Glass, Glass | Glass, Cocoa Beans, Glass | Glass, Glass, Glass
8x Green Stained Glass: Glass, Glass, Glass | Glass, Cactus Green, Glass | Glass, Glass, Glass
8x Red Stained Glass: Glass, Glass, Glass | Glass, Rose Red, Glass | Glass, Glass, Glass
8x Black Stained Glass: Glass, Glass, Glass | Glass, Inc Sac, Glass | Glass, Glass, Glass
//
//Stained Glass Panes
//
16x White Stained Glass Panes: White Stained Glass, White Stained Glass, White Stained Glass | White Stained Glass, White Stained Glass, White Stained Glass
16x Orange Stained Glass Panes: Orange Stained Glass, Orange Stained Glass, Orange Stained Glass | Orange Stained Glass, Orange Stained Glass, Orange Stained Glass
16x Magenta Stained Glass Panes: Magenta Stained Glass, Magenta Stained Glass, Magenta Stained Glass | Magenta Stained Glass, Magenta Stained Glass, Magenta Stained Glass
16x Light Blue Stained Glass Panes: Light Blue Stained Glass, Light Blue Stained Glass, Light Blue Stained Glass | Light Blue Stained Glass, Light Blue Stained Glass, Light Blue Stained Glass
16x Yellow Stained Glass Panes: Yellow Stained Glass, Yellow Stained Glass, Yellow Stained Glass | Yellow Stained Glass, Yellow Stained Glass, Yellow Stained Glass
16x Lime Stained Glass Panes: Lime Stained Glass, Lime Stained Glass, Lime Stained Glass | Lime Stained Glass, Lime Stained Glass, Lime Stained Glass
16x Pink Stained Glass Panes: Pink Stained Glass, Pink Stained Glass, Pink Stained Glass | Pink Stained Glass, Pink Stained Glass, Pink Stained Glass
16x Gray Stained Glass Panes: Gray Stained Glass, Gray Stained Glass, Gray Stained Glass | Gray Stained Glass, Gray Stained Glass, Gray Stained Glass
16x Light Gray Stained Glass Panes: Light Gray Stained Glass, Light Gray Stained Glass, Light Gray Stained Glass | Light Gray Stained Glass, Light Gray Stained Glass, Light Gray Stained Glass
16x Cyan Stained Glass Panes: Cyan Stained Glass, Cyan Stained Glass, Cyan Stained Glass | Cyan Stained Glass, Cyan Stained Glass, Cyan Stained Glass
16x Purple Stained Glass Panes: Purple Stained Glass, Purple Stained Glass, Purple Stained Glass | Purple Stained Glass, Purple Stained Glass, Purple Stained Glass
16x Blue Stained Glass Panes: Blue Stained Glass, Blue Stained Glass, Blue Stained Glass | Blue Stained Glass, Blue Stained Glass, Blue Stained Glass
16x Brown Stained Glass Panes: Brown Stained Glass, Brown Stained Glass, Brown Stained Glass | Brown Stained Glass, Brown Stained Glass, Brown Stained Glass
16x Green Stained Glass Panes: Green Stained Glass, Green Stained Glass, Green Stained Glass | Green Stained Glass, Green Stained Glass, Green Stained Glass
16x Black Stained Glass Panes: Black Stained Glass, Black Stained Glass, Black Stained Glass | Black Stained Glass, Black Stained Glass, Black Stained Glass
1x Enchantment Table: None, Book, None | Diamond, Obsidian, Diamond | Obsidian, Obsidian, Obsidian

View file

@ -9,10 +9,10 @@
"sits on {user}'s face while slamming a {item} into their crotch.",
"starts slapping {user} silly with a {item}.",
"holds {user} down and repeatedly {hits} them with a {item}.",
"prods {user} with a {item}.",
"prods {user} with a {mod} {item}.",
"picks up a {item} and {hits} {user} with it.",
"ties {user} to a chair and {throws} a {item} at them.",
"{hits} {user} {where} with a {item}.",
"{hits} {user} on the head with a {item}.",
"ties {user} to a pole and whips them with a {item}."
],
"parts": {
@ -29,8 +29,6 @@
"diamond sword",
"baguette",
"physics textbook",
"toaster",
"portrait of Richard Stallman",
"television",
"mau5head",
"five ton truck",
@ -60,10 +58,10 @@
"slaps",
"smacks"
],
"where": [
"in the chest",
"on the head",
"on the bum"
"mod": [
"flaming",
"sticky",
"dripping"
]
}
}
}

View file

21
disabled_stuff/dice.py → plugins/dice.py Normal file → Executable file
View file

@ -14,7 +14,7 @@ sign_re = re.compile(r'[+-]?(?:\d*d)?(?:\d+|F)', re.I)
split_re = re.compile(r'([\d+-]*)d?(F|\d*)', re.I)
def n_rolls(count, n):
def nrolls(count, n):
"""roll an n-sided die count times"""
if n == "F":
return [random.randint(-1, 1) for x in xrange(min(count, 100))]
@ -36,7 +36,7 @@ def n_rolls(count, n):
#@hook.regex(valid_diceroll, re.I)
@hook.command
def dice(inp):
"""dice <dice roll> -- Simulates dice rolls. Example of <dice roll>:
"""dice <diceroll> -- Simulates dicerolls. Example of <diceroll>:
'dice 2d20-d5+4 roll 2'. D20s, subtract 1D5, add 4"""
try: # if inp is a re.match object...
@ -49,7 +49,7 @@ def dice(inp):
spec = whitespace_re.sub('', inp)
if not valid_diceroll_re.match(spec):
return "Invalid dice roll"
return "Invalid diceroll"
groups = sign_re.findall(spec)
total = 0
@ -59,7 +59,7 @@ def dice(inp):
count, side = split_re.match(roll).groups()
count = int(count) if count not in " +-" else 1
if side.upper() == "F": # fudge dice are basically 1d3-2
for fudge in n_rolls(count, "F"):
for fudge in nrolls(count, "F"):
if fudge == 1:
rolls.append("\x033+\x0F")
elif fudge == -1:
@ -73,15 +73,14 @@ def dice(inp):
side = int(side)
try:
if count > 0:
d = n_rolls(count, side)
rolls += map(str, d)
total += sum(d)
dice = nrolls(count, side)
rolls += map(str, dice)
total += sum(dice)
else:
d = n_rolls(-count, side)
rolls += [str(-x) for x in d]
total -= sum(d)
dice = nrolls(-count, side)
rolls += [str(-x) for x in dice]
total -= sum(dice)
except OverflowError:
# I have never seen this happen. If you make this happen, you win a cookie
return "Thanks for overflowing a float, jerk >:["
if desc:

7
disabled_stuff/dictionary.py → plugins/dictionary.py Normal file → Executable file
View file

@ -1,6 +1,5 @@
# Plugin by GhettoWizard and Scaevolus
import re
from util import hook
from util import http
@ -19,10 +18,10 @@ def define(inp):
'//div[@class="example"]')
if not definition:
return u'No results for {} :('.format(inp)
return 'No results for ' + inp + ' :('
def format_output(show_examples):
result = u'{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
result = '{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
correction = h.xpath('//span[@class="correct-word"]/text()')
if correction:
@ -77,7 +76,7 @@ def etymology(inp):
etym = h.xpath('//dl')
if not etym:
return u'No etymology found for {} :('.format(inp)
return 'No etymology found for {} :('.format(inp)
etym = etym[0].text_content()

View file

@ -9,10 +9,10 @@ def domainr(inp):
except (http.URLError, http.HTTPError) as e:
return "Unable to get data for some reason. Try again later."
if data['query'] == "":
return "An error occurred: {status} - {message}".format(**data['error'])
return "An error occurrred: {status} - {message}".format(**data['error'])
domains = ""
for domain in data['results']:
domains += ("\x034" if domain['availability'] == "taken" else (
"\x033" if domain['availability'] == "available" else "\x031")) + domain['domain'] + "\x0f" + domain[
'path'] + ", "
"\x033" if domain['availability'] == "available" else "\x031")) + domain['domain'] + "\x0f" + domain[
'path'] + ", "
return "Domains: " + domains

0
disabled_stuff/down.py → plugins/down.py Normal file → Executable file
View file

4
disabled_stuff/drama.py → plugins/drama.py Normal file → Executable file
View file

@ -1,7 +1,5 @@
import re
from util import hook, http, text
import re
api_url = "http://encyclopediadramatica.se/api.php?action=opensearch"
ed_url = "http://encyclopediadramatica.se/"

6
disabled_stuff/eightball.py → plugins/eightball.py Normal file → Executable file
View file

@ -1,8 +1,6 @@
import random
from util import hook, text
color_codes = {
"<r>": "\x02\x0305",
"<g>": "\x02\x0303",
@ -15,9 +13,9 @@ with open("plugins/data/8ball_responses.txt") as f:
@hook.command('8ball')
def eightball(inp, action=None):
def eightball(input, me=None):
"""8ball <question> -- The all knowing magic eight ball,
in electronic form. Ask and it shall be answered!"""
magic = text.multiword_replace(random.choice(responses), color_codes)
action("shakes the magic 8 ball... {}".format(magic))
me("shakes the magic 8 ball... {}".format(magic))

10
disabled_stuff/fact.py → plugins/fact.py Normal file → Executable file
View file

@ -2,7 +2,7 @@ from util import hook, http, web
@hook.command(autohelp=False)
def fact(inp):
def fact(inp, say=False, nick=False):
"""fact -- Gets a random fact from OMGFACTS."""
attempts = 0
@ -20,10 +20,10 @@ def fact(inp):
response = soup.find('a', {'class': 'surprise'})
link = response['href']
fact_data = ''.join(response.find(text=True))
fact = ''.join(response.find(text=True))
if fact_data:
fact_data = fact_data.strip()
if fact:
fact = fact.strip()
break
else:
if attempts > 2:
@ -34,4 +34,4 @@ def fact(inp):
url = web.try_isgd(link)
return "{} - {}".format(fact_data, url)
return "{} - {}".format(fact, url)

35
disabled_stuff/factoids.py → plugins/factoids.py Normal file → Executable file
View file

@ -1,14 +1,10 @@
# Written by Scaevolus 2010
from util import hook, http, text, execute
import string
import re
from util import hook, http, text, pyexec
re_lineends = re.compile(r'[\r\n]*')
db_ready = False
# some simple "shortcodes" for formatting purposes
shortcodes = {
'[b]': '\x02',
@ -20,12 +16,9 @@ shortcodes = {
def db_init(db):
global db_ready
if not db_ready:
db.execute("create table if not exists mem(word, data, nick,"
" primary key(word))")
db.commit()
db_ready = True
db.execute("create table if not exists mem(word, data, nick,"
" primary key(word))")
db.commit()
def get_memory(db, word):
@ -112,8 +105,8 @@ def info(inp, notice=None, db=None):
@hook.regex(r'^\? ?(.+)')
def factoid(inp, message=None, db=None, bot=None, action=None, conn=None, input=None):
"""?<word> -- Shows what data is associated with <word>."""
def factoid(inp, say=None, db=None, bot=None, me=None, conn=None, input=None):
"?<word> -- Shows what data is associated with <word>."
try:
prefix_on = bot.config["plugins"]["factoids"].get("prefix", False)
except KeyError:
@ -137,9 +130,9 @@ def factoid(inp, message=None, db=None, bot=None, action=None, conn=None, input=
if data.startswith("<py>"):
code = data[4:].strip()
variables = 'input="""{}"""; nick="{}"; chan="{}"; bot_nick="{}";'.format(arguments.replace('"', '\\"'),
input.nick, input.chan,
input.conn.nick)
result = pyexec.eval_py(variables + code)
input.nick, input.chan,
input.conn.nick)
result = execute.eval_py(variables + code)
else:
result = data
@ -148,15 +141,15 @@ def factoid(inp, message=None, db=None, bot=None, action=None, conn=None, input=
if result.startswith("<act>"):
result = result[5:].strip()
action(result)
me(result)
elif result.startswith("<url>"):
url = result[5:].strip()
try:
message(http.get(url))
say(http.get(url))
except http.HttpError:
message("Could not fetch URL.")
say("Could not fetch URL.")
else:
if prefix_on:
message("\x02[{}]:\x02 {}".format(factoid_id, result))
say("\x02[{}]:\x02 {}".format(factoid_id, result))
else:
message(result)
say(result)

View file

@ -1,7 +1,5 @@
from urllib import quote_plus
from util import hook, http
from urllib import quote_plus
api_url = "http://api.fishbans.com/stats/{}/"
@ -53,5 +51,6 @@ def bancount(inp):
if not out:
return "The user \x02{}\x02 has no bans.".format(user)
else:
# dat string.
return "Bans for \x02{}\x02: ".format(user) + ", ".join(out) + ". More info " \
"at {}".format(user_url)

8
disabled_stuff/fmylife.py → plugins/fmylife.py Normal file → Executable file
View file

@ -8,9 +8,9 @@ def refresh_cache():
soup = http.get_soup('http://www.fmylife.com/random/')
for e in soup.find_all('div', {'class': 'post article'}):
fml_id = int(e['id'])
id = int(e['id'])
text = ''.join(e.find('p').find_all(text=True))
fml_cache.append((fml_id, text))
fml_cache.append((id, text))
# do an initial refresh of the cache
refresh_cache()
@ -21,9 +21,9 @@ def fml(inp, reply=None):
"""fml -- Gets a random quote from fmyfife.com."""
# grab the last item in the fml cache and remove it
fml_id, text = fml_cache.pop()
id, text = fml_cache.pop()
# reply with the fml we grabbed
reply('(#{}) {}'.format(fml_id, text))
reply('(#{}) {}'.format(id, text))
# refresh fml cache if its getting empty
if len(fml_cache) < 3:
refresh_cache()

4
disabled_stuff/fortune.py → plugins/fortune.py Normal file → Executable file
View file

@ -1,7 +1,5 @@
import random
from util import hook
import random
with open("plugins/data/fortunes.txt") as f:
fortunes = [line.strip() for line in f.readlines()

19
plugins/gcalc.py Executable file
View file

@ -0,0 +1,19 @@
from util import hook, http
@hook.command("math")
@hook.command
def calc(inp):
"""calc <term> -- Calculate <term> with Google Calc."""
soup = http.get_soup('http://www.google.com/search', q=inp)
result = soup.find('h2', {'class': 'r'})
exponent = result.find('sup')
if not result:
return "Could not calculate '{}'".format(inp)
if not exponent:
return result.contents[0]
if exponent:
return "{}^{}".format(result.contents[0]*2)

10
disabled_stuff/geoip.py → plugins/geoip.py Normal file → Executable file
View file

@ -1,19 +1,17 @@
from util import hook, http
import os.path
import pygeoip
import json
import gzip
from StringIO import StringIO
import pygeoip
from util import hook, http
# load region database
with open("./plugins/data/geoip_regions.json", "rb") as f:
regions = json.loads(f.read())
if os.path.isfile(os.path.abspath("./plugins/data/GeoLiteCity.dat")):
# initialise geolocation database
# initalise geolocation database
geo = pygeoip.GeoIP(os.path.abspath("./plugins/data/GeoLiteCity.dat"))
else:
download = http.get("http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz")
@ -51,4 +49,4 @@ def geoip(inp):
data["cc"] = record["country_code"] or "N/A"
data["country"] = record["country_name"] or "Unknown"
data["city"] = record["city"] or "Unknown"
return u"\x02Country:\x02 {country} ({cc}), \x02City:\x02 {city}{region}".format(**data)
return "\x02Country:\x02 {country} ({cc}), \x02City:\x02 {city}{region}".format(**data)

Some files were not shown because too many files have changed in this diff Show more