Compare commits
312 commits
testing!
...
ChaosChemn
Author | SHA1 | Date | |
---|---|---|---|
358b415566 | |||
3e1ea6ac4e | |||
48b627ad4b | |||
1f1ff649c9 | |||
Florian Schlegel | 8344fe7693 | ||
Florian Schlegel | a6992d5d1a | ||
21db4efd98 | |||
8941d59dc2 | |||
Florian Schlegel | 09ce708709 | ||
29cc95f0ad | |||
Florian Schlegel | 4a02f545ea | ||
28176ad2ad | |||
651d4a953e | |||
80711e1278 | |||
Florian Schlegel | a88d5ef0bd | ||
Markus Schmidl | 827c5c73e8 | ||
580415ed76 | |||
Florian Schlegel | c562a2c7ae | ||
4b5e86c237 | |||
11687a9ad0 | |||
Markus Schmidl | 296de07e14 | ||
Markus Schmidl | dfbead6946 | ||
e30eca5ebd | |||
2a3c9f52dc | |||
f88c3267d4 | |||
2b18eaac5a | |||
Florian Schlegel | 0650046d18 | ||
4e386c9008 | |||
05bfb9099a | |||
bfa3fb6e74 | |||
d415d0fc69 | |||
433d97d276 | |||
121715115a | |||
620de651ce | |||
3f205eaafa | |||
59cd8380d2 | |||
7cce9bf27e | |||
0ba2001b62 | |||
63fc042027 | |||
9421d8160d | |||
4b4ac2d918 | |||
05a68faf1d | |||
40328cf24f | |||
fb471bee17 | |||
48ab7417b8 | |||
97a3283eff | |||
6d147e1677 | |||
c99c44616c | |||
1062e69e56 | |||
5ca45fea4b | |||
04af154c5b | |||
f82041fc87 | |||
a027bd780f | |||
a611e0df45 | |||
e49ec9a9c9 | |||
5ee62107f9 | |||
4652ed90a3 | |||
ff3ef576b7 | |||
ec9f5e9777 | |||
7f3b433209 | |||
2cb772674a | |||
e46cb5c826 | |||
b917b495f7 | |||
4b7c8ffa75 | |||
7cf3d88c96 | |||
21d06ae4f0 | |||
50e2f72be4 | |||
1aacd8c511 | |||
6518fe7136 | |||
fd7253ded7 | |||
f05a35dd96 | |||
8340f55adf | |||
10907bf214 | |||
d834ae9070 | |||
31d9031dcc | |||
17b75a2ba9 | |||
0acb22e0a7 | |||
1be204236a | |||
a7a6f8c01e | |||
1bcf687ea2 | |||
b9bf09e6b6 | |||
914bc255ab | |||
2028075d2f | |||
8b1de13c8e | |||
d32619063a | |||
9cfdc0b706 | |||
5d3280b9d5 | |||
807cbf3f07 | |||
c7d2535098 | |||
44cb335bc0 | |||
90a91c1ef8 | |||
13df70da1b | |||
5008da1331 | |||
281a77c67c | |||
92796a218f | |||
45a1f65748 | |||
160785e92c | |||
763d73ea7a | |||
694cbbe81f | |||
e8876c2c48 | |||
b0c6815085 | |||
f7af1b0726 | |||
2c6e01a41d | |||
b6558ccdd5 | |||
27b62feb5f | |||
29258fdcac | |||
86a0333afd | |||
526d1de989 | |||
d6683b32f4 | |||
004ceb79fc | |||
a76ff29d4b | |||
4447e6cd1f | |||
b4d7e200a3 | |||
7265413a21 | |||
6086a7c6da | |||
6169be6da1 | |||
ee0ad67a16 | |||
ada153c8bc | |||
3a13621ae4 | |||
289561e76a | |||
c21b358f9b | |||
136acd126d | |||
a7e931541f | |||
223bef30a5 | |||
cd5ae1d32b | |||
6cc7554cd8 | |||
398b34fad5 | |||
10ef353782 | |||
1c9216ac1d | |||
a9d0d006ab | |||
c2884242b3 | |||
294a97b629 | |||
2fde060dc4 | |||
df1023da55 | |||
954ff2ad00 | |||
afdf5ccfe9 | |||
fa66cf3c87 | |||
6c6c108549 | |||
90bb260f5f | |||
af8b07d20b | |||
728ab6f60b | |||
d3aa2d3edd | |||
4f5a8e3ed5 | |||
d7195dce0e | |||
efef951501 | |||
ae1c9d0788 | |||
8b6647f521 | |||
aecf61746f | |||
c5765cc5f6 | |||
75908c6ab6 | |||
0ae8d3d5f9 | |||
6f6779dcc5 | |||
62a92b104b | |||
a8bf157ced | |||
d17234828c | |||
d10dcbac68 | |||
1febd1362d | |||
1f403bcd7a | |||
6035f1b1fc | |||
e29ea1c613 | |||
b25b8d6cec | |||
cda99f1852 | |||
e94c607b3e | |||
6decd65a19 | |||
b65e6e5a75 | |||
fdbcb967bb | |||
8b8623eb9e | |||
57e53e8eb7 | |||
be3df6718f | |||
1e22ca4995 | |||
4236b7bc29 | |||
97e7741434 | |||
3df53f95a8 | |||
91c827a03b | |||
fb84e17e34 | |||
3e073c8278 | |||
8317ba0920 | |||
bb73e70112 | |||
017fd4fc2e | |||
b3a8703d15 | |||
a37fc245d0 | |||
2eb6112f2f | |||
a59becca73 | |||
77459a0879 | |||
b489b9d3c7 | |||
8b18c33ce5 | |||
cdf8922f4d | |||
f55c8f8d4e | |||
78912b908f | |||
fb08870f4a | |||
2fa3a5a015 | |||
6b4f3ac546 | |||
323d045868 | |||
4ccfd1e3ca | |||
834cbaabd8 | |||
d3fbf1bc80 | |||
3825c94c9d | |||
9c7e2074f5 | |||
8d7f853426 | |||
49bb446c27 | |||
44c7bceaf4 | |||
0bb1574ebd | |||
85d8c4e5cb | |||
2d5208cbde | |||
d78f96b3ec | |||
9bc72bc57f | |||
8d42933554 | |||
e75fe73563 | |||
29b25e0b1f | |||
2b5f5e925d | |||
f95b607914 | |||
181b43df71 | |||
1ecdd3a246 | |||
13c7e5915b | |||
9c94cb01f9 | |||
2e66e03c7d | |||
a5a5fd2dfb | |||
cbe4e3177e | |||
f51bcf4ecf | |||
439ef0ba1c | |||
b2c9f46d78 | |||
186f272062 | |||
df6ee28462 | |||
99fe34a0b1 | |||
cd4b65de3d | |||
b6d1620cec | |||
0a19fd9347 | |||
3d739483de | |||
12e2a445d7 | |||
d58a8b5c65 | |||
5e7d1e9c92 | |||
21eb5760fd | |||
b6ce9b7e50 | |||
5258e13de2 | |||
12203d2580 | |||
b5a2497b00 | |||
05782766e9 | |||
853b4b7db8 | |||
b05056ff28 | |||
ce0063f4aa | |||
2e20487676 | |||
436dfc356c | |||
a42b8513c6 | |||
d83d82978e | |||
8a6803a22a | |||
c308b7dcb5 | |||
c9c3fbf671 | |||
a2c5964438 | |||
b6c3a233eb | |||
cfe9ebd054 | |||
a6130ab780 | |||
dd40b71252 | |||
cd30b053f6 | |||
42a72f068e | |||
b5ae12f50b | |||
51c866de6d | |||
72babfceb2 | |||
47eae62559 | |||
46f571382c | |||
72dce244b4 | |||
2ae2a8575a | |||
b38c540bf3 | |||
52f6260e1c | |||
651db7168f | |||
dd50cb4a36 | |||
839871f636 | |||
af9f024d63 | |||
d673f8d15c | |||
f8ad033f8e | |||
52b14b367a | |||
a16b1776f8 | |||
a45d470363 | |||
9b92d73f3a | |||
0abac29523 | |||
3a142e4810 | |||
4f2c690b2d | |||
a49bcc881c | |||
bfd600cf49 | |||
f9f15f3597 | |||
aea91cc33f | |||
7474904e97 | |||
a5d5845faf | |||
92e61a5348 | |||
57d9ec985a | |||
afa81ae7c4 | |||
80d976ba23 | |||
764a74a3ea | |||
5867cb05c7 | |||
f5e4b67777 | |||
d3e5099dab | |||
dabf61a520 | |||
c0b3285c4a | |||
f98774032f | |||
45330ddfb4 | |||
348de62f17 | |||
5b1258f544 | |||
483226d2ad | |||
0030669682 | |||
d5163a846a | |||
00f7e35a24 | |||
e5038156ea | |||
a69c4eceb3 | |||
b460fb2fd2 | |||
e8947a603b | |||
ae258e6c37 | |||
59d615aa88 | |||
8b629ee886 | |||
1bba6262bc | |||
d9f613f6f4 | |||
cb7f9b736f | |||
ecab6076ea | |||
1b3d3b51e7 |
1
.gitignore
vendored
Executable file → Normal file
1
.gitignore
vendored
Executable file → Normal file
|
@ -1,5 +1,6 @@
|
|||
persist
|
||||
config
|
||||
config.ssl
|
||||
gitflow
|
||||
*.db
|
||||
*.log
|
||||
|
|
|
@ -22,6 +22,7 @@ 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!)
|
||||
|
|
5
README.md
Executable file → Normal file
5
README.md
Executable file → Normal 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,6 +20,9 @@ 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,47 +1,28 @@
|
|||
#!/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'] # so 'import hook' works without duplication
|
||||
sys.path += ['plugins', 'lib'] # add stuff to the sys.path for easy imports
|
||||
os.chdir(sys.path[0] or '.') # do stuff relative to the install directory
|
||||
|
||||
|
||||
class Bot(object):
|
||||
pass
|
||||
|
||||
print 'CloudBot DEV <http://git.io/cloudbotirc>'
|
||||
|
||||
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)
|
||||
|
||||
# create new bot object
|
||||
bot = Bot()
|
||||
bot.vars = {}
|
||||
|
||||
# record start time for the uptime command
|
||||
bot.start_time = time.time()
|
||||
|
||||
print 'Loading plugins...'
|
||||
print 'Begin Plugin Loading.'
|
||||
|
||||
# bootstrap the reloader
|
||||
eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(),
|
134
config.default
134
config.default
|
@ -1,65 +1,77 @@
|
|||
{
|
||||
"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"]
|
||||
"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": "."
|
||||
}
|
||||
},
|
||||
"moderators": {
|
||||
"perms": ["addfactoid", "delfactoid", "ignore"],
|
||||
"users": ["examplec!user@example.com"]
|
||||
}
|
||||
},
|
||||
"plugins":
|
||||
{
|
||||
"factoids":
|
||||
{
|
||||
"prefix": false
|
||||
"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": ""
|
||||
},
|
||||
"ignore":
|
||||
{
|
||||
"ignored": []
|
||||
}
|
||||
},
|
||||
"censored_strings":
|
||||
[
|
||||
"mypass",
|
||||
"mysecret"
|
||||
]
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
|
2
core/config.py
Executable file → Normal file
2
core/config.py
Executable file → Normal file
|
@ -24,4 +24,4 @@ def config():
|
|||
print 'error: malformed config', e
|
||||
|
||||
|
||||
bot._config_mtime = 0
|
||||
bot._config_mtime = 0
|
||||
|
|
0
core/db.py
Executable file → Normal file
0
core/db.py
Executable file → Normal file
60
core/irc.py
Executable file → Normal file
60
core/irc.py
Executable file → Normal file
|
@ -44,7 +44,16 @@ class crlf_tcp(object):
|
|||
return socket.socket(socket.AF_INET, socket.TCP_NODELAY)
|
||||
|
||||
def run(self):
|
||||
self.socket.connect((self.host, self.port))
|
||||
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)
|
||||
|
||||
thread.start_new_thread(self.recv_loop, ())
|
||||
thread.start_new_thread(self.send_loop, ())
|
||||
|
||||
|
@ -55,17 +64,25 @@ 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()
|
||||
|
@ -79,6 +96,8 @@ 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)
|
||||
|
@ -86,13 +105,19 @@ class crlf_tcp(object):
|
|||
|
||||
def send_loop(self):
|
||||
while True:
|
||||
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:]
|
||||
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:]
|
||||
|
||||
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"""
|
||||
|
@ -114,10 +139,13 @@ 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
|
||||
|
@ -135,6 +163,7 @@ 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
|
||||
|
@ -205,13 +234,18 @@ class IRC(object):
|
|||
self.channels.remove(channel)
|
||||
|
||||
def msg(self, target, text):
|
||||
""" makes the bot send a message to a user """
|
||||
""" makes the bot send a PRIVMSG to a target """
|
||||
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] = ':' + params[-1]
|
||||
self.send(command + ' ' + ' '.join(map(censor, params)))
|
||||
params[-1] = u':' + params[-1]
|
||||
self.send(u"{} {}".format(command, ' '.join(params)))
|
||||
else:
|
||||
self.send(command)
|
||||
|
||||
|
|
35
core/main.py
Executable file → Normal file
35
core/main.py
Executable file → Normal file
|
@ -13,29 +13,34 @@ class Input(dict):
|
|||
if chan == conn.nick.lower(): # is a PM
|
||||
chan = nick
|
||||
|
||||
def say(msg, chan=chan):
|
||||
conn.msg(chan, msg)
|
||||
def message(message, target=chan):
|
||||
"""sends a message to a specific or current channel/user"""
|
||||
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)
|
||||
def reply(message, target=chan):
|
||||
"""sends a message to the current channel/user with a prefix"""
|
||||
if target == nick:
|
||||
conn.msg(target, message)
|
||||
else:
|
||||
conn.msg(chan, '(' + nick + ') ' + msg)
|
||||
conn.msg(target, u"({}) {}".format(nick, message))
|
||||
|
||||
def me(msg, chan=chan):
|
||||
conn.msg(chan, "\x01{} {}\x01".format("ACTION", 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 notice(msg, nick=nick):
|
||||
conn.cmd('NOTICE', [nick, 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])
|
||||
|
||||
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, say=say, reply=reply, pm=pm, bot=bot,
|
||||
me=me, lastparam=paraml[-1])
|
||||
notice=notice, message=message, reply=reply, bot=bot,
|
||||
action=action, ctcp=ctcp, lastparam=paraml[-1])
|
||||
|
||||
# make dict keys accessible as attributes
|
||||
def __getattr__(self, key):
|
||||
|
|
0
core/reload.py
Executable file → Normal file
0
core/reload.py
Executable file → Normal file
|
@ -1,14 +1,12 @@
|
|||
from util import hook
|
||||
import random
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
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("//")]
|
||||
|
@ -17,8 +15,9 @@ 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, me=None, nick=None, conn=None, notice=None):
|
||||
def lart(inp, action=None, nick=None, conn=None, notice=None):
|
||||
"""lart <user> -- LARTs <user>."""
|
||||
target = inp.strip()
|
||||
|
||||
|
@ -34,31 +33,11 @@ def lart(inp, me=None, nick=None, conn=None, notice=None):
|
|||
phrase = random.choice(larts)
|
||||
|
||||
# act out the message
|
||||
me(phrase.format(**values))
|
||||
action(phrase.format(**values))
|
||||
|
||||
|
||||
@hook.command
|
||||
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):
|
||||
def insult(inp, nick=None, action=None, conn=None, notice=None):
|
||||
"""insult <user> -- Makes the bot insult <user>."""
|
||||
target = inp.strip()
|
||||
|
||||
|
@ -72,11 +51,11 @@ def insult(inp, nick=None, me=None, conn=None, notice=None):
|
|||
target = inp
|
||||
|
||||
out = 'insults {}... "{}"'.format(target, random.choice(insults))
|
||||
me(out)
|
||||
action(out)
|
||||
|
||||
|
||||
@hook.command
|
||||
def flirt(inp, me=None, conn=None, notice=None):
|
||||
def flirt(inp, action=None, conn=None, notice=None):
|
||||
"""flirt <user> -- Make the bot flirt with <user>."""
|
||||
target = inp.strip()
|
||||
|
||||
|
@ -90,4 +69,4 @@ def flirt(inp, me=None, conn=None, notice=None):
|
|||
target = inp
|
||||
|
||||
out = 'flirts with {}... "{}"'.format(target, random.choice(flirts))
|
||||
me(out)
|
||||
action(out)
|
4
plugins/brainfuck.py → disabled_stuff/brainfuck.py
Executable file → Normal file
4
plugins/brainfuck.py → disabled_stuff/brainfuck.py
Executable file → Normal 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
|
4
plugins/choose.py → disabled_stuff/choose.py
Executable file → Normal file
4
plugins/choose.py → disabled_stuff/choose.py
Executable file → Normal 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
plugins/coin.py → disabled_stuff/coin.py
Executable file → Normal file
11
plugins/coin.py → disabled_stuff/coin.py
Executable file → Normal file
|
@ -1,9 +1,10 @@
|
|||
from util import hook
|
||||
import random
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def coin(inp, me=None):
|
||||
def coin(inp, action=None):
|
||||
"""coin [amount] -- Flips [amount] of coins."""
|
||||
|
||||
if inp:
|
||||
|
@ -15,10 +16,10 @@ def coin(inp, me=None):
|
|||
amount = 1
|
||||
|
||||
if amount == 1:
|
||||
me("flips a coin and gets {}.".format(random.choice(["heads", "tails"])))
|
||||
action("flips a coin and gets {}.".format(random.choice(["heads", "tails"])))
|
||||
elif amount == 0:
|
||||
me("makes a coin flipping motion with its hands.")
|
||||
action("makes a coin flipping motion with its hands.")
|
||||
else:
|
||||
heads = int(random.normalvariate(.5 * amount, (.75 * amount) ** .5))
|
||||
tails = amount - heads
|
||||
me("flips {} coins and gets {} heads and {} tails.".format(amount, heads, tails))
|
||||
action("flips {} coins and gets {} heads and {} tails.".format(amount, heads, tails))
|
37
disabled_stuff/correction.py
Normal file
37
disabled_stuff/correction.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
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)
|
||||
|
60
disabled_stuff/cryptocoins.py
Normal file
60
disabled_stuff/cryptocoins.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
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']))
|
8
plugins/cypher.py → disabled_stuff/cypher.py
Executable file → Normal file
8
plugins/cypher.py → disabled_stuff/cypher.py
Executable file → Normal file
|
@ -1,4 +1,5 @@
|
|||
import base64
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
|
@ -10,9 +11,10 @@ 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)
|
||||
|
@ -26,7 +28,7 @@ def cypher(inp):
|
|||
|
||||
passwd = inp.split(" ")[0]
|
||||
inp = " ".join(inp.split(" ")[1:])
|
||||
return encode(passwd,inp)
|
||||
return encode(passwd, inp)
|
||||
|
||||
|
||||
@hook.command
|
||||
|
@ -34,4 +36,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)
|
BIN
disabled_stuff/data/GeoLiteCity.dat
Normal file
BIN
disabled_stuff/data/GeoLiteCity.dat
Normal file
Binary file not shown.
9
plugins/data/flirts.txt → disabled_stuff/data/flirts.txt
Executable file → Normal file
9
plugins/data/flirts.txt → disabled_stuff/data/flirts.txt
Executable file → Normal file
|
@ -44,4 +44,11 @@ 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.
|
||||
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.
|
0
plugins/data/fortunes.txt → disabled_stuff/data/fortunes.txt
Executable file → Normal file
0
plugins/data/fortunes.txt → disabled_stuff/data/fortunes.txt
Executable file → Normal file
0
plugins/data/insults.txt → disabled_stuff/data/insults.txt
Executable file → Normal file
0
plugins/data/insults.txt → disabled_stuff/data/insults.txt
Executable file → Normal file
620
disabled_stuff/data/itemids.txt
Normal file
620
disabled_stuff/data/itemids.txt
Normal file
|
@ -0,0 +1,620 @@
|
|||
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)
|
79
disabled_stuff/data/kills.json
Normal file
79
disabled_stuff/data/kills.json
Normal file
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
}
|
0
plugins/data/kills.txt → disabled_stuff/data/kills.txt
Executable file → Normal file
0
plugins/data/kills.txt → disabled_stuff/data/kills.txt
Executable file → Normal file
0
plugins/data/larts.txt → disabled_stuff/data/larts.txt
Executable file → Normal file
0
plugins/data/larts.txt → disabled_stuff/data/larts.txt
Executable file → Normal file
62
plugins/data/recipes.txt → disabled_stuff/data/recipes.txt
Executable file → Normal file
62
plugins/data/recipes.txt → disabled_stuff/data/recipes.txt
Executable file → Normal 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 _frozen
|
||||
//Edited by CHCMATT for Minecraft version: 1.7.4
|
||||
//
|
||||
//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,7 +21,10 @@
|
|||
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
|
||||
|
@ -117,6 +120,7 @@
|
|||
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
|
||||
//
|
||||
|
@ -125,7 +129,8 @@
|
|||
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 Button: Stone | Stone
|
||||
1x Stone Button: Stone
|
||||
1x Wooden Button: Wooden Planks
|
||||
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
|
||||
|
@ -133,8 +138,13 @@
|
|||
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: none, slime ball, none | none, piston, none
|
||||
1x Redstone Lamp: none, redstone dust, none | redstone dust, glowstone block, redstone | none, redstone dust, none
|
||||
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
|
||||
//
|
||||
//Food Recipes
|
||||
//
|
||||
|
@ -169,6 +179,11 @@
|
|||
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
|
||||
//
|
||||
|
@ -214,4 +229,41 @@
|
|||
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
|
||||
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
|
|
@ -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 {mod} {item}.",
|
||||
"prods {user} with a {item}.",
|
||||
"picks up a {item} and {hits} {user} with it.",
|
||||
"ties {user} to a chair and {throws} a {item} at them.",
|
||||
"{hits} {user} on the head with a {item}.",
|
||||
"{hits} {user} {where} with a {item}.",
|
||||
"ties {user} to a pole and whips them with a {item}."
|
||||
],
|
||||
"parts": {
|
||||
|
@ -29,6 +29,8 @@
|
|||
"diamond sword",
|
||||
"baguette",
|
||||
"physics textbook",
|
||||
"toaster",
|
||||
"portrait of Richard Stallman",
|
||||
"television",
|
||||
"mau5head",
|
||||
"five ton truck",
|
||||
|
@ -58,10 +60,10 @@
|
|||
"slaps",
|
||||
"smacks"
|
||||
],
|
||||
"mod": [
|
||||
"flaming",
|
||||
"sticky",
|
||||
"dripping"
|
||||
"where": [
|
||||
"in the chest",
|
||||
"on the head",
|
||||
"on the bum"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
0
plugins/data/slogans.txt → disabled_stuff/data/slogans.txt
Executable file → Normal file
0
plugins/data/slogans.txt → disabled_stuff/data/slogans.txt
Executable file → Normal file
21
plugins/dice.py → disabled_stuff/dice.py
Executable file → Normal file
21
plugins/dice.py → disabled_stuff/dice.py
Executable file → Normal 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 nrolls(count, n):
|
||||
def n_rolls(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 nrolls(count, n):
|
|||
#@hook.regex(valid_diceroll, re.I)
|
||||
@hook.command
|
||||
def dice(inp):
|
||||
"""dice <diceroll> -- Simulates dicerolls. Example of <diceroll>:
|
||||
"""dice <dice roll> -- Simulates dice rolls. Example of <dice roll>:
|
||||
'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 diceroll"
|
||||
return "Invalid dice roll"
|
||||
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 nrolls(count, "F"):
|
||||
for fudge in n_rolls(count, "F"):
|
||||
if fudge == 1:
|
||||
rolls.append("\x033+\x0F")
|
||||
elif fudge == -1:
|
||||
|
@ -73,14 +73,15 @@ def dice(inp):
|
|||
side = int(side)
|
||||
try:
|
||||
if count > 0:
|
||||
dice = nrolls(count, side)
|
||||
rolls += map(str, dice)
|
||||
total += sum(dice)
|
||||
d = n_rolls(count, side)
|
||||
rolls += map(str, d)
|
||||
total += sum(d)
|
||||
else:
|
||||
dice = nrolls(-count, side)
|
||||
rolls += [str(-x) for x in dice]
|
||||
total -= sum(dice)
|
||||
d = n_rolls(-count, side)
|
||||
rolls += [str(-x) for x in d]
|
||||
total -= sum(d)
|
||||
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
plugins/dictionary.py → disabled_stuff/dictionary.py
Executable file → Normal file
7
plugins/dictionary.py → disabled_stuff/dictionary.py
Executable file → Normal file
|
@ -1,5 +1,6 @@
|
|||
# Plugin by GhettoWizard and Scaevolus
|
||||
import re
|
||||
|
||||
from util import hook
|
||||
from util import http
|
||||
|
||||
|
@ -18,10 +19,10 @@ def define(inp):
|
|||
'//div[@class="example"]')
|
||||
|
||||
if not definition:
|
||||
return 'No results for ' + inp + ' :('
|
||||
return u'No results for {} :('.format(inp)
|
||||
|
||||
def format_output(show_examples):
|
||||
result = '{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
|
||||
result = u'{}: '.format(h.xpath('//dt[@class="title-word"]/a/text()')[0])
|
||||
|
||||
correction = h.xpath('//span[@class="correct-word"]/text()')
|
||||
if correction:
|
||||
|
@ -76,7 +77,7 @@ def etymology(inp):
|
|||
etym = h.xpath('//dl')
|
||||
|
||||
if not etym:
|
||||
return 'No etymology found for {} :('.format(inp)
|
||||
return u'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 occurrred: {status} - {message}".format(**data['error'])
|
||||
return "An error occurred: {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
plugins/down.py → disabled_stuff/down.py
Executable file → Normal file
0
plugins/down.py → disabled_stuff/down.py
Executable file → Normal file
4
plugins/drama.py → disabled_stuff/drama.py
Executable file → Normal file
4
plugins/drama.py → disabled_stuff/drama.py
Executable file → Normal file
|
@ -1,6 +1,8 @@
|
|||
from util import hook, http, text
|
||||
import re
|
||||
|
||||
from util import hook, http, text
|
||||
|
||||
|
||||
api_url = "http://encyclopediadramatica.se/api.php?action=opensearch"
|
||||
ed_url = "http://encyclopediadramatica.se/"
|
||||
|
6
plugins/eightball.py → disabled_stuff/eightball.py
Executable file → Normal file
6
plugins/eightball.py → disabled_stuff/eightball.py
Executable file → Normal file
|
@ -1,6 +1,8 @@
|
|||
import random
|
||||
|
||||
from util import hook, text
|
||||
|
||||
|
||||
color_codes = {
|
||||
"<r>": "\x02\x0305",
|
||||
"<g>": "\x02\x0303",
|
||||
|
@ -13,9 +15,9 @@ with open("plugins/data/8ball_responses.txt") as f:
|
|||
|
||||
|
||||
@hook.command('8ball')
|
||||
def eightball(input, me=None):
|
||||
def eightball(inp, action=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)
|
||||
me("shakes the magic 8 ball... {}".format(magic))
|
||||
action("shakes the magic 8 ball... {}".format(magic))
|
105
disabled_stuff/encrypt.py
Normal file
105
disabled_stuff/encrypt.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
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)
|
10
plugins/fact.py → disabled_stuff/fact.py
Executable file → Normal file
10
plugins/fact.py → disabled_stuff/fact.py
Executable file → Normal file
|
@ -2,7 +2,7 @@ from util import hook, http, web
|
|||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def fact(inp, say=False, nick=False):
|
||||
def fact(inp):
|
||||
"""fact -- Gets a random fact from OMGFACTS."""
|
||||
|
||||
attempts = 0
|
||||
|
@ -20,10 +20,10 @@ def fact(inp, say=False, nick=False):
|
|||
|
||||
response = soup.find('a', {'class': 'surprise'})
|
||||
link = response['href']
|
||||
fact = ''.join(response.find(text=True))
|
||||
fact_data = ''.join(response.find(text=True))
|
||||
|
||||
if fact:
|
||||
fact = fact.strip()
|
||||
if fact_data:
|
||||
fact_data = fact_data.strip()
|
||||
break
|
||||
else:
|
||||
if attempts > 2:
|
||||
|
@ -34,4 +34,4 @@ def fact(inp, say=False, nick=False):
|
|||
|
||||
url = web.try_isgd(link)
|
||||
|
||||
return "{} - {}".format(fact, url)
|
||||
return "{} - {}".format(fact_data, url)
|
35
plugins/factoids.py → disabled_stuff/factoids.py
Executable file → Normal file
35
plugins/factoids.py → disabled_stuff/factoids.py
Executable file → Normal file
|
@ -1,10 +1,14 @@
|
|||
# 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',
|
||||
|
@ -16,9 +20,12 @@ shortcodes = {
|
|||
|
||||
|
||||
def db_init(db):
|
||||
db.execute("create table if not exists mem(word, data, nick,"
|
||||
" primary key(word))")
|
||||
db.commit()
|
||||
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
|
||||
|
||||
|
||||
def get_memory(db, word):
|
||||
|
@ -105,8 +112,8 @@ def info(inp, notice=None, db=None):
|
|||
|
||||
|
||||
@hook.regex(r'^\? ?(.+)')
|
||||
def factoid(inp, say=None, db=None, bot=None, me=None, conn=None, input=None):
|
||||
"?<word> -- Shows what data is associated with <word>."
|
||||
def factoid(inp, message=None, db=None, bot=None, action=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:
|
||||
|
@ -130,9 +137,9 @@ def factoid(inp, say=None, db=None, bot=None, me=None, conn=None, input=None):
|
|||
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 = execute.eval_py(variables + code)
|
||||
input.nick, input.chan,
|
||||
input.conn.nick)
|
||||
result = pyexec.eval_py(variables + code)
|
||||
else:
|
||||
result = data
|
||||
|
||||
|
@ -141,15 +148,15 @@ def factoid(inp, say=None, db=None, bot=None, me=None, conn=None, input=None):
|
|||
|
||||
if result.startswith("<act>"):
|
||||
result = result[5:].strip()
|
||||
me(result)
|
||||
action(result)
|
||||
elif result.startswith("<url>"):
|
||||
url = result[5:].strip()
|
||||
try:
|
||||
say(http.get(url))
|
||||
message(http.get(url))
|
||||
except http.HttpError:
|
||||
say("Could not fetch URL.")
|
||||
message("Could not fetch URL.")
|
||||
else:
|
||||
if prefix_on:
|
||||
say("\x02[{}]:\x02 {}".format(factoid_id, result))
|
||||
message("\x02[{}]:\x02 {}".format(factoid_id, result))
|
||||
else:
|
||||
say(result)
|
||||
message(result)
|
|
@ -1,6 +1,8 @@
|
|||
from util import hook, http
|
||||
from urllib import quote_plus
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
api_url = "http://api.fishbans.com/stats/{}/"
|
||||
|
||||
|
||||
|
@ -51,6 +53,5 @@ 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
plugins/fmylife.py → disabled_stuff/fmylife.py
Executable file → Normal file
8
plugins/fmylife.py → disabled_stuff/fmylife.py
Executable file → Normal 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'}):
|
||||
id = int(e['id'])
|
||||
fml_id = int(e['id'])
|
||||
text = ''.join(e.find('p').find_all(text=True))
|
||||
fml_cache.append((id, text))
|
||||
fml_cache.append((fml_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
|
||||
id, text = fml_cache.pop()
|
||||
fml_id, text = fml_cache.pop()
|
||||
# reply with the fml we grabbed
|
||||
reply('(#{}) {}'.format(id, text))
|
||||
reply('(#{}) {}'.format(fml_id, text))
|
||||
# refresh fml cache if its getting empty
|
||||
if len(fml_cache) < 3:
|
||||
refresh_cache()
|
4
plugins/fortune.py → disabled_stuff/fortune.py
Executable file → Normal file
4
plugins/fortune.py → disabled_stuff/fortune.py
Executable file → Normal file
|
@ -1,6 +1,8 @@
|
|||
from util import hook
|
||||
import random
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
with open("plugins/data/fortunes.txt") as f:
|
||||
fortunes = [line.strip() for line in f.readlines()
|
||||
if not line.startswith("//")]
|
13
disabled_stuff/freddy.py
Normal file
13
disabled_stuff/freddy.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
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))
|
||||
|
10
plugins/geoip.py → disabled_stuff/geoip.py
Executable file → Normal file
10
plugins/geoip.py → disabled_stuff/geoip.py
Executable file → Normal file
|
@ -1,17 +1,19 @@
|
|||
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")):
|
||||
# initalise geolocation database
|
||||
# initialise 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")
|
||||
|
@ -49,4 +51,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 "\x02Country:\x02 {country} ({cc}), \x02City:\x02 {city}{region}".format(**data)
|
||||
return u"\x02Country:\x02 {country} ({cc}), \x02City:\x02 {city}{region}".format(**data)
|
|
@ -1,12 +1,14 @@
|
|||
from util import hook, http
|
||||
import json
|
||||
import urllib2
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
shortcuts = {"cloudbot": "ClouDev/CloudBot"}
|
||||
|
||||
|
||||
def truncate(msg):
|
||||
nmsg = msg.split(" ")
|
||||
nmsg = msg.split()
|
||||
out = None
|
||||
x = 0
|
||||
for i in nmsg:
|
||||
|
@ -50,8 +52,8 @@ def ghissues(inp):
|
|||
return "Repo has no open issues"
|
||||
except ValueError:
|
||||
return "Invalid data returned. Check arguments (.github issues username/repo [number]"
|
||||
fmt = "Issue: #{} ({}) by {}: {} | {} {}".format(number, state, user.login, title, truncate(body), gitio.gitio(data.url))
|
||||
fmt1 = "Issue: #{} ({}) by {}: {} {}".format(number, state, user.login, title, gitio.gitio(data.url))
|
||||
fmt = "Issue: #%s (%s) by %s: %s | %s %s" # (number, state, user.login, title, truncate(body), gitio.gitio(data.url))
|
||||
fmt1 = "Issue: #%s (%s) by %s: %s %s" # (number, state, user.login, title, gitio.gitio(data.url))
|
||||
number = data["number"]
|
||||
if data["state"] == "open":
|
||||
state = u"\x033\x02OPEN\x02\x0f"
|
8
plugins/google.py → disabled_stuff/google.py
Executable file → Normal file
8
plugins/google.py → disabled_stuff/google.py
Executable file → Normal file
|
@ -1,4 +1,5 @@
|
|||
import random
|
||||
|
||||
from util import hook, http, text
|
||||
|
||||
|
||||
|
@ -20,8 +21,7 @@ def googleimage(inp):
|
|||
raise IOError('error searching for images: {}: {}'.format(parsed['responseStatus'], ''))
|
||||
if not parsed['responseData']['results']:
|
||||
return 'no images found'
|
||||
return random.choice(parsed['responseData']['results'][:10]) \
|
||||
['unescapedUrl']
|
||||
return random.choice(parsed['responseData']['results'][:10])['unescapedUrl']
|
||||
|
||||
|
||||
@hook.command('search')
|
||||
|
@ -48,6 +48,4 @@ def google(inp):
|
|||
content = http.html.fromstring(content).text_content()
|
||||
content = text.truncate_str(content, 150)
|
||||
|
||||
out = '{} -- \x02{}\x02: "{}"'.format(result['unescapedUrl'], title, content)
|
||||
|
||||
return out
|
||||
return u'{} -- \x02{}\x02: "{}"'.format(result['unescapedUrl'], title, content)
|
|
@ -8,6 +8,7 @@ import re
|
|||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
max_length = 100
|
||||
|
||||
|
||||
|
@ -164,4 +165,4 @@ lang_pairs = [
|
|||
("vi", "Vietnamese"),
|
||||
("cy", "Welsh"),
|
||||
("yi", "Yiddish")
|
||||
]
|
||||
]
|
22
disabled_stuff/googleurlparse.py
Normal file
22
disabled_stuff/googleurlparse.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
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!"
|
89
disabled_stuff/history.py
Normal file
89
disabled_stuff/history.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
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)
|
|
@ -7,17 +7,17 @@ db_ready = False
|
|||
|
||||
def db_init(db):
|
||||
"""check to see that our db has the horoscope table and return a connection."""
|
||||
db.execute("create table if not exists horoscope(nick primary key, sign)")
|
||||
db.commit()
|
||||
db_ready = True
|
||||
global db_ready
|
||||
if not db_ready:
|
||||
db.execute("create table if not exists horoscope(nick primary key, sign)")
|
||||
db.commit()
|
||||
db_ready = True
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def horoscope(inp, db=None, notice=None, nick=None):
|
||||
"""horoscope <sign> -- Get your horoscope."""
|
||||
|
||||
if not db_ready:
|
||||
db_init(db)
|
||||
db_init(db)
|
||||
|
||||
# check if the user asked us not to save his details
|
||||
dontsave = inp.endswith(" dontsave")
|
||||
|
@ -32,16 +32,16 @@ def horoscope(inp, db=None, notice=None, nick=None):
|
|||
sign = db.execute("select sign from horoscope where nick=lower(?)",
|
||||
(nick,)).fetchone()
|
||||
if not sign:
|
||||
notice(horoscope.__doc__)
|
||||
notice("horoscope <sign> -- Get your horoscope")
|
||||
return
|
||||
sign = sign[0]
|
||||
|
||||
url = "http://my.horoscope.com/astrology/free-daily-horoscope-%s.html" % sign
|
||||
url = "http://my.horoscope.com/astrology/free-daily-horoscope-{}.html".format(sign)
|
||||
soup = http.get_soup(url)
|
||||
|
||||
title = soup.find_all('h1', {'class': 'h1b'})[1]
|
||||
horoscope = soup.find('div', {'class': 'fontdef1'})
|
||||
result = "\x02%s\x02 %s" % (title, horoscope)
|
||||
horoscope_text = soup.find('div', {'class': 'fontdef1'})
|
||||
result = u"\x02%s\x02 %s" % (title, horoscope_text)
|
||||
result = text.strip_html(result)
|
||||
#result = unicode(result, "utf8").replace('flight ','')
|
||||
|
||||
|
@ -50,7 +50,7 @@ def horoscope(inp, db=None, notice=None, nick=None):
|
|||
|
||||
if inp and not dontsave:
|
||||
db.execute("insert or replace into horoscope(nick, sign) values (?,?)",
|
||||
(nick.lower(), sign))
|
||||
(nick.lower(), sign))
|
||||
db.commit()
|
||||
|
||||
return result
|
||||
return result
|
|
@ -1,7 +1,9 @@
|
|||
from util import hook, http, timeformat
|
||||
from urllib import urlencode
|
||||
import re
|
||||
|
||||
from util import hook, http, timeformat
|
||||
|
||||
|
||||
hulu_re = (r'(.*://)(www.hulu.com|hulu.com)(.*)', re.I)
|
||||
|
||||
|
||||
|
@ -10,7 +12,7 @@ def hulu_url(match):
|
|||
data = http.get_json("http://www.hulu.com/api/oembed.json?url=http://www.hulu.com" + match.group(3))
|
||||
showname = data['title'].split("(")[-1].split(")")[0]
|
||||
title = data['title'].split(" (")[0]
|
||||
return "{}: {} - {}".format(showname, title, timeformat.timeformat(int(data['duration'])))
|
||||
return "{}: {} - {}".format(showname, title, timeformat.format_time(int(data['duration'])))
|
||||
|
||||
|
||||
@hook.command('hulu')
|
||||
|
@ -21,7 +23,7 @@ def hulu_search(inp):
|
|||
data = result.find('results').find('videos').find('video')
|
||||
showname = data.find('show').find('name').text
|
||||
title = data.find('title').text
|
||||
duration = timeformat.timeformat(int(float(data.find('duration').text)))
|
||||
duration = timeformat.format_time(int(float(data.find('duration').text)))
|
||||
description = data.find('description').text
|
||||
rating = data.find('content-rating').text
|
||||
return "{}: {} - {} - {} ({}) {}".format(showname, title, description, duration, rating,
|
12
plugins/imdb.py → disabled_stuff/imdb.py
Executable file → Normal file
12
plugins/imdb.py → disabled_stuff/imdb.py
Executable file → Normal file
|
@ -1,8 +1,10 @@
|
|||
# IMDb lookup plugin by Ghetto Wizard (2011) and blha303 (2013)
|
||||
|
||||
from util import hook, http, text
|
||||
import re
|
||||
|
||||
from util import hook, http, text
|
||||
|
||||
|
||||
id_re = re.compile("tt\d+")
|
||||
imdb_re = (r'(.*:)//(imdb.com|www.imdb.com)(:[0-9]+)?(.*)', re.I)
|
||||
|
||||
|
@ -37,10 +39,10 @@ def imdb(inp):
|
|||
|
||||
@hook.regex(*imdb_re)
|
||||
def imdb_url(match):
|
||||
id = match.group(4).split('/')[-1]
|
||||
if id == "":
|
||||
id = match.group(4).split('/')[-2]
|
||||
content = http.get_json("http://www.omdbapi.com/", i=id)
|
||||
imdb_id = match.group(4).split('/')[-1]
|
||||
if imdb_id == "":
|
||||
imdb_id = match.group(4).split('/')[-2]
|
||||
content = http.get_json("http://www.omdbapi.com/", i=imdb_id)
|
||||
if content.get('Error', None) == 'Movie not found!':
|
||||
return 'Movie not found!'
|
||||
elif content['Response'] == 'True':
|
82
disabled_stuff/imgur.py
Normal file
82
disabled_stuff/imgur.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
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))
|
|
@ -5,7 +5,7 @@ from util import hook, http, urlnorm
|
|||
|
||||
@hook.command
|
||||
def isup(inp):
|
||||
"isup -- uses isup.me to see if a site is up or not"
|
||||
"""isup -- uses isup.me to see if a site is up or not"""
|
||||
|
||||
# slightly overcomplicated, esoteric URL parsing
|
||||
scheme, auth, path, query, fragment = urlparse.urlsplit(inp.strip())
|
||||
|
@ -25,4 +25,4 @@ def isup(inp):
|
|||
elif "is up" in content:
|
||||
return "It's just you. {} is \x02\x033up\x02\x0f.".format(url)
|
||||
else:
|
||||
return "Huh? That doesn't look like a site on the interweb."
|
||||
return "Huh? That doesn't look like a site on the interweb."
|
|
@ -1,6 +1,7 @@
|
|||
from util import hook, http
|
||||
import re
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def kernel(inp, reply=None):
|
33
disabled_stuff/kill.py
Normal file
33
disabled_stuff/kill.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
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())
|
16
plugins/lastfm.py → disabled_stuff/lastfm.py
Executable file → Normal file
16
plugins/lastfm.py → disabled_stuff/lastfm.py
Executable file → Normal file
|
@ -1,6 +1,8 @@
|
|||
from util import hook, http, timesince
|
||||
from datetime import datetime
|
||||
|
||||
from util import hook, http, timesince
|
||||
|
||||
|
||||
api_url = "http://ws.audioscrobbler.com/2.0/?format=json"
|
||||
|
||||
|
||||
|
@ -34,10 +36,10 @@ def lastfm(inp, nick='', db=None, bot=None, notice=None):
|
|||
api_key=api_key, user=user, limit=1)
|
||||
|
||||
if 'error' in response:
|
||||
return "Error: {}.".format(response["message"])
|
||||
return u"Error: {}.".format(response["message"])
|
||||
|
||||
if not "track" in response["recenttracks"] or len(response["recenttracks"]["track"]) == 0:
|
||||
return 'No recent tracks for user "{}" found.'.format(user)
|
||||
return u'No recent tracks for user "{}" found.'.format(user)
|
||||
|
||||
tracks = response["recenttracks"]["track"]
|
||||
|
||||
|
@ -64,18 +66,18 @@ def lastfm(inp, nick='', db=None, bot=None, notice=None):
|
|||
album = track["album"]["#text"]
|
||||
artist = track["artist"]["#text"]
|
||||
|
||||
out = '{} {} "{}"'.format(user, status, title)
|
||||
out = u'{} {} "{}"'.format(user, status, title)
|
||||
if artist:
|
||||
out += " by \x02{}\x0f".format(artist)
|
||||
out += u" by \x02{}\x0f".format(artist)
|
||||
if album:
|
||||
out += " from the album \x02{}\x0f".format(album)
|
||||
out += u" from the album \x02{}\x0f".format(album)
|
||||
|
||||
# append ending based on what type it was
|
||||
out += ending
|
||||
|
||||
if inp and not dontsave:
|
||||
db.execute("insert or replace into lastfm(nick, acc) values (?,?)",
|
||||
(nick.lower(), user))
|
||||
(nick.lower(), user))
|
||||
db.commit()
|
||||
|
||||
return out
|
|
@ -6,7 +6,7 @@ from util import hook, web, http
|
|||
def lmgtfy(inp):
|
||||
"""lmgtfy [phrase] - Posts a google link for the specified phrase"""
|
||||
|
||||
link = "http://lmgtfy.com/?q={}".format(http.quote_plus(inp))
|
||||
link = u"http://lmgtfy.com/?q={}".format(http.quote_plus(inp))
|
||||
|
||||
try:
|
||||
return web.isgd(link)
|
0
plugins/log.py → disabled_stuff/log.py
Executable file → Normal file
0
plugins/log.py → disabled_stuff/log.py
Executable file → Normal file
|
@ -38,6 +38,6 @@ def lyrics(inp):
|
|||
else:
|
||||
lyricsum = " / ".join(lyricsum.strip().split("\n")[0:4]) # truncate, format
|
||||
return "\x02{}\x02 by \x02{}\x02 {}{} - {}".format(title, artist, web.try_isgd(link), pasteurl,
|
||||
lyricsum[:-3])
|
||||
lyricsum[:-3])
|
||||
else:
|
||||
return "No song results. " + url + inp.replace(" ", "+")
|
41
plugins/metacritic.py → disabled_stuff/metacritic.py
Executable file → Normal file
41
plugins/metacritic.py → disabled_stuff/metacritic.py
Executable file → Normal file
|
@ -9,15 +9,13 @@ from util import hook, http
|
|||
@hook.command('mc')
|
||||
@hook.command
|
||||
def metacritic(inp):
|
||||
"""mc [all|movie|tv|album|x360|ps3|wii|pc|ds|3ds|vita] <title>
|
||||
"""mc [all|movie|tv|album|x360|ps3|pc|gba|ds|3ds|wii|vita|wiiu|xone|ps4] <title>
|
||||
Gets rating for <title> from metacritic on the specified medium."""
|
||||
|
||||
# if the results suck, it's metacritic's fault
|
||||
|
||||
args = inp.strip()
|
||||
|
||||
game_platforms = ('x360', 'ps3', 'pc', 'ds', 'wii', '3ds', 'gba',
|
||||
'psp', 'vita')
|
||||
game_platforms = ('x360', 'ps3', 'pc', 'gba', 'ds', '3ds', 'wii',
|
||||
'vita', 'wiiu', 'xone', 'ps4')
|
||||
|
||||
all_platforms = game_platforms + ('all', 'movie', 'tv', 'album')
|
||||
|
||||
|
@ -43,38 +41,7 @@ def metacritic(inp):
|
|||
except HTTPError:
|
||||
return 'error fetching results'
|
||||
|
||||
''' result format:
|
||||
-- game result, with score
|
||||
-- subsequent results are the same structure, without first_result class
|
||||
<li class="result first_result">
|
||||
<div class="result_type">
|
||||
<strong>Game</strong>
|
||||
<span class="platform">WII</span>
|
||||
</div>
|
||||
<div class="result_wrap">
|
||||
<div class="basic_stats has_score">
|
||||
<div class="main_stats">
|
||||
<h3 class="product_title basic_stat">...</h3>
|
||||
<div class="std_score">
|
||||
<div class="score_wrap">
|
||||
<span class="label">Metascore: </span>
|
||||
<span class="data metascore score_favorable">87</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="more_stats extended_stats">...</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
-- other platforms are the same basic layout
|
||||
-- if it doesn't have a score, there is no div.basic_score
|
||||
-- the <div class="result_type"> changes content for non-games:
|
||||
<div class="result_type"><strong>Movie</strong></div>
|
||||
'''
|
||||
|
||||
# get the proper result element we want to pull data from
|
||||
|
||||
result = None
|
||||
|
||||
if not doc.find_class('query_results'):
|
||||
|
@ -128,7 +95,7 @@ def metacritic(inp):
|
|||
release = None
|
||||
|
||||
try:
|
||||
score = result.find_class('metascore')[0].text_content()
|
||||
score = result.find_class('metascore_w')[0].text_content()
|
||||
except IndexError:
|
||||
score = None
|
||||
|
154
disabled_stuff/minecraft_bukget.py
Normal file
154
disabled_stuff/minecraft_bukget.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
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)
|
30
plugins/minecraft_items.py → disabled_stuff/minecraft_items.py
Executable file → Normal file
30
plugins/minecraft_items.py → disabled_stuff/minecraft_items.py
Executable file → Normal file
|
@ -1,9 +1,11 @@
|
|||
""" plugin by _303 (?)
|
||||
"""
|
||||
|
||||
from util import hook
|
||||
import re
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
pattern = re.compile(r'^(?P<count>\d+)x (?P<name>.+?): (?P<ingredients>.*)$')
|
||||
|
||||
recipelist = []
|
||||
|
@ -42,29 +44,29 @@ with open("plugins/data/itemids.txt") as f:
|
|||
if line.startswith("//"):
|
||||
continue
|
||||
parts = line.strip().split()
|
||||
id = parts[0]
|
||||
itemid = parts[0]
|
||||
name = " ".join(parts[1:])
|
||||
ids.append((id, name))
|
||||
ids.append((itemid, name))
|
||||
|
||||
|
||||
@hook.command("mcid")
|
||||
@hook.command
|
||||
def mcitem(input, reply=None):
|
||||
def mcitem(inp, reply=None):
|
||||
"""mcitem <item/id> -- gets the id from an item or vice versa"""
|
||||
input = input.lower().strip()
|
||||
inp = inp.lower().strip()
|
||||
|
||||
if input == "":
|
||||
if inp == "":
|
||||
reply("error: no input.")
|
||||
return
|
||||
|
||||
results = []
|
||||
|
||||
for id, name in ids:
|
||||
if input == id:
|
||||
results = ["\x02[{}]\x02 {}".format(id, name)]
|
||||
for item_id, item_name in ids:
|
||||
if inp == item_id:
|
||||
results = ["\x02[{}]\x02 {}".format(item_id, item_name)]
|
||||
break
|
||||
elif input in name.lower():
|
||||
results.append("\x02[{}]\x02 {}".format(id, name))
|
||||
elif inp in item_name.lower():
|
||||
results.append("\x02[{}]\x02 {}".format(item_id, item_name))
|
||||
|
||||
if not results:
|
||||
return "No matches found."
|
||||
|
@ -80,12 +82,12 @@ def mcitem(input, reply=None):
|
|||
|
||||
@hook.command("mccraft")
|
||||
@hook.command
|
||||
def mcrecipe(input, reply=None):
|
||||
def mcrecipe(inp, reply=None):
|
||||
"""mcrecipe <item> -- gets the crafting recipe for an item"""
|
||||
input = input.lower().strip()
|
||||
inp = inp.lower().strip()
|
||||
|
||||
results = [recipe.line for recipe in recipelist
|
||||
if input in recipe.output]
|
||||
if inp in recipe.output]
|
||||
|
||||
if not results:
|
||||
return "No matches found."
|
232
disabled_stuff/minecraft_ping.py
Normal file
232
disabled_stuff/minecraft_ping.py
Normal file
|
@ -0,0 +1,232 @@
|
|||
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)
|
47
plugins/minecraft_status.py → disabled_stuff/minecraft_status.py
Executable file → Normal file
47
plugins/minecraft_status.py → disabled_stuff/minecraft_status.py
Executable file → Normal file
|
@ -1,6 +1,7 @@
|
|||
from util import hook, http
|
||||
import json
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def mcstatus(inp):
|
||||
|
@ -17,37 +18,27 @@ def mcstatus(inp):
|
|||
out = []
|
||||
|
||||
# use a loop so we don't have to update it if they add more servers
|
||||
yes = []
|
||||
no = []
|
||||
green = []
|
||||
yellow = []
|
||||
red = []
|
||||
for server, status in data.items():
|
||||
if status == "green":
|
||||
yes.append(server)
|
||||
green.append(server)
|
||||
elif status == "yellow":
|
||||
yellow.append(server)
|
||||
else:
|
||||
no.append(server)
|
||||
if yes:
|
||||
out = "\x033\x02Online\x02\x0f: " + ", ".join(yes)
|
||||
if no:
|
||||
red.append(server)
|
||||
|
||||
if green:
|
||||
out = "\x033\x02Online\x02\x0f: " + ", ".join(green)
|
||||
if yellow:
|
||||
out += " "
|
||||
if no:
|
||||
out += "\x034\x02Offline\x02\x0f: " + ", ".join(no)
|
||||
if yellow:
|
||||
out += "\x02Issues\x02: " + ", ".join(yellow)
|
||||
if red:
|
||||
out += " "
|
||||
if red:
|
||||
out += "\x034\x02Offline\x02\x0f: " + ", ".join(red)
|
||||
|
||||
return "\x0f" + out.replace(".mojang.com", ".mj") \
|
||||
.replace(".minecraft.net", ".mc")
|
||||
|
||||
|
||||
@hook.command("haspaid")
|
||||
@hook.command
|
||||
def mcpaid(inp):
|
||||
"""mcpaid <username> -- Checks if <username> has a premium Minecraft account."""
|
||||
|
||||
user = inp.strip()
|
||||
|
||||
try:
|
||||
status = http.get("http://www.minecraft.net/haspaid.jsp", user=user)
|
||||
except (http.URLError, http.HTTPError) as e:
|
||||
return "Unable to get user registration status: {}".format(e)
|
||||
|
||||
if "true" in status:
|
||||
return 'The account "{}" is a premium Minecraft account!'.format(inp)
|
||||
else:
|
||||
return 'The account "{}" is not a premium Minecraft account!'.format(inp)
|
101
disabled_stuff/minecraft_user.py
Normal file
101
disabled_stuff/minecraft_user.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
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."
|
51
disabled_stuff/minecraft_wiki.py
Normal file
51
disabled_stuff/minecraft_wiki.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
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."
|
|
@ -1,6 +1,7 @@
|
|||
# Plugin by Infinity - <https://github.com/infinitylabs/UguuBot>
|
||||
|
||||
import random
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
|
@ -23,11 +24,11 @@ refresh_cache()
|
|||
|
||||
@hook.command(autohelp=False)
|
||||
def mlia(inp, reply=None):
|
||||
"mlia -- Gets a random quote from MyLifeIsAverage.com."
|
||||
"""mlia -- Gets a random quote from MyLifeIsAverage.com."""
|
||||
# grab the last item in the mlia cache and remove it
|
||||
id, text = mlia_cache.pop()
|
||||
mlia_id, text = mlia_cache.pop()
|
||||
# reply with the mlia we grabbed
|
||||
reply('({}) {}'.format(id, text))
|
||||
reply('({}) {}'.format(mlia_id, text))
|
||||
# refresh mlia cache if its getting empty
|
||||
if len(mlia_cache) < 3:
|
||||
refresh_cache()
|
0
disabled_stuff/mtg.py
Executable file → Normal file
0
disabled_stuff/mtg.py
Executable file → Normal file
2
disabled_stuff/mygengo_translate.py
Executable file → Normal file
2
disabled_stuff/mygengo_translate.py
Executable file → Normal 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
|
||||
|
||||
|
|
13
plugins/namegen.py → disabled_stuff/namegen.py
Executable file → Normal file
13
plugins/namegen.py → disabled_stuff/namegen.py
Executable file → Normal file
|
@ -1,6 +1,7 @@
|
|||
# Plugin by Lukeroge
|
||||
import json
|
||||
import os
|
||||
|
||||
from util import hook, text, textgen
|
||||
import json, os
|
||||
|
||||
|
||||
GEN_DIR = "./plugins/data/name_files/"
|
||||
|
@ -8,14 +9,14 @@ GEN_DIR = "./plugins/data/name_files/"
|
|||
|
||||
def get_generator(_json):
|
||||
data = json.loads(_json)
|
||||
return textgen.TextGenerator(data["name"], data["templates"],
|
||||
data["default_templates"], data["parts"])
|
||||
return textgen.TextGenerator(data["templates"],
|
||||
data["parts"], default_templates=data["default_templates"])
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def namegen(inp, notice=None):
|
||||
"namegen [generator] -- Generates some names using the chosen generator. " \
|
||||
"'namegen list' will display a list of all generators."
|
||||
"""namegen [generator] -- Generates some names using the chosen generator.
|
||||
'namegen list' will display a list of all generators."""
|
||||
|
||||
# clean up the input
|
||||
inp = inp.strip().lower()
|
95
disabled_stuff/newegg.py
Normal file
95
disabled_stuff/newegg.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
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,6 +1,8 @@
|
|||
import re
|
||||
|
||||
from util import hook, http
|
||||
|
||||
|
||||
newgrounds_re = (r'(.*:)//(www.newgrounds.com|newgrounds.com)(:[0-9]+)?(.*)', re.I)
|
||||
valid = set('0123456789')
|
||||
|
|
@ -1,16 +1,18 @@
|
|||
from util import hook
|
||||
import re
|
||||
|
||||
db_inited = False
|
||||
from util import hook
|
||||
|
||||
|
||||
def cleanSQL(sql):
|
||||
db_ready = False
|
||||
|
||||
|
||||
def clean_sql(sql):
|
||||
return re.sub(r'\s+', " ", sql).strip()
|
||||
|
||||
|
||||
def db_init(db):
|
||||
global db_inited
|
||||
if db_inited:
|
||||
global db_ready
|
||||
if db_ready:
|
||||
return
|
||||
|
||||
exists = db.execute("""
|
||||
|
@ -20,7 +22,7 @@ def db_init(db):
|
|||
""").fetchone()[0] == 1
|
||||
|
||||
if not exists:
|
||||
db.execute(cleanSQL("""
|
||||
db.execute(clean_sql("""
|
||||
create virtual table todos using fts4(
|
||||
user,
|
||||
text,
|
||||
|
@ -30,7 +32,7 @@ def db_init(db):
|
|||
|
||||
db.commit()
|
||||
|
||||
db_inited = True
|
||||
db_ready = True
|
||||
|
||||
|
||||
def db_getall(db, nick, limit=-1):
|
||||
|
@ -44,14 +46,14 @@ def db_getall(db, nick, limit=-1):
|
|||
""", (nick, limit))
|
||||
|
||||
|
||||
def db_get(db, nick, id):
|
||||
def db_get(db, nick, note_id):
|
||||
return db.execute("""
|
||||
select added, text from todos
|
||||
where lower(user) = lower(?)
|
||||
order by added desc
|
||||
limit 1
|
||||
offset ?
|
||||
""", (nick, id)).fetchone()
|
||||
""", (nick, note_id)).fetchone()
|
||||
|
||||
|
||||
def db_del(db, nick, limit='all'):
|
||||
|
@ -91,7 +93,7 @@ def db_search(db, nick, query):
|
|||
@hook.command("notes")
|
||||
@hook.command
|
||||
def note(inp, nick='', chan='', db=None, notice=None, bot=None):
|
||||
"note(s) <add|del|list|search> args -- Manipulates your list of notes."
|
||||
"""note(s) <add|del|list|search> args -- Manipulates your list of notes."""
|
||||
|
||||
db_init(db)
|
||||
|
29
disabled_stuff/osrc.py
Normal file
29
disabled_stuff/osrc.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
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)
|
12
plugins/password.py → disabled_stuff/password.py
Executable file → Normal file
12
plugins/password.py → disabled_stuff/password.py
Executable file → Normal file
|
@ -1,8 +1,10 @@
|
|||
# based on password generation code by TheNoodle
|
||||
from util import hook
|
||||
# TODO: Add some kind of pronounceable password generation
|
||||
# TODO: Improve randomness
|
||||
import string
|
||||
import random
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
@hook.command
|
||||
def password(inp, notice=None):
|
||||
|
@ -39,10 +41,10 @@ def password(inp, notice=None):
|
|||
if not okay:
|
||||
okay = okay + list(string.ascii_lowercase)
|
||||
|
||||
password = ""
|
||||
pw = ""
|
||||
|
||||
# generates password
|
||||
for x in range(length):
|
||||
password = password + random.choice(okay)
|
||||
pw = pw + random.choice(okay)
|
||||
|
||||
notice(password)
|
||||
notice(pw)
|
10
plugins/potato.py → disabled_stuff/potato.py
Executable file → Normal file
10
plugins/potato.py → disabled_stuff/potato.py
Executable file → Normal file
|
@ -1,8 +1,10 @@
|
|||
# coding=utf-8
|
||||
from util import hook
|
||||
import re
|
||||
import random
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
potatoes = ['AC Belmont', 'AC Blue Pride', 'AC Brador', 'AC Chaleur', 'AC Domino', 'AC Dubuc', 'AC Glacier Chip',
|
||||
'AC Maple Gold', 'AC Novachip', 'AC Peregrine Red', 'AC Ptarmigan', 'AC Red Island', 'AC Saguenor',
|
||||
'AC Stampede Russet', 'AC Sunbury', 'Abeille', 'Abnaki', 'Acadia', 'Acadia Russet', 'Accent',
|
||||
|
@ -37,7 +39,7 @@ potatoes = ['AC Belmont', 'AC Blue Pride', 'AC Brador', 'AC Chaleur', 'AC Domino
|
|||
|
||||
|
||||
@hook.command
|
||||
def potato(inp, me=None, input=None):
|
||||
def potato(inp, action=None):
|
||||
"""potato <user> - Makes <user> a tasty little potato."""
|
||||
inp = inp.strip()
|
||||
|
||||
|
@ -50,5 +52,5 @@ def potato(inp, me=None, input=None):
|
|||
method = random.choice(['bakes', 'fries', 'boils', 'roasts'])
|
||||
side_dish = random.choice(['side salad', 'dollop of sour cream', 'piece of chicken', 'bowl of shredded bacon'])
|
||||
|
||||
me("{} a {} {} {} potato for {} and serves it with a small {}!".format(method, flavor, size, potato_type, inp,
|
||||
side_dish))
|
||||
action("{} a {} {} {} potato for {} and serves it with a small {}!".format(method, flavor, size, potato_type, inp,
|
||||
side_dish))
|
38
disabled_stuff/pre.py
Normal file
38
disabled_stuff/pre.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
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)
|
2
plugins/pyexec.py → disabled_stuff/python.py
Executable file → Normal file
2
plugins/pyexec.py → disabled_stuff/python.py
Executable file → Normal file
|
@ -1,5 +1,5 @@
|
|||
from util import hook
|
||||
from util.execute import eval_py
|
||||
from util.pyexec import eval_py
|
||||
|
||||
|
||||
@hook.command
|
|
@ -8,9 +8,9 @@ def qrcode(inp):
|
|||
"""qrcode [link] returns a link for a QR code."""
|
||||
|
||||
args = {
|
||||
"cht": "qr", # chart type
|
||||
"cht": "qr", # chart type (QR)
|
||||
"chs": "200x200", # dimensions
|
||||
"chl": inp
|
||||
"chl": inp # data
|
||||
}
|
||||
|
||||
link = http.prepare_url("http://chart.googleapis.com/chart", args)
|
4
plugins/quote.py → disabled_stuff/quote.py
Executable file → Normal file
4
plugins/quote.py → disabled_stuff/quote.py
Executable file → Normal file
|
@ -8,8 +8,8 @@ from util import hook
|
|||
def format_quote(q, num, n_quotes):
|
||||
"""Returns a formatted string of a quote"""
|
||||
ctime, nick, msg = q
|
||||
return "[{}/{}] <{}> {}".format((num, n_quotes,
|
||||
nick, msg))
|
||||
return "[{}/{}] <{}> {}".format(num, n_quotes,
|
||||
nick, msg)
|
||||
|
||||
|
||||
def create_table_if_not_exists(db):
|
|
@ -1,9 +1,11 @@
|
|||
import urllib
|
||||
import json
|
||||
import re
|
||||
from util import hook
|
||||
|
||||
import oauth2 as oauth
|
||||
|
||||
from util import hook
|
||||
|
||||
|
||||
def getdata(inp, types, api_key, api_secret):
|
||||
consumer = oauth.Consumer(api_key, api_secret)
|
||||
|
@ -27,18 +29,18 @@ def rdio(inp, bot=None):
|
|||
except IndexError:
|
||||
return "No results."
|
||||
if 'name' in info:
|
||||
if 'artist' in info and 'album' in info: #Track
|
||||
if 'artist' in info and 'album' in info: # Track
|
||||
name = info['name']
|
||||
artist = info['artist']
|
||||
album = info['album']
|
||||
url = info['shortUrl']
|
||||
return u"\x02{}\x02 by \x02{}\x02 - {} {}".format(name, artist, album, url)
|
||||
elif 'artist' in info and not 'album' in info: #Album
|
||||
elif 'artist' in info and not 'album' in info: # Album
|
||||
name = info['name']
|
||||
artist = info['artist']
|
||||
url = info['shortUrl']
|
||||
return u"\x02{}\x02 by \x02{}\x02 - {}".format(name, artist, url)
|
||||
else: #Artist
|
||||
else: # Artist
|
||||
name = info['name']
|
||||
url = info['shortUrl']
|
||||
return u"\x02{}\x02 - {}".format(name, url)
|
||||
|
@ -115,15 +117,15 @@ def rdio_url(match, bot=None):
|
|||
data = json.loads(response[1])
|
||||
info = data['result']
|
||||
if 'name' in info:
|
||||
if 'artist' in info and 'album' in info: #Track
|
||||
if 'artist' in info and 'album' in info: # Track
|
||||
name = info['name']
|
||||
artist = info['artist']
|
||||
album = info['album']
|
||||
return u"Rdio track: \x02{}\x02 by \x02{}\x02 - {}".format(name, artist, album)
|
||||
elif 'artist' in info and not 'album' in info: #Album
|
||||
elif 'artist' in info and not 'album' in info: # Album
|
||||
name = info['name']
|
||||
artist = info['artist']
|
||||
return u"Rdio album: \x02{}\x02 by \x02{}\x02".format(name, artist)
|
||||
else: #Artist
|
||||
else: # Artist
|
||||
name = info['name']
|
||||
return u"Rdio artist: \x02{}\x02".format(name)
|
106
disabled_stuff/recipe.py
Normal file
106
disabled_stuff/recipe.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
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))
|
79
disabled_stuff/reddit.py
Normal file
79
disabled_stuff/reddit.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
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)
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue