Misc & lint fixes

This commit is contained in:
dave 2017-01-01 14:59:01 -08:00
parent e11d068a6e
commit fa8783e6cc
42 changed files with 1726 additions and 1593 deletions

View File

@ -6,7 +6,8 @@ from pyircbot import PyIRCBot
if __name__ == "__main__":
" logging level and facility "
logging.basicConfig(level=logging.INFO, format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
logging.basicConfig(level=logging.INFO,
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
log = logging.getLogger('main')
" parse command line args "

View File

@ -24,6 +24,7 @@ try:
except:
from io import BytesIO as StringIO
IRCEvent = namedtuple("IRCEvent", "args prefix trailing")
UserPrefix = namedtuple("UserPrefix", "nick username hostname")
ServerPrefix = namedtuple("ServerPrefix", "hostname")
@ -74,7 +75,8 @@ class IRCCore(asynchat.async_chat):
while self.alive:
try:
asyncore.loop(map=self.asynmap, timeout=1)
except Exception as e:
except Exception:
self.log.error("Loop error: ")
self.log.error(IRCCore.trace())
@ -86,7 +88,7 @@ class IRCCore(asynchat.async_chat):
logging.info("Loop: reconnecting")
try:
self._connect()
except Exception as e2:
except Exception:
self.log.error("Error reconnecting: ")
self.log.error(IRCCore.trace())
@ -126,7 +128,7 @@ class IRCCore(asynchat.async_chat):
:param data: the data that was recieved
:type data: str"""
#self.log.info("<< %(message)s", {"message":repr(data)})
self.buffer.write(data)
def found_terminator(self):
@ -156,7 +158,7 @@ class IRCCore(asynchat.async_chat):
self.log.error("Connection failed (handle_error)")
self.log.error(str(args))
self.log.error(str(kwargs))
self.log.error(IRCCore.trace());
self.log.error(IRCCore.trace())
def _connect(self):
"""Connect to IRC"""
@ -175,7 +177,8 @@ class IRCCore(asynchat.async_chat):
self.connect(socketInfo[0][4])
self.log.info("Connection established")
self._fileno = self.socket.fileno()
self.asynmap[self._fileno] = self # http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html
# See http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html
self.asynmap[self._fileno] = self
self.log.info("_connect: Socket map: %s" % str(self.asynmap))
def handle_connect(self):
@ -221,12 +224,12 @@ class IRCCore(asynchat.async_chat):
for index, arg in enumerate(args):
args[index] = arg.strip()
self.fire_hook("_RECV", args=args, prefix=prefix, trailing=trailing)
if not command in self.hookcalls:
self.log.warning("Unknown command: cmd='%s' prefix='%s' args='%s' trailing='%s'" % (command, prefix, args, trailing))
if command not in self.hookcalls:
self.log.warning("Unknown command: cmd='%s' prefix='%s' args='%s' trailing='%s'" % (command, prefix, args,
trailing))
else:
self.fire_hook(command, args=args, prefix=prefix, trailing=trailing)
" Module related code "
def initHooks(self):
"""Defines hooks that modules can listen for events of"""
@ -343,7 +346,9 @@ class IRCCore(asynchat.async_chat):
:param prefix: the prefix to disassemble
:type prefix: str
:returns: object -- an UserPrefix object with the properties `nick`, `username`, `hostname` or a ServerPrefix object with the property `hostname`"""
:returns: object -- an UserPrefix object with the properties `nick`, `username`, `hostname` or a ServerPrefix
object with the property `hostname`
"""
if "!" in prefix:
nick, prefix = prefix.split("!")
username, hostname = prefix.split("@")
@ -432,7 +437,7 @@ class IRCCore(asynchat.async_chat):
:type mode: str
:param extra: additional argument if the mode needs it. Example: user@*!*
:type extra: str"""
if extra != None:
if extra is not None:
self.sendRaw("MODE %s %s %s" % (channel, mode, extra))
else:
self.sendRaw("MODE %s %s" % (channel, mode))
@ -464,6 +469,13 @@ class IRCCore(asynchat.async_chat):
:type message: str"""
self.sendRaw("QUIT :%s" % message, prio=0)
def act_PASS(self, password):
"""
Send server password, for use on connection
"""
self.sendRaw("PASS %s" % password, prio=0)
class OutputQueueRunner(Thread):
"""Rate-limited output queue"""
def __init__(self, bot):
@ -488,14 +500,14 @@ class OutputQueueRunner(Thread):
self.process_queue_item()
lastSend = time()
except queue.Empty:
#self.log.info("Queue is empty")
# self.log.debug("Queue is empty")
pass
sleep(0.01)
def process_queue_item(self):
"""Remove 1 item from queue and process it"""
prio, text = self.bot.outputQueue.get(block=True, timeout=10)
#self.log.info("%s>> %s" % (prio,text))
# self.log.debug("%s>> %s" % (prio,text))
self.bot.outputQueue.task_done()
self.log.debug("> {}".format(text.decode('UTF-8')))
self.bot.send(text)
@ -508,7 +520,7 @@ class OutputQueueRunner(Thread):
self.bot.outputQueue.get(block=False)
except queue.Empty:
pass
#self.log.info("output queue cleared")
# self.log.debug("output queue cleared")
return length
def flush(self):
@ -518,4 +530,4 @@ class OutputQueueRunner(Thread):
self.process_queue_item()
except:
pass
#self.log.info("output queue flushed")
# self.log.debug("output queue flushed")

View File

@ -7,7 +7,6 @@
"""
import logging
import os
from .pyircbot import PyIRCBot
@ -70,6 +69,7 @@ class ModuleBase:
writable. The bot's data dir *should* always be writable"""
return self.bot.getDataPath(self.moduleName) + (f if f else '')
class ModuleHook:
def __init__(self, hook, method):
self.hook = hook

View File

@ -7,11 +7,12 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase
class AttributeStorage(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["attributes"]
self.db = None
@ -51,12 +52,6 @@ class AttributeStorage(ModuleBase):
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;""")
c.close()
# self.getItem('xMopxShell', 'name')
# self.getKey('xMopxShell', 'name')
# self.setKey('xMopxShell', 'name', 'dave')
# SELECT `i`.`id`, `i`.`item`, `a`.`attribute`, `v`.`value` FROM `items` `i` INNER JOIN `values` `v` on `v`.`itemid`=`i`.`id` INNER JOIN `attribute` `a` on `a`.`id`=`v`.`attributeid` ORDER BY `i`.`id` ASC, `a`.`id` ASC LIMIT 1000 ;
def getItem(self, name):
"""Get all values for a item
@ -76,13 +71,11 @@ class AttributeStorage(ModuleBase):
on `a`.`id`=`v`.`attributeid`
WHERE
`i`.`item`=%s;""",
(name,)
)
`i`.`item`=%s;""", (name,))
item = {}
while True:
row = c.fetchone()
if row == None:
if row is None:
break
item[row["attribute"]] = row["value"]
c.close()
@ -117,12 +110,10 @@ class AttributeStorage(ModuleBase):
WHERE
`i`.`item`=%s
AND
`a`.`attribute`=%s;""",
(item,key)
)
`a`.`attribute`=%s;""", (item, key))
row = c.fetchone()
c.close()
if row == None:
if row is None:
return None
return row["value"]
@ -145,7 +136,7 @@ class AttributeStorage(ModuleBase):
c = self.db.connection.query("SELECT `id` FROM `attribute` WHERE `attribute`=%s;", (attribute))
row = c.fetchone()
attributeId = -1
if row == None:
if row is None:
c = self.db.connection.query("INSERT INTO `attribute` (`attribute`) VALUES (%s);", (attribute))
attributeId = c.lastrowid
else:
@ -156,19 +147,22 @@ class AttributeStorage(ModuleBase):
c = self.db.connection.query("SELECT `id` FROM `items` WHERE `item`=%s;", (item))
row = c.fetchone()
itemId = -1
if row == None:
if row is None:
c = self.db.connection.query("INSERT INTO `items` (`item`) VALUES (%s);", (item))
itemId = c.lastrowid
else:
itemId = row["id"]
c.close()
if value == None:
if value is None:
# delete it
c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;", (itemId, attributeId))
self.log.info("AttributeStorage: Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value))
c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;",
(itemId, attributeId))
self.log.info("AttributeStorage: Stored item %s attribute %s value: %s (Deleted)" %
(itemId, attributeId, value))
else:
# add attribute
c = self.db.connection.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (%s, %s, %s);", (itemId, attributeId, value))
c = self.db.connection.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) "
"VALUES (%s, %s, %s);", (itemId, attributeId, value))
self.log.info("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()

View File

@ -7,11 +7,12 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase
class AttributeStorageLite(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["attributes"]
self.db = None
@ -49,10 +50,6 @@ class AttributeStorageLite(ModuleBase):
) ;""")
c.close()
#print(self.setKey('xmopxshell', 'name', 'dave'))
#print(self.getKey('xmopxshell', 'name'))
#print(self.getItem('xMopxShell'))
def getItem(self, name):
"""Get all values for a item
@ -72,23 +69,22 @@ class AttributeStorageLite(ModuleBase):
on `a`.`id`=`v`.`attributeid`
WHERE
`i`.`item`=?;""",
(name.lower(),)
)
`i`.`item`=?;""", (name.lower(),))
item = {}
while True:
row = c.fetchone()
if row == None:
if row is None:
break
item[row["attribute"]] = row["value"]
c.close()
if len(item)==0:
if not item:
return {}
return item
def get(self, item, key):
return self.getKey(item, key)
def getKey(self, item, key):
"""Get the value of an key on an item
@ -112,18 +108,17 @@ class AttributeStorageLite(ModuleBase):
WHERE
`i`.`item`=?
AND
`a`.`attribute`=?;""",
(item.lower(),key.lower())
)
`a`.`attribute`=?;""", (item.lower(), key.lower()))
row = c.fetchone()
c.close()
if row == None:
if row is None:
return None
return row["value"]
def set(self, item, key, value):
return self.setKey(item, key, value)
def setKey(self, item, key, value):
"""Set the key on an item
@ -140,7 +135,7 @@ class AttributeStorageLite(ModuleBase):
c = self.db.query("SELECT `id` FROM `attribute` WHERE `attribute`=?;", (attribute,))
row = c.fetchone()
attributeId = -1
if row == None:
if row is None:
c = self.db.query("INSERT INTO `attribute` (`attribute`) VALUES (?);", (attribute,))
attributeId = c.lastrowid
else:
@ -151,19 +146,19 @@ class AttributeStorageLite(ModuleBase):
c = self.db.query("SELECT `id` FROM `items` WHERE `item`=?;", (item,))
row = c.fetchone()
itemId = -1
if row == None:
if row is None:
c = self.db.query("INSERT INTO `items` (`item`) VALUES (?);", (item,))
itemId = c.lastrowid
else:
itemId = row["id"]
c.close()
if value == None:
if value is None:
# delete it
c = self.db.query("DELETE FROM `values` WHERE `itemid`=? AND `attributeid`=? ;", (itemId, attributeId))
self.log.info("Stored item %s attribute %s value: %s (Deleted)" % (itemId, attributeId, value))
else:
# add attribute
c = self.db.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (?, ?, ?);", (itemId, attributeId, value))
c = self.db.query("REPLACE INTO `values` (`itemid`, `attributeid`, `value`) VALUES (?, ?, ?);",
(itemId, attributeId, value))
self.log.info("Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()

View File

@ -10,9 +10,10 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
from requests import get
from time import time
class BitcoinPrice(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.cache = None
self.cacheAge = 0
@ -23,20 +24,19 @@ class BitcoinPrice(ModuleBase):
def btc(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
replyTo = prefix.nick if not "#" in args[0] else args[0]
replyTo = prefix.nick if "#" not in args[0] else args[0]
cmd = self.bot.messageHasCommand([".btc", ".bitcoin"], trailing)
if cmd:
data = self.getApi()
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (
prefix.nick,
"\x02\x0307Bitcoin:\x03\x02 \x0307{buy:.0f}\x0f$ - High: \x0307{high:.0f}\x0f$ - Low: \x0307{low:.0f}\x0f$ - Volume: \x0307{vol_cur:.0f}\x03฿".format(**data['ticker'])
"\x02\x0307Bitcoin:\x03\x02 \x0307{buy:.0f}\x0f$ - High: \x0307{high:.0f}\x0f$ - "
"Low: \x0307{low:.0f}\x0f$ - Volume: \x0307{vol_cur:.0f}\x03฿".format(**data['ticker'])
))
def getApi(self):
if self.cache == None or time()-self.cacheAge>self.config["cache"]:
if self.cache is None or time() - self.cacheAge > self.config["cache"]:
self.cache = get("https://btc-e.com/api/2/btc_usd/ticker").json()
self.cacheAge = time()
return self.cache

View File

@ -1,17 +1,19 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
import datetime
import time
import math
class Calc(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.calc)]
self.timers = {}
self.sqlite = self.bot.getBestModuleForService("sqlite")
if self.sqlite==None:
if self.sqlite is None:
self.log.error("Calc: SQLIite service is required.")
return
@ -61,12 +63,12 @@ class Calc(ModuleBase):
c.close()
def timeSince(self, channel, timetype):
if not channel in self.timers:
if channel not in self.timers:
self.createDefaultTimers(channel)
return time.time() - self.timers[channel][timetype]
def updateTimeSince(self, channel, timetype):
if not channel in self.timers:
if channel not in self.timers:
self.createDefaultTimers(channel)
self.timers[channel][timetype] = time.time()
@ -86,10 +88,9 @@ class Calc(ModuleBase):
sender = self.bot.decodePrefix(prefix)
foundCalc = False
commandFound = ""
for cmd in self.config["cmd_calc"]:
if trailing[0:len(cmd)] == cmd and ( len(trailing) == len(cmd) or (trailing[len(cmd):len(cmd)+1] in [" ", "="])):
commandFound=cmd
if trailing[0:len(cmd)] == cmd and (len(trailing) == len(cmd) or
(trailing[len(cmd):len(cmd) + 1] in [" ", "="])):
foundCalc = True
if foundCalc:
@ -107,7 +108,8 @@ class Calc(ModuleBase):
self.bot.act_PRIVMSG(args[0], "Sorry %s, I don't know what '%s' is." % (sender.nick, calcWord))
else:
if self.config["delaySubmit"] > 0 and self.timeSince(args[0], "add") < self.config["delaySubmit"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delaySubmit"], self.timeSince(args[0], "add")))
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delaySubmit"],
self.timeSince(args[0], "add")))
else:
self.addNewCalc(args[0], calcWord, calcDefinition, prefix)
self.bot.act_PRIVMSG(args[0], "Thanks for the info, %s." % sender.nick)
@ -115,48 +117,57 @@ class Calc(ModuleBase):
elif len(calcCmd) > 0:
" Lookup the word in calcCmd "
if self.config["delayCalcSpecific"]>0 and self.timeSince(args[0], "calcspec") < self.config["delayCalcSpecific"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalcSpecific"], self.timeSince(args[0], "calcspec")))
if self.config["delayCalcSpecific"] > 0 and \
self.timeSince(args[0], "calcspec") < self.config["delayCalcSpecific"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalcSpecific"],
self.timeSince(args[0], "calcspec")))
else:
randCalc = self.getSpecificCalc(args[0], calcCmd)
if randCalc==None:
if randCalc is None:
self.bot.act_PRIVMSG(args[0], "Sorry %s, I don't know what '%s' is." % (sender.nick, calcCmd))
else:
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" % (randCalc["word"], randCalc["definition"], randCalc["by"]))
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" %
(randCalc["word"], randCalc["definition"], randCalc["by"]))
self.updateTimeSince(args[0], "calcspec")
else:
if self.config["delayCalc"] > 0 and self.timeSince(args[0], "calc") < self.config["delayCalc"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalc"], self.timeSince(args[0], "calc")))
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalc"],
self.timeSince(args[0], "calc")))
else:
randCalc = self.getRandomCalc(args[0])
if randCalc == None:
if randCalc is None:
self.bot.act_PRIVMSG(args[0], "This channel has no calcs, %s :(" % (sender.nick,))
else:
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" % (randCalc["word"], randCalc["definition"], randCalc["by"]))
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" % (randCalc["word"],
randCalc["definition"], randCalc["by"]))
self.updateTimeSince(args[0], "calc")
return
cmd = self.bot.messageHasCommand(self.config["cmd_match"], trailing, True)
if cmd:
if self.config["delayMatch"] > 0 and self.timeSince(args[0], "match") < self.config["delayMatch"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayMatch"], self.timeSince(args[0], "match")))
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayMatch"],
self.timeSince(args[0], "match")))
else:
term = cmd.args_str
if term.strip()=='':
if not term.strip():
return
c = self.sql.getCursor()
channelId = self.getChannelId(args[0])
c.execute("SELECT * FROM `calc_words` WHERE `word` LIKE ? AND `channel`=? ORDER BY `word` ASC ;", ("%%"+term+"%%", channelId))
c.execute("SELECT * FROM `calc_words` WHERE `word` LIKE ? AND `channel`=? ORDER BY `word` ASC ;",
("%%" + term + "%%", channelId))
rows = c.fetchall()
if len(rows)==0:
if not rows:
self.bot.act_PRIVMSG(args[0], "%s: Sorry, no matches" % sender.nick)
else:
matches = []
for row in rows[0:10]:
if row == None:
if not row:
break
matches.append(row["word"])
self.bot.act_PRIVMSG(args[0], "%s: %s match%s (%s\x03)" % (sender.nick, len(matches), "es" if len(matches)>1 else "", ", \x03".join(matches) ))
self.bot.act_PRIVMSG(args[0], "%s: %s match%s (%s\x03)" %
(sender.nick, len(matches), "es" if len(matches) > 1 else
"", ", \x03".join(matches)))
self.updateTimeSince(args[0], "match")
def addNewCalc(self, channel, word, definition, prefix):
@ -171,7 +182,7 @@ class Calc(ModuleBase):
host = sender.hostname
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
if len(rows)==0:
if not rows:
c.execute("INSERT INTO `calc_addedby` (`username`, `userhost`) VALUES (?, ?) ;", (name, host,))
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
@ -180,50 +191,59 @@ class Calc(ModuleBase):
" Check if the word exists"
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? AND `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_words` (`channel`, `word`, `status`) VALUES (?, ?, ?) ;", (channelId, word, 'approved'))
if not rows:
c.execute("INSERT INTO `calc_words` (`channel`, `word`, `status`) VALUES (?, ?, ?) ;",
(channelId, word, 'approved'))
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? AND `word`=? ;", (channelId, word))
rows = c.fetchall()
wordId = rows[0]["id"]
" Add definition "
c.execute("INSERT INTO `calc_definitions` (`word`, `definition`, `addedby`, `date`, `status`) VALUES (?, ?, ?, ?, ?) ;", (wordId, definition, addedId, datetime.datetime.now(), 'approved',))
c.execute("INSERT INTO `calc_definitions` (`word`, `definition`, `addedby`, `date`, `status`) VALUES "
"(?, ?, ?, ?, ?) ;", (wordId, definition, addedId, datetime.datetime.now(), 'approved',))
c.close()
pass
def getSpecificCalc(self, channel, word):
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE `cdq`.`word`=`cw`.`id` AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as `definitionId` FROM `calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' AND `cw`.`word`=? COLLATE NOCASE ORDER BY RANDOM() LIMIT 1 ;", (channelId, word.lower()))
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE `cdq`.`word`=`cw`.`id` "
"AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as `definitionId` FROM "
"`calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' AND `cw`.`word`=? "
"COLLATE NOCASE ORDER BY RANDOM() LIMIT 1 ;", (channelId, word.lower()))
word = c.fetchone()
if word == None:
if word is None:
return None
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` ON `ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` ON "
"`ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
who = c.fetchone()
if who == None:
if who is None:
return None
c.close()
return {"word": word["word"], "definition": who["definition"], "by": who["username"]}
def getRandomCalc(self, channel):
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
for i in range(0, 5):
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE `cdq`.`word`=`cw`.`id` AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as `definitionId` FROM `calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' ORDER BY RANDOM() LIMIT 1 ;", (channelId,))
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE "
"`cdq`.`word`=`cw`.`id` AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as "
"`definitionId` FROM `calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' "
"ORDER BY RANDOM() LIMIT 1 ;", (channelId,))
word = c.fetchone()
if word == None:
if word is None:
return None
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` ON `ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` "
"ON `ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
who = c.fetchone()
if who == None:
if who is None:
continue
c.close()
@ -235,7 +255,7 @@ class Calc(ModuleBase):
channelId = self.getChannelId(channel)
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? and `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
if not rows:
c.close()
return False
@ -252,7 +272,7 @@ class Calc(ModuleBase):
c = self.sql.getCursor()
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
if len(rows)==0:
if not rows:
c.execute("INSERT INTO `calc_channels` (`channel`) VALUES (?);", (channel,))
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()

View File

@ -6,16 +6,14 @@
"""
from pyircbot.modulebase import ModuleBase, ModuleHook
import os
import time
from threading import Timer
from operator import itemgetter
from random import choice
class CardsAgainstHumanity(ModuleBase):
def __init__(self, bot, moduleName):
# init the base module
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.scramble)]
# Dictionary
@ -30,20 +28,19 @@ class CardsAgainstHumanity(ModuleBase):
# Per channel games
self.games = {}
def scramble(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
if not channel in self.games:
if channel not in self.games:
self.games[channel] = cardsGame(self, channel, self.whites, self.blacks)
self.games[channel].stuff(args, prefix, trailing)
def ondisable(self):
self.log.info("CAH: Unload requested, ending games...")
# for game in self.games:
# self.games[game].gameover()
class cardsGame:
def __init__(self, master, channel, whites, blacks):
self.master = master
@ -63,6 +60,7 @@ class cardsGame:
self.allowPick = 0
self.choices = {}
self.czarTimer = None
def stuff(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
sender = prefix.nick
@ -98,31 +96,38 @@ class cardsGame:
self.removeAndReplenishCards(sender, cardChoices)
self.sendCards(sender)
del self.choices[sender]
if sender in timers:
if sender in self.timers:
self.timers[sender].cancel()
if self.allDrawn():
self.readChoices()
self.master.bot.act_PRIVMSG(self.channel,self.czar+"! Please choose the winner!")
czarTimer = Timer(180,self.kick,(self.czar,"taking too long to pick a choice. The next turn iwll be made."))
self.master.bot.act_PRIVMSG(self.channel,
self.czar + "! Please choose the winner!")
self.czarTimer = Timer(180, self.kick, (self.czar, "taking too long to pick a "
"choice. The next turn iwll be made."))
self.makeTurn()
else:
self.master.bot.act_PRIVMSG(self.channel,sender+", you picked a card that was out of the range. Please don't do that.")
self.master.bot.act_PRIVMSG(self.channel, sender + ", you picked a card that was "
"out of the range. Please don't do that.")
else:
self.master.bot.act_PRIVMSG(self.channel,sender+", you picked "+str(len(cards))+" cards. You were supposed to pick "+str(self.allowPick))
self.master.bot.act_PRIVMSG(self.channel, sender + ", you picked " + str(len(cards)) +
" cards. You were supposed to pick " + str(self.allowPick))
elif self.master.bot.messageHasCommand(".choose", trailing):
if sender == self.czar:
choice = trailing.split()[1:]
if len(choice) == 1:
if self.checkChoiceBounds(int(choice[0])):
self.master.bot.act_PRIVMSG(self.channel,list(self.choices.keys())[int(choice[0])]+", you won the round!")
if self.czarTimer!=None:
self.master.bot.act_PRIVMSG(self.channel, list(self.choices.keys())[int(choice[0])] + ", you "
"won the round!")
if self.czarTimer is not None:
self.czarTimer.cancel()
self.makeTurn()
else:
self.master.bot.act_PRIVMSG(self.channel,sender+", your choice was out of the range. Please don't do that.")
self.master.bot.act_PRIVMSG(self.channel, sender + ", your choice was out of the range. Please "
"don't do that.")
else:
self.master.bot.act_PRIVMSG(self.channel,sender+", you picked "+str(len(choice))+" "+" winners. You were only supposed to pick 1.")
self.master.bot.act_PRIVMSG(self.channel, sender + ", you picked " + str(len(choice)) + " winners."
" You were only supposed to pick 1.")
elif self.master.bot.messageHasCommand('.leave', trailing):
if sender in self.players:
self.kick(sender, 'choosing to leave the game you dolt')
@ -133,10 +138,12 @@ class cardsGame:
if not self.started:
if nick not in self.players:
self.players[nick] = False
self.master.bot.act_PRIVMSG(self.channel, nick+" has joined the game! | The players currently are "+str(self.players))
self.master.bot.act_PRIVMSG(self.channel, nick + " has joined the game! | The players currently are " +
str(self.players))
else:
print("the game has already started!")
self.master.bot.act_PRIVMSG(self.channel, "The game has already started!")
def markReady(self, nick):
if not self.started:
if nick in self.players:
@ -152,22 +159,27 @@ class cardsGame:
else:
print("game has already started!")
self.master.bot.act_PRIVMSG(self.channel, "The game has already started!")
def deal(self, nick):
self.players[nick] = [self.pickWhite() for i in range (7)]
def pickWhite(self):
card = choice(self.whites)
self.whites.remove(card)
return card
def pickBlack(self):
card = choice(self.blacks)
self.blacks.remove(card)
return card
def sendCards(self, nick):
cards = ""
for card in self.players[nick]:
cards += str(self.players[nick].index(card)) + ". "
cards += card + " "
self.master.bot.act_PRIVMSG(nick, "Your cards are " + cards)
def readCard(self, card):
count = card.count('_')
if count == 0:
@ -177,6 +189,7 @@ class cardsGame:
count = 1
self.master.bot.act_PRIVMSG(self.channel, "The black card is \"" + card + "\" Pick " + str(count))
return count
def pickCzar(self):
index = self.lastCzar + 1
if index < len(self.players):
@ -185,17 +198,21 @@ class cardsGame:
else:
self.lastCzar = 0
return 0
def announceCzar(self):
self.master.bot.act_PRIVMSG(self.channel, "The Czar is " + self.czar + "!")
def checkBounds(self, cards):
for item in cards:
if int(item) > 6 or int(item) < 0:
return False
return True
def checkChoiceBounds(self, choice):
if choice < 0 or choice > len(self.choices) - 1:
return False
return True
def makeTurn(self):
self.choices.clear()
card = self.pickBlack()
@ -210,12 +227,14 @@ class cardsGame:
self.timers[player] = Timer(180, self.kick, (player, "taking more than 180 seconds for their turn."))
self.timers[player].start()
self.announceCzar()
def kick(self, nick, reason):
del self.players[nick]
if nick in self.timers:
self.timers[nick].cancel()
del self.timers[nick]
self.master.bot.act_PRIVMSG(self.channel, nick + " has been kicked due to " + reason)
if len(self.players) <= 1:
self.master.bot.act_PRIVMSG(self.channel, "The game is being shut down due to having <=1 players")
self.started = False
@ -224,21 +243,23 @@ class cardsGame:
timer.cancel()
self.timers.clear()
self.players.clear()
def removeAndReplenishCards(self, nick, cards):
for card in cards:
self.players[nick].remove(card)
self.players[nick].append(self.pickWhite())
def readChoices(self):
if '_' in self.currentBlack:
for player in list(self.choices.keys()):
cardInstance = str(list(self.choices.keys()).index(player)) + ". " + self.currentBlack
cardInstance = list(cardInstance) # do this as opposed to space to preserve spaces
for choice in self.choices[player]:
for plr_choice in self.choices[player]:
for char in cardInstance:
if char == '_':
print(char)
choice = choice.replace('.','')
cardInstance[cardInstance.index(char)] = choice
plr_choice = plr_choice.replace('.', '')
cardInstance[cardInstance.index(char)] = plr_choice
break
self.master.bot.act_PRIVMSG(self.channel, ''.join(cardInstance))
else:

View File

@ -11,9 +11,10 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import time
import hashlib
class CryptoWallet(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.handle_message)]
def getMods(self):
@ -31,7 +32,8 @@ class CryptoWallet(ModuleBase):
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(args[0], ".setaddr: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], supportedStr))
self.bot.act_PRIVMSG(args[0], ".setaddr: '%s' is not a supported currency. Supported currencies are: %s" %
(cmd.args[0], supportedStr))
return
if len(cmd.args[1]) < 16 or len(cmd.args[1]) > 42:
self.bot.act_PRIVMSG(args[0], ".setaddr: '%s' appears to be an invalid address." % (cmd.args[1]))
@ -42,7 +44,8 @@ class CryptoWallet(ModuleBase):
# Set their address
attr.setKey(prefix.nick, "cryptowallet-%s-address" % cmd.args[0].lower(), cmd.args[1])
self.bot.act_PRIVMSG(args[0], ".setaddr: Your address has been saved as: %s. Please verify that this is correct or your coins could be lost." % (cmd.args[1]))
self.bot.act_PRIVMSG(args[0], ".setaddr: Your address has been saved as: %s. Please verify that this is correct"
" or your coins could be lost." % (cmd.args[1]))
def handle_getbal(self, args, prefix, trailing, cmd):
usage = ".getbal <currency>"
@ -55,7 +58,8 @@ class CryptoWallet(ModuleBase):
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], supportedStr))
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
(cmd.args[0], supportedStr))
return
# Just make sure they have a wallet
@ -80,7 +84,8 @@ class CryptoWallet(ModuleBase):
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], supportedStr))
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
(cmd.args[0], supportedStr))
return
# Just make sure they have a wallet
@ -88,8 +93,9 @@ class CryptoWallet(ModuleBase):
# check that they have a withdraw addr
withdrawaddr = attr.getKey(prefix.nick, "cryptowallet-%s-address" % cmd.args[0].lower())
if withdrawaddr == None:
self.bot.act_PRIVMSG(args[0], ".withdraw: You need to set a withdraw address before withdrawing. Try .setaddr")
if withdrawaddr is None:
self.bot.act_PRIVMSG(args[0], ".withdraw: You need to set a withdraw address before withdrawing. "
"Try .setaddr")
return
# fetch RPC and check balance
@ -101,26 +107,33 @@ class CryptoWallet(ModuleBase):
withdrawamount = float(cmd.args[1])
if balance < withdrawamount or withdrawamount < 0:
self.bot.act_PRIVMSG(args[0], ".withdraw: You don't have enough %s to withdraw %s" % (cmd.args[0].upper(), withdrawamount))
self.bot.act_PRIVMSG(args[0], ".withdraw: You don't have enough %s to withdraw %s" %
(cmd.args[0].upper(), withdrawamount))
return
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
self.bot.act_PRIVMSG(args[0], ".withdraw: Withdrawing that much would put you below the reserve (%s %s)." % (client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(args[0], ".withdraw: The reserve is to cover network transaction fees. To recover it you must close your account. (Talk to an admin)")
self.bot.act_PRIVMSG(args[0], ".withdraw: Withdrawing that much would put you below the reserve (%s %s)." %
(client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(args[0], ".withdraw: The reserve is to cover network transaction fees. To recover it "
"you must close your account. (Talk to an admin)")
return
# Check if the precision is wrong
if not client.checkPrecision(withdrawamount):
self.bot.act_PRIVMSG(args[0], ".withdraw: %s has maximum %s decimal places" % (cmd.args[0].upper(), client.precision))
self.bot.act_PRIVMSG(args[0], ".withdraw: %s has maximum %s decimal places" % (cmd.args[0].upper(),
client.precision))
return
# Create a transaction
txn = client.send(walletname, withdrawaddr, withdrawamount)
if txn:
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: %s %s sent to %s. "% (prefix.nick, withdrawamount, client.name, withdrawaddr))
self.bot.act_PRIVMSG(prefix.nick, "Withdrawal: (You)->%s: Transaction ID: %s" % (prefix.nick, withdrawaddr, txn))
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: %s %s sent to %s. " %
(prefix.nick, withdrawamount, client.name, withdrawaddr))
self.bot.act_PRIVMSG(prefix.nick, "Withdrawal: (You)->%s: Transaction ID: %s" %
(prefix.nick, withdrawaddr, txn))
else:
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: Transaction create failed. Maybe the transaction was too large for the network? Try a smaller increment." % prefix.nick)
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: Transaction create failed. Maybe the transaction was too "
"large for the network? Try a smaller increment." % prefix.nick)
def handle_send(self, args, prefix, trailing, cmd):
usage = ".send <currency> <amount> <nick or address>"
@ -133,7 +146,8 @@ class CryptoWallet(ModuleBase):
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], supportedStr))
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
(cmd.args[0], supportedStr))
return
# Just make sure they have a wallet
@ -148,35 +162,42 @@ class CryptoWallet(ModuleBase):
withdrawamount = float(cmd.args[1])
if balance < withdrawamount or withdrawamount < 0:
self.bot.act_PRIVMSG(args[0], "%s: .send: You don't have enough %s to send %s" % (prefix.nick, cmd.args[0].upper(), withdrawamount))
self.bot.act_PRIVMSG(args[0], "%s: .send: You don't have enough %s to send %s" %
(prefix.nick, cmd.args[0].upper(), withdrawamount))
return
# Check if the precision is wrong
if not client.checkPrecision(withdrawamount):
self.bot.act_PRIVMSG(args[0], ".send: %s has maximum %s decimal places" % (cmd.args[0].upper(), client.precision))
self.bot.act_PRIVMSG(args[0], ".send: %s has maximum %s decimal places" %
(cmd.args[0].upper(), client.precision))
return
# Check if the recierver is a dogecoin address
if len(cmd.args[2]) == 34 and cmd.args[2][0:1] == "D":
# Check if we can cover network fees
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
self.bot.act_PRIVMSG(args[0], ".send: Sending that much would put you below the reserve (%s %s)." % (client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(args[0], ".send: The reserve is to cover network transaction fees. To recover it you must close your account. (Talk to an admin)")
self.bot.act_PRIVMSG(args[0], ".send: Sending that much would put you below the reserve (%s %s)." %
(client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(args[0], ".send: The reserve is to cover network transaction fees. To recover it "
"you must close your account. (Talk to an admin)")
return
# Create a transaction
txn = client.send(walletname, cmd.args[2], withdrawamount)
if txn:
self.bot.act_PRIVMSG(args[0], "%s: .send: %s %s sent to %s. "% (prefix.nick, withdrawamount, client.name, cmd.args[2]))
self.bot.act_PRIVMSG(args[0], "%s: .send: %s %s sent to %s. " %
(prefix.nick, withdrawamount, client.name, cmd.args[2]))
self.bot.act_PRIVMSG(prefix.nick, "Send: (You)->%s: Transaction ID: %s" % (cmd.args[2], txn))
else:
self.bot.act_PRIVMSG(args[0], "%s: .send: Transaction create failed. Maybe the address is invalid or transaction too large for the network? Try a smaller increment."%prefix.nick)
self.bot.act_PRIVMSG(args[0], "%s: .send: Transaction create failed. Maybe the address is invalid or "
"transaction too large for the network? Try a smaller increment." %
prefix.nick)
else:
# Move between local wallets
# Check if dest user has a password set
destUserPassword = attr.getKey(cmd.args[2], "password")
if destUserPassword == None:
if destUserPassword is None:
self.bot.act_PRIVMSG(args[0], "%s .send: %s doesn't have a password set." % (prefix.nick, cmd.args[2]))
return
@ -197,7 +218,8 @@ class CryptoWallet(ModuleBase):
print(destWalletName)
if client.canMove(srcWalletName, destWalletName, withdrawamount):
if client.move(srcWalletName, destWalletName, withdrawamount):
self.bot.act_PRIVMSG(args[0], "%s .send: %s %s sent to %s. "% (prefix.nick, withdrawamount, client.name, cmd.args[2]))
self.bot.act_PRIVMSG(args[0], "%s .send: %s %s sent to %s. " %
(prefix.nick, withdrawamount, client.name, cmd.args[2]))
else:
self.bot.act_PRIVMSG(args[0], "%s: uh-oh, something went wrong doing that." % prefix.nick)
@ -212,44 +234,48 @@ class CryptoWallet(ModuleBase):
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(args[0], ".getaddr: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], supportedStr))
self.bot.act_PRIVMSG(args[0], ".getaddr: '%s' is not a supported currency. Supported currencies are: %s" %
(cmd.args[0], supportedStr))
return
# Just make sure they have a wallet
self.checkUserHasWallet(prefix.nick, cmd.args[0])
walletaddr = attr.getKey(prefix.nick, "cryptowallet-depoaddr-%s" % cmd.args[0].lower())
self.bot.act_PRIVMSG(args[0], "%s: your %s deposit address is: %s" % (prefix.nick, cmd.args[0].upper(), walletaddr))
self.bot.act_PRIVMSG(args[0], "%s: your %s deposit address is: %s" %
(prefix.nick, cmd.args[0].upper(), walletaddr))
def handle_curinfo(self, args, prefix, trailing, cmd):
attr, rpc = self.getMods()
usage = ".curinfo [<currency>]"
# Check for args
if len(cmd.args) == 0:
self.bot.act_PRIVMSG(args[0], ".curinfo: supported currencies: %s. Use '.curinfo BTC' to see details. " % ', '.join([x.upper() for x in rpc.getSupported()]))
self.bot.act_PRIVMSG(args[0], ".curinfo: supported currencies: %s. Use '.curinfo BTC' to see details. " %
', '.join([x.upper() for x in rpc.getSupported()]))
return
else:
if not rpc.isSupported(cmd.args[0]):
self.bot.act_PRIVMSG(args[0], ".curinfo: '%s' is not a supported currency. Supported currencies are: %s" % (cmd.args[0], ', '.join([x.upper() for x in rpc.getSupported()])))
self.bot.act_PRIVMSG(args[0], ".curinfo: '%s' is not a supported currency. Supported currencies are: "
"%s" % (cmd.args[0], ', '.join([x.upper() for x in rpc.getSupported()])))
return
else:
info = rpc.getInfo(cmd.args[0])
self.bot.act_PRIVMSG(args[0], ".curinfo: %s - %s. More info: %s" % (args[0], info["name"], info["link"]))
self.bot.act_PRIVMSG(args[0], ".curinfo: %s - %s. More info: %s" %
(args[0], info["name"], info["link"]))
def checkUserHasWallet(self, username, currency):
# Ensure the user has a wallet in the client
attr, rpc = self.getMods()
currency = currency.lower()
username = username.lower()
if attr.getKey(username, "cryptowallet-account-%s"%currency)==None:
if attr.getKey(username, "cryptowallet-account-%s" % currency) is None:
randName = self.md5(str(time.time()))[0:16]
attr.setKey(username, "cryptowallet-account-%s" % currency, randName)
# Generate a deposit addr to nudge the wallet
wallet = rpc.getRpc(currency.lower())
address = wallet.getAcctAddr(randName)
attr.setKey(username, "cryptowallet-depoaddr-%s" % currency, address)
elif attr.getKey(username, "cryptowallet-depoaddr-%s"%currency)==None:
elif attr.getKey(username, "cryptowallet-depoaddr-%s" % currency) is None:
walletName = attr.getKey(username, "cryptowallet-account-%s" % currency)
wallet = rpc.getRpc(currency.lower())
address = wallet.getAcctAddr(walletName)

View File

@ -7,30 +7,29 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase
from bitcoinrpc.authproxy import AuthServiceProxy
from math import floor
from threading import Thread
from time import sleep
class CryptoWalletRPC(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["bitcoinrpc"]
self.loadConfig()
self.rpcservices = {}
self.loadrpcservices()
def loadrpcservices(self):
# Create a dict of abbreviation=>BitcoinRPC objcet relation
self.log.info("CryptoWalletRPC: loadrpcservices: connecting to RPCs")
count = len(list(self.config["types"].keys()))
num = 0
for key in self.config["types"]:
self.rpcservices[key.lower()]=BitcoinRPC(self, key, self.config["types"][key]["host"], self.config["types"][key]["port"], self.config["types"][key]["username"], self.config["types"][key]["password"], self.config["types"][key]["precision"], self.config["types"][key]["reserve"])
num+=1
self.rpcservices[key.lower()] = BitcoinRPC(self, key, self.config["types"][key]["host"],
self.config["types"][key]["port"],
self.config["types"][key]["username"],
self.config["types"][key]["password"],
self.config["types"][key]["precision"],
self.config["types"][key]["reserve"])
def getRpc(self, currencyAbbr):
# Return the rpc for the currency requested
@ -125,9 +124,8 @@ class BitcoinRPC:
try:
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.username, self.password, self.host, self.port))
except Exception as e:
self.log.info("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" % (self.name, self.host, self.port, str(e)))
self.log.error("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" %
(self.name, self.host, self.port, str(e)))
return
self.log.info("CryptoWalletRPC: %s: Connected to %s:%s" % (self.name, self.host, self.port))

View File

@ -7,19 +7,16 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase ModuleHook
import random
import os
import time
import math
import hashlib
from threading import Timer
class DogeDice(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks = [ModuleHook("PRIVMSG", self.gotMsg)]
self.loadConfig()
# Load attribute storage
self.attr = self.bot.getBestModuleForService("attributes")
# Load doge RPC
@ -31,13 +28,14 @@ class DogeDice(ModuleBase):
prefixObj = self.bot.decodePrefix(prefix)
# Ignore messages from users not logged in
loggedinfrom = self.attr.getKey(prefixObj.nick, "loggedinfrom")
if loggedinfrom==None:
if loggedinfrom is None:
# Send them a hint?
return
elif prefixObj.hostname == loggedinfrom:
if args[0][0] == "#":
# create a blank game obj if there isn't one (and whitelisted ? )
if not args[0] in self.games and (not self.config["channelWhitelistOn"] or (self.config["channelWhitelistOn"] and args[0][1:] in self.config["channelWhitelist"]) ):
if not args[0] in self.games and (not self.config["channelWhitelistOn"] or
(self.config["channelWhitelistOn"] and args[0][1:] in self.config["channelWhitelist"])):
self.games[args[0]] = gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
@ -58,6 +56,7 @@ class DogeDice(ModuleBase):
first = list(self.games.keys())[0]
self.games[first].gameover()
class gameObj:
def __init__(self, master, channel):
self.master = master
@ -110,15 +109,15 @@ class gameObj:
cmd = self.master.bot.messageHasCommand(".join", trailing)
if cmd:
if len(self.players) - 1 < self.maxPlayers:
if self.getPlayer(prefix.nick)==None:
if self.getPlayer(prefix.nick) is None:
userWallet = self.master.attr.getKey(prefix.nick, "dogeaccountname")
if userWallet == None:
if userWallet is None:
self.master.bot.act_PRIVMSG(self.channel, "%s: You don't have enough DOGE!" % (prefix.nick))
return
balance = self.master.doge.getBal(userWallet)
# check if the room is 'opened' already:
if len(self.players)==0:
if not self.players:
# require an amount
if len(cmd.args) == 1:
# Check if they have enough coins
@ -128,7 +127,8 @@ class gameObj:
return
if bet < self.master.config["minBet"]:
self.master.bot.act_PRIVMSG(self.channel, "%s: Minimum bet is %s DOGE!" % (prefix.nick, self.master.config["minBet"]))
self.master.bot.act_PRIVMSG(self.channel, "%s: Minimum bet is %s DOGE!" %
(prefix.nick, self.master.config["minBet"]))
return
if balance >= bet:
@ -138,9 +138,11 @@ class gameObj:
self.bet = bet
self.master.bot.act_PRIVMSG(self.channel, "%s: You have joined!" % (prefix.nick))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: You don't have enough DOGE!" % (prefix.nick))
self.master.bot.act_PRIVMSG(self.channel, "%s: You don't have enough DOGE!" %
(prefix.nick))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: You need to specify a bet amount: .join 10" % (prefix.nick))
self.master.bot.act_PRIVMSG(self.channel, "%s: You need to specify a bet amount: "
".join 10" % (prefix.nick))
else:
# no amount required
if balance >= self.bet:
@ -148,20 +150,25 @@ class gameObj:
newPlayer.dogeWalletName = userWallet
self.players.append(newPlayer)
self.master.bot.act_PRIVMSG(self.channel, "%s: You have joined!" % (prefix.nick))
if self.canStart() and self.startCountdownTimer == None:
if self.canStart() and self.startCountdownTimer is None:
self.initStartCountdown()
self.master.bot.act_PRIVMSG(self.channel, "The game will start in %s seconds! Bet is %s DOGE each!" % (self.master.config["lobbyIdleSeconds"], self.bet))
self.master.bot.act_PRIVMSG(self.channel, "The game will start in %s seconds! "
"Bet is %s DOGE each!" %
(self.master.config["lobbyIdleSeconds"], self.bet))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: You don't have enough DOGE!" % (prefix.nick))
self.master.bot.act_PRIVMSG(self.channel, "%s: You don't have enough DOGE!" %
(prefix.nick))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: you're already in the game. Quit with .leave" % (prefix.nick))
self.master.bot.act_PRIVMSG(self.channel, "%s: you're already in the game. Quit with .leave" %
(prefix.nick))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: the game is full (%s/%)! Cannot join." % (prefix.nick, len(self.players), self.maxPlayers))
self.master.bot.act_PRIVMSG(self.channel, "%s: the game is full (%s/%)! Cannot join." %
(prefix.nick, len(self.players), self.maxPlayers))
# Leave game
cmd = self.master.bot.messageHasCommand(".leave", trailing)
if cmd:
if self.getPlayer(prefix.nick)==None:
if self.getPlayer(prefix.nick) is None:
self.master.bot.act_PRIVMSG(self.channel, "%s: You're not in the game." % (prefix.nick))
else:
self.removePlayer(prefix.nick)
@ -169,7 +176,7 @@ class gameObj:
if not self.canStart() and self.startCountdownTimer:
self.clearTimer(self.startCountdownTimer)
self.startCountdownTimer = None
self.master.bot.act_PRIVMSG(self.channel, "Game start aborted." )
self.master.bot.act_PRIVMSG(self.channel, "Game canceled.")
self.step = 0
elif self.step == 2:
pass
@ -201,7 +208,6 @@ class gameObj:
elif self.step == 4:
pass
#senderIsOp = self.master.attr.getKey(prefix.nick, "op")=="yes"
def clearTimer(self, timer):
if timer:
timer.cancel()
@ -219,6 +225,7 @@ class gameObj:
def canStart(self):
# Return true if the step is 'lobby' mode and player count is OK
return self.step == 0 and len(self.players) >= self.minPlayers
def initStartCountdown(self):
# Start the game-start countdown
self.startCountdownTimer = Timer(self.master.config["lobbyIdleSeconds"], self.lobbyCountdownDone)
@ -277,7 +284,7 @@ class gameObj:
maxRollNames.append(player.nick)
maxRollValue = player.rollValue
if player.rollValue == maxRollValue:
if not player.nick in maxRollNames:
if player.nick not in maxRollNames:
maxRollNames.append(player.nick)
pot = self.master.doge.getAcctBal(self.walletName)
@ -285,9 +292,11 @@ class gameObj:
DOGEeach = math.floor(DOGEeachDec * 100000000) / 100000000
if len(maxRollNames) == 1:
self.master.bot.act_PRIVMSG(self.channel, "We have a winner - %s! Winnings are: %s DOGE" % (maxRollNames[0], DOGEeach))
self.master.bot.act_PRIVMSG(self.channel, "We have a winner - %s! Winnings are: %s DOGE" %
(maxRollNames[0], DOGEeach))
else:
self.master.bot.act_PRIVMSG(self.channel, "We have a tie between %s - The take is %s DOGE each" % (' and '.join(maxRollNames), DOGEeach))
self.master.bot.act_PRIVMSG(self.channel, "We have a tie between %s - The take is %s DOGE each" %
(' and '.join(maxRollNames), DOGEeach))
# Pay out
for nick in maxRollNames:

View File

@ -7,15 +7,15 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase
from bitcoinrpc.authproxy import AuthServiceProxy
class DogeRPC(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["dogerpc"]
self.loadConfig()
self.rpc = DogeController(self)
def getBal(self, acct):
@ -54,6 +54,7 @@ class DogeRPC(ModuleBase):
return self.rpc.con.sendfrom(fromAcct, toAddr, amount)
return False
class DogeController:
"RPC instance control class"
def __init__(self, master):
@ -74,6 +75,7 @@ class DogeController:
def connect(self):
"Connect to RPC endpoint"
self.log.info("DogeRPC: Connecting to dogecoind")
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.config["username"], self.config["password"], self.config["host"], self.config["port"]))
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.config["username"], self.config["password"],
self.config["host"], self.config["port"]))
self.con.getinfo()
self.log.info("DogeRPC: Connected to %s:%s" % (self.config["host"], self.config["port"]))

View File

@ -10,15 +10,13 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
import random
import os
import time
from threading import Timer
class DogeScramble(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.scramble)]
self.loadConfig()
# Load attribute storage
self.attr = None
serviceProviders = self.bot.getmodulesbyservice("attributes")
@ -39,16 +37,18 @@ class DogeScramble(ModuleBase):
if channel[0] == "#":
# Ignore messages from users without a dogewallet password
prefixObj = self.bot.decodePrefix(prefix)
if self.attr.getKey(prefixObj.nick, "password")==None:
if self.attr.getKey(prefixObj.nick, "password") is None:
return
if not channel in self.games:
if channel not in self.games:
self.games[channel] = scrambleGame(self, channel)
self.games[channel].scramble(args, prefix, trailing)
def ondisable(self):
self.log.info("DogeScramble: Unload requested, ending games...")
for game in self.games:
self.games[game].gameover()
class scrambleGame:
def __init__(self, master, channel):
self.master = master
@ -68,11 +68,11 @@ class scrambleGame:
# Cooldown between words
self.nextTimer = None
# How many guesses submitted this round
self.guesses = 0;
self.guesses = 0
# How many games in a row where nobody guessed
self.gamesWithoutGuesses = 0;
self.gamesWithoutGuesses = 0
# What file are we using
self.category_file = None;
self.category_file = None
# How many words in this category have been used?
self.category_count = 0
# How long between categories
@ -87,20 +87,23 @@ class scrambleGame:
self.lastwinner = None
self.lastwinvalue = 0
self.delayHint = self.master.config["hintDelay"];
self.delayNext = self.master.config["delayNext"];
self.maxHints = self.master.config["maxHints"];
self.abortAfterNoGuesses = self.master.config["abortAfterNoGuesses"];
self.delayHint = self.master.config["hintDelay"]
self.delayNext = self.master.config["delayNext"]
self.maxHints = self.master.config["maxHints"]
self.abortAfterNoGuesses = self.master.config["abortAfterNoGuesses"]
def gameover(self):
self.clearTimers();
self.clearTimers()
self.running = False
def clearTimers(self):
self.clearTimer(self.nextTimer)
self.clearTimer(self.hintTimer)
def clearTimer(self, timer):
if timer:
timer.cancel()
def scramble(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
sender = prefix.nick
@ -127,7 +130,9 @@ class scrambleGame:
self.master.bot.act_PRIVMSG(self.channel, "%s got the word - %s!" % (sender, self.currentWord))
if not useraddr:
self.master.bot.act_PRIVMSG(self.channel, "%s: to win DOGE, you must set an wallet address by PMing me \".setdogeaddr\". Next word in %s seconds." % (prefix.nick, self.delayNext))
self.master.bot.act_PRIVMSG(self.channel, "%s: to win DOGE, you must set an wallet address by PMing me "
"\".setdogeaddr\". Next word in %s seconds." %
(prefix.nick, self.delayNext))
else:
winamount = float(self.master.config["winAmount"])
if self.lastwinner == prefix.nick:
@ -135,7 +140,8 @@ class scrambleGame:
self.lastwinvalue = winamount
self.lastwinner = prefix.nick
self.master.bot.act_PRIVMSG(self.channel, "%s won %s DOGE! Next word in %s seconds." % (prefix.nick, round(winamount, 8), self.delayNext))
self.master.bot.act_PRIVMSG(self.channel, "%s won %s DOGE! Next word in %s seconds." %
(prefix.nick, round(winamount, 8), self.delayNext))
self.master.doge.move('', userwallet, winamount)
self.currentWord = None
@ -159,7 +165,8 @@ class scrambleGame:
def startNewWord(self):
self.currentWord = self.pickWord()
self.scrambled = self.scrambleWord(self.currentWord)
self.master.bot.act_PRIVMSG(self.channel, "[Category: %s] Unscramble this: %s " % (self.category_name, self.scrambled))
self.master.bot.act_PRIVMSG(self.channel, "[Category: %s] Unscramble this: %s " %
(self.category_name, self.scrambled))
self.clearTimer(self.hintTimer)
self.hintTimer = Timer(self.delayHint, self.giveHint)
@ -191,7 +198,8 @@ class scrambleGame:
def abortWord(self):
cur = self.currentWord
self.currentWord = None
self.master.bot.act_PRIVMSG(self.channel, "Word expired - the answer was '%s'. Next word in %s seconds." % (cur, self.delayNext))
self.master.bot.act_PRIVMSG(self.channel, "Word expired - the answer was '%s'. Next word in %s seconds." %
(cur, self.delayNext))
self.hintsGiven = 0
self.clearTimer(self.nextTimer)
@ -246,7 +254,6 @@ class scrambleGame:
skip -= 1
picked = f.readline().strip().lower()
f.close()
self.master.log.info("DogeScramble: picked %s for %s" % (picked, self.channel))
self.lastwords.append(picked)
if len(self.lastwords) > 5:

View File

@ -11,9 +11,10 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import time
import hashlib
class DogeWallet(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.gotmsg)]
# Load attribute storage
self.attr = self.bot.getBestModuleForService("attributes")
@ -33,45 +34,50 @@ class DogeWallet(ModuleBase):
cmd = self.bot.messageHasCommand(".setpass", trailing)
if cmd:
if len(cmd.args) == 0:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: usage: \".setpass newpass\" or \".setpass oldpass newpass\"")
self.bot.act_PRIVMSG(prefix.nick, ".setpass: usage: \".setpass newpass\" or "
"\".setpass oldpass newpass\"")
else:
oldpass = self.attr.getKey(prefix.nick, "password")
if oldpass == None:
if oldpass is None:
self.attr.setKey(prefix.nick, "password", cmd.args[0])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." % cmd.args[0])
else:
if len(cmd.args) == 2:
if cmd.args[0] == oldpass:
self.attr.setKey(prefix.nick, "password", cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." % cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." %
cmd.args[1])
else:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Old password incorrect.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: You must provide the old password when setting a new one.")
self.bot.act_PRIVMSG(prefix.nick, ".setpass: You must provide the old password when setting a "
"new one.")
cmd = self.bot.messageHasCommand(".setdogeaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: You must first set a password with .setpass")
else:
if len(cmd.args) == 2:
if userpw == cmd.args[0]:
self.attr.setKey(prefix.nick, "dogeaddr", cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: Your doge address has been set to \"%s\"." % cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: Your doge address has been set to \"%s\"." %
cmd.args[1])
# if they don't have a wallet name, we'll make one now
if self.attr.getKey(prefix.nick, "dogeaccountname")==None:
if self.attr.getKey(prefix.nick, "dogeaccountname") is None:
randName = self.md5(str(time.time()))[0:10]
self.attr.setKey(prefix.nick, "dogeaccountname", randName)
else:
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: usage: \".setdogeaddr password address\" or \".setdogeaddr mypassword D8VNy3zkMGspffcFSWWqsxx7GrtVsmF2up\"")
self.bot.act_PRIVMSG(prefix.nick, ".setdogeaddr: usage: \".setdogeaddr password address\" or "
"\".setdogeaddr mypassword D8VNy3zkMGspffcFSWWqsxx7GrtVsmF2up\"")
cmd = self.bot.messageHasCommand(".getdogebal", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: You must first set a password with .setpass")
else:
if len(cmd.args) == 1:
@ -94,9 +100,9 @@ class DogeWallet(ModuleBase):
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
useraddr = self.attr.getKey(prefix.nick, "dogeaddr")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a password with .setpass")
elif useraddr==None:
elif useraddr is None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a withdraw address .setdogeaddr")
else:
if len(cmd.args) == 2:
@ -110,21 +116,25 @@ class DogeWallet(ModuleBase):
if walletbal >= desiredAmount:
txn = self.doge.send(walletname, useraddr, desiredAmount)
if txn:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: %s DOGE sent to %s. Transaction ID: %s"% (desiredAmount, useraddr, txn))
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: %s DOGE sent to %s. Transaction ID: "
"%s" % (desiredAmount, useraddr, txn))
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: Unable to create transaction. Please contact an Operator.")
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: Unable to create transaction. "
"Please contact an Operator.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You only have %s DOGE. You cannot withdraw %s DOGE." % (walletbal, desiredAmount))
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You only have %s DOGE. You cannot "
"withdraw %s DOGE." % (walletbal, desiredAmount))
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: usage: \".withdrawdoge password amount\" - \".withdrawdoge mypassword 5.0\" - ")
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: usage: \".withdrawdoge password amount\" - "
"\".withdrawdoge mypassword 5.0\" - ")
cmd = self.bot.messageHasCommand(".getdepositaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: You must first set a password with .setpass")
else:
if len(cmd.args) == 1:
@ -139,12 +149,10 @@ class DogeWallet(ModuleBase):
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: usage: \".getdepositaddr password\"")
cmd = self.bot.messageHasCommand(".login", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args) == 1:
@ -160,7 +168,7 @@ class DogeWallet(ModuleBase):
cmd = self.bot.messageHasCommand(".logout", trailing)
if cmd:
loggedin = self.attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
if loggedin is None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
self.attr.setKey(prefix.nick, "loggedinfrom", None)

View File

@ -14,11 +14,11 @@ import random
from threading import Timer
import os
class DuckHunt(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.hunt)]
self.loadConfig()
self.jsonPath = self.getFilePath("scores.json")
@ -36,7 +36,7 @@ class DuckHunt(ModuleBase):
cmd = self.bot.messageHasCommand("!huntscore", trailing, False)
if cmd:
scores = self.loadScores()
if not fromWho in scores:
if fromWho not in scores:
self.bot.act_PRIVMSG(fromWho, "You have no points :(")
else:
scores = scores[fromWho]
@ -57,8 +57,10 @@ class DuckHunt(ModuleBase):
shots += kill["misses"]
misses += kill["misses"]
self.bot.act_PRIVMSG(fromWho, "You've shot %s %s for a total weight of %s lbs." % (kills, self.config["animalSpeciesPlural"], weight))
self.bot.act_PRIVMSG(fromWho, "%s prime catches, %s runts, %s bullets used and %s misses." % (prime, runts, shots, misses))
self.bot.act_PRIVMSG(fromWho, "You've shot %s %s for a total weight of %s lbs." %
(kills, self.config["animalSpeciesPlural"], weight))
self.bot.act_PRIVMSG(fromWho, "%s prime catches, %s runts, %s bullets used and %s misses." %
(prime, runts, shots, misses))
# self.bot.act_PRIVMSG(fromWho, "More info & highscores: http://duckhunt.xmopx.net/")
self.log.info("DuckHunt: %s used !huntscore" % fromWho)
return
@ -71,13 +73,14 @@ class DuckHunt(ModuleBase):
if cmd:
if self.isDuckOut:
if not fromWho in self.misses:
if fromWho not in self.misses:
self.misses[fromWho] = 0
shotIn = round(time.time() - self.outStart, 2)
if random.randint(0, 100) <= self.config["missChance"]:
self.bot.act_PRIVMSG(self.config["activeChannel"], "%s fires after %s seconds and misses!" % (fromWho, shotIn))
self.bot.act_PRIVMSG(self.config["activeChannel"], "%s fires after %s seconds and misses!" %
(fromWho, shotIn))
self.misses[fromWho] += 1
return
@ -121,8 +124,7 @@ class DuckHunt(ModuleBase):
self.misses = {}
self.startHunt();
self.startHunt()
def startHunt(self):
" Creates a timer that waits a certain amount of time then sends out a bird \\_o< quack"
@ -137,7 +139,7 @@ class DuckHunt(ModuleBase):
self.outStart = time.time()
def getRandWeight(self, minW, maxW):
weight = maxW-minW;
weight = maxW - minW
weight = float(weight) * random.random()
return round(weight + minW, 2)
@ -149,9 +151,9 @@ class DuckHunt(ModuleBase):
def addKillFor(self, playername, kill):
scores = self.loadScores()
if scores==None:
if scores is None:
scores = {}
if not playername in scores:
if playername not in scores:
scores[playername] = []
scores[playername].append(kill)
self.saveScores(scores)

View File

@ -1,3 +1,4 @@
"""
.. module:: Error
:synopsis: Module to deliberately cause an error for testing handling.
@ -6,9 +7,9 @@
"""
#!/usr/bin/env python
from pyircbot.modulebase import ModuleBase, ModuleHook
class Error(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)

View File

@ -8,16 +8,12 @@
"""
from pyircbot.modulebase import ModuleBase, ModuleHook
import random
import os
import time
from threading import Timer
class GameBase(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.gotMsg)]
self.loadConfig()
# Load attribute storage
self.attr = self.bot.getBestModuleForService("attributes")
# Load doge RPC
@ -28,13 +24,14 @@ class GameBase(ModuleBase):
def gotMsg(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
# Ignore messages from users not logged in
if self.attr.getKey(prefixObj.nick, "loggedinfrom")==None:
# Send them a hint?
if not self.attr.getKey(prefixObj.nick, "loggedinfrom"):
# TODO Send them a hint?
return
else:
if args[0][0] == "#":
# create a blank game obj if there isn't one (and whitelisted ? )
if not args[0] in self.games and (not self.config["channelWhitelistOn"] or (self.config["channelWhitelistOn"] and args[0][1:] in self.config["channelWhitelist"]) ):
if not args[0] in self.games and (not self.config["channelWhitelistOn"] or
(self.config["channelWhitelistOn"] and args[0][1:] in self.config["channelWhitelist"])):
self.games[args[0]] = gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
@ -48,6 +45,7 @@ class GameBase(ModuleBase):
for game in self.games:
self.games[game].gameover()
class gameObj:
def __init__(self, master, channel):
self.master = master
@ -65,8 +63,8 @@ class gameObj:
def gameover(self):
pass
class playerObj:
def __init__(self, game, nick):
self.game = game
self.nick = nick

View File

@ -10,13 +10,14 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
from datetime import datetime
class Inventory(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
if not serviceProviders:
self.log.error("Inventory: Could not find a valid sqlite service provider")
else:
self.log.info("Inventory: Selecting sqlite service provider: %s" % serviceProviders[0])
@ -49,14 +50,14 @@ class Inventory(ModuleBase):
newItem = cmd.args_str
if self.has_item(newItem):
self.bot.act_PRIVMSG(args[0], self.config["dupe_msg"] %
{"item":newItem,})
self.bot.act_PRIVMSG(args[0], self.config["dupe_msg"] % {"item": newItem})
return
dropped = self.add_item(prefixObj.nick, newItem)
if len(dropped) > 0:
self.bot.act_PRIVMSG(args[0], self.config["swap_msg"] %
{"adjective":(adjective+" ") if adjective else "", "recv_item":newItem, "drop_item":", ".join(dropped)})
{"adjective": (adjective + " ") if adjective else "",
"recv_item": newItem, "drop_item": ", ".join(dropped)})
else:
self.bot.act_PRIVMSG(args[0], self.config["recv_msg"] %
{"item": newItem, "adjective": "these " if newItem[-1:] == "s" else "this "})
@ -69,9 +70,8 @@ class Inventory(ModuleBase):
else:
self.bot.act_PRIVMSG(args[0], self.config["inv_msg"] % {"itemlist": ", ".join(inv)})
def has_item(self, itemName):
c = self.db.query("SELECT COUNT(*) as `num` FROM `inventory` WHERE `item`=? COLLATE NOCASE", (itemName,)) #
c = self.db.query("SELECT COUNT(*) as `num` FROM `inventory` WHERE `item`=? COLLATE NOCASE", (itemName,))
row = c.fetchone()
c.close()
return row["num"] > 0
@ -81,7 +81,7 @@ class Inventory(ModuleBase):
c = self.db.query("SELECT * FROM `inventory` ORDER BY RANDOM() LIMIT %s,1000000" % self.config["limit"])
while True:
row = c.fetchone()
if row == None:
if row is None:
break
dropped.append(row["item"])
self.db.query("DELETE FROM `inventory` WHERE `id`=?", (row["id"],)).close()
@ -96,7 +96,7 @@ class Inventory(ModuleBase):
c = self.db.query("SELECT * FROM `inventory`")
while True:
row = c.fetchone()
if row == None:
if row is None:
break
inv.append(row["item"])
c.close()

View File

@ -11,6 +11,7 @@ from pyircbot.modulebase import ModuleBase, ModuleHook
BASE_URL = "http://lmgtfy.com/?q="
class LMGTFY(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)

View File

@ -13,10 +13,11 @@ import re
import time
import praw # TODO: enable/disable modules
import datetime
from requests import get,head
from requests import head
import html.parser
from threading import Thread
class LinkTitler(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
@ -32,11 +33,12 @@ class LinkTitler(ModuleBase):
sender = self.bot.decodePrefix(prefix)
# Youtube
matches = re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-z0-9]+)', re.I).findall(trailing)
if len(matches)>0:
matches = re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-z0-9]+)', re.I) \
.findall(trailing)
if matches:
done = []
for item in matches:
if not item in done:
if item not in done:
vidinfo = self.get_video_description(item)
if vidinfo:
self.bot.act_PRIVMSG(args[0], vidinfo)
@ -44,9 +46,10 @@ class LinkTitler(ModuleBase):
return
# reddit threads
matches = re.compile(r'(?:reddit\.com/.*?comments/([a-zA-Z0-9]+)/|https?://(www\.)?redd.it/([a-zA-Z0-9]+))').findall(trailing)
matches = re.compile(r'(?:reddit\.com/.*?comments/([a-zA-Z0-9]+)/|https?://(www\.)?redd.it/([a-zA-Z0-9]+))') \
.findall(trailing)
# Either [('', '', '2ibrz7')] or [('2ibrz7', '', '')]
if len(matches)>0:
if matches:
done = []
for match in matches:
submissionId = match[0]
@ -58,9 +61,9 @@ class LinkTitler(ModuleBase):
# TODO configurable user agent
r = praw.Reddit(self.config["agent"])
submission = r.get_submission(submission_id=submissionId)
#for i in range(0,18):
# self.bot.act_PRIVMSG(args[0], "\x031,%sTEST%s\x0f" %(i,i))
msg = "👽 \x02\x031,15REDDIT\x0f\x02 :: %(title)s \x02on \x02%(domain)s%(nsfw)s\x02 - points \x02%(points)s\x02 (%(percent)s↑) - comments \x02%(comments)s\x02 - by \x02%(author)s\x02 on \x02%(date)s\x02" % {
msg = "👽 \x02\x031,15REDDIT\x0f\x02 :: %(title)s \x02on \x02%(domain)s%(nsfw)s\x02 - points " \
"\x02%(points)s\x02 (%(percent)s↑) - comments \x02%(comments)s\x02 - by \x02%(author)s\x02 on " \
"\x02%(date)s\x02" % {
"title": submission.title,
"domain": submission.domain,
"nsfw": "[NSFW]" if submission.over_18 else "",
@ -78,7 +81,7 @@ class LinkTitler(ModuleBase):
# generic <title>
matches = re.compile(r'(https?://([a-zA-Z0-9_\-\.]+/([^ ]+)?))').findall(trailing)
if len(matches)>0:
if matches:
done = []
for match in matches:
if match[0] in done:
@ -88,7 +91,7 @@ class LinkTitler(ModuleBase):
headers = self.url_headers(match[0])
# Don't mess with unknown content types
if not "Content-Type" in headers:
if "Content-Type" not in headers:
continue
if "text/html" in headers["Content-Type"]:
@ -98,7 +101,10 @@ class LinkTitler(ModuleBase):
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02" % (sender.nick, title))
else:
# Unknown types, just print type and size
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02, %s" % (sender.nick, headers["Content-Type"], self.nicesize(int(headers["Content-Length"])) if "Content-Length" in headers else "unknown size"))
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02, %s" %
(sender.nick, headers["Content-Type"],
self.nicesize(int(headers["Content-Length"])) if
"Content-Length" in headers else "unknown size"))
return
@ -110,7 +116,10 @@ class LinkTitler(ModuleBase):
return "<1kb"
def url_headers(self, url):
"HEAD requests a url to check content type & length, returns something like: {'type': 'image/jpeg', 'size': '90583'}"
"""
HEAD requests a url to check content type & length.
Returns something like: {'type': 'image/jpeg', 'size': '90583'}"
"""
self.log.info("url_headers(%s)" % (url,))
resp = head(url=url, allow_redirects=True)
return resp.headers
@ -152,8 +161,10 @@ class LinkTitler(ModuleBase):
')?' # end of time part
) # http://stackoverflow.com/a/16742742
return ISO_8601_period_rx.match(stamp).groupdict()
def get_video_description(self, vid_id):
apidata = get('https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=%s&key=%s' % (vid_id, self.config["youtube_api_key"])).json()
apidata = get('https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=%s'
'&key=%s' % (vid_id, self.config["youtube_api_key"])).json()
if not apidata['pageInfo']['totalResults']:
return
@ -165,11 +176,11 @@ class LinkTitler(ModuleBase):
out = '\x02\x031,0You\x0f\x030,4Tube\x02\x0f :: \x02%s\x02' % snippet["title"]
out += ' - length \x02'
if duration["hours"]!=None:
if duration["hours"] is not None:
out += '%dh ' % int(duration["hours"])
if duration["minutes"]!=None:
if duration["minutes"] is not None:
out += '%dm ' % int(duration["minutes"])
if duration["seconds"]!=None:
if duration["seconds"] is not None:
out += "%ds\x02" % int(duration["seconds"])
totalvotes = float(video["statistics"]["dislikeCount"]) + float(video["statistics"]["likeCount"])

View File

@ -7,7 +7,7 @@
"""
from pyircbot.modulebase import ModuleBase,ModuleHook
from pyircbot.modulebase import ModuleBase
import sys
try:
@ -15,12 +15,12 @@ try:
except:
import pymysql as MySQLdb # python 3.x
class MySQL(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["mysql"]
self.loadConfig()
self.connection = self.getConnection()
def getConnection(self):
@ -39,11 +39,11 @@ class Connection:
c.execute("SHOW TABLES;")
tables = c.fetchall()
if len(tables) == 0:
return False;
return False
key = list(tables[0].keys())[0]
for table in tables:
if table[key] == tablename:
return True;
return True
return False
def query(self, queryText, args=()):
@ -97,7 +97,8 @@ class Connection:
# Connects to the database server, and selects a database (Or attempts to create it if it doesn't exist yet)
def _connect(self):
self.log.info("MySQL: Connecting to db host at %s" % self.config["host"])
self.connection = MySQLdb.connect(host=self.config["host"],user=self.config["username"] ,passwd=self.config["password"])
self.connection = MySQLdb.connect(host=self.config["host"], user=self.config["username"],
passwd=self.config["password"])
self.log.info("MySQL: Connected.")
self.connection.autocommit(True)
c = None

View File

@ -12,9 +12,10 @@ from requests import get
from lxml import etree
from datetime import datetime, timedelta
class NFLLive(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.cache = None
self.cacheAge = 0
@ -22,7 +23,7 @@ class NFLLive(ModuleBase):
def nflitup(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
replyTo = prefix.nick if "#" not in args[0] else args[0]
cmd = self.bot.messageHasCommand(".nfl", trailing)
if cmd:
@ -37,7 +38,7 @@ class NFLLive(ModuleBase):
# sort games
for game in games["games"]:
if not game["time"]==None:
if game["time"] is not None:
liveGames.append(game)
elif game["quarter"] == "P" and game["startdate"].day == datetime.now().day:
gamesLaterToday.append(game)
@ -200,7 +201,9 @@ class NFLLive(ModuleBase):
"gamenum": game.attrib["gsis"],
"starttime": game.attrib["t"],
"startdate":datetime.strptime(game.attrib["eid"][0:-2]+" "+game.attrib["t"], "%Y%m%d %I:%M")+timedelta(hours=12) # NHL provides a 12 hour EST clock with all times PM. Add 12 hours so the datetime obj is PM instead of AM.
"startdate": datetime.strptime(game.attrib["eid"][0:-2] + " " + game.attrib["t"], "%Y%m%d %I:%M") + \
timedelta(hours=12) # NHL provides a 12 hour EST clock with all times PM.
# Add 12 hours so the datetime obj is PM instead of AM.
}
# Add 4 more hours to make it GMT

View File

@ -8,12 +8,12 @@
"""
from pyircbot.modulebase import ModuleBase, ModuleHook
import time
import hashlib
class NickUser(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.gotmsg)]
self.services = ["login"]
@ -41,28 +41,31 @@ class NickUser(ModuleBase):
cmd = self.bot.messageHasCommand(".setpass", trailing)
if cmd:
if len(cmd.args) == 0:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: usage: \".setpass newpass\" or \".setpass oldpass newpass\"")
self.bot.act_PRIVMSG(prefix.nick, ".setpass: usage: \".setpass newpass\" or "
"\".setpass oldpass newpass\"")
else:
attr = self.bot.getBestModuleForService("attributes")
oldpass = attr.getKey(prefix.nick, "password")
if oldpass == None:
if oldpass is None:
attr.setKey(prefix.nick, "password", cmd.args[0])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." % cmd.args[0])
else:
if len(cmd.args) == 2:
if cmd.args[0] == oldpass:
attr.setKey(prefix.nick, "password", cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." % cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Your password has been set to \"%s\"." %
cmd.args[1])
else:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: Old password incorrect.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".setpass: You must provide the old password when setting a new one.")
self.bot.act_PRIVMSG(prefix.nick,
".setpass: You must provide the old password when setting a new one.")
cmd = self.bot.messageHasCommand(".login", trailing)
if cmd:
attr = self.bot.getBestModuleForService("attributes")
userpw = attr.getKey(prefix.nick, "password")
if userpw==None:
if userpw is None:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args) == 1:
@ -79,7 +82,7 @@ class NickUser(ModuleBase):
if cmd:
attr = self.bot.getBestModuleForService("attributes")
loggedin = attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
if loggedin is None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
attr.setKey(prefix.nick, "loggedinfrom", None)

View File

@ -11,33 +11,30 @@ from time import time,sleep
from threading import Thread
from pyircbot.modulebase import ModuleBase, ModuleHook
class PingResponder(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.timer = PingRespondTimer(self)
self.hooks = [
ModuleHook("PING", self.pingrespond),
ModuleHook("_RECV", self.resettimer)
]
def pingrespond(self, args, prefix, trailing):
"""Respond to the PING command"""
# got a ping? send it right back
self.bot.act_PONG(trailing)
self.log.info("%s Responded to a ping: %s" % (self.bot.get_nick(), trailing))
def resettimer(self, msg):
"""Resets the connection failure timer"""
self.timer.reset()
def ondisable(self):
self.timer.disable()
class PingRespondTimer(Thread):
"Tracks last ping from server, and reconnects if over a threshold"
def __init__(self, master):

View File

@ -10,13 +10,14 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
from datetime import datetime
class RandQuote(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
if not serviceProviders:
self.log.error("RandQuote: Could not find a valid sqlite service provider")
else:
self.log.info("RandQuote: Selecting sqlite service provider: %s" % serviceProviders[0])
@ -32,12 +33,12 @@ class RandQuote(ModuleBase):
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.logquote),ModuleHook("PRIVMSG", self.fetchquotes)]
self.hooks = [ModuleHook("PRIVMSG", self.logquote),
ModuleHook("PRIVMSG", self.fetchquotes)]
def fetchquotes(self, args, prefix, trailing):
if not args[0][0] == "#":
return
prefixObj = self.bot.decodePrefix(prefix)
cmd = self.bot.messageHasCommand([".randomquote", ".randquote", ".rq"], trailing)
if cmd:
c = self.db.query("SELECT * FROM `chat` ORDER BY RANDOM() LIMIT 1;")
@ -53,7 +54,6 @@ class RandQuote(ModuleBase):
self.db.query("INSERT INTO `chat` (`date`, `sender`, `message`) VALUES (?, ?, ?)",
(int(datetime.now().timestamp()), prefixObj.nick, trailing)).close()
# Trim quotes
deleteIds = []
c = self.db.query("SELECT * FROM `chat` ORDER BY `date` DESC LIMIT %s, 1000000;" % self.config["limit"])
while True:
row = c.fetchone()

View File

@ -13,13 +13,14 @@ from time import sleep
import re
import pytz
class Remind(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
if not serviceProviders:
self.log.error("Remind: Could not find a valid sqlite service provider")
else:
self.log.info("Remind: Selecting sqlite service provider: %s" % serviceProviders[0])
@ -36,7 +37,8 @@ class Remind(ModuleBase):
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.remindin),ModuleHook("PRIVMSG", self.remindat)]
self.hooks = [ModuleHook("PRIVMSG", self.remindin),
ModuleHook("PRIVMSG", self.remindat)]
self.disabled = False
@ -45,7 +47,6 @@ class Remind(ModuleBase):
self.t.daemon = True
self.t.start()
def monitor_thread(self):
while True:
sleep(self.config["precision"])
@ -110,7 +111,7 @@ class Remind(ModuleBase):
def remindat(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
replyTo = prefixObj.nick if "#" not in args[0] else args[0]
# Lots of code borrowed from https://github.com/embolalia/willie/blob/master/willie/modules/remind.py
cmd = self.bot.messageHasCommand([".at", ".remind"], trailing, True)
@ -126,18 +127,19 @@ class Remind(ModuleBase):
hour = int(hour)
minute = int(minute)
if not second == None:
if second is not None:
second = int(second)
except:
self.bot.act_PRIVMSG(replyTo, "%s: .at - Remind at a time. Example: .at 20:45EST Do your homework!" % prefixObj.nick)
self.bot.act_PRIVMSG(replyTo, "%s: .at - Remind at a time. Example: .at 20:45EST Do your homework!" %
prefixObj.nick)
return
now = datetime.now()
remindAt = datetime.now()
# if there was timezone, make sure the time we're reminding them at is relative to their timezone
if not tz == None:
if tz is not None:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
@ -145,17 +147,18 @@ class Remind(ModuleBase):
return
remindAt = theirzone.localize(remindAt, is_dst=Remind.is_dst(theirzone))
# Set the hour and minute we'll remind them at today. If the ends up being in the past, we'll add a day alter
# Set the hour and minute we'll remind them at today.
# If the ends up being in the past, we'll add a day alter
remindAt = remindAt.replace(hour=hour).replace(minute=minute).replace(microsecond=0)
# Set seconds
if second == None:
if second is None:
remindAt = remindAt.replace(second=0)
else:
remindAt = remindAt.replace(second=second)
# if there was timezone, convert remindAt to our zone
if not tz == None:
if tz is not None:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
@ -183,7 +186,8 @@ class Remind(ModuleBase):
diffHours = int(timediff.seconds / 60 / 60)
diffMins = int((timediff.seconds - diffHours * 60 * 60) / 60)
self.bot.act_PRIVMSG(replyTo, "%s: Ok, will do. Approx %sh%sm to go." % (prefixObj.nick, diffHours, diffMins))
self.bot.act_PRIVMSG(replyTo, "%s: Ok, will do. Approx %sh%sm to go." %
(prefixObj.nick, diffHours, diffMins))
@staticmethod
def is_dst(tz):
@ -203,26 +207,27 @@ class Remind(ModuleBase):
def remindin(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
replyTo = prefixObj.nick if "#" not in args[0] else args[0]
cmd = self.bot.messageHasCommand([".in", ".after"], trailing, True)
if cmd:
if len(cmd.args)==0:
self.bot.act_PRIVMSG(replyTo, "%s: .in - Remind after x amount of time. Example: .in 1week5d2h1m Go fuck yourself" %
(prefixObj.nick, diffHours, diffMins))
if not cmd.args:
self.bot.act_PRIVMSG(replyTo, "%s: .in - Remind after x amount of time. Example: .in 1week5d2h1m Go "
"fuck yourself" % prefixObj.nick)
return
timepieces = re.compile(r'([0-9]+)([a-zA-Z]+)').findall(cmd.args[0])
if len(timepieces)==0:
self.bot.act_PRIVMSG(replyTo, "%s: .in - Remind after x amount of time. Example: .in 1week5d2h1m Go fuck yourself" %
(prefixObj.nick, diffHours, diffMins))
if not timepieces:
self.bot.act_PRIVMSG(replyTo, "%s: .in - Remind after x amount of time. Example: .in 1week5d2h1m Go "
"fuck yourself" % prefixObj.nick)
return
delaySeconds = 0
for match in timepieces:
# ('30', 'm')
if not match[1] in Remind.scaling:
self.bot.act_PRIVMSG(replyTo, "%s: Sorry, I don't understand the time unit '%s'" % (prefixObj.nick, match[1]))
self.bot.act_PRIVMSG(replyTo, "%s: Sorry, I don't understand the time unit '%s'" %
(prefixObj.nick, match[1]))
return
delaySeconds += (Remind.scaling[match[1]] * int(match[0]))

View File

@ -8,15 +8,14 @@
"""
from pyircbot.modulebase import ModuleBase
import sys
import sqlite3
class SQLite(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = []
self.services = ["sqlite"]
self.loadConfig()
def opendb(self, dbname):
return Connection(self, dbname)
@ -36,7 +35,7 @@ class Connection:
c.execute("SELECT * FROM SQLITE_MASTER WHERE `type`='table' AND `name`=?", (tablename,))
tables = c.fetchall()
if len(tables) == 0:
return False;
return False
return True
@staticmethod
@ -82,7 +81,7 @@ class Connection:
# Test the connection
c = self.connection.cursor()
derp=c.execute("SELECT * FROM SQLITE_MASTER")
derp = c.execute("SELECT * FROM SQLITE_MASTER") # NOQA
c.close()
def close(self):

View File

@ -10,25 +10,24 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import random
import json
import os
import time
from threading import Timer
from operator import itemgetter
class Scramble(ModuleBase):
def __init__(self, bot, moduleName):
# init the base module
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.scramble)]
self.loadConfig()
# Dictionary
self.wordsCount=0;
self.wordsCount = 0
self.wordsFile = self.getFilePath("words.txt")
print(self.wordsFile)
wordsF = open(self.wordsFile, "r")
while True:
word = wordsF.readline()
if word=="":
if not word:
break
self.wordsCount += 1
wordsF.close
@ -46,7 +45,7 @@ class Scramble(ModuleBase):
def scramble(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
if not channel in self.games:
if channel not in self.games:
self.games[channel] = scrambleGame(self, channel)
self.games[channel].scramble(args, prefix, trailing)
@ -55,7 +54,7 @@ class Scramble(ModuleBase):
def getScore(self, player, add=0):
player = player.lower()
if not player in self.scores:
if player not in self.scores:
self.scores[player] = 0
if not add == 0:
self.scores[player] += add
@ -75,6 +74,7 @@ class Scramble(ModuleBase):
self.games[game].gameover()
self.saveScores()
class scrambleGame:
def __init__(self, master, channel):
self.master = master
@ -94,24 +94,27 @@ class scrambleGame:
# Cooldown between words
self.nextTimer = None
# How many gamesWithoutGuesses submitted this round
self.guesses = 0;
self.guesses = 0
# How many games in a row where nobody guessed
self.gamesWithoutGuesses = 0;
self.gamesWithoutGuesses = 0
self.delayHint = self.master.config["hintDelay"];
self.delayNext = self.master.config["delayNext"];
self.maxHints = self.master.config["maxHints"];
self.abortAfterNoGuesses = self.master.config["abortAfterNoGuesses"];
self.delayHint = self.master.config["hintDelay"]
self.delayNext = self.master.config["delayNext"]
self.maxHints = self.master.config["maxHints"]
self.abortAfterNoGuesses = self.master.config["abortAfterNoGuesses"]
def gameover(self):
self.clearTimers();
self.clearTimers()
self.running = False
def clearTimers(self):
self.clearTimer(self.nextTimer)
self.clearTimer(self.hintTimer)
def clearTimer(self, timer):
if timer:
timer.cancel()
def scramble(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
sender = prefix.nick
@ -145,12 +148,14 @@ class scrambleGame:
if cmd:
someone = cmd.args.strip()
if len(someone) > 0:
self.master.bot.act_PRIVMSG(self.channel, "%s: %s has a score of %s" % (sender, someone, self.master.getScoreNoWrite(someone)))
self.master.bot.act_PRIVMSG(self.channel, "%s: %s has a score of %s" %
(sender, someone, self.master.getScoreNoWrite(someone)))
else:
self.master.bot.act_PRIVMSG(self.channel, "%s: %s" % (sender, self.master.getScore(sender)))
if self.currentWord and trailing.strip().lower() == self.currentWord:
playerScore = self.master.getScore(sender, 1)
self.master.bot.act_PRIVMSG(self.channel, "%s guessed the word - %s! %s now has %s points. Next word in %s seconds." % (sender, self.currentWord, sender, playerScore, self.delayNext))
self.master.bot.act_PRIVMSG(self.channel, "%s guessed the word - %s! %s now has %s points. Next word in %s "
"seconds." % (sender, self.currentWord, sender, playerScore, self.delayNext))
self.currentWord = None
self.clearTimers()
self.hintsGiven = 0
@ -201,14 +206,16 @@ class scrambleGame:
def abortWord(self):
cur = self.currentWord
self.currentWord = None
self.master.bot.act_PRIVMSG(self.channel, "Word expired - the answer was %s. Next word in %s seconds." % (cur, self.delayNext))
self.master.bot.act_PRIVMSG(self.channel, "Word expired - the answer was %s. Next word in %s seconds." %
(cur, self.delayNext))
self.hintsGiven = 0
self.clearTimer(self.nextTimer)
if self.guesses == 0:
self.gamesWithoutGuesses += 1
if self.gamesWithoutGuesses >= self.abortAfterNoGuesses:
self.master.bot.act_PRIVMSG(self.channel, "No one seems to be playing - type .scrambleon to start again.")
self.master.bot.act_PRIVMSG(self.channel, "No one seems to be playing - type .scrambleon to "
"start again.")
self.gameover()
return
else:

View File

@ -11,11 +11,11 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import sqlite3
import time
class Seen(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.lastSeen)]
self.loadConfig()
# if the database doesnt exist, it will be created
sql = self.getSql()
c = sql.cursor()
@ -24,7 +24,7 @@ class Seen(ModuleBase):
if len(c.fetchall()) == 0:
self.log.info("Seen: Creating database")
# if no, create it.
c.execute("CREATE TABLE `seen` (`nick` VARCHAR(32), `date` INTEGER, PRIMARY KEY(`nick`))");
c.execute("CREATE TABLE `seen` (`nick` VARCHAR(32), `date` INTEGER, PRIMARY KEY(`nick`))")
self.x = "asdf"
def lastSeen(self, args, prefix, trailing):
@ -39,14 +39,16 @@ class Seen(ModuleBase):
# self.log.info("Seen: %s on %s" % (nick.lower(), datest))
sql.commit()
if trailing.startswith(".seen"):
cmdargs = trailing.split(" ");
cmdargs = trailing.split(" ")
# query the DB for the user
if len(cmdargs) >= 2:
searchnic = cmdargs[1].lower();
searchnic = cmdargs[1].lower()
c.execute("SELECT * FROM `seen` WHERE `nick`= ? ", [searchnic])
rows = c.fetchall()
if len(rows) == 1:
self.bot.act_PRIVMSG(args[0], "I last saw %s on %s (%s)."% (cmdargs[1], time.strftime("%m/%d/%y at %I:%M %p", time.localtime(rows[0]['date'])), self.config["timezone"]));
self.bot.act_PRIVMSG(args[0], "I last saw %s on %s (%s)." %
(cmdargs[1], time.strftime("%m/%d/%y at %I:%M %p",
time.localtime(rows[0]['date'])), self.config["timezone"]))
else:
self.bot.act_PRIVMSG(args[0], "Sorry, I haven't seen %s!" % cmdargs[1])
c.close()
@ -54,7 +56,7 @@ class Seen(ModuleBase):
def getSql(self):
# return a SQL reference to the database
path = self.getFilePath('database.sql3')
sql = sqlite3.connect(path);
sql = sqlite3.connect(path)
sql.row_factory = self.dict_factory
return sql

View File

@ -10,17 +10,22 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
from time import sleep
class Services(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("_CONNECT", self.doConnect), ModuleHook("433", self.nickTaken), ModuleHook("001", self.initservices), ModuleHook("INVITE", self.invited), ]
self.hooks = [ModuleHook("_CONNECT", self.doConnect),
ModuleHook("433", self.nickTaken),
ModuleHook("001", self.initservices),
ModuleHook("INVITE", self.invited), ]
self.current_nick = 0
self.do_ghost = False
def doConnect(self, args, prefix, trailing):
"""Hook for when the IRC conneciton is opened"""
self.bot.act_NICK(self.config["user"]["nick"][0])
self.bot.act_USER(self.config["user"]["username"], self.config["user"]["hostname"], self.config["user"]["realname"])
self.bot.act_USER(self.config["user"]["username"], self.config["user"]["hostname"],
self.config["user"]["realname"])
def nickTaken(self, args, prefix, trailing):
"""Hook that responds to 433, meaning our nick is taken"""
@ -35,7 +40,8 @@ class Services(ModuleBase):
def initservices(self, args, prefix, trailing):
"""Hook that sets our initial nickname"""
if self.do_ghost:
self.bot.act_PRIVMSG(self.config["ident"]["ghost_to"], self.config["ident"]["ghost_cmd"] % {"nick":self.config["user"]["nick"][0], "password":self.config["user"]["password"]})
self.bot.act_PRIVMSG(self.config["ident"]["ghost_to"], self.config["ident"]["ghost_cmd"] %
{"nick": self.config["user"]["nick"][0], "password": self.config["user"]["password"]})
sleep(2)
self.bot.act_NICK(self.config["user"]["nick"][0])
self.do_initservices()
@ -50,7 +56,8 @@ class Services(ModuleBase):
"""Identify with nickserv and join startup channels"""
" id to nickserv "
if self.config["ident"]["enable"]:
self.bot.act_PRIVMSG(self.config["ident"]["to"], self.config["ident"]["command"] % {"password":self.config["user"]["password"]})
self.bot.act_PRIVMSG(self.config["ident"]["to"], self.config["ident"]["command"] %
{"password": self.config["user"]["password"]})
" join plain channels "
for channel in self.config["channels"]:
@ -60,5 +67,6 @@ class Services(ModuleBase):
" request invite for private message channels "
for channel in self.config["privatechannels"]["list"]:
self.log.info("Requesting invite to %s" % channel)
self.bot.act_PRIVMSG(self.config["privatechannels"]["to"], self.config["privatechannels"]["command"] % {"channel":channel})
self.bot.act_PRIVMSG(self.config["privatechannels"]["to"], self.config["privatechannels"]["command"] %
{"channel": channel})

View File

@ -10,9 +10,10 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import datetime
from time import mktime
class Tell(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
@ -24,7 +25,7 @@ class Tell(ModuleBase):
if not self.db.tableExists("tells"):
self.log.info("Remind: Creating table: tells")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `tells` (
self.db.query("""CREATE TABLE IF NOT EXISTS `tells` (
`id` INTEGER PRIMARY KEY,
`sender` varchar(64),
`channel` varchar(64),
@ -34,7 +35,8 @@ class Tell(ModuleBase):
) ;""").close()
# Purge expired tells
self.db.query("DELETE FROM `tells` WHERE `when`<?", (int(mktime(datetime.datetime.now().timetuple()))-self.config["maxage"],)).close()
self.db.query("DELETE FROM `tells` WHERE `when`<?",
(int(mktime(datetime.datetime.now().timetuple())) - self.config["maxage"],)).close()
self.hooks = [
ModuleHook(["JOIN", "PRIVMSG"], self.showtell),
@ -42,7 +44,6 @@ class Tell(ModuleBase):
]
def showtell(self, args, prefix, trailing):
#print("%s - %s - %s" % (args, prefix, trailing))
prefix = self.bot.decodePrefix(prefix)
# Look for tells for this person
@ -67,30 +68,30 @@ class Tell(ModuleBase):
def tellcmds(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
replyTo = prefixObj.nick if "#" not in args[0] else args[0]
cmd = self.bot.messageHasCommand(".tell", trailing)
if cmd:
if len(cmd.args) < 2:
self.bot.act_PRIVMSG(replyTo, "%s: .tell <person> <message> - Tell someone something the next time they're seen. Example: .tell antiroach Do your homework!" % prefixObj.nick)
self.bot.act_PRIVMSG(replyTo, "%s: .tell <person> <message> - Tell someone something the next time "
"they're seen. Example: .tell antiroach Do your homework!" % prefixObj.nick)
return
recip = cmd.args[0]
message = ' '.join(cmd.args[1:]).strip()
if message=="":
self.bot.act_PRIVMSG(replyTo, "%s: .tell <person> <message> - Tell someone something the next time they're seen. Example: .tell antiroach Do your homework!" % prefixObj.nick)
if not message:
self.bot.act_PRIVMSG(replyTo, "%s: .tell <person> <message> - Tell someone something the next time "
"they're seen. Example: .tell antiroach Do your homework!" %
prefixObj.nick)
return
self.db.query("INSERT INTO `tells` (`sender`, `channel`, `when`, `recip`, `message`) VALUES (?, ?, ?, ?, ?);",
(
prefixObj.nick,
self.db.query("INSERT INTO `tells` (`sender`, `channel`, `when`, `recip`, `message`) VALUES "
"(?, ?, ?, ?, ?);", (prefixObj.nick,
args[0] if "#" in args[0] else "",
int(mktime(datetime.datetime.now().timetuple())),
recip,
message
)
).close()
message)).close()
self.bot.act_PRIVMSG(replyTo, "%s: I'll pass that along." % prefixObj.nick)
@ -136,14 +137,12 @@ class Tell(ModuleBase):
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
chunks = (
(60 * 60 * 24 * 365, ('year', 'years')),
chunks = ((60 * 60 * 24 * 365, ('year', 'years')),
(60 * 60 * 24 * 30, ('month', 'months')),
(60 * 60 * 24 * 7, ('week', 'weeks')),
(60 * 60 * 24, ('day', 'days')),
(60 * 60, ('hour', 'hours')),
(60, ('minute', 'minutes'))
)
(60, ('minute', 'minutes')))
# Convert int or float (unix epoch) to datetime.datetime for comparison
if isinstance(d, int) or isinstance(d, float):
@ -186,11 +185,11 @@ class Tell(ModuleBase):
return s
@staticmethod
def timeuntil(d, now=None):
def timeuntil(d, now=None): # not used?
"""
Like timesince, but returns a string measuring the time until
the given time.
"""
if not now:
now = datetime.datetime.now()
return timesince(now, d)
return Tell.timesince(now, d)

View File

@ -9,6 +9,7 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
class Test(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)

View File

@ -13,18 +13,18 @@ from pyircbot.modulebase import ModuleBase, ModuleHook
COMMAND_PREFIX = ".text-"
class TextCDC(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks.append(ModuleHook("PRIVMSG", self.handleMessage))
self.loadConfig()
self.prefixes = [person for person in self.config["people"]]
self.bot = bot
self.timer = None
self.setupTimer()
def ondisable(self):
if self.timer != None:
if self.timer is not None:
self.timer.cancel()
def handleMessage(self, args, prefix, trailing):
@ -32,14 +32,15 @@ class TextCDC(ModuleBase):
p = self.bot.decodePrefix(prefix)
if self.bot.messageHasCommand(".textstatus", trailing):
# self.bot.act_PRIVMSG(channel, "POP: %s" % "Good" if setupPop() != None else "Failed.")
self.bot.act_PRIVMSG(channel, "SMTP: %s" % "Good" if setupSMTP() != None else "Failed.")
self.bot.act_PRIVMSG(channel, "SMTP: %s" % "Good" if self.setupSMTP() is not None else "Failed.")
for prefix in self.prefixes:
if self.bot.messageHasCommand(COMMAND_PREFIX + prefix, trailing):
email = self.config["people"][prefix]["email-addr"]
message = ' '.join(trailing.split(" ")[1:])
smtp = self.setupSMTP()
try:
smtp.sendmail(self.config["account"]["auth"]["username"], email, "Subject:\n\n%s -%s" % (message, p.nick))
smtp.sendmail(self.config["account"]["auth"]["username"], email, "Subject:\n\n%s -%s" %
(message, p.nick))
smtp.quit()
self.bot.act_PRIVMSG(channel, "Message sent.")
except Exception as e:
@ -79,12 +80,13 @@ class TextCDC(ModuleBase):
return None
def setupTimer(self):
self.timer = Timer(self.config["interval"], self.checkMail, [self.bot, self.config["people"], self.config["output-channels"]],{})
self.timer = Timer(self.config["interval"], self.checkMail, [self.bot, self.config["people"],
self.config["output-channels"]], {})
self.timer.start()
def checkMail(self, bot, people, channels, imapObj=None):
try:
if imapObj == None:
if imapObj is None:
imapObj = self.setupIMAP()
for person in people:
emailAddr = people[person]["email-addr"]
@ -96,7 +98,8 @@ class TextCDC(ModuleBase):
for messageId in messageIds:
message = imapObj.fetch(messageId, "BODY[TEXT]")
if (message[0] == "OK"):
messageText = message[1][0][1].decode("utf-8").split("-----Original Message-----")[0].rstrip()
messageText = message[1][0][1].decode("utf-8").split("-----Original Message-----")[0] \
.rstrip()
for channel in channels:
bot.act_PRIVMSG(channel, "Message from %s: %s" % (person, messageText))
imapObj.store(messageId, "+FLAGS", "\\Deleted")
@ -105,7 +108,7 @@ class TextCDC(ModuleBase):
imapObj.logout()
self.setupTimer()
except Exception as e:
if imapObj != None:
if imapObj is not None:
imapObj.logout()
self.setupTimer()
raise e

View File

@ -10,10 +10,10 @@ from time import sleep,time
from pyircbot.modulebase import ModuleBase, ModuleHook
from random import randrange, choice
class Triggered(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.loadConfig()
self.quietuntil = time()
self.hooks.append(ModuleHook("PRIVMSG", self.check))

View File

@ -18,7 +18,6 @@ class UnoPlay(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.servicesModule = self.bot.getmodulebyname("Services")
self.mynick = self.servicesModule.config["user"]["nick"][0]
self.hooks = [ModuleHook("PRIVMSG", self.unoplay),
ModuleHook("PRIVMSG", self.trigger),
ModuleHook("NOTICE", self.decklisten)]
@ -30,6 +29,8 @@ class UnoPlay(ModuleBase):
self.cards = []
def trigger(self, args, prefix, trailing):
if trailing.startswith("["): # anti-znc buffer playback
return
if self.config["enable_trigger"] and "!jo" in trailing:
self.bot.act_PRIVMSG(self.config["unochannel"], "jo")
elif trailing == "jo":
@ -44,10 +45,10 @@ class UnoPlay(ModuleBase):
self.bot.act_PRIVMSG(self.config["unochannel"], "jo")
def unoplay(self, args, prefix, trailing):
ogtrailing = trailing
if trailing.startswith("["): # anti-znc buffer playback
return
trailing = self.stripcolors(trailing)
self.log.debug("> %s" % ogtrailing)
self.log.debug("> %s" % trailing)
if self.config["unobot"] not in prefix:
return
@ -60,15 +61,15 @@ class UnoPlay(ModuleBase):
self.current_card = self.parsecard(message)
self.log.debug(">> top card: %s" % str(self.current_card))
if self.mynick in trailing:
if self.bot.get_nick() in trailing:
self.shouldgo = True
# See if someone passed to us
if "passes" in trailing and self.mynick in trailing:
if "passes" in trailing and self.bot.get_nick() in trailing:
self.shouldgo = True
# Play after someone was droppped
if "continuing with" in trailing and self.mynick in trailing:
if "continuing with" in trailing and self.bot.get_nick() in trailing:
self.shouldgo = True
# Parse misc played cards
@ -79,7 +80,7 @@ class UnoPlay(ModuleBase):
self.log.debug(">> current card: %s" % str(self.current_card))
# After someone plays to us
if "to %s" % self.mynick in trailing:
if "to %s" % self.bot.get_nick() in trailing:
self.shouldgo = True
# After color change
@ -98,15 +99,15 @@ class UnoPlay(ModuleBase):
self.current_card[2]['number'] = -1
self.current_card[2]['type'] = None
self.log.debug("Color changed to %s " % self.current_card[2]['color'])
if "urrent player %s" % self.mynick in trailing:
if "urrent player %s" % self.bot.get_nick() in trailing:
self.shouldgo = True
# After color change to us
if "play continues with %s" % self.mynick in trailing:
if "play continues with %s" % self.bot.get_nick() in trailing:
self.shouldgo = True
# We need to choose a color
if "hoose a color %s" % self.mynick in trailing:
if "hoose a color %s" % self.bot.get_nick() in trailing:
self.pickcolor()
# Reset
@ -225,13 +226,12 @@ class UnoPlay(ModuleBase):
self.bot.act_PRIVMSG(self.config["unochannel"], "pl %s" % card)
def decklisten(self, args, prefix, trailing):
if trailing.startswith("["): # anti-znc buffer playback
return
if self.config["unobot"] not in prefix:
return
ogtrailing = trailing
trailing = self.stripcolors(trailing)
self.log.debug("> %s" % (ogtrailing, ))
self.log.debug("> %s" % (trailing, ))
cards = []

View File

@ -8,12 +8,12 @@
"""
from pyircbot.modulebase import ModuleBase, ModuleHook
import json
from requests import get
class Urban(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.urban)]
def urban(self, args, prefix, trailing):
@ -24,12 +24,13 @@ class Urban(ModuleBase):
if cmd.args_str.strip() == "":
self.bot.act_PRIVMSG(args[0], ".u/.urban <phrase> -- looks up <phrase> on urbandictionary.com")
return
definitions = get("http://www.urbandictionary.com/iphone/search/define", params={"term":cmd.args_str}).json()["list"]
definitions = get("http://www.urbandictionary.com/iphone/search/define",
params={"term": cmd.args_str}).json()["list"]
if len(definitions) == 0:
self.bot.act_PRIVMSG(args[0], "Urban definition: no results!")
else:
defstr = definitions[0]['definition'].replace('\n', ' ').replace('\r', '')
if len(defstr) > 360:
defstr = defstr[0:360] + "..."
self.bot.act_PRIVMSG(args[0], "Urban definition: %s - http://urbanup.com/%s" % (defstr, definitions[0]['defid']))
self.bot.act_PRIVMSG(args[0], "Urban definition: %s - http://urbanup.com/%s" %
(defstr, definitions[0]['defid']))

View File

@ -9,25 +9,25 @@
from pyircbot.modulebase import ModuleBase, ModuleHook
from requests import get
from urllib.parse import urlencode
class Weather(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
assert not "get an API key" in self.config["apikey"]
assert "get an API key" not in self.config["apikey"]
self.login = self.bot.getBestModuleForService("login")
try:
assert not self.login == None
assert self.login is not None
except AssertionError as _ae:
self.log.error("Weather: A 'login' service is required")
return
self.attr = self.bot.getBestModuleForService("attributes")
try:
assert not self.attr == None
except AssertionError as _ae:
assert self.attr is not None
except AssertionError as _ae: # NOQA
self.log.error("Weather: An 'attributes' service is required")
return
@ -50,7 +50,7 @@ class Weather(ModuleBase):
return
weatherZip = self.attr.get(fromWho, "weather-zip")
if weatherZip == None:
if weatherZip is None:
self.bot.act_PRIVMSG(replyTo, "%s: you must set a location with .setloc" % (fromWho,))
return
@ -59,19 +59,21 @@ class Weather(ModuleBase):
cmd = self.bot.messageHasCommand(".setloc", trailing)
if cmd and not args[0] == "#":
if len(cmd.args)==0:
self.bot.act_PRIVMSG(fromWho, ".setloc: set your location for weather lookup. Example: .setloc Rochester, NY")
if not cmd.args:
self.bot.act_PRIVMSG(fromWho, ".setloc: set your location for weather lookup. Example: "
".setloc Rochester, NY")
return
weatherLoc = cmd.args_str
try:
result = self.getWeather(weatherLoc)
result = self.getWeather(weatherLoc) # NOQA
except LocationNotSpecificException as lnse:
self.bot.act_PRIVMSG(fromWho, "'%s': location not specific enough. Did you mean: %s" % (weatherLoc, self.alternates_to_str(lnse.alternates)))
self.bot.act_PRIVMSG(fromWho, "'%s': location not specific enough. Did you mean: %s" %
(weatherLoc, self.alternates_to_str(lnse.alternates)))
return
except LocationException as le:
self.bot.act_PRIVMSG(fromWho, "'%s': location not found" % weatherLoc)
self.bot.act_PRIVMSG(fromWho, "'%s': location not found: %s" % (weatherLoc, le))
return
if not self.login.check(prefixObj.nick, prefixObj.hostname):
@ -80,7 +82,7 @@ class Weather(ModuleBase):
self.attr.set(fromWho, "weather-zip", weatherLoc)
self.bot.act_PRIVMSG(fromWho, "Saved your location as %s" % self.attr.get(fromWho, "weather-zip"))
if self.attr.get(fromWho, "weather-zip")==None:
if self.attr.get(fromWho, "weather-zip") is None:
self.bot.act_PRIVMSG(fromWho, "Tip: choose C or F with .wunit <C/F>")
cmd = self.bot.messageHasCommand(".wunit", trailing)
@ -92,7 +94,7 @@ class Weather(ModuleBase):
except:
pass
if unit == None:
if unit is None:
self.bot.act_PRIVMSG(fromWho, ".wunit: set your preferred temperature unit to C or F")
return
@ -101,15 +103,17 @@ class Weather(ModuleBase):
return
self.attr.set(fromWho, "weather-unit", unit.lower())
self.bot.act_PRIVMSG(fromWho, "Saved your preferred unit as %s" % self.attr.get(fromWho, "weather-unit").upper())
self.bot.act_PRIVMSG(fromWho, "Saved your preferred unit as %s" %
self.attr.get(fromWho, "weather-unit").upper())
def send_weather(self, target, hilight, location, units=None):
try:
self.bot.act_PRIVMSG(target, "%s: %s" % (hilight, self.getWeather(location, units)))
except LocationNotSpecificException as lnse:
self.bot.act_PRIVMSG(target, "'%s': location not specific enough. Did you mean: %s" % (location, self.alternates_to_str(lnse.alternates)))
self.bot.act_PRIVMSG(target, "'%s': location not specific enough. Did you mean: %s" %
(location, self.alternates_to_str(lnse.alternates)))
except LocationException as le:
self.bot.act_PRIVMSG(target, "'%s': location not found" % location)
self.bot.act_PRIVMSG(target, "'%s': location not found: %s" % (location, le))
def alternates_to_str(self, alternates):
pieces = []
@ -122,11 +126,12 @@ class Weather(ModuleBase):
return ' -- '.join(pieces)
def getWeather(self, zipcode, unit=None):
if unit==None:
if unit is None:
unit = self.config["defaultUnit"]
unit = unit.lower()
# Get data
data = get("http://api.wunderground.com/api/%s/geolookup/conditions/forecast10day/q/%s.json" % (self.config["apikey"], zipcode)).json()
data = get("http://api.wunderground.com/api/%s/geolookup/conditions/forecast10day/q/%s.json" %
(self.config["apikey"], zipcode)).json()
if "results" in data["response"]:
raise LocationNotSpecificException(data["response"]["results"])
@ -147,23 +152,25 @@ class Weather(ModuleBase):
# build wind speed
wind_speed = data["current_observation"]["wind_mph"] if unit == "f" else data["current_observation"]["wind_kph"]
wind_speed_gust = data["current_observation"]["wind_gust_mph"] if unit=="f" else data["current_observation"]["wind_gust_mph"]
wind_speed_gust = data["current_observation"]["wind_gust_mph"] if unit == "f" \
else data["current_observation"]["wind_gust_mph"]
if not wind_speed == wind_speed_gust and float(wind_speed_gust) > 0:
wind_speed = "%s-%s" % (wind_speed, wind_speed_gust)
else:
wind_speed = "%s" % (wind_speed,)
# return message
return "\x02%(city)s, %(state)s:\x02 %(sky)s, \x02%(temp)s°%(unit)s\x02. %(wind_str)s %(wind_speed)smph (%(wind_dir)s). \x02Next 5 days:\x02 %(fiveday)s" % {
return "\x02%(city)s, %(state)s:\x02 %(sky)s, \x02%(temp)s°%(unit)s\x02. %(wind_str)s %(wind_speed)smph " \
"(%(wind_dir)s). \x02Next 5 days:\x02 %(fiveday)s" % {
"city": data["current_observation"]["display_location"]["city"],
"state": data["current_observation"]["display_location"]["state"],
"sky": data["forecast"]["simpleforecast"]["forecastday"][0]["conditions"],
"temp": int(data["current_observation"]["temp_f"]) if unit=="f" else int(data["current_observation"]["temp_c"]),
"temp": int(data["current_observation"]["temp_f"]) if unit == "f"
else int(data["current_observation"]["temp_c"]),
"unit": unit.upper(),
"wind_str": self.shorten_windstr(data["current_observation"]["wind_string"].lower()),
"wind_speed": wind_speed,
"wind_dir": self.deg_to_arrow(int(data["current_observation"]["wind_degrees"])),
"fiveday":fiveday
}
"fiveday": fiveday}
def shorten_windstr(self, windstr):
if "gusting" in windstr:
@ -174,8 +181,6 @@ class Weather(ModuleBase):
return "Varying"
return windstr[0:12]
def icon2emoji(self,icon):
if "partlycloudy" in icon or "mostlycloudy" in icon:
return "⛅️"
@ -208,9 +213,11 @@ class Weather(ModuleBase):
elif deg > 22:
return ""
class LocationException(Exception):
pass
class LocationNotSpecificException(LocationException):
def __init__(self, alternates):
self.alternates = alternates

View File

@ -12,9 +12,10 @@ from requests import get
import time
import re
class Youtube(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
ModuleBase.__init__(self, bot, moduleName)
self.hooks = [ModuleHook("PRIVMSG", self.youtube)]
def getISOdurationseconds(self, stamp):
@ -24,7 +25,7 @@ class Youtube(ModuleBase):
'(?:(?P<months>\d+)M)?' # months
'(?:(?P<weeks>\d+)W)?' # weeks
'(?:(?P<days>\d+)D)?' # days
'(?:T' # time part must begin with a T
'(?:T' # time part begins with a T
'(?:(?P<hours>\d+)H)?' # hours
'(?:(?P<minutes>\d+)M)?' # minutes
'(?:(?P<seconds>\d+)S)?' # seconds
@ -38,11 +39,12 @@ class Youtube(ModuleBase):
if not cmd:
cmd = self.bot.messageHasCommand(".yt", trailing)
if cmd and args[0][0:1] == "#":
#TOTO search youtube
# TODO search youtube
if cmd.args_str.strip() == "":
self.bot.act_PRIVMSG(args[0], '.youtube <query> -- returns the first YouTube search result for <query>')
return
j = get("http://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc&max-results=1", params={"q":trailing}).json()
j = get("http://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc&max-results=1",
params={"q": trailing}).json()
if 'error' in j or j['data']['totalItems'] == 0:
self.bot.act_PRIVMSG(args[0], "YouTube: No results found.")
else:
@ -52,7 +54,8 @@ class Youtube(ModuleBase):
self.bot.act_PRIVMSG(args[0], "http://youtu.be/%s :: %s" % (vid_id, vidinfo))
def get_video_description(self, vid_id):
apidata = get('https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=%s&key=%s' % (vid_id, self.config["api_key"])).json()
apidata = get('https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=%s'
'&key=%s' % (vid_id, self.config["api_key"])).json()
if not apidata['pageInfo']['totalResults']:
return
@ -64,9 +67,9 @@ class Youtube(ModuleBase):
out = '\x02\x031,0You\x0f\x030,4Tube\x02\x0f :: \x02%s\x02' % snippet["title"]
out += ' - \x02'
if duration["hours"]!=None:
if duration["hours"] is not None:
out += '%dh ' % int(duration["hours"])
if duration["minutes"]!=None:
if duration["minutes"] is not None:
out += '%dm ' % int(duration["minutes"])
out += "%ds\x02" % int(duration["seconds"])

View File

@ -17,8 +17,7 @@ import os.path
ParsedCommand = namedtuple("ParsedCommand", "command args args_str message")
class PyIRCBot:
class PyIRCBot(object):
""":param botconfig: The configuration of this instance of the bot. Passed by main.py.
:type botconfig: dict
"""
@ -58,6 +57,7 @@ class PyIRCBot:
self.act_ACTION = self.irc.act_ACTION
self.act_KICK = self.irc.act_KICK
self.act_QUIT = self.irc.act_QUIT
self.act_PASS = self.irc.act_PASS
self.get_nick = self.irc.get_nick
self.decodePrefix = IRCCore.decodePrefix
@ -96,7 +96,6 @@ class PyIRCBot:
:param message: Quit message
:type message: str
"""
#Close all modules
self.closeAllModules()
self.irc.kill(message=message, alive=not sys_exit)
@ -129,7 +128,7 @@ class PyIRCBot:
:param moduleName: Name of the module to import
:type moduleName: str"""
" check if already exists "
if not name in self.modules:
if name not in self.modules:
self.log.info("Importing %s" % name)
" attempt to load "
try:
@ -156,9 +155,7 @@ class PyIRCBot:
self.unloadmodule(name)
" delete all references to the module"
if name in self.modules:
item = self.modules[name]
del self.modules[name]
del item
" delete copy that python stores in sys.modules "
if name in sys.modules:
del sys.modules[name]
@ -173,7 +170,7 @@ class PyIRCBot:
self.log.warning("Module %s already loaded" % name)
return False
" check if needs to be imported, and verify it was "
if not name in self.modules:
if name not in self.modules:
importResult = self.importmodule(name)
if not importResult[0]:
return importResult
@ -192,10 +189,8 @@ class PyIRCBot:
self.moduleInstances[name].ondisable()
" unload all hooks "
self.unloadModuleHooks(self.moduleInstances[name])
" remove the instance "
item = self.moduleInstances.pop(name)
" delete the instance"
del item
" remove & delete the instance "
self.moduleInstances.pop(name)
self.log.info("Module %s unloaded" % name)
return (True, None)
else:
@ -270,7 +265,7 @@ class PyIRCBot:
:param name: name of the module to return
:type name: str
:returns: object -- the module object"""
if not name in self.moduleInstances:
if name not in self.moduleInstances:
return None
return self.moduleInstances[name]
@ -372,20 +367,10 @@ class PyIRCBot:
return False
# Verified! Return the set.
<<<<<<< HEAD
return ParsedCommand(command,
args.split(" "),
args,
message)
=======
ob = type('ParsedCommand', (object,), {})
ob.command = command
ob.args = [] if args=="" else args.split(" ")
ob.args_str = args
ob.message = message
return ob
# return (True, command, args, message)
>>>>>>> Add unoplayer module
@staticmethod
def load(filepath):

View File

@ -11,6 +11,7 @@ import logging
from pyircbot import jsonrpc
from threading import Thread
class BotRPC(Thread):
""":param main: A reference to the PyIRCBot instance this instance will control
:type main: PyIRCBot

View File

@ -1,9 +1,11 @@
from sys import argv, exit
from pyircbot import jsonrpc
def connect(host, port):
return jsonrpc.ServerProxy(jsonrpc.JsonRpc20(), jsonrpc.TransportTcpIp(addr=(host, port), timeout=60.0))
if __name__ == "__main__":
if len(argv) is not 3:
print("Expected ip and port arguments")