Compare commits
No commits in common. "ChaosChemnitz" and "testing!" have entirely different histories.
ChaosChemn
...
testing!
186 changed files with 2050 additions and 4155 deletions
1
.gitignore
vendored
Normal file → Executable file
1
.gitignore
vendored
Normal file → Executable file
|
@ -1,6 +1,5 @@
|
|||
persist
|
||||
config
|
||||
config.ssl
|
||||
gitflow
|
||||
*.db
|
||||
*.log
|
||||
|
|
|
@ -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
0
LICENSE
Normal file → Executable file
5
README.md
Normal file → Executable file
5
README.md
Normal file → Executable 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`
|
||||
|
||||
|
|
|
@ -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(),
|
134
config.default
134
config.default
|
@ -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
2
core/config.py
Normal file → Executable 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
0
core/db.py
Normal file → Executable file
60
core/irc.py
Normal file → Executable file
60
core/irc.py
Normal file → Executable 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
35
core/main.py
Normal file → Executable 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
0
core/reload.py
Normal file → Executable 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)
|
||||
|
|
@ -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.
|
@ -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)
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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))
|
||||
|
|
@ -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!"
|
|
@ -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)
|
|
@ -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))
|
|
@ -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())
|
|
@ -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)
|
|
@ -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)
|
|
@ -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."
|
|
@ -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
0
disabled_stuff/mtg.py
Normal file → Executable file
2
disabled_stuff/mygengo_translate.py
Normal file → Executable file
2
disabled_stuff/mygengo_translate.py
Normal file → Executable 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
|
||||
|
||||
|
|
|
@ -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."
|
||||
|
||||
|
|
@ -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)
|
|
@ -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)
|
|
@ -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))
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
0
disabled_stuff/repaste.py
Normal file → Executable 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)
|
||||
|
|
@ -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'])
|
|
@ -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
42
disabled_stuff/suggest.py
Normal file → Executable 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>', ''))
|
|
@ -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")
|
|
@ -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
0
disabled_stuff/urlhistory.py
Normal file → Executable 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
0
disabled_stuff/wordoftheday.py
Normal file → Executable file
0
disabled_stuff/wrapper.old
Normal file → Executable file
0
disabled_stuff/wrapper.old
Normal file → Executable 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)
|
|
@ -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
50
plugins/admin.py
Normal file → Executable 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)
|
||||
|
|
|
@ -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)
|
|
@ -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))
|
||||
|
|
@ -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
16
plugins/bitcoin.py
Executable 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
4
disabled_stuff/brainfuck.py → plugins/brainfuck.py
Normal file → Executable 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
|
|
@ -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
4
disabled_stuff/choose.py → plugins/choose.py
Normal file → Executable 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
11
disabled_stuff/coin.py → plugins/coin.py
Normal file → Executable 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
1
plugins/core_ctcp.py
Normal file → Executable file
|
@ -1,5 +1,4 @@
|
|||
import time
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
|
|
1
plugins/core_misc.py
Normal file → Executable file
1
plugins/core_misc.py
Normal file → Executable 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
31
plugins/core_sieve.py
Normal file → Executable 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
30
plugins/correction.py
Normal 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
8
disabled_stuff/cypher.py → plugins/cypher.py
Normal file → Executable 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)
|
9
disabled_stuff/data/flirts.txt → plugins/data/flirts.txt
Normal file → Executable file
9
disabled_stuff/data/flirts.txt → plugins/data/flirts.txt
Normal file → Executable 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 it’s 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.
|
0
disabled_stuff/data/fortunes.txt → plugins/data/fortunes.txt
Normal file → Executable file
0
disabled_stuff/data/fortunes.txt → plugins/data/fortunes.txt
Normal file → Executable file
0
disabled_stuff/data/insults.txt → plugins/data/insults.txt
Normal file → Executable file
0
disabled_stuff/data/insults.txt → plugins/data/insults.txt
Normal file → Executable file
537
plugins/data/itemids.txt
Executable file
537
plugins/data/itemids.txt
Executable 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)
|
0
disabled_stuff/data/kills.txt → plugins/data/kills.txt
Normal file → Executable file
0
disabled_stuff/data/kills.txt → plugins/data/kills.txt
Normal file → Executable file
0
disabled_stuff/data/larts.txt → plugins/data/larts.txt
Normal file → Executable file
0
disabled_stuff/data/larts.txt → plugins/data/larts.txt
Normal file → Executable file
62
disabled_stuff/data/recipes.txt → plugins/data/recipes.txt
Normal file → Executable file
62
disabled_stuff/data/recipes.txt → plugins/data/recipes.txt
Normal file → Executable 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
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
0
disabled_stuff/data/slogans.txt → plugins/data/slogans.txt
Normal file → Executable file
0
disabled_stuff/data/slogans.txt → plugins/data/slogans.txt
Normal file → Executable file
21
disabled_stuff/dice.py → plugins/dice.py
Normal file → Executable file
21
disabled_stuff/dice.py → plugins/dice.py
Normal file → Executable 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
7
disabled_stuff/dictionary.py → plugins/dictionary.py
Normal file → Executable 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()
|
||||
|
|
@ -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
0
disabled_stuff/down.py → plugins/down.py
Normal file → Executable file
4
disabled_stuff/drama.py → plugins/drama.py
Normal file → Executable file
4
disabled_stuff/drama.py → plugins/drama.py
Normal file → Executable 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
6
disabled_stuff/eightball.py → plugins/eightball.py
Normal file → Executable 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
10
disabled_stuff/fact.py → plugins/fact.py
Normal file → Executable 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
35
disabled_stuff/factoids.py → plugins/factoids.py
Normal file → Executable 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)
|
|
@ -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
8
disabled_stuff/fmylife.py → plugins/fmylife.py
Normal file → Executable 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
4
disabled_stuff/fortune.py → plugins/fortune.py
Normal file → Executable 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
19
plugins/gcalc.py
Executable 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
10
disabled_stuff/geoip.py → plugins/geoip.py
Normal file → Executable 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
Reference in a new issue