Initial commit
This commit is contained in:
commit
ee76802e74
39
NormalBot.py
Normal file
39
NormalBot.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import socket;
|
||||||
|
|
||||||
|
class NotRunningException (Exception):
|
||||||
|
pass;
|
||||||
|
|
||||||
|
class IRCBot:
|
||||||
|
# The IRC bot class. This can be reused, and will be the superclass of the actual minerbot.
|
||||||
|
def __init__(self, name, user, realname, owner):
|
||||||
|
self.name = name;
|
||||||
|
self.owner = owner;
|
||||||
|
self.user = user;
|
||||||
|
self.realname = realname;
|
||||||
|
self.running = False;
|
||||||
|
|
||||||
|
def begin(self, server, port, channels):
|
||||||
|
self.irc = socket.socket();
|
||||||
|
self.running = True;
|
||||||
|
self.irc.connect((server, port));
|
||||||
|
self.irc.send("NICK " + self.name + "\r\n");
|
||||||
|
self.irc.send("USER " + self.user + " 8 * " + self.realname + "\r\n");
|
||||||
|
for chan in channels:
|
||||||
|
self.irc.send("JOIN " + chan + "\r\n");
|
||||||
|
while True:
|
||||||
|
data = self.irc.recv(4096);
|
||||||
|
#print data;
|
||||||
|
if data.find("PING") != -1:
|
||||||
|
self.irc.send("PONG " + data.split()[1] + "\r\n");
|
||||||
|
elif data.find("PRIVMSG") != -1:
|
||||||
|
self.spokento(data)
|
||||||
|
|
||||||
|
def spokento(self, data):
|
||||||
|
if not self.running:
|
||||||
|
raise Exception("spokento was prematurely called.");
|
||||||
|
data_parts = data.split(" ",3);
|
||||||
|
id = data_parts[0];
|
||||||
|
nick = id.split("!")[0][1:];
|
||||||
|
message = data_parts[3][1:];
|
||||||
|
print(nick + ": " + message);
|
||||||
|
self.irc.send("PRIVMSG " + data_parts[2] + " :" + nick + ": " + message + "\r\n");
|
BIN
NormalBot.pyc
Normal file
BIN
NormalBot.pyc
Normal file
Binary file not shown.
12
bfc.py
Executable file
12
bfc.py
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#programlines = sys.stdin.readlines()
|
||||||
|
|
||||||
|
symbols = ["<",">","+","-","[","]",",","."]
|
||||||
|
def clean(i):
|
||||||
|
cleanedChars = []
|
||||||
|
|
||||||
|
for char in i:
|
||||||
|
if char in symbols:
|
||||||
|
cleanedChars.append(char);
|
||||||
|
|
||||||
|
return "".join(cleanedChars)
|
16
bot_runner.py
Normal file
16
bot_runner.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import minerbot
|
||||||
|
|
||||||
|
while(True):
|
||||||
|
bot = minerbot.minerbot("minerbot","minerbot","minerobber")
|
||||||
|
f = open("/home/minerobber/misc/mbchan.txt")
|
||||||
|
channels = f.read().split("\n")
|
||||||
|
f.close()
|
||||||
|
# try:
|
||||||
|
val = bot.begin("localhost",6667,channels)
|
||||||
|
if val == 0:
|
||||||
|
break
|
||||||
|
# except Exception as e:
|
||||||
|
# raise e
|
||||||
|
# bot.addNote("minerobber","Minerbot Crash","Crashed with {}: {}".format(type(e).__name__,str(e)))
|
||||||
|
# finally:
|
||||||
|
# reload(minerbot)
|
42
chaninfo.py
Normal file
42
chaninfo.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class ChanInfoError(Exception):
|
||||||
|
pass;
|
||||||
|
|
||||||
|
class ChannelInfo:
|
||||||
|
"""A class for obtaining info for a Twitch Channel"""
|
||||||
|
def __init__(self,channel,client_id):
|
||||||
|
self.channel = channel;
|
||||||
|
self.client_id = client_id;
|
||||||
|
self.resp = requests.get("https://api.twitch.tv/kraken/streams/{!s}?client_id={!s}".format(channel,client_id));
|
||||||
|
if self.resp.json().get("error") != None:
|
||||||
|
raise ChanInfoError("{status} {error} - \"{message}\"".format(**self.resp.json()))
|
||||||
|
|
||||||
|
"""If the channel is online, returns true. Else, returns false."""
|
||||||
|
def isOnline(self):
|
||||||
|
return self.resp.json().get('stream') != None;
|
||||||
|
|
||||||
|
"""Get the status of the stream."""
|
||||||
|
def getStatus(self):
|
||||||
|
return self.resp.json()['stream']['channel']['status']
|
||||||
|
|
||||||
|
"""Get the game."""
|
||||||
|
def getGame(self):
|
||||||
|
return self.resp.json()['stream']['game']
|
||||||
|
|
||||||
|
"""Get whether to display "playing" or "being"."""
|
||||||
|
def getDisplay(self):
|
||||||
|
return self.getGame() == "Creative"
|
||||||
|
|
||||||
|
"""Get viewer count."""
|
||||||
|
def getViewers(self):
|
||||||
|
return self.resp.json()['stream']['viewers']
|
||||||
|
|
||||||
|
"""Get embed frame (for HTML)"""
|
||||||
|
def getEmbed(self, width=950, height=700, autoplay=False):
|
||||||
|
return "<iframe src='http://player.twitch.tv/?channel={}&autoplay={}' width='{!s}' height='{!s}' frameborder='0' scrolling='no' allowfullscreen='true'></iframe>".format(self.channel,str(autoplay).lower(),width,height)
|
||||||
|
|
||||||
|
|
||||||
|
"""Update data, just runs the init again."""
|
||||||
|
def update(self):
|
||||||
|
self.__init__(self.channel,self.client_id)
|
BIN
chaninfo.pyc
Normal file
BIN
chaninfo.pyc
Normal file
Binary file not shown.
27
choose_parser.py
Normal file
27
choose_parser.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
testString = 'say "Jasper Oxide" "Are you really that stupid?"'
|
||||||
|
def parse(text,debug=False):
|
||||||
|
lines = [text.rstrip()]
|
||||||
|
result = []
|
||||||
|
for line in lines:
|
||||||
|
linetable = []
|
||||||
|
words = line.split(" ")
|
||||||
|
i=0
|
||||||
|
while i < len(words):
|
||||||
|
if words[i].startswith('"'):
|
||||||
|
if words[i].endswith('"'):
|
||||||
|
linetable.append(words[i][1:-1])
|
||||||
|
i = i + 1
|
||||||
|
continue
|
||||||
|
part = words[i][1:]
|
||||||
|
i=i+1
|
||||||
|
while not words[i].endswith('"'):
|
||||||
|
part = part + " " + words[i]
|
||||||
|
i = i + 1
|
||||||
|
part = part + " " + words[i][:-1]
|
||||||
|
linetable.append(part)
|
||||||
|
else:
|
||||||
|
part = words[i]
|
||||||
|
linetable.append(part)
|
||||||
|
i = i + 1
|
||||||
|
result.append(linetable)
|
||||||
|
return result[0][1:]
|
BIN
choose_parser.pyc
Normal file
BIN
choose_parser.pyc
Normal file
Binary file not shown.
40
colorbot.py
Normal file
40
colorbot.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import socket;
|
||||||
|
|
||||||
|
class NotRunningException (Exception):
|
||||||
|
pass;
|
||||||
|
|
||||||
|
class IRCBot:
|
||||||
|
# The IRC bot class. This can be reused, and will be the superclass of the actual minerbot.
|
||||||
|
def __init__(self, name, user, realname, owner):
|
||||||
|
self.name = name;
|
||||||
|
self.owner = owner;
|
||||||
|
self.user = user;
|
||||||
|
self.realname = realname;
|
||||||
|
self.running = False;
|
||||||
|
|
||||||
|
def begin(self, server, port, channels):
|
||||||
|
self.irc = socket.socket();
|
||||||
|
self.running = True;
|
||||||
|
self.irc.connect((server, port));
|
||||||
|
self.irc.send("NICK " + self.name + "\r\n");
|
||||||
|
self.irc.send("USER " + self.user + " 8 * " + self.realname + "\r\n");
|
||||||
|
for chan in channels:
|
||||||
|
self.irc.send("JOIN " + chan + "\r\n");
|
||||||
|
while True:
|
||||||
|
data = self.irc.recv(4096);
|
||||||
|
#print data;
|
||||||
|
if data.find("PING") != -1:
|
||||||
|
self.irc.send("PONG " + data.split()[1] + "\r\n");
|
||||||
|
elif data.find("PRIVMSG") != -1:
|
||||||
|
self.spokento(data)
|
||||||
|
|
||||||
|
def spokento(self, data):
|
||||||
|
if not self.running:
|
||||||
|
raise Exception("spokento was prematurely called.");
|
||||||
|
data_parts = data.split(" ",3);
|
||||||
|
id = data_parts[0];
|
||||||
|
nick = id.split("!")[0][1:];
|
||||||
|
message = data_parts[3][1:-2];
|
||||||
|
print(nick + ": " + message);
|
||||||
|
if nick == self.owner and message.find("!colortest") == 0:
|
||||||
|
self.irc.send("PRIVMSG "+data_parts[2]+" :\x034,1yo\x0f")
|
BIN
colorbot.pyc
Normal file
BIN
colorbot.pyc
Normal file
Binary file not shown.
10531
data/a-words.txt
Normal file
10531
data/a-words.txt
Normal file
File diff suppressed because it is too large
Load Diff
2111
data/k-words.txt
Normal file
2111
data/k-words.txt
Normal file
File diff suppressed because it is too large
Load Diff
9584
data/m-words.txt
Normal file
9584
data/m-words.txt
Normal file
File diff suppressed because it is too large
Load Diff
1
data/synopses.json
Normal file
1
data/synopses.json
Normal file
File diff suppressed because one or more lines are too long
1
data/titles.json
Normal file
1
data/titles.json
Normal file
File diff suppressed because one or more lines are too long
3927
data/w-words.txt
Normal file
3927
data/w-words.txt
Normal file
File diff suppressed because it is too large
Load Diff
20
kwam.py
Normal file
20
kwam.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
class KWAMPlugin:
|
||||||
|
def __init__(self,bot):
|
||||||
|
for i in "kwam":
|
||||||
|
with open("data/"+i+"-words.txt") as f:
|
||||||
|
setattr(self,i,[line.replace("\n","") for line in f.readlines()])
|
||||||
|
self.bot=bot
|
||||||
|
self.answerRequests = True
|
||||||
|
|
||||||
|
def answer(self,channel,nick,msg):
|
||||||
|
if not msg.startswith("!kwam"):
|
||||||
|
return
|
||||||
|
if nick==self.bot.owner:
|
||||||
|
if msg.startswith("!kwam "):
|
||||||
|
self.answerRequests = msg.endswith("on")
|
||||||
|
return
|
||||||
|
if self.answerRequests:
|
||||||
|
words = [random.choice(self.k),random.choice(self.w),random.choice(self.a),random.choice(self.m)]
|
||||||
|
self.bot.mention(channel,nick," ".join(words))
|
35
lua.py
Normal file
35
lua.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
from subapi import SubAPI
|
||||||
|
|
||||||
|
class LuaPlugin:
|
||||||
|
"""Handles lua execution"""
|
||||||
|
def __init__(self,bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.channels = dict()
|
||||||
|
|
||||||
|
def addChannel(self,chan):
|
||||||
|
self.channels[chan]=SubAPI()
|
||||||
|
self.channels[chan].addListener(self.outWithIt(chan))
|
||||||
|
self.channels[chan].start(["/usr/bin/lua"])
|
||||||
|
|
||||||
|
def outWithIt(self,chan):
|
||||||
|
def handler(msg):
|
||||||
|
if msg.strip()=="Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio":
|
||||||
|
return
|
||||||
|
self.bot.say(chan,msg)
|
||||||
|
return handler
|
||||||
|
|
||||||
|
def handleCommand(self,chan,sender,cmd):
|
||||||
|
if cmd.strip()=="!lua":
|
||||||
|
self.bot.mention(chan,sender,"Use !lua <lua command> to execute lua.")
|
||||||
|
elif not cmd.startswith("!lua "):
|
||||||
|
return
|
||||||
|
elif cmd.strip()=="!lua start" and not self.channels[chan]:
|
||||||
|
self.addChannel(chan)
|
||||||
|
self.bot.say(chan,"Lua session started")
|
||||||
|
elif cmd.strip()=="!lua reset" and self.channels[chan]:
|
||||||
|
self.channels[chan].stop()
|
||||||
|
del self.channels[chan]
|
||||||
|
self.addChannel(chan)
|
||||||
|
self.bot.say(chan,"Lua session reset")
|
||||||
|
else:
|
||||||
|
self.channels[chan].sendInput(cmd.strip.split(" ",2)[1])
|
42
markov.py
Normal file
42
markov.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import random,json
|
||||||
|
class Chain:
|
||||||
|
def __init__(self):
|
||||||
|
self.map = {}
|
||||||
|
|
||||||
|
def addWord(self,lastWord,word):
|
||||||
|
if lastWord in self.map and not word in self.map[lastWord]:
|
||||||
|
self.map[lastWord].append(word)
|
||||||
|
elif not lastWord in self.map:
|
||||||
|
self.map[lastWord] = [word]
|
||||||
|
|
||||||
|
def train(self,sentance):
|
||||||
|
words = sentance.split(" ")
|
||||||
|
lastWord = words.pop(0)
|
||||||
|
self.addWord("",lastWord)
|
||||||
|
for word in words:
|
||||||
|
self.addWord(lastWord,word)
|
||||||
|
lastWord = word
|
||||||
|
self.addWord(lastWord,"")
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
lastWord = random.choice(self.map[""])
|
||||||
|
sentence = lastWord
|
||||||
|
while lastWord != "":
|
||||||
|
word = random.choice(self.map[lastWord])
|
||||||
|
sentence += " " + word
|
||||||
|
lastWord = word
|
||||||
|
return sentence[:-1]
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return json.dumps(self.map)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_json(cls,jsonstr):
|
||||||
|
ret = cls()
|
||||||
|
ret.map = json.loads(jsonstr)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def addLinesFromFile(chain,filename):
|
||||||
|
with open(filename) as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
chain.train(line.rstrip())
|
BIN
markov.pyc
Normal file
BIN
markov.pyc
Normal file
Binary file not shown.
17
markovuniverse.py
Normal file
17
markovuniverse.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import markov
|
||||||
|
|
||||||
|
def chainFromFile(filename):
|
||||||
|
with open(filename) as f:
|
||||||
|
return markov.Chain.from_json(f.read())
|
||||||
|
|
||||||
|
titles = chainFromFile("data/titles.json")
|
||||||
|
synopses = chainFromFile("data/synopses.json")
|
||||||
|
|
||||||
|
def new_episode():
|
||||||
|
title = titles.generate().encode("utf-8")
|
||||||
|
synopsis = synopses.generate().encode("utf-8")
|
||||||
|
return (title,synopsis)
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
details = new_episode()
|
||||||
|
print "New episode:\n{} - {}".format(*details)
|
BIN
markovuniverse.pyc
Normal file
BIN
markovuniverse.pyc
Normal file
Binary file not shown.
86
mbtilde.py
Normal file
86
mbtilde.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import sieve,plugin
|
||||||
|
class Solver(plugin.Plugin):
|
||||||
|
def __init__(self,bot):
|
||||||
|
plugin.Plugin.__init__(self,bot,"!mbtilde ([a-z]+) ([A-Za-z0-9]+)(?: (.+))?")
|
||||||
|
|
||||||
|
def answer(self,c,n,m):
|
||||||
|
if not self.cmd.search(m):
|
||||||
|
return
|
||||||
|
if n!=self.bot.owner:
|
||||||
|
self.bot.say(c,"Don't tell me what to do!")
|
||||||
|
return
|
||||||
|
if c!="#bots":
|
||||||
|
self.bot.say(c,"Remember: tildebot only awards tildes in \#bots.")
|
||||||
|
plugin.Plugin.answer(self,c,n,m) # call super method
|
||||||
|
|
||||||
|
def run(self,cmd):
|
||||||
|
if not cmd.startswith("!mbtilde"):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
parts = cmd.split()
|
||||||
|
parts.pop(0)
|
||||||
|
parts = [part.strip() for part in parts]
|
||||||
|
try:
|
||||||
|
return getattr(self,parts[0])(*parts[1:])
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def request(self,c,n,m):
|
||||||
|
self.bot.say(c,self._request())
|
||||||
|
|
||||||
|
def _request(self):
|
||||||
|
return "!tilde"
|
||||||
|
|
||||||
|
def add(self,c,n,m):
|
||||||
|
self.bot.say(c,self._add(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _add(self,num1,num2):
|
||||||
|
return int(num1)+int(num2)
|
||||||
|
|
||||||
|
def sub(self,c,n,m):
|
||||||
|
self.bot.say(c,self._sub(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _sub(self,num1,num2):
|
||||||
|
return int(num1)-int(num2)
|
||||||
|
|
||||||
|
def mult(self,c,n,m):
|
||||||
|
self.bot.say(c,self._mult(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _mult(self,num1,num2):
|
||||||
|
return int(num1)*int(num2)
|
||||||
|
|
||||||
|
def div(self,c,n,m):
|
||||||
|
self.bot.say(c,self._div(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _div(self,num1,num2):
|
||||||
|
return int(num1)/int(num2)
|
||||||
|
|
||||||
|
def pow(self,c,n,m):
|
||||||
|
self.bot.say(c,self._pow(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _pow(self,num1,num2):
|
||||||
|
return int(num1)**int(num2)
|
||||||
|
|
||||||
|
def mod(self,c,n,m):
|
||||||
|
self.bot.say(c,self._mod(m.group(2),m.group(3)))
|
||||||
|
|
||||||
|
def _mod(self,num1,num2):
|
||||||
|
return int(num1)%int(num2)
|
||||||
|
|
||||||
|
def primefac(self,c,n,m):
|
||||||
|
self.bot.say(c,self._primefac(m.group(2)))
|
||||||
|
|
||||||
|
def _primefac(self,num):
|
||||||
|
return sieve.primefactors(int(num))
|
||||||
|
|
||||||
|
def score(self,c,n,m):
|
||||||
|
self.bot.say(c,self._score())
|
||||||
|
|
||||||
|
def _score(self,d):
|
||||||
|
return "!tildescore"
|
||||||
|
|
||||||
|
def say(self,c,n,m):
|
||||||
|
self.bot.say(c,self._say(m.group(2)))
|
||||||
|
|
||||||
|
def _say(self,msg):
|
||||||
|
return msg
|
BIN
mbtilde.pyc
Normal file
BIN
mbtilde.pyc
Normal file
Binary file not shown.
27
minerbot.commands
Normal file
27
minerbot.commands
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
if message.find("!steven-universe") == 0:
|
||||||
|
elif message.find("!log") == 0:
|
||||||
|
if message.find("!quit") == 0 and nick == self.owner:
|
||||||
|
elif message.find("!rollcall") == 0:
|
||||||
|
elif message.find("!twitch ") == 0:
|
||||||
|
elif message.find("!choose ") == 0:
|
||||||
|
elif message.strip == "!last5said":
|
||||||
|
elif message.find("!dicegame") == 0:
|
||||||
|
elif message.find("!online") == 0:
|
||||||
|
elif message.find("!reload\r\n") == 0 and self.owner == nick:
|
||||||
|
# elif message.find("!shop") == 0:
|
||||||
|
elif message.find("!tbadmin") == 0 and self.owner == nick:
|
||||||
|
elif message.find("!announce ") == 0:
|
||||||
|
# elif message.find("!guessing_game") == 0 and self.gg_state == "not-active":
|
||||||
|
# elif message.find("!join_guessing_game") == 0 and self.gg_state == "player-wait":
|
||||||
|
elif message.find("!reloadchannels") == 0 and nick == self.owner:
|
||||||
|
elif message.find("!save") == 0 and nick == self.owner:
|
||||||
|
elif message.find("!load") == 0 and nick == self.owner:
|
||||||
|
#elif message.find("!money") == 0:
|
||||||
|
elif message.find("!update-qdb-commits") == 0 and self.owner == nick:
|
||||||
|
elif message.find("!run ") == 0 and self.owner == nick:
|
||||||
|
#elif message.find("!tell") == 0:
|
||||||
|
elif message.find("!note ") == 0:
|
||||||
|
# elif message.find("!get-gg-state") == 0 and self.owner == nick:
|
||||||
|
elif message.find("!getStock") == 0:
|
||||||
|
elif message.find("!mbtilde ") == 0:
|
||||||
|
# elif message.find("!helpme") == 0:
|
414
minerbot.py
Normal file
414
minerbot.py
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
import socket,random,subprocess,threading,time,cPickle,string,time,prss,randwords,pstocks,chaninfo,primefac,choose_parser,notes,mbtilde,kwam,lua,urn,scplugin,json,math;
|
||||||
|
import os.path as fs;
|
||||||
|
from email.mime.text import MIMEText;
|
||||||
|
import markovuniverse as mu;
|
||||||
|
zws = ""
|
||||||
|
class NotRunningException (Exception):
|
||||||
|
pass;
|
||||||
|
|
||||||
|
log_format = "{} [{}] {}: {}"
|
||||||
|
|
||||||
|
def loadLNR():
|
||||||
|
with open("/home/minerobber/lnr.txt") as f:
|
||||||
|
return [l.rstrip() for l in f if l.rstrip()]
|
||||||
|
|
||||||
|
def saveLNR(lnr):
|
||||||
|
with open("/home/minerobber/lnr.txt","w") as f:
|
||||||
|
f.write("\n".join(lnr))
|
||||||
|
|
||||||
|
def filterNick(nick):
|
||||||
|
if len(nick) == 1:
|
||||||
|
print "Either "+nick+" is not a nick, or the person who has that nick needs a longer nick."
|
||||||
|
return nick
|
||||||
|
s = nick[0]+zws+nick[1:]
|
||||||
|
return s.encode('utf-8')
|
||||||
|
|
||||||
|
def log(channel, nick, message):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(log_format.format(time.strftime("%Y-%m-%d %H:%M:%S"),channel,nick,message))
|
||||||
|
with open("/home/minerobber/logs/"+time.strftime("%Y-%m-%d")+".txt","ab") as fh:
|
||||||
|
fh.write(log_format.format(time.strftime("%Y-%m-%d %H:%M:%S"),channel,nick,message))
|
||||||
|
|
||||||
|
def announce(channel, nick, ann, prssfeed):
|
||||||
|
prssfeed.addItem("Announcement by {} in {}".format(channel, nick),"https://tilde.town/~{}".format(nick),ann)
|
||||||
|
with open(fs.expanduser("~/public_html/announcements/rss.xml"),"wb") as rss:
|
||||||
|
rss.write(prssfeed.make())
|
||||||
|
with open(fs.expanduser("~/public_html/announcements/index.text"),"ab") as html:
|
||||||
|
html.write('{}, while in {}, announced: "{}" \n'.format(nick, channel, ann));
|
||||||
|
subprocess.check_output(["make -C ~/public_html/announcements -B"],shell=True)
|
||||||
|
cPickle.dump(prssfeed,open("/home/minerobber/misc/annrss","wb"))
|
||||||
|
|
||||||
|
def logJoin(channel,nick):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" "+nick+" joined "+channel)
|
||||||
|
|
||||||
|
def logPart(channel,nick):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" "+nick+" left "+channel)
|
||||||
|
|
||||||
|
def getBotanyPlantPath(user,file="{0}_plant_data.json"):
|
||||||
|
return "/home/{{0}}/.botany/{}".format(file).format(user)
|
||||||
|
|
||||||
|
def hasBotanyPlant(user):
|
||||||
|
return fs.exists(getBotanyPlantPath(user))
|
||||||
|
|
||||||
|
def hasVisitors(user):
|
||||||
|
return fs.exists(getBotanyPlantPath(user,"visitors.json"))
|
||||||
|
|
||||||
|
def getBotanyPlant(user):
|
||||||
|
if not hasBotanyPlant(user):
|
||||||
|
return False, {}
|
||||||
|
else:
|
||||||
|
with open(getBotanyPlantPath(user)) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
# if not hasVisitors(user): # TODO: fix this
|
||||||
|
return True, data
|
||||||
|
# else:
|
||||||
|
# with open(getBotanyPlantPath(user,"visitors.json")):
|
||||||
|
# return True, data, json.load(f)
|
||||||
|
|
||||||
|
#def getBotanyLastWatered(dlw,vt):
|
||||||
|
# rvt = []
|
||||||
|
# for t in vt:
|
||||||
|
# if t < time.time():
|
||||||
|
# rvt.append(t)
|
||||||
|
# if not rvt:
|
||||||
|
# return dlw
|
||||||
|
# allts = [dlw]+rvt
|
||||||
|
# allts.sort()
|
||||||
|
# diffs = [(j-i)/86400.0 for i, j in zip(allts[:-1], allts[1:])]
|
||||||
|
# lve = next((x for x in diffs if x > 5), None)
|
||||||
|
# if not lve:
|
||||||
|
# return allts[-1]
|
||||||
|
# return allts[:diffs.index(lve)+1][-1] #this should actually work, believe it or not
|
||||||
|
|
||||||
|
class minerbot:
|
||||||
|
def __init__(self, name, user, owner):
|
||||||
|
self.name = name;
|
||||||
|
self.owner = owner;
|
||||||
|
self.user = user;
|
||||||
|
self.running = False;
|
||||||
|
self.reload = 0;
|
||||||
|
|
||||||
|
def begin(self, server, port, channels):
|
||||||
|
# declare variables here
|
||||||
|
self.irc = socket.socket();
|
||||||
|
self.randWordsList = randwords.corpus;
|
||||||
|
self.userList = [];
|
||||||
|
self.running = True;
|
||||||
|
self.channels = channels;
|
||||||
|
self.kwam = kwam.KWAMPlugin(self)
|
||||||
|
self.lua = lua.LuaPlugin(self)
|
||||||
|
self.rss = prss.PageRSS("Announcements","https://tilde.town/~minerobber/announcements","Announcements made by tilde.town members in IRC.",time.localtime())
|
||||||
|
if fs.isfile("/home/minerobber/misc/annrss"):
|
||||||
|
self.rss = cPickle.load(open("/home/minerobber/misc/annrss"))
|
||||||
|
self.notebook = notes.DatedNotebook()
|
||||||
|
self.solver = mbtilde.Solver(self)
|
||||||
|
self.urn = urn.UrnPlugin(self)
|
||||||
|
if fs.isfile("/home/minerobber/lnr.txt"):
|
||||||
|
self.lnr = loadLNR()
|
||||||
|
else:
|
||||||
|
self.lnr = []
|
||||||
|
saveLNR([])
|
||||||
|
# self.xkcd = xkcdpl.XKCDPlugin(self)
|
||||||
|
# self.g7sc = scplugin.G7SCPlugin(self,"!shinycalc")
|
||||||
|
#self.quiz = quiz.QuizGame("/home/minerobber/quiz.txt")
|
||||||
|
# connecting, as well as main loop
|
||||||
|
self.irc.connect((server, port));
|
||||||
|
self.irc.send("NICK " + self.name + "\r\n");
|
||||||
|
self.irc.send("USER " + self.user + " 8 * Making an IRC bot is fun!\r\n");
|
||||||
|
self.irc.recv(4096)
|
||||||
|
for chan in channels:
|
||||||
|
self.irc.send("JOIN " + chan + "\r\n");
|
||||||
|
while self.running:
|
||||||
|
data = self.irc.recv(4096);
|
||||||
|
if data.find("PING") != -1:
|
||||||
|
self.irc.send("PONG " + data.split()[1] + "\r\n");
|
||||||
|
elif data.find("NAMES") != -1 and not fs.isfile("/home/minerobber/userList"):
|
||||||
|
users = data[5:-3]
|
||||||
|
for name in users.split(" "):
|
||||||
|
table = []
|
||||||
|
table.append(name)
|
||||||
|
table.append(0)
|
||||||
|
self.userList.append(table);
|
||||||
|
elif data.find("PART") != -1:
|
||||||
|
logPart(data.split(" ")[2],data.split(" ")[0].split("!")[0][1:])
|
||||||
|
elif data.find("PRIVMSG") != -1:
|
||||||
|
self.spokento(data)
|
||||||
|
self.save()
|
||||||
|
return self.reload;
|
||||||
|
|
||||||
|
def runCMD(self, cmd):
|
||||||
|
i = subprocess.check_output([cmd],shell=True)
|
||||||
|
if "\n" in i:
|
||||||
|
i.replace("\n","; ")
|
||||||
|
return i;
|
||||||
|
|
||||||
|
def addNote(self,touser,fromuser,msg):
|
||||||
|
# print "ADDNOTE: {} {} {}".format(touser,fromuser,msg)
|
||||||
|
self.notebook.addNote(touser,fromuser,msg)
|
||||||
|
|
||||||
|
def readNotes(self,user):
|
||||||
|
# print "READNOTES: {}".format(user)
|
||||||
|
for msg in self.notebook.readNotes(user):
|
||||||
|
self.say(user,msg)
|
||||||
|
|
||||||
|
def haveNotesFor(self,user):
|
||||||
|
# print "CHECK: {}".format(user)
|
||||||
|
return self.notebook.checkNotes(user)
|
||||||
|
|
||||||
|
def spokento(self, data):
|
||||||
|
if not self.running:
|
||||||
|
raise Exception("spokento was prematurely called.");
|
||||||
|
data_parts = data.split(" ",3);
|
||||||
|
id = data_parts[0];
|
||||||
|
nick = id.split("!")[0][1:];
|
||||||
|
message = data_parts[3][1:];
|
||||||
|
channel = data_parts[2];
|
||||||
|
if nick=="tilde.town":
|
||||||
|
return
|
||||||
|
print "[" + channel + "] " + nick + ": " + message;
|
||||||
|
log(channel, nick, message)
|
||||||
|
self.rss.pubDate = time.localtime()
|
||||||
|
if self.haveNotesFor(nick):
|
||||||
|
self.readNotes(nick)
|
||||||
|
if message.strip()=="!water minerbot":
|
||||||
|
self.mention(channel, nick, "BZZ-ZAP! Please don't water me! I'm not waterproofed yet!!!!! BZZ-BZZ-ZZZ-ZAP!")
|
||||||
|
# elif message.find("!urlme "):
|
||||||
|
# parts = message.split()
|
||||||
|
# if len(parts)>1:
|
||||||
|
# self.mention(channel,nick,"https://tilde.town/~{}/{}".format(nick,parts[1]))
|
||||||
|
# elif message.find("!talklikeme"):
|
||||||
|
# self.say(channel,"!talklike "+nick)
|
||||||
|
# elif message.strip()=="!lnrdebug":
|
||||||
|
# self.say(channel,"lnr = {!s}".format(self.lnr))
|
||||||
|
# return
|
||||||
|
elif message.find("!plant ")==0:
|
||||||
|
ok, data = getBotanyPlant(message.split(" ",1)[1].rstrip())
|
||||||
|
if not ok:
|
||||||
|
self.mention(channel,nick,"{} doesn't have a plant".format(message.split(" ",1)[1].rstrip()))
|
||||||
|
else:
|
||||||
|
# user requested does indeed have a plant, and data is the loaded JSON representation of said plant
|
||||||
|
msg = "{d[owner]}'s ".format(d=data)
|
||||||
|
status = data["description"]
|
||||||
|
if data["is_dead"]:
|
||||||
|
status = "dead "+status
|
||||||
|
status+=" was watered"
|
||||||
|
lastwatered = data["last_watered"] #,[x['timestamp'] for x in visitors])
|
||||||
|
if (lastwatered-time.time())<=(24*60*60):
|
||||||
|
status+=" today"
|
||||||
|
hours = str(int(math.floor((time.time()-lastwatered)/3600)))
|
||||||
|
if hours=='0':
|
||||||
|
seconds = str(int(math.floor((time.time()-lastwatered)/60)))
|
||||||
|
if seconds=='1':
|
||||||
|
status+=" (about a second ago)"
|
||||||
|
else:
|
||||||
|
status+=" (about {} seconds ago)".format(seconds)
|
||||||
|
elif hours=='1':
|
||||||
|
status+=" (about an hour ago)"
|
||||||
|
else:
|
||||||
|
status+=" (about {} hours ago)".format(hours)
|
||||||
|
self.mention(channel,nick,msg+status)
|
||||||
|
elif message.find("!steven-universe") == 0:
|
||||||
|
self.mention(channel, nick, "\"{}\" - {}".format(*mu.new_episode()))
|
||||||
|
elif message.find("!quit") == 0 and nick == self.owner:
|
||||||
|
self.irc.send("QUIT :beep boop I'm a bot.\r\n");
|
||||||
|
self.running = False;
|
||||||
|
elif message.find("!rollcall") == 0:
|
||||||
|
self.say(channel,"Hey! I'm " + self.name + "! I'm a mess of code. Ask my developer (my nick, but replace bot with \"obber\") about commands of mine!")
|
||||||
|
elif message.find("!twitch ") == 0:
|
||||||
|
mparts = message.split(" ")
|
||||||
|
if len(mparts) == 2:
|
||||||
|
c = chaninfo.ChannelInfo(mparts[1][:-2],"h7lvoe263k42haljbhlbv2ag1nzt5nd")
|
||||||
|
if not c.isOnline():
|
||||||
|
self.say(channel,"{} is not streaming.".format(c.channel))
|
||||||
|
verb = "playing"
|
||||||
|
if c.getDisplay():
|
||||||
|
verb = "being"
|
||||||
|
self.say(channel, '{} is {} {}. Status: "{}"; Viewers: {!s}'.format(c.channel,verb,c.getGame(),c.getStatus(),c.getViewers()))
|
||||||
|
elif message.find("!choose ") == 0:
|
||||||
|
self.say(channel,nick+": "+random.choice(choose_parser.parse(message)))
|
||||||
|
elif message.strip == "!last5said":
|
||||||
|
with open("/home/minerobber/log.txt") as f:
|
||||||
|
lines = []
|
||||||
|
for line in f:
|
||||||
|
lines.append(line.strip())
|
||||||
|
for line in lines[:-5]:
|
||||||
|
self.say(nick,line)
|
||||||
|
elif message.find("!dicegame") == 0:
|
||||||
|
message_parts = message.split(" ",2)
|
||||||
|
sides = 6
|
||||||
|
choice = int(random.uniform(1,sides))
|
||||||
|
b_choice = int(random.uniform(1,sides))
|
||||||
|
if b_choice > choice:
|
||||||
|
winMSG = "I win!"
|
||||||
|
else:
|
||||||
|
if b_choice == choice:
|
||||||
|
winMSG = "It's a tie!"
|
||||||
|
else:
|
||||||
|
winMSG = "You win!"
|
||||||
|
self.say(channel,"You rolled a " + str(choice) + ", and I rolled a " + str(b_choice) + ". " + winMSG)
|
||||||
|
elif channel == self.name and nick == self.owner:
|
||||||
|
# d = False
|
||||||
|
# if message.startwith("s "):
|
||||||
|
# d=True
|
||||||
|
# message=message.split(" ",2)[1]
|
||||||
|
print(self.owner + " used the global to say: \"" + message + "\"")
|
||||||
|
# if d:
|
||||||
|
self.globalmsg(message)
|
||||||
|
# else:
|
||||||
|
# self.globalmsg("[GLOBAL] "+message)
|
||||||
|
# self.globalmsg(("[GLOBAL] " if not d else "") + message)
|
||||||
|
elif message.find("!lnr") == 0:
|
||||||
|
if nick==self.owner and len(message.split(" "))>1:
|
||||||
|
self.lnr.append(message.split(" ",1)[1].rstrip())
|
||||||
|
saveLNR(self.lnr)
|
||||||
|
self.mention(channel,nick,"I'll remember that...")
|
||||||
|
return
|
||||||
|
for i in self.lnr:
|
||||||
|
self.mention(nick,nick,"Late night rambling: {}".format(i))
|
||||||
|
self.mention(channel,nick,"All late night ramblings have been PM'd to you.")
|
||||||
|
elif message.find("!online") == 0:
|
||||||
|
results = self.runCMD("onlinepeople4irc")
|
||||||
|
leet = string.maketrans("aelosiuUc","43105|Uu(")
|
||||||
|
self.say(channel, results.translate(leet))
|
||||||
|
elif message.find("!reload\r\n") == 0 and self.owner == nick:
|
||||||
|
self.irc.send("QUIT :Reloading bot code...\r\n");
|
||||||
|
self.reload = 1;
|
||||||
|
self.running = False;
|
||||||
|
elif message.find("!announce ") == 0:
|
||||||
|
announce(channel, nick, " ".join(message.split(" ")[1:]), self.rss)
|
||||||
|
elif message.find("!reloadchannels") == 0 and nick == self.owner:
|
||||||
|
channels = []
|
||||||
|
with open("/home/minerobber/misc/mbchan.txt") as f:
|
||||||
|
channels = f.readlines()
|
||||||
|
self.channels_2 = channels
|
||||||
|
for channel in self.channels_2:
|
||||||
|
if channel not in self.channels:
|
||||||
|
self.irc.send("JOIN {}\r\n".format(channel))
|
||||||
|
self.channels = self.channels_2
|
||||||
|
elif message.find("!save") == 0 and nick == self.owner:
|
||||||
|
self.save()
|
||||||
|
elif message.find("!load") == 0 and nick == self.owner:
|
||||||
|
self.load()
|
||||||
|
elif message.find("!update-qdb-commits") == 0 and self.owner == nick:
|
||||||
|
self.say(channel, self.runCMD("/home/minerobber/qdb-commits-gen.sh"))
|
||||||
|
elif message.find("!run ") == 0 and self.owner == nick:
|
||||||
|
prog = message.split(" ",1)[1]
|
||||||
|
nprog = which(prog.split(" ",1)[0])
|
||||||
|
if nprog is None:
|
||||||
|
self.say(channel,"Error: program does not exist!")
|
||||||
|
else:
|
||||||
|
self.say(channel,self.runCMD(prog.replace(prog.split(" ",1)[0],nprog)))
|
||||||
|
elif message.find("!tell") == 0:
|
||||||
|
self.say(nick,"DEPRECATED: Use new \"!note\" command (same syntax)")
|
||||||
|
elif message.find("!note ") == 0:
|
||||||
|
parts = message.split(" ",2)
|
||||||
|
if not len(parts) == 3:
|
||||||
|
self.mention(channel,nick,"usage: !note <user> <message>")
|
||||||
|
else:
|
||||||
|
self.addNote(parts[1],nick,parts[2])
|
||||||
|
self.mention(channel,nick,"Message sent for {}.".format(parts[1]))
|
||||||
|
elif message.find("!getStock") == 0:
|
||||||
|
self.mention(channel,nick,"This command is out-of-service while my developer figures out what's wrong with me.")
|
||||||
|
return
|
||||||
|
ticker = pstocks.StockTicker(format="{0} ({1}) is currently priced at {2}. (a change of {3})")
|
||||||
|
parts = message.split(" ")
|
||||||
|
if len(parts) < 2:
|
||||||
|
self.say(channel, "Usage: '!getStock <ticker>'")
|
||||||
|
return
|
||||||
|
for symbol in parts[1:]:
|
||||||
|
ticker.addSymbol(symbol)
|
||||||
|
for message in ticker.getTickerValues():
|
||||||
|
self.say(channel,message)
|
||||||
|
elif message.find("!mbtilde ") == 0:
|
||||||
|
if nick != self.owner:
|
||||||
|
self.say(channel,"Don't tell me what to do!")
|
||||||
|
return
|
||||||
|
if channel != "#bots":
|
||||||
|
self.say(channel,"Remember: tildebot only awards tildes in \#bots.")
|
||||||
|
result = self.solver.run(message)
|
||||||
|
if result:
|
||||||
|
if type(result)==str:
|
||||||
|
self.say(channel,result)
|
||||||
|
else:
|
||||||
|
self.say(channel,str(result))
|
||||||
|
elif message.strip()=="!discord":
|
||||||
|
self.mention(channel,nick,"The discord invite link is: https://discord.gg/RS8gJAV")
|
||||||
|
self.solver.answer(channel,nick,message)
|
||||||
|
#self.xkcd.answer(channel,nick,message)
|
||||||
|
#self.xkcd.check_for_new_xkcd(channel)
|
||||||
|
self.kwam.answer(channel,nick,message)
|
||||||
|
# self.g7sc.handleCommand(channel,nick,message)
|
||||||
|
# self.urn.onMessage(self,channel,nick,message)
|
||||||
|
# self.lua.handleCommand(channel,nick,message)
|
||||||
|
|
||||||
|
def globalmsg(self,message):
|
||||||
|
for chan in self.channels:
|
||||||
|
self.say(chan,message)
|
||||||
|
|
||||||
|
def say(self, chan, message):
|
||||||
|
try:
|
||||||
|
if type(message)!=str:
|
||||||
|
message = str(message)
|
||||||
|
message = message.replace("\n","")
|
||||||
|
self.irc.send("PRIVMSG " + chan + " :" + message + "\r\n")
|
||||||
|
if chan.find("#") == 0:
|
||||||
|
log(chan, self.name, message)
|
||||||
|
print("[{}] {}: {}".format(chan,self.name,message))
|
||||||
|
except:
|
||||||
|
self.say(chan,"Failed to send message, try again!")
|
||||||
|
|
||||||
|
def mention(self,chan,nick,message):
|
||||||
|
self.say(chan,nick+": "+message)
|
||||||
|
|
||||||
|
# def playQuizGame(self,channel,nick,message):
|
||||||
|
# if self.quiz.notPlaying(nick):
|
||||||
|
# self.quiz.addPlayer(nick)
|
||||||
|
# self.mention(channel,nick,self.quiz.getQuestion(nick)+" Use !a, !b, !c, or !d to answer.")
|
||||||
|
# else:
|
||||||
|
# if message.rstrip() not in ("!a","!b","!c","!d"):
|
||||||
|
# return
|
||||||
|
# if not self.quiz.answer(nick,message[1]):
|
||||||
|
# self.mention(channel,nick,"Close, but no dice! Try again!")
|
||||||
|
# else:
|
||||||
|
# self.mention(channel,nick,"Correct!")
|
||||||
|
# self.quiz.addPoint(nick)
|
||||||
|
# self.quiz.save()
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
# self.quiz.save()
|
||||||
|
saveLNR(self.lnr)
|
||||||
|
return
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
# self.quiz.load()
|
||||||
|
return
|
||||||
|
|
||||||
|
def num(s):
|
||||||
|
try:
|
||||||
|
int(s)
|
||||||
|
except ValueError:
|
||||||
|
float(s)
|
||||||
|
|
||||||
|
def wait(s, minutes):
|
||||||
|
if minutes:
|
||||||
|
time.sleep(s * 60)
|
||||||
|
else:
|
||||||
|
time.sleep(s)
|
||||||
|
|
||||||
|
def which(s):
|
||||||
|
import os
|
||||||
|
def is_exe(fpath):
|
||||||
|
return fs.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
fpath, fname = fs.split(s)
|
||||||
|
if fpath:
|
||||||
|
if is_exe(program):
|
||||||
|
return program
|
||||||
|
else:
|
||||||
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
|
path = path.strip('"')
|
||||||
|
exe_file = os.path.join(path, s)
|
||||||
|
if is_exe(exe_file):
|
||||||
|
return exe_file
|
||||||
|
return None;
|
380
minerbot.py.save
Normal file
380
minerbot.py.save
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
import socket,random,subprocess,threading,time,cPickle,string,time,prss,randwords,pstocks,chaninfo,primefac,re;
|
||||||
|
import os.path as fs;
|
||||||
|
from email.mime.text import MIMEText;
|
||||||
|
#with open("zws.txt","rb") as f:
|
||||||
|
# zws = f.readAll()
|
||||||
|
zws = ""
|
||||||
|
class NotRunningException (Exception):
|
||||||
|
pass;
|
||||||
|
|
||||||
|
log_format = "{} [{}] {}: {}"
|
||||||
|
|
||||||
|
def filterNick(nick):
|
||||||
|
if len(nick) == 1:
|
||||||
|
print "Either "+nick+" is not a nick, or the person who has that nick needs a longer nick."
|
||||||
|
return nick
|
||||||
|
s = nick[0]+zws+nick[1:]
|
||||||
|
return s.encode('utf-8')
|
||||||
|
|
||||||
|
def log(channel, nick, message):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(log_format.format(time.strftime("%Y-%m-%d %H:%M:%S"),channel,nick,message))
|
||||||
|
with open("/home/minerobber/logs/"+time.strftime("%Y-%m-%d")+".txt","ab") as fh:
|
||||||
|
fh.write(log_format.format(time.strftime("%Y-%m-%d %H:%M:%S"),channel,nick,message))
|
||||||
|
|
||||||
|
def logPublic(channel, nick, message):
|
||||||
|
with open("/home/minerobber/public_html/public_msgs.txt","ab") as fh:
|
||||||
|
fh.write(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" ["+channel+"] "+nick+": "+message)
|
||||||
|
|
||||||
|
def announce(channel, nick, ann, prssfeed):
|
||||||
|
prssfeed.addItem("Announcement by {} in {}".format(channel, nick),"https://tilde.town/~{}".format(nick),ann)
|
||||||
|
with open(fs.expanduser("~/public_html/announcements/rss.xml"),"wb") as rss:
|
||||||
|
rss.write(prssfeed.make())
|
||||||
|
with open(fs.expanduser("~/public_html/announcements/index.text"),"ab") as html:
|
||||||
|
html.write('{}, while in {}, announced: "{}" \n'.format(nick, channel, ann));
|
||||||
|
subprocess.check_output(["make -C ~/public_html/announcements -B"],shell=True)
|
||||||
|
cPickle.dump(prssfeed,open("/home/minerobber/misc/annrss","wb"))
|
||||||
|
|
||||||
|
def logJoin(channel,nick):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" "+nick+" joined "+channel)
|
||||||
|
|
||||||
|
def logPart(channel,nick):
|
||||||
|
with open("/home/minerobber/log.txt","ab") as fh:
|
||||||
|
fh.write(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" "+nick+" left "+channel)
|
||||||
|
|
||||||
|
class minerbot:
|
||||||
|
def __init__(self, name, user, owner):
|
||||||
|
self.name = name;
|
||||||
|
self.owner = owner;
|
||||||
|
self.user = user;
|
||||||
|
self.running = False;
|
||||||
|
self.reload = 0;
|
||||||
|
|
||||||
|
def begin(self, server, port, channels):
|
||||||
|
# declare variables here
|
||||||
|
self.irc = socket.socket();
|
||||||
|
self.randWordsList = randwords.corpus;
|
||||||
|
self.userList = [];
|
||||||
|
if fs.isfile("/home/minerobber/userList"):
|
||||||
|
self.load();
|
||||||
|
self.running = True;
|
||||||
|
self.channels = channels;
|
||||||
|
self.emailTemplate = ["~{0} wanted me to tell you:\n"]
|
||||||
|
self.rss = prss.PageRSS("Announcements","https://tilde.town/~minerobber/announcements","Announcements made by tilde.town members in IRC.",time.localtime())
|
||||||
|
if fs.isfile("/home/minerobber/misc/annrss"):
|
||||||
|
self.rss = cPickle.load(open("/home/minerobber/misc/annrss"))
|
||||||
|
# self.guessgameplaying = False;
|
||||||
|
# self.gg_players = {};
|
||||||
|
# self.gg_state = "not-active";
|
||||||
|
# self.gg_votes = {}
|
||||||
|
# connecting, as well as main loop
|
||||||
|
self.irc.connect((server, port));
|
||||||
|
self.irc.send("NICK " + self.name + "\r\n");
|
||||||
|
self.irc.send("USER " + self.user + " 8 * Making an IRC bot is fun!\r\n");
|
||||||
|
for chan in channels:
|
||||||
|
self.irc.send("JOIN " + chan + "\r\n");
|
||||||
|
while self.running:
|
||||||
|
data = self.irc.recv(4096);
|
||||||
|
#print data;
|
||||||
|
if data.find("PING") != -1:
|
||||||
|
self.irc.send("PONG " + data.split()[1] + "\r\n");
|
||||||
|
elif data.find("NAMES") != -1 and not fs.isfile("/home/minerobber/userList"):
|
||||||
|
users = data[5:-3]
|
||||||
|
for name in users.split(" "):
|
||||||
|
table = []
|
||||||
|
table.append(name)
|
||||||
|
table.append(0)
|
||||||
|
self.userList.append(table);
|
||||||
|
elif data.find("JOIN") != -1:
|
||||||
|
logJoin(data.split(" ")[2],data.split(" ")[0].split("!")[0][1:])
|
||||||
|
if data.split(" ")[2] == "#music" and data.split(" ")[0].split("!")[0][1:] != self.nick:
|
||||||
|
self.say(data.split(" ")[2],"Hello, "+data.split(" ")[0].split("!")[0][1:]+"! If you want to listen along, the URL is: https://tilde.town/~kc/jukebot/listen")
|
||||||
|
elif data.find("PART") != -1:
|
||||||
|
logPart(data.split(" ")[2],data.split(" ")[0].split("!")[0][1:])
|
||||||
|
elif data.find("PRIVMSG") != -1:
|
||||||
|
self.spokento(data)
|
||||||
|
self.save()
|
||||||
|
return self.reload;
|
||||||
|
|
||||||
|
def runCMD(self, cmd):
|
||||||
|
i = subprocess.check_output([cmd],shell=True)
|
||||||
|
if "\n" in i:
|
||||||
|
i.replace("\n","; ")
|
||||||
|
return i;
|
||||||
|
|
||||||
|
def sendEmail(self, channel, sender, recipient, text):
|
||||||
|
msg = MIMEText("~{0} wanted me to tell you:\n> {1}".format(sender,text))
|
||||||
|
msg["From"] = "minerbot-messages@tilde.town"
|
||||||
|
msg["To"] = "{0}@tilde.town".format(recipient)
|
||||||
|
msg["Subject"] = "Message from ~{0}".format(sender)
|
||||||
|
msg["Cc"] = "{0}@tilde.town".format(sender)
|
||||||
|
mail = subprocess.Popen("{0} -t -oi".format(which("sendmail")).split(" "),stdin=subprocess.PIPE)
|
||||||
|
mail.communicate(msg.as_string())
|
||||||
|
self.say(channel,"Mail sent!")
|
||||||
|
# mail.close()
|
||||||
|
|
||||||
|
def spokento(self, data):
|
||||||
|
if not self.running:
|
||||||
|
raise Exception("spokento was prematurely called.");
|
||||||
|
data_parts = data.split(" ",3);
|
||||||
|
id = data_parts[0];
|
||||||
|
nick = id.split("!")[0][1:];
|
||||||
|
message = data_parts[3][1:];
|
||||||
|
channel = data_parts[2];
|
||||||
|
print "[" + channel + "] " + nick + ": " + message;
|
||||||
|
log(channel, nick, message)
|
||||||
|
self.rss.pubDate = time.localtime()
|
||||||
|
if message.find(self.owner) != -1:
|
||||||
|
logPublic(channel,nick,message)
|
||||||
|
elif message.find("!log") == 0:
|
||||||
|
logPublic(channel,nick,message.split(" ",2)[1])
|
||||||
|
if message.find("!quit") == 0 and nick == self.owner:
|
||||||
|
self.irc.send("QUIT :beep boop I'm a bot.\r\n");
|
||||||
|
self.running = False;
|
||||||
|
elif message.find("!rollcall") == 0:
|
||||||
|
self.say(channel,"Hey! I'm " + self.name + "! Use '!help' to see a list of my commands.")
|
||||||
|
elif message.find("!twitch ") == 0:
|
||||||
|
mparts = message.split(" ")
|
||||||
|
if len(mparts) == 2:
|
||||||
|
c = chaninfo.ChannelInfo(mparts[1][:-2],"h7lvoe263k42haljbhlbv2ag1nzt5nd")
|
||||||
|
if not c.isOnline():
|
||||||
|
return
|
||||||
|
verb = "playing"
|
||||||
|
if c.getDisplay():
|
||||||
|
verb = "being"
|
||||||
|
self.say(channel, '{} is {} {}. Status: "{}"; Viewers: {!s}'.format(c.channel,verb,c.getGame(),c.getStatus(),c.getViewers()))
|
||||||
|
elif message.strip == "!last5said":
|
||||||
|
with open("/home/minerobber/log.txt") as f:
|
||||||
|
lines = []
|
||||||
|
for line in f:
|
||||||
|
lines.append(line.strip())
|
||||||
|
for line in lines[:-5]:
|
||||||
|
self.say(nick,line)
|
||||||
|
elif message.find("!dicegame") == 0:
|
||||||
|
message_parts = message.split(" ",2)
|
||||||
|
sides = 6
|
||||||
|
choice = int(random.uniform(1,sides))
|
||||||
|
b_choice = int(random.uniform(1,sides))
|
||||||
|
if b_choice > choice:
|
||||||
|
winMSG = "I win!"
|
||||||
|
else:
|
||||||
|
if b_choice == choice:
|
||||||
|
winMSG = "It's a tie!"
|
||||||
|
else:
|
||||||
|
winMSG = "You win!"
|
||||||
|
self.say(channel,"You rolled a " + str(choice) + ", and I rolled a " + str(b_choice) + ". " + winMSG)
|
||||||
|
elif channel == self.name and nick == self.owner:
|
||||||
|
print(self.owner + " used the global to say: \"" + message + "\"")
|
||||||
|
for chan in self.channels:
|
||||||
|
self.say(chan,"[GLOBAL] " + message)
|
||||||
|
elif message.find("!online") == 0:
|
||||||
|
results = self.runCMD("onlinepeople4irc")
|
||||||
|
leet = string.maketrans("aelosiuUc","43105|Uu(")
|
||||||
|
self.say(channel, results.translate(leet))
|
||||||
|
elif message.find("!reload") == 0 and self.owner == nick:
|
||||||
|
self.irc.send("QUIT :Reloading bot code...\r\n");
|
||||||
|
self.reload = 1;
|
||||||
|
self.running = False;
|
||||||
|
# elif message.find("!shop") == 0:
|
||||||
|
#nyi
|
||||||
|
elif message.find("!tbadmin") == 0 and self.owner == nick:
|
||||||
|
message_parts = message.split(" ")
|
||||||
|
if message_parts[1] == "add":
|
||||||
|
for i in self.userList:
|
||||||
|
if message_parts[2] == i[0]:
|
||||||
|
i[1] += int(message_parts[3])
|
||||||
|
self.save()
|
||||||
|
elif message_parts[1] == "rm":
|
||||||
|
for i in self.userList:
|
||||||
|
if message_parts[2] == i[0]:
|
||||||
|
i[1] += int(message_parts[3])
|
||||||
|
self.save()
|
||||||
|
elif message_parts[1] == "view":
|
||||||
|
for i in self.userList:
|
||||||
|
if message_parts[2] == i[0]:
|
||||||
|
self.say(channel,i[0] + " has " + str(i[1]) + " tildebucks.")
|
||||||
|
elif message.find("!announce ") == 0:
|
||||||
|
announce(channel, nick, " ".join(message.split(" ")[1:]), self.rss)
|
||||||
|
# elif message.find("!guessing_game") == 0 and self.gg_state == "not-active":
|
||||||
|
# thread = threading.Thread(target=self.playGuessingGame, args=(channel));
|
||||||
|
# elif message.find("!join_guessing_game") == 0 and self.gg_state == "player-wait":
|
||||||
|
# self.gg_players.append(nick);
|
||||||
|
elif message.find("!save") == 0 and nick == self.owner:
|
||||||
|
self.save()
|
||||||
|
elif message.find("!load") == 0 and nick == self.owner:
|
||||||
|
self.load()
|
||||||
|
#elif message.find("!money") == 0:
|
||||||
|
# for i in self.userList:
|
||||||
|
# if i[0] == nick:
|
||||||
|
# self.say(channel,(nick + " has " + str(i[1]) + " tildebucks."))
|
||||||
|
elif message.find("!update-qdb-commits") == 0 and self.owner == nick:
|
||||||
|
self.say(channel, self.runCMD("/home/minerobber/qdb-commits-gen.sh"))
|
||||||
|
elif message.find("!run ") == 0 and self.owner == nick:
|
||||||
|
prog = message.split(" ",1)[1]
|
||||||
|
nprog = which(prog.split(" ",1)[0])
|
||||||
|
if nprog is None:
|
||||||
|
self.say(channel,"Error: program does not exist!")
|
||||||
|
else:
|
||||||
|
self.say(channel,self.runCMD(prog.replace(prog.split(" ",1)[0],nprog)))
|
||||||
|
elif message.find("!tell") == 0:
|
||||||
|
parts = message.split(" ",2)
|
||||||
|
if not len(parts) == 3:
|
||||||
|
self.say(channel,"Usage: !tell <user> <message>")
|
||||||
|
else:
|
||||||
|
self.sendEmail(channel,nick,parts[1],parts[2][:-2])
|
||||||
|
# elif message.find("!get-gg-state") == 0 and self.owner == nick:
|
||||||
|
# self.say(channel, "GG-State: " + self.gg_state)
|
||||||
|
elif message.find("!getStock") == 0:
|
||||||
|
ticker = pstocks.StockTicker(format="{0} ({1}) is currently priced at {2}. (a change of {3})")
|
||||||
|
parts = message.split(" ")
|
||||||
|
if len(parts) < 2:
|
||||||
|
self.say(channel, "Usage: '!getStock <ticker>'")
|
||||||
|
return
|
||||||
|
for symbol in parts[1:]:
|
||||||
|
ticker.addSymbol(symbol)
|
||||||
|
for message in ticker.getTickerValues():
|
||||||
|
self.say(channel,message)
|
||||||
|
elif message.find("!mbtilde ") == 0:
|
||||||
|
if nick != self.owner:
|
||||||
|
self.say(channel,"Don't tell me what to do!")
|
||||||
|
return
|
||||||
|
if channel != "#bots":
|
||||||
|
self.say(channel,"Remember: tildebot only awards tildes in \#bots.")
|
||||||
|
parts = message.split(" ",2)
|
||||||
|
parts = [s.rstrip() for s in parts]
|
||||||
|
if parts[1] == "request":
|
||||||
|
self.say("#bots","!tilde")
|
||||||
|
if parts[1] == "add":
|
||||||
|
nums = [int(s) for s in parts[2].split(" ")]
|
||||||
|
self.say(channel,"{!s}".format(sum(nums)))
|
||||||
|
if parts[1] == "sub":
|
||||||
|
nums = [int(s) for s in parts[2].split(" ",1)]
|
||||||
|
self.say(channel,"{!s}".format(nums[1]-nums[0]))
|
||||||
|
if parts[1] == "mult":
|
||||||
|
nums = [int(s) for s in parts[2].split(" ",1)]
|
||||||
|
self.say(channel,"{!s}".format(nums[1]*nums[0]))
|
||||||
|
if parts[1] == "divide":
|
||||||
|
nums = [int(s) for s in parts[2].split(" ",1)]
|
||||||
|
try:
|
||||||
|
self.say(channel,"{!s}".format(nums[0]/nums[1]))
|
||||||
|
except ZeroDivisionError:
|
||||||
|
self.say(channel,"Bugger off!")
|
||||||
|
if parts[1] == "mod":
|
||||||
|
nums = [int(s) for s in parts[2].split(" ",1)]
|
||||||
|
self.say(channel,"{!s}".format(nums[0]%nums[1]))
|
||||||
|
if parts[1] == "factor":
|
||||||
|
self.say(channel,"{!s},{!s}".format(*list(primefac.primefac(int(parts[2]))))
|
||||||
|
elif message.find("!rpg") and channel=="#rpg":
|
||||||
|
parts = message.split(" ")
|
||||||
|
if len(parts) < 2:
|
||||||
|
self.say(channel,"Usage: !rpg <action> [parameters]")
|
||||||
|
if parts[1]=="roll" and len(parts)==3:
|
||||||
|
descriptor = parts[2].rstrip()
|
||||||
|
t = re.match(descriptor,r"^(\d+)d(\d+)$")
|
||||||
|
if not t:
|
||||||
|
self.say(channel,"Usage: !rpg roll <amount of dice>d<number of sides on each>")
|
||||||
|
self.say(channel,"Example: !rpg roll 1d100")
|
||||||
|
number = t.match(0)
|
||||||
|
sides =
|
||||||
|
# elif message.find("!helpme") == 0:
|
||||||
|
# help_parts = message.split(" ",2)
|
||||||
|
# if len(help_parts) < 2:
|
||||||
|
# self.say(channel,"Commands: 'dicegame', 'online', 'tell';")
|
||||||
|
# else:
|
||||||
|
# if help_parts[1] == "dicegame":
|
||||||
|
# self.say(channel,"Play a dice game against " + self.name + ". Usage: '!dicegame'")
|
||||||
|
# elif help_parts[1] == "online":
|
||||||
|
# self.say(channel,"Returns a list of online users, as well as a user count. Usage: '!online'")
|
||||||
|
# elif help_parts[1] == "tell":
|
||||||
|
# self.say(channel,"Sends a user an email to let them know of something. Usage: '!tell <user> <thing to tell them>'")
|
||||||
|
# elif help_parts[1] == "words":
|
||||||
|
# self.say(channel,"Generates a random string of words. Usage: '!words'")
|
||||||
|
# elif help_parts[1] == "getStock":
|
||||||
|
# self.say(channel,"Gets stock info for a specific ticker. Usage: '!getStock <ticker>'")
|
||||||
|
# elif self.gg_state == "player-wait-vote" and message.find("!guess"):
|
||||||
|
# if nick in self.gg_players:
|
||||||
|
# for i in self.gg_votes:
|
||||||
|
# if i[0] == nick:
|
||||||
|
# return;
|
||||||
|
# self.gg_votes.append({nick,int(message.split(" ")[1])})
|
||||||
|
# if self.gg_state == "player-wait-vote":
|
||||||
|
# playerDouble = {};
|
||||||
|
# for i in self.gg_votes:
|
||||||
|
# if i[0] in self.gg_players:
|
||||||
|
# playerDouble.append(i[0])
|
||||||
|
# if self.gg_players == playerDouble:
|
||||||
|
# self.gg_state = "all-voted"
|
||||||
|
# self.randWordsList.append(message)
|
||||||
|
|
||||||
|
def say(self, chan, message):
|
||||||
|
self.irc.send("PRIVMSG " + chan + " :" + message + "\r\n")
|
||||||
|
if chan.find("#") == 0:
|
||||||
|
log(chan, self.name, message)
|
||||||
|
|
||||||
|
def playGuessingGame(self,chan):
|
||||||
|
self.gg_players = []
|
||||||
|
self.say(chan, "Generating number to guess...")
|
||||||
|
gg_number = random.uniform(1,100)
|
||||||
|
self.gg_state = "player-wait"
|
||||||
|
self.say(chan, "Game will start soon! To join, type \"!join_guessing_game\"")
|
||||||
|
wait(15, True)
|
||||||
|
self.gg_state = "started"
|
||||||
|
self.say(chan, "The game has started!")
|
||||||
|
playerString = "Players: "
|
||||||
|
for player in self.gg_players:
|
||||||
|
playerString += player + " "
|
||||||
|
self.say(chan, playerString)
|
||||||
|
self.say(chan,"How to play: guess a number between 1 and 100.")
|
||||||
|
self.gg_state = "player-wait-vote"
|
||||||
|
while not self.gg_state == "all-voted":
|
||||||
|
wait(5,False)
|
||||||
|
correct_players = [];
|
||||||
|
for i in self.gg_votes:
|
||||||
|
if gg_number == i[1]:
|
||||||
|
correct_players.append(i[0])
|
||||||
|
correctVoteString = "Winners: "
|
||||||
|
for player in correct_players:
|
||||||
|
correctVoteString += player + " "
|
||||||
|
self.say(chan, correctVoteString)
|
||||||
|
self.say(chan, "All of the winners get 3 tildebucks!")
|
||||||
|
for user in self.userList:
|
||||||
|
if user[0] in correct_players:
|
||||||
|
user[1] += 3;
|
||||||
|
self.save()
|
||||||
|
self.gg_state = "not-active"
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
cPickle.dump(self.userList, open("/home/minerobber/userList","wb"))
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
cPickle.load(open("/home/minerobber/userList","rb"))
|
||||||
|
|
||||||
|
def num(s):
|
||||||
|
try:
|
||||||
|
int(s)
|
||||||
|
except ValueError:
|
||||||
|
float(s)
|
||||||
|
|
||||||
|
def wait(s, minutes):
|
||||||
|
if minutes:
|
||||||
|
time.sleep(s * 60)
|
||||||
|
else:
|
||||||
|
time.sleep(s)
|
||||||
|
|
||||||
|
def which(s):
|
||||||
|
import os
|
||||||
|
def is_exe(fpath):
|
||||||
|
return fs.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
|
||||||
|
fpath, fname = fs.split(s)
|
||||||
|
if fpath:
|
||||||
|
if is_exe(program):
|
||||||
|
return program
|
||||||
|
else:
|
||||||
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
|
path = path.strip('"')
|
||||||
|
exe_file = os.path.join(path, s)
|
||||||
|
if is_exe(exe_file):
|
||||||
|
return exe_file
|
||||||
|
return None;
|
BIN
minerbot.pyc
Normal file
BIN
minerbot.pyc
Normal file
Binary file not shown.
35
notes.py
Normal file
35
notes.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import time
|
||||||
|
class BasicNotebook:
|
||||||
|
def __init__(self):
|
||||||
|
self.messages = {}
|
||||||
|
|
||||||
|
def _addToNotes(self,touser,msgformat):
|
||||||
|
if touser in self.messages:
|
||||||
|
self.messages[touser].append(msgformat)
|
||||||
|
else:
|
||||||
|
self.messages[touser]=[msgformat]
|
||||||
|
|
||||||
|
def addNote(self,touser,fromuser,msg):
|
||||||
|
self._addToNotes(touser,[fromuser,msg])
|
||||||
|
|
||||||
|
def _readNotes(self,user,fmtstr):
|
||||||
|
if not self.checkNotes(user):
|
||||||
|
return []
|
||||||
|
ret = []
|
||||||
|
for messageI in self.messages[user]:
|
||||||
|
ret.append(fmtstr.format(*messageI))
|
||||||
|
del self.messages[user]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def readNotes(self,user):
|
||||||
|
return self._readNotes(user,"{0} left a message: {1}")
|
||||||
|
|
||||||
|
def checkNotes(self,user):
|
||||||
|
return user in self.messages.keys()
|
||||||
|
|
||||||
|
class DatedNotebook(BasicNotebook):
|
||||||
|
def addNote(self,touser,fromuser,msg):
|
||||||
|
self._addToNotes(touser,[fromuser,msg,time.strftime("%H:%M:%S"),time.strftime("%A, %B %d, %Y")])
|
||||||
|
|
||||||
|
def readNotes(self,user):
|
||||||
|
return self._readNotes(user,"{0} left a message at {2} on {3}: {1}")
|
8
out.lua
Normal file
8
out.lua
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
if not table.pack then table.pack = function(...) return { n = select("#", ...), ... } end end
|
||||||
|
if not table.unpack then table.unpack = unpack end
|
||||||
|
local load = load if _VERSION:find("5.1") then load = function(x, n, _, env) local f, e = loadstring(x, n) if not f then return f, e end if env then setfenv(f, env) end return f end end
|
||||||
|
local _select, _unpack, _pack, _error = select, table.unpack, table.pack, error
|
||||||
|
local _libs = {}
|
||||||
|
local print1
|
||||||
|
print1 = print
|
||||||
|
return print1("lua")
|
25
plugin.py
Normal file
25
plugin.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
class Plugin:
|
||||||
|
def __init__(self,bot,command_format):
|
||||||
|
self.bot = bot
|
||||||
|
self.cmd = re.compile(command_format)
|
||||||
|
|
||||||
|
def answer(self,channel,nick,message):
|
||||||
|
m = self.cmd.search(message)
|
||||||
|
if m and hasattr(self,m.group(1).replace(" ","_")):
|
||||||
|
getattr(self,m.group(1).replace(" ","_"))(channel,nick,message)
|
||||||
|
|
||||||
|
class TestPlugin(Plugin):
|
||||||
|
def __init__(self,bot):
|
||||||
|
Plugin.__init__(self,bot,"!test ([A-Za-z]+)(?: (.+))?")
|
||||||
|
self.is_bot=True
|
||||||
|
|
||||||
|
# def is_not_a_bot(self):
|
||||||
|
# self.is_bot=False
|
||||||
|
|
||||||
|
def say(self,c,n,m):
|
||||||
|
if self.is_bot:
|
||||||
|
self.bot.mention(c,n,m)
|
||||||
|
else:
|
||||||
|
print(m)
|
BIN
plugin.pyc
Normal file
BIN
plugin.pyc
Normal file
Binary file not shown.
54
pokemon.py
Normal file
54
pokemon.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import json,os.path,copy
|
||||||
|
class Pokemon:
|
||||||
|
def __init__(self):
|
||||||
|
self.pkmns = dict()
|
||||||
|
def __getitem__(self,k):
|
||||||
|
return self.pkmns[k]
|
||||||
|
def add(self,**kwargs):
|
||||||
|
self.pkmns[kwargs["name"]] = kwargs
|
||||||
|
|
||||||
|
class PCBox:
|
||||||
|
"""Pokemon box"""
|
||||||
|
def __init__(self):
|
||||||
|
self.pokemon = []
|
||||||
|
|
||||||
|
def move(self,pkmn):
|
||||||
|
self.pokemon.append(pkmn)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
return self.pokemon
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromList(cls,l):
|
||||||
|
ret = cls()
|
||||||
|
ret.pokemon = l
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class PokemonGame:
|
||||||
|
"""A game of Pokemon. Up to 6 mons, 300000 pokeyen, and 4 moves per Pokemon."""
|
||||||
|
def __init__(self,owner,prompt):
|
||||||
|
self.setupPKMNList()
|
||||||
|
try:
|
||||||
|
with open(os.path.join("/home/minerobber/.pkmn/",owner+".json"),"r") as f:
|
||||||
|
self.data = json.load(f)
|
||||||
|
self.name = self.data["name"]
|
||||||
|
self.pokeyen = self.data["pokeyen"]
|
||||||
|
self.pkmn = self.data["pkmn"]
|
||||||
|
self.pc = []
|
||||||
|
for item in self.data["boxes"]:
|
||||||
|
self.pc.append(PCBox.fromList(item))
|
||||||
|
except IOError as e:
|
||||||
|
self.name = prompt()
|
||||||
|
self.pokeyen = 3000
|
||||||
|
self.pkmn = []
|
||||||
|
self.pc = [PCBox()]*20
|
||||||
|
|
||||||
|
def addPKMN(self,type):
|
||||||
|
if len(self.pkmn)==6:
|
||||||
|
return False
|
||||||
|
self.pkmn.append(copy.copy(self.pkmnl[type]))
|
||||||
|
|
||||||
|
def setupPKMNList(self):
|
||||||
|
self.pkmnl = Pokemon()
|
||||||
|
self.pkmnl.add(name="Charmander",maxhp=39,atk=52,dfn=43,spa=60,sde=50,speed=65,evolves=dict(at=16,to="Charmeleon"))
|
||||||
|
self.pkmnl.add(name="Charmeleon")
|
3
prod.py
Normal file
3
prod.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from minerbot import minerbot;
|
||||||
|
bot = minerbot("minerbot", "minerbot","minerobber");
|
||||||
|
bot.begin("localhost",6667,["#bots","#minerobber","#tildetown"]);
|
26
prss.py
Normal file
26
prss.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
"""A python module for writing RSS."""
|
||||||
|
import time
|
||||||
|
class PageRSS:
|
||||||
|
"""A helper class for creating a page's RSS."""
|
||||||
|
def __init__(self, title, description, link, date):
|
||||||
|
self.items = []
|
||||||
|
self.title = title
|
||||||
|
self.description = description
|
||||||
|
self.link = link
|
||||||
|
self.pubDate = date
|
||||||
|
|
||||||
|
"""Add items to RSS feed."""
|
||||||
|
def addItem(self, title, link, desc):
|
||||||
|
item = {}
|
||||||
|
item['title'] = title
|
||||||
|
item['link'] = link
|
||||||
|
item['desc'] = desc
|
||||||
|
self.items.append(item)
|
||||||
|
|
||||||
|
"""Generates RSS feed."""
|
||||||
|
def make(self):
|
||||||
|
contents = "<?xml version='1.0' ?><rss version='2.0'><channel><title>{}</title><link>{}</link><description>{}</description><pubDate>{}</pubDate>".format(self.title,self.link,self.description,time.strftime("%a, %d %b %Y %H:%M:%S %z",self.pubDate))
|
||||||
|
for i in self.items:
|
||||||
|
contents += "<item><title>{}</title><link>{}</link><description>{}</description></item>".format(i['title'],i['link'],i['desc'])
|
||||||
|
contents += "</channel></rss>"
|
||||||
|
return contents
|
20
pstocks/__init__.py
Normal file
20
pstocks/__init__.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import getters
|
||||||
|
class StockTicker:
|
||||||
|
"""A stock ticker to track certain stocks with."""
|
||||||
|
def __init__(self, data=["s","n","l1","c1"], format="{1} ({0}) {2} ({3})"):
|
||||||
|
self.symbols = []
|
||||||
|
self.data = data
|
||||||
|
self.format = format
|
||||||
|
|
||||||
|
def addSymbol(self,symbol):
|
||||||
|
self.symbols.append(symbol)
|
||||||
|
|
||||||
|
def removeSymbol(self,symbol):
|
||||||
|
self.symbols = [x for x in self.symbols if x != symbol]
|
||||||
|
|
||||||
|
def getTickerValues(self):
|
||||||
|
reader = getters.getStocks(self.symbols,"".join(self.data))
|
||||||
|
ret = []
|
||||||
|
for row in reader:
|
||||||
|
ret.append(self.format.format(*row))
|
||||||
|
return ret
|
BIN
pstocks/__init__.pyc
Normal file
BIN
pstocks/__init__.pyc
Normal file
Binary file not shown.
19
pstocks/getters.py
Normal file
19
pstocks/getters.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import csv,requests;
|
||||||
|
from urllib import quote_plus as urlencode;
|
||||||
|
|
||||||
|
def generatorFromText(text):
|
||||||
|
for line in text.splitlines():
|
||||||
|
yield line
|
||||||
|
|
||||||
|
def getCSVFile(url):
|
||||||
|
r = requests.get(url)
|
||||||
|
reader = csv.reader(generatorFromText(r.text))
|
||||||
|
return reader
|
||||||
|
|
||||||
|
def getStocks(symbols,data):
|
||||||
|
symbol_string = ""
|
||||||
|
if type(symbols) is str:
|
||||||
|
symbol_string = symbols
|
||||||
|
else:
|
||||||
|
symbol_string = "+".join(symbols)
|
||||||
|
return getCSVFile("http://finance.yahoo.com/d/quotes.csv?s="+urlencode(symbol_string)+"&f="+data)
|
BIN
pstocks/getters.pyc
Normal file
BIN
pstocks/getters.pyc
Normal file
Binary file not shown.
32
randwords.py
Normal file
32
randwords.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import wordfreq,string,random
|
||||||
|
corpus = open("corpus").read().split("\n")
|
||||||
|
strs = corpus
|
||||||
|
filter = ""
|
||||||
|
for c in string.punctuation:
|
||||||
|
if c != "'":
|
||||||
|
filter += c
|
||||||
|
def getListFreqDict(list):
|
||||||
|
nl = []
|
||||||
|
for s in list:
|
||||||
|
ls = s.split(" ")
|
||||||
|
filter(ls,None)
|
||||||
|
lsc = ls[:]
|
||||||
|
for word in ls:
|
||||||
|
if word.find("http://") != -1 or word.find("https://") != -1:
|
||||||
|
lsc.remove(word);
|
||||||
|
s = " ".join(lsc)
|
||||||
|
nl.add(s)
|
||||||
|
ret = wordfreq.getFreqDict(" ".join(nl),filterchars=filter)
|
||||||
|
return ret
|
||||||
|
def getRandomWords(freqDict):
|
||||||
|
t = ""
|
||||||
|
for s in freqDict:
|
||||||
|
t += "{} ".format(s) * freqDict[s]
|
||||||
|
listW = [x for x in t.split(" ") if x != ""]
|
||||||
|
len = random.randint(1,20)
|
||||||
|
ret = ""
|
||||||
|
while len != 0:
|
||||||
|
ret += random.choice(listW)
|
||||||
|
ret += " "
|
||||||
|
len -= 1
|
||||||
|
return ret[:-1]+random.choice(".!?;")
|
BIN
randwords.pyc
Normal file
BIN
randwords.pyc
Normal file
Binary file not shown.
45
scplugin.py
Normal file
45
scplugin.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import shinycalc
|
||||||
|
|
||||||
|
class G7SCPlugin:
|
||||||
|
|
||||||
|
help = "Generates shiny chances for pokemon generation 7 shiny hunting! Subcommands: shiny, hidden_ability, perfect_ivs"
|
||||||
|
|
||||||
|
"""Handles lua execution"""
|
||||||
|
def __init__(self,bot,prefix):
|
||||||
|
self.bot = bot
|
||||||
|
self.prefix = prefix
|
||||||
|
|
||||||
|
def handleCommand(self,chan,sender,cmd):
|
||||||
|
if cmd.strip()==prefix:
|
||||||
|
self.bot.mention(chan,sender,G7SCPlugin.help)
|
||||||
|
elif not cmd.startswith(prefix+" "):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
parts = cmd.strip().split()
|
||||||
|
if not hasattr(self,parts[1]):
|
||||||
|
self.bot.mention(chan,sender,G7SCPlugin.help)
|
||||||
|
raise Exception()
|
||||||
|
args = parts[2:]
|
||||||
|
# args.insert(0,self)
|
||||||
|
self.bot.mention(chan,sender,getattr(self,parts[1])(*args))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def shiny(self,*args):
|
||||||
|
shinycalc.setChain(int(args[0]))
|
||||||
|
shiny = shinycalc.generateShiny()
|
||||||
|
ret = "1/{!s} chance of the pokemon being shiny.".format(shiny[0])
|
||||||
|
if shiny[1]:
|
||||||
|
ret += " (Or not. Shiny values from 1-69 aren't known yet.)"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def hidden_ability(self,*args):
|
||||||
|
shinycalc.setChain(int(args[0]))
|
||||||
|
ha = shinycalc.generateHA()
|
||||||
|
return "{!s}% chance of a hidden ability.".format(ha)
|
||||||
|
|
||||||
|
def perfect_ivs(self,*args):
|
||||||
|
shinycalc.setChain(int(args[0]))
|
||||||
|
ivs = shinycalc.generateIVs()
|
||||||
|
return "{!s} guaranteed perfect IV(s).".format(ivs)
|
BIN
scplugin.pyc
Normal file
BIN
scplugin.pyc
Normal file
Binary file not shown.
53
shinycalc.py
Executable file
53
shinycalc.py
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
chain = 0
|
||||||
|
|
||||||
|
def setChain(c):
|
||||||
|
global chain
|
||||||
|
chain = (c%256)
|
||||||
|
|
||||||
|
def generateShiny():
|
||||||
|
if chain<70:
|
||||||
|
return (4096,chain!=0)
|
||||||
|
else:
|
||||||
|
return (1024,False)
|
||||||
|
|
||||||
|
def generateIVs():
|
||||||
|
if chain<=4:
|
||||||
|
return 0
|
||||||
|
elif chain<=9:
|
||||||
|
return 1
|
||||||
|
elif chain<=19:
|
||||||
|
return 2
|
||||||
|
elif chain<=29:
|
||||||
|
return 3
|
||||||
|
else:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
def generateHA():
|
||||||
|
if chain<10:
|
||||||
|
return 0
|
||||||
|
elif chain<20:
|
||||||
|
return 5
|
||||||
|
elif chain<30:
|
||||||
|
return 10
|
||||||
|
else:
|
||||||
|
return 15
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Calculates shiny chance and IVs for SOS battles in generation 7.")
|
||||||
|
parser.add_argument("chain",type=int,help="Chain value. Due to overflow bug, will not be calculated hgher than 255 (handled automatically)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
setChain(args.chain)
|
||||||
|
|
||||||
|
shiny = generateShiny()
|
||||||
|
iv = generateIVs()
|
||||||
|
ha = generateHA()
|
||||||
|
|
||||||
|
print "Shiny chance: 1/"+str(shiny[0])+("*" if shiny[1] else "")
|
||||||
|
print str(iv)+" guaranteed perfect IV(s)"
|
||||||
|
print "Hidden Ability chance: "+str(ha)+"%"
|
||||||
|
if shiny[1]:
|
||||||
|
print "* Shiny chances for chain values below 70 are not known."
|
BIN
shinycalc.pyc
Normal file
BIN
shinycalc.pyc
Normal file
Binary file not shown.
3
show.py
Normal file
3
show.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from minerbot import minerbot;
|
||||||
|
bot = minerbot("minerbot", "minerbot","minerobber");
|
||||||
|
bot.begin("irc.badnik.net",6667,["#ImANoob"]);
|
19
sieve.py
Normal file
19
sieve.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
def primes(n):
|
||||||
|
if n<=2:
|
||||||
|
return []
|
||||||
|
sieve=[True]*(n+1)
|
||||||
|
for x in range(3,int(n**0.5)+1,2):
|
||||||
|
for y in range(3,(n//x)+1,2):
|
||||||
|
sieve[(x*y)]=False
|
||||||
|
|
||||||
|
return [2]+[i for i in range(3,n,2) if sieve[i]]
|
||||||
|
|
||||||
|
def primefactors(n):
|
||||||
|
primelist = primes(100)
|
||||||
|
lpf = 2
|
||||||
|
for prime in primelist:
|
||||||
|
print "Checking prime: "+str(prime)
|
||||||
|
if n%prime == 0 and prime > lpf:
|
||||||
|
print "Better prime found: "+str(prime)
|
||||||
|
lpf = prime
|
||||||
|
return "{!s},{!s}".format(lpf,n/lpf)
|
35
subapi.py
Normal file
35
subapi.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import subprocess as sp
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
class SubAPI:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.outputListeners = set()
|
||||||
|
|
||||||
|
|
||||||
|
def start(self, args, listenDaemon=True):
|
||||||
|
self.program = sp.Popen(args, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.STDOUT, universal_newlines=True)
|
||||||
|
|
||||||
|
self.t = Thread(target=self.listen, daemon=listenDaemon)
|
||||||
|
self.t.start()
|
||||||
|
|
||||||
|
|
||||||
|
def listen(self):
|
||||||
|
while self.program.stdout.readable():
|
||||||
|
outputLine = self.program.stdout.readline()[:-1]
|
||||||
|
for listener in self.outputListeners:
|
||||||
|
listener(outputLine)
|
||||||
|
|
||||||
|
def sendInput(self, command):
|
||||||
|
self.program.stdin.write(command+"\n")
|
||||||
|
self.program.stdin.flush()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.program.terminate()
|
||||||
|
self.program.stdout.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
subapi.pyc
Normal file
BIN
subapi.pyc
Normal file
Binary file not shown.
7
sugrocks.py
Normal file
7
sugrocks.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def doMethod(m):
|
||||||
|
return requests.get("https://api.sug.rocks/{}.json".format(m)).json()
|
||||||
|
|
||||||
|
def schedule():
|
||||||
|
return doMethod("schedule")
|
BIN
sugrocks.pyc
Normal file
BIN
sugrocks.pyc
Normal file
Binary file not shown.
2
t.tt
Normal file
2
t.tt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
def BLANK(self,c,n,m):
|
||||||
|
self.bot.say(c,self._BLANK(m.group(2),m.group(3)))
|
3
test.py
Normal file
3
test.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from minerbot import minerbot;
|
||||||
|
bot = minerbot("minerbot", "testuser","minerobber");
|
||||||
|
bot.begin("localhost",6667,["#minerobber"]);
|
5
testurn.py
Normal file
5
testurn.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import urn
|
||||||
|
|
||||||
|
bot = urn.TestBot()
|
||||||
|
urnp = urn.UrnPlugin(bot)
|
||||||
|
urnp.onMessage("#tildetown","minerobber","!urn (print! \"lua\")")
|
32
urn.py
Normal file
32
urn.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
class TestBot:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def say(self,chan,message):
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
class NFile:
|
||||||
|
def __init__(self,bot,chan):
|
||||||
|
self.bot = bot
|
||||||
|
self.chan = chan
|
||||||
|
def write(self,c):
|
||||||
|
self.bot.say(self.chan,c)
|
||||||
|
|
||||||
|
class UrnPlugin:
|
||||||
|
def __init__(self,bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
def onMessage(self,chan,nick,message):
|
||||||
|
parts = message.strip().split()
|
||||||
|
if parts[0]!="!urn":
|
||||||
|
return
|
||||||
|
with open("te.urn","w") as f:
|
||||||
|
f.write(" ".join(parts[1:]))
|
||||||
|
subprocess.call("urn te.urn",shell=True)
|
||||||
|
t = subprocess.Popen("lua out.lua",shell=True,stdout=subprocess.PIPE)
|
||||||
|
out = t.communicate()[0]
|
||||||
|
lines = [l.strip() for l in out.strip().split("\n")]
|
||||||
|
for line in lines:
|
||||||
|
if line:
|
||||||
|
self.bot.say(chan,line)
|
14
wordfreq.py
Normal file
14
wordfreq.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import string
|
||||||
|
def getFreqDict(corpus, filterchars=string.punctuation):
|
||||||
|
corpus = corpus.lower()
|
||||||
|
for c in filterchars:
|
||||||
|
corpus = corpus.replace(c,"")
|
||||||
|
words = corpus.split()
|
||||||
|
words = filter(None,words)
|
||||||
|
freq = {}
|
||||||
|
for word in words:
|
||||||
|
if word in freq:
|
||||||
|
freq[word] += 1
|
||||||
|
else:
|
||||||
|
freq.update({word: 1})
|
||||||
|
return freq
|
BIN
wordfreq.pyc
Normal file
BIN
wordfreq.pyc
Normal file
Binary file not shown.
37
xkcd.py
Normal file
37
xkcd.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class InvalidComic(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Comic(object):
|
||||||
|
def __init__(self,num=None,donterror=False):
|
||||||
|
if num:
|
||||||
|
r = requests.get("https://xkcd.com/{!s}/info.0.json".format(num))
|
||||||
|
if r.status_code!=200:
|
||||||
|
if donterror:
|
||||||
|
self.num = num
|
||||||
|
self.fakeit = True
|
||||||
|
else:
|
||||||
|
raise InvalidComic("Invalid XKCD comic \""+str(num)+"\"")
|
||||||
|
else:
|
||||||
|
self.__dict__.update(r.json())
|
||||||
|
self.fakeit = False
|
||||||
|
else:
|
||||||
|
r = requests.get("https://xkcd.com/info.0.json")
|
||||||
|
if r.status_code!=200:
|
||||||
|
if donterror:
|
||||||
|
self.num = 0
|
||||||
|
self.fakeit = True
|
||||||
|
else:
|
||||||
|
raise InvalidComic("Cannot locate latest comic.")
|
||||||
|
else:
|
||||||
|
self.__dict__.update(r.json())
|
||||||
|
self.fakeit = False
|
||||||
|
|
||||||
|
def __getattr__(self,k):
|
||||||
|
if k=="fakeit" or k=="num":
|
||||||
|
return object.__getattr__(self,k)
|
||||||
|
if self.fakeit:
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return object.__getattr__(self,k)
|
Loading…
Reference in New Issue
Block a user