Convert tabs to spaces

This commit is contained in:
dave 2015-11-01 18:03:11 -08:00
parent 3acf60d6e9
commit 20c1ffd2fc
30 changed files with 3069 additions and 3069 deletions

View File

@ -7,29 +7,29 @@ from pyircbot import PyIRCBot
if __name__ == "__main__":
" logging level and facility "
logging.basicConfig(level=logging.DEBUG, format="%(asctime)-15s %(levelname)-8s %(message)s")
log = logging.getLogger('main')
" parse command line args "
parser = OptionParser()
parser.add_option("-c", "--config", action="store", type="string", dest="config", help="Path to config file")
(options, args) = parser.parse_args()
log.debug(options)
if not options.config:
log.critical("No bot config file specified (-c). Exiting.")
sys.exit(0)
botconfig = PyIRCBot.load(options.config)
log.debug(botconfig)
bot = PyIRCBot(botconfig)
try:
bot.loop()
except KeyboardInterrupt:
bot.kill()
" logging level and facility "
logging.basicConfig(level=logging.DEBUG, format="%(asctime)-15s %(levelname)-8s %(message)s")
log = logging.getLogger('main')
" parse command line args "
parser = OptionParser()
parser.add_option("-c", "--config", action="store", type="string", dest="config", help="Path to config file")
(options, args) = parser.parse_args()
log.debug(options)
if not options.config:
log.critical("No bot config file specified (-c). Exiting.")
sys.exit(0)
botconfig = PyIRCBot.load(options.config)
log.debug(botconfig)
bot = PyIRCBot(botconfig)
try:
bot.loop()
except KeyboardInterrupt:
bot.kill()

View File

@ -1,6 +1,6 @@
"""
.. module:: Core
:synopsis: Core module of the bot
:synopsis: Core module of the bot
.. moduleauthor:: Dave Pedu <dave@davepedu.com>

View File

@ -1,6 +1,6 @@
"""
.. module:: ModuleBase
:synopsis: Base class that modules will extend
:synopsis: Base class that modules will extend
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,65 +11,65 @@ import os
from .pyircbot import PyIRCBot
class ModuleBase:
"""All modules will extend this class
:param bot: A reference to the main bot passed when this module is created
:type bot: PyIRCBot
:param moduleName: The name assigned to this module
:type moduleName: str
"""
def __init__(self, bot, moduleName):
self.moduleName=moduleName
"""Assigned name of this module"""
self.bot = bot
"""Reference to the master PyIRCBot object"""
self.hooks=[]
"""Hooks (aka listeners) this module has"""
self.services=[]
"""If this module provides services usable by another module, they're listed
here"""
self.config={}
"""Configuration dictionary. Autoloaded from `%(datadir)s/%(modulename)s.json`"""
self.log = logging.getLogger("Module.%s" % self.moduleName)
"""Logger object for this module"""
# Autoload config if available
self.loadConfig()
self.log.info("Loaded module %s" % self.moduleName)
def loadConfig(self):
"""Loads this module's config into self.config"""
configPath = self.bot.getConfigPath(self.moduleName)
if not configPath == None:
self.config = PyIRCBot.load(configPath)
def ondisable(self):
"""Called when the module should be disabled. Your module should do any sort
of clean-up operations here like ending child threads or saving data files.
"""
pass
def getConfigPath(self):
"""Returns the absolute path of this module's json config file"""
return self.bot.getConfigPath(self.moduleName)
def getFilePath(self, f=None):
"""Returns the absolute path to a file in this Module's data dir
:param f: The file name included in the path
:type channel: str
:Warning: .. Warning:: this does no error checking if the file exists or is\
writable. The bot's data dir *should* always be writable"""
return self.bot.getDataPath(self.moduleName) + (f if f else '')
"""All modules will extend this class
:param bot: A reference to the main bot passed when this module is created
:type bot: PyIRCBot
:param moduleName: The name assigned to this module
:type moduleName: str
"""
def __init__(self, bot, moduleName):
self.moduleName=moduleName
"""Assigned name of this module"""
self.bot = bot
"""Reference to the master PyIRCBot object"""
self.hooks=[]
"""Hooks (aka listeners) this module has"""
self.services=[]
"""If this module provides services usable by another module, they're listed
here"""
self.config={}
"""Configuration dictionary. Autoloaded from `%(datadir)s/%(modulename)s.json`"""
self.log = logging.getLogger("Module.%s" % self.moduleName)
"""Logger object for this module"""
# Autoload config if available
self.loadConfig()
self.log.info("Loaded module %s" % self.moduleName)
def loadConfig(self):
"""Loads this module's config into self.config"""
configPath = self.bot.getConfigPath(self.moduleName)
if not configPath == None:
self.config = PyIRCBot.load(configPath)
def ondisable(self):
"""Called when the module should be disabled. Your module should do any sort
of clean-up operations here like ending child threads or saving data files.
"""
pass
def getConfigPath(self):
"""Returns the absolute path of this module's json config file"""
return self.bot.getConfigPath(self.moduleName)
def getFilePath(self, f=None):
"""Returns the absolute path to a file in this Module's data dir
:param f: The file name included in the path
:type channel: str
:Warning: .. Warning:: this does no error checking if the file exists or is\
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
self.method=method
def __init__(self, hook, method):
self.hook=hook
self.method=method

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: AttributeStorage
:synopsis: An item key->value storage engine based on mysql
:synopsis: An item key->value storage engine based on mysql
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -10,165 +10,165 @@
from pyircbot.modulebase import ModuleBase,ModuleHook
class AttributeStorage(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["attributes"]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("mysql")
if len(serviceProviders)==0:
self.log.error("AttributeStorage: Could not find a valid mysql service provider")
else:
self.log.info("AttributeStorage: Selecting mysql service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0]
if not self.db.connection.tableExists("attribute"):
self.log.info("AttributeStorage: Creating table: attribute")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `attribute` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute` varchar(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `attribute` (`attribute`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;""")
c.close()
if not self.db.connection.tableExists("items"):
self.log.info("AttributeStorage: Creating table: items")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item` varchar(512) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;""")
c.close()
if not self.db.connection.tableExists("values"):
self.log.info("AttributeStorage: Creating table: values")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `values` (
`itemid` int(11) NOT NULL,
`attributeid` int(11) NOT NULL,
`value` varchar(512) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`itemid`,`attributeid`)
) 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
:param name: the item
:type name: str
:returns: dict -- the item's values expressed as a dict"""
c = self.db.connection.query("""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`
WHERE
`i`.`item`=%s;""",
(name,)
)
item = {}
while True:
row = c.fetchone()
if row == None:
break
item[row["attribute"]]=row["value"]
c.close()
if len(item)==0:
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
:param item: the item to fetch a key from
:type item: str
:param key: they key who's value to return
:type key: str
:returns: str -- the item from the database or **None**"""
c = self.db.connection.query("""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`
WHERE
`i`.`item`=%s
AND
`a`.`attribute`=%s;""",
(item,key)
)
row = c.fetchone()
c.close()
if row == 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
:param item: the item name to set the key on
:type item: str
:param key: the key to set
:type key: tuple
:param value: the value to set
:type value: str"""
item = item.lower()
attribute = key.lower()
# Check attribute exists
c = self.db.connection.query("SELECT `id` FROM `attribute` WHERE `attribute`=%s;", (attribute))
row = c.fetchone()
attributeId = -1
if row == None:
c = self.db.connection.query("INSERT INTO `attribute` (`attribute`) VALUES (%s);", (attribute))
attributeId = c.lastrowid
else:
attributeId = row["id"]
c.close()
# check item exists
c = self.db.connection.query("SELECT `id` FROM `items` WHERE `item`=%s;", (item))
row = c.fetchone()
itemId = -1
if row == 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:
# delete it
c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;", (itemId, attributeId))
self.log.debug("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))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["attributes"]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("mysql")
if len(serviceProviders)==0:
self.log.error("AttributeStorage: Could not find a valid mysql service provider")
else:
self.log.info("AttributeStorage: Selecting mysql service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0]
if not self.db.connection.tableExists("attribute"):
self.log.info("AttributeStorage: Creating table: attribute")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `attribute` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute` varchar(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `attribute` (`attribute`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;""")
c.close()
if not self.db.connection.tableExists("items"):
self.log.info("AttributeStorage: Creating table: items")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item` varchar(512) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;""")
c.close()
if not self.db.connection.tableExists("values"):
self.log.info("AttributeStorage: Creating table: values")
c = self.db.connection.query("""CREATE TABLE IF NOT EXISTS `values` (
`itemid` int(11) NOT NULL,
`attributeid` int(11) NOT NULL,
`value` varchar(512) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`itemid`,`attributeid`)
) 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
:param name: the item
:type name: str
:returns: dict -- the item's values expressed as a dict"""
c = self.db.connection.query("""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`
WHERE
`i`.`item`=%s;""",
(name,)
)
item = {}
while True:
row = c.fetchone()
if row == None:
break
item[row["attribute"]]=row["value"]
c.close()
if len(item)==0:
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
:param item: the item to fetch a key from
:type item: str
:param key: they key who's value to return
:type key: str
:returns: str -- the item from the database or **None**"""
c = self.db.connection.query("""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`
WHERE
`i`.`item`=%s
AND
`a`.`attribute`=%s;""",
(item,key)
)
row = c.fetchone()
c.close()
if row == 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
:param item: the item name to set the key on
:type item: str
:param key: the key to set
:type key: tuple
:param value: the value to set
:type value: str"""
item = item.lower()
attribute = key.lower()
# Check attribute exists
c = self.db.connection.query("SELECT `id` FROM `attribute` WHERE `attribute`=%s;", (attribute))
row = c.fetchone()
attributeId = -1
if row == None:
c = self.db.connection.query("INSERT INTO `attribute` (`attribute`) VALUES (%s);", (attribute))
attributeId = c.lastrowid
else:
attributeId = row["id"]
c.close()
# check item exists
c = self.db.connection.query("SELECT `id` FROM `items` WHERE `item`=%s;", (item))
row = c.fetchone()
itemId = -1
if row == 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:
# delete it
c = self.db.connection.query("DELETE FROM `values` WHERE `itemid`=%s AND `attributeid`=%s ;", (itemId, attributeId))
self.log.debug("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))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: AttributeStorageLite
:synopsis: An item key->value storage engine based on Sqlite
:synopsis: An item key->value storage engine based on Sqlite
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -10,159 +10,159 @@
from pyircbot.modulebase import ModuleBase,ModuleHook
class AttributeStorageLite(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["attributes"]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("AttributeStorage: Could not find a valid sqlite service provider")
else:
self.log.info("AttributeStorage: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("attributes.db")
if not self.db.tableExists("attribute"):
self.log.info("AttributeStorage: Creating table: attribute")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `attribute` (
`id` INTEGER PRIMARY KEY,
`attribute` varchar(128) UNIQUE
) ;""")
c.close()
if not self.db.tableExists("items"):
self.log.info("AttributeStorage: Creating table: items")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `items` (
`id` INTEGER PRIMARY KEY,
`item` varchar(512)
) ;""")
c.close()
if not self.db.tableExists("values"):
self.log.info("AttributeStorage: Creating table: values")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `values` (
`itemid` INTEGER NOT NULL,
`attributeid` INTEGER NOT NULL,
`value` TEXT,
PRIMARY KEY (`itemid`, `attributeid`)
) ;""")
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
:param name: the item
:type name: str
:returns: dict -- the item's values expressed as a dict"""
c = self.db.query("""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`
WHERE
`i`.`item`=?;""",
(name.lower(),)
)
item = {}
while True:
row = c.fetchone()
if row == None:
break
item[row["attribute"]]=row["value"]
c.close()
if len(item)==0:
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
:param item: the item to fetch a key from
:type item: str
:param key: they key who's value to return
:type key: str
:returns: str -- the item from the database or **None**"""
c = self.db.query("""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`
WHERE
`i`.`item`=?
AND
`a`.`attribute`=?;""",
(item.lower(),key.lower())
)
row = c.fetchone()
c.close()
if row == 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
:param item: the item name to set the key on
:type item: str
:param key: the key to set
:type key: tuple
:param value: the value to set
:type value: str"""
item = item.lower()
attribute = key.lower()
# Check attribute exists
c = self.db.query("SELECT `id` FROM `attribute` WHERE `attribute`=?;", (attribute,))
row = c.fetchone()
attributeId = -1
if row == None:
c = self.db.query("INSERT INTO `attribute` (`attribute`) VALUES (?);", (attribute,))
attributeId = c.lastrowid
else:
attributeId = row["id"]
c.close()
# check item exists
c = self.db.query("SELECT `id` FROM `items` WHERE `item`=?;", (item,))
row = c.fetchone()
itemId = -1
if row == None:
c = self.db.query("INSERT INTO `items` (`item`) VALUES (?);", (item,))
itemId = c.lastrowid
else:
itemId = row["id"]
c.close()
if value == None:
# delete it
c = self.db.query("DELETE FROM `values` WHERE `itemid`=? AND `attributeid`=? ;", (itemId, attributeId))
self.log.debug("AttributeStorage: 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))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["attributes"]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("AttributeStorage: Could not find a valid sqlite service provider")
else:
self.log.info("AttributeStorage: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("attributes.db")
if not self.db.tableExists("attribute"):
self.log.info("AttributeStorage: Creating table: attribute")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `attribute` (
`id` INTEGER PRIMARY KEY,
`attribute` varchar(128) UNIQUE
) ;""")
c.close()
if not self.db.tableExists("items"):
self.log.info("AttributeStorage: Creating table: items")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `items` (
`id` INTEGER PRIMARY KEY,
`item` varchar(512)
) ;""")
c.close()
if not self.db.tableExists("values"):
self.log.info("AttributeStorage: Creating table: values")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `values` (
`itemid` INTEGER NOT NULL,
`attributeid` INTEGER NOT NULL,
`value` TEXT,
PRIMARY KEY (`itemid`, `attributeid`)
) ;""")
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
:param name: the item
:type name: str
:returns: dict -- the item's values expressed as a dict"""
c = self.db.query("""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`
WHERE
`i`.`item`=?;""",
(name.lower(),)
)
item = {}
while True:
row = c.fetchone()
if row == None:
break
item[row["attribute"]]=row["value"]
c.close()
if len(item)==0:
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
:param item: the item to fetch a key from
:type item: str
:param key: they key who's value to return
:type key: str
:returns: str -- the item from the database or **None**"""
c = self.db.query("""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`
WHERE
`i`.`item`=?
AND
`a`.`attribute`=?;""",
(item.lower(),key.lower())
)
row = c.fetchone()
c.close()
if row == 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
:param item: the item name to set the key on
:type item: str
:param key: the key to set
:type key: tuple
:param value: the value to set
:type value: str"""
item = item.lower()
attribute = key.lower()
# Check attribute exists
c = self.db.query("SELECT `id` FROM `attribute` WHERE `attribute`=?;", (attribute,))
row = c.fetchone()
attributeId = -1
if row == None:
c = self.db.query("INSERT INTO `attribute` (`attribute`) VALUES (?);", (attribute,))
attributeId = c.lastrowid
else:
attributeId = row["id"]
c.close()
# check item exists
c = self.db.query("SELECT `id` FROM `items` WHERE `item`=?;", (item,))
row = c.fetchone()
itemId = -1
if row == None:
c = self.db.query("INSERT INTO `items` (`item`) VALUES (?);", (item,))
itemId = c.lastrowid
else:
itemId = row["id"]
c.close()
if value == None:
# delete it
c = self.db.query("DELETE FROM `values` WHERE `itemid`=? AND `attributeid`=? ;", (itemId, attributeId))
self.log.debug("AttributeStorage: 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))
self.log.debug("AttributeStorage: Stored item %s attribute %s value: %s" % (itemId, attributeId, value))
c.close()

View File

@ -1,6 +1,6 @@
"""
.. module:: BitcoinPrice
:synopsis: Provides .bitcoin to show price indexes
:synopsis: Provides .bitcoin to show price indexes
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,32 +11,32 @@ from requests import get
from time import time
class BitcoinPrice(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.cache = None
self.cacheAge = 0
self.hooks=[
ModuleHook(["PRIVMSG"], self.btc)
]
def btc(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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'])
))
def getApi(self):
if self.cache == 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
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.cache = None
self.cacheAge = 0
self.hooks=[
ModuleHook(["PRIVMSG"], self.btc)
]
def btc(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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'])
))
def getApi(self):
if self.cache == 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

@ -4,258 +4,258 @@ import time
import math
class Calc(ModuleBase):
def __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:
self.log.error("Calc: SQLIite service is required.")
return
self.sql = self.sqlite.opendb("calc.db")
if not self.sql.tableExists("calc_addedby"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_addedby` (
`id` INTEGER PRIMARY KEY,
`username` varchar(32),
`userhost` varchar(128)
) ;
""")
c.close()
if not self.sql.tableExists("calc_channels"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_channels` (
`id` INTEGER PRIMARY KEY,
`channel` varchar(32)
) ;
""")
if not self.sql.tableExists("calc_definitions"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_definitions` (
`id` INTEGER PRIMARY KEY,
`word` INTEGET,
`definition` varchar(512),
`addedby` INTEGER,
`date` timestamp,
`status` varchar(16)
) ;
""")
if not self.sql.tableExists("calc_words"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_words` (
`id` INTEGER PRIMARY KEY,
`channel` INTEGER,
`word` varchar(512),
`status` varchar(32),
unique(`channel`,`word`)
);
""")
c.close()
def timeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
return time.time()-self.timers[channel][timetype]
def updateTimeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
self.timers[channel][timetype] = time.time()
def createDefaultTimers(self, channel):
self.timers[channel]={"add":0, "calc":0, "calcspec":0, "match":0}
def remainingToStr(self, total, elasped):
remaining = total-elasped
minutes = int(math.floor(remaining/60))
seconds = int(remaining - (minutes*60))
return "Please wait %s minute(s) and %s second(s)." % (minutes, seconds)
def calc(self, args, prefix, trailing):
# Channel only
if not args[0][0]=="#":
return
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
foundCalc=True
if foundCalc:
calcCmd = trailing[len(cmd)-1:].strip()
if "=" in calcCmd[1:]:
" Add a new calc "
calcWord, calcDefinition = calcCmd.split("=", 1)
calcWord = calcWord.strip()
calcDefinition = calcDefinition.strip()
if self.config["allowDelete"] and calcDefinition == "":
result = self.deleteCalc(args[0], calcWord)
if result:
self.bot.act_PRIVMSG(args[0], "Calc deleted, %s." % sender.nick)
else:
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")))
else:
self.addNewCalc(args[0], calcWord, calcDefinition, prefix)
self.bot.act_PRIVMSG(args[0], "Thanks for the info, %s." % sender.nick)
self.updateTimeSince(args[0], "add")
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")))
else:
randCalc = self.getSpecificCalc(args[0], calcCmd)
if randCalc==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.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")))
else:
randCalc = self.getRandomCalc(args[0])
if randCalc == 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.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")))
else:
term = cmd.args_str
if 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))
rows = c.fetchall()
if len(rows)==0:
self.bot.act_PRIVMSG(args[0], "%s: Sorry, no matches" % sender.nick)
else:
matches = []
for row in rows[0:10]:
if row == None:
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.updateTimeSince(args[0], "match")
def addNewCalc(self, channel, word, definition, prefix):
sender = self.bot.decodePrefix(prefix)
" Find the channel ID"
channelId = self.getChannelId(channel)
" Check if we need to add a user"
c = self.sql.getCursor()
name = sender.nick
host = sender.hostname
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
if len(rows)==0:
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()
addedId = rows[0]["id"]
" 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'))
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.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()))
word = c.fetchone()
if word == 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"], ))
who = c.fetchone()
if who == 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,))
word = c.fetchone()
if word == 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"], ))
who = c.fetchone()
if who == None:
continue
c.close()
return {"word":word["word"], "definition":who["definition"], "by":who["username"]}
def deleteCalc(self, channel, word):
" Return true if deleted something, false if it doesnt exist"
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? and `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
c.close()
return False
wordId = rows[0]["id"]
#c.execute("DELETE FROM `calc_words` WHERE `id`=? ;", (wordId,))
#c.execute("DELETE FROM `calc_definitions` WHERE `word`=? ;", (wordId,))
c.execute("UPDATE `calc_definitions` SET `status`='deleted' WHERE `word`=? ;", (wordId,))
c.close()
return True
def getChannelId(self, channel):
c = self.sql.getCursor()
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_channels` (`channel`) VALUES (?);", (channel,))
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
chId = rows[0]["id"]
c.close()
return chId
def __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:
self.log.error("Calc: SQLIite service is required.")
return
self.sql = self.sqlite.opendb("calc.db")
if not self.sql.tableExists("calc_addedby"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_addedby` (
`id` INTEGER PRIMARY KEY,
`username` varchar(32),
`userhost` varchar(128)
) ;
""")
c.close()
if not self.sql.tableExists("calc_channels"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_channels` (
`id` INTEGER PRIMARY KEY,
`channel` varchar(32)
) ;
""")
if not self.sql.tableExists("calc_definitions"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_definitions` (
`id` INTEGER PRIMARY KEY,
`word` INTEGET,
`definition` varchar(512),
`addedby` INTEGER,
`date` timestamp,
`status` varchar(16)
) ;
""")
if not self.sql.tableExists("calc_words"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_words` (
`id` INTEGER PRIMARY KEY,
`channel` INTEGER,
`word` varchar(512),
`status` varchar(32),
unique(`channel`,`word`)
);
""")
c.close()
def timeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
return time.time()-self.timers[channel][timetype]
def updateTimeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
self.timers[channel][timetype] = time.time()
def createDefaultTimers(self, channel):
self.timers[channel]={"add":0, "calc":0, "calcspec":0, "match":0}
def remainingToStr(self, total, elasped):
remaining = total-elasped
minutes = int(math.floor(remaining/60))
seconds = int(remaining - (minutes*60))
return "Please wait %s minute(s) and %s second(s)." % (minutes, seconds)
def calc(self, args, prefix, trailing):
# Channel only
if not args[0][0]=="#":
return
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
foundCalc=True
if foundCalc:
calcCmd = trailing[len(cmd)-1:].strip()
if "=" in calcCmd[1:]:
" Add a new calc "
calcWord, calcDefinition = calcCmd.split("=", 1)
calcWord = calcWord.strip()
calcDefinition = calcDefinition.strip()
if self.config["allowDelete"] and calcDefinition == "":
result = self.deleteCalc(args[0], calcWord)
if result:
self.bot.act_PRIVMSG(args[0], "Calc deleted, %s." % sender.nick)
else:
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")))
else:
self.addNewCalc(args[0], calcWord, calcDefinition, prefix)
self.bot.act_PRIVMSG(args[0], "Thanks for the info, %s." % sender.nick)
self.updateTimeSince(args[0], "add")
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")))
else:
randCalc = self.getSpecificCalc(args[0], calcCmd)
if randCalc==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.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")))
else:
randCalc = self.getRandomCalc(args[0])
if randCalc == 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.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")))
else:
term = cmd.args_str
if 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))
rows = c.fetchall()
if len(rows)==0:
self.bot.act_PRIVMSG(args[0], "%s: Sorry, no matches" % sender.nick)
else:
matches = []
for row in rows[0:10]:
if row == None:
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.updateTimeSince(args[0], "match")
def addNewCalc(self, channel, word, definition, prefix):
sender = self.bot.decodePrefix(prefix)
" Find the channel ID"
channelId = self.getChannelId(channel)
" Check if we need to add a user"
c = self.sql.getCursor()
name = sender.nick
host = sender.hostname
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
if len(rows)==0:
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()
addedId = rows[0]["id"]
" 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'))
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.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()))
word = c.fetchone()
if word == 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"], ))
who = c.fetchone()
if who == 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,))
word = c.fetchone()
if word == 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"], ))
who = c.fetchone()
if who == None:
continue
c.close()
return {"word":word["word"], "definition":who["definition"], "by":who["username"]}
def deleteCalc(self, channel, word):
" Return true if deleted something, false if it doesnt exist"
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? and `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
c.close()
return False
wordId = rows[0]["id"]
#c.execute("DELETE FROM `calc_words` WHERE `id`=? ;", (wordId,))
#c.execute("DELETE FROM `calc_definitions` WHERE `word`=? ;", (wordId,))
c.execute("UPDATE `calc_definitions` SET `status`='deleted' WHERE `word`=? ;", (wordId,))
c.close()
return True
def getChannelId(self, channel):
c = self.sql.getCursor()
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_channels` (`channel`) VALUES (?);", (channel,))
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
chId = rows[0]["id"]
c.close()
return chId

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Error
:synopsis: Module to provide a multi-type cryptocurrency wallet
:synopsis: Module to provide a multi-type cryptocurrency wallet
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,214 +12,214 @@ import time
import hashlib
class CryptoWallet(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def getMods(self):
return (self.bot.getBestModuleForService("attributes"), self.bot.getBestModuleForService("login"), self.bot.getBestModuleForService("bitcoinrpc"))
def handle_setaddr(self, args, prefix, trailing, cmd):
usage = ".setaddr <currency> <address>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==2:
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: usage: .setaddr BTC 1xyWx6X5EABprhe3s9XduNxLn5NCtpSNB")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".setaddr: '%s' appears to be an invalid address." % (cmd.args[1]))
return
# Just make sure they have a wallet
self.checkUserHasWallet(prefix.nick, cmd.args[0])
# Set their address
attr.setKey(prefix.nick, "cryptowallet-%s-address"%cmd.args[0].lower(), cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".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>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".getbal: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==1:
self.bot.act_PRIVMSG(prefix.nick, ".getbal: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".getbal: usage: .getbal BTC")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".getbal: '%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])
# fetch RPC and tell them the balance
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s"%cmd.args[0].lower())
amount = 0.0
if walletname:
client = rpc.getRpc(cmd.args[0].lower())
amount = client.getBal(walletname)
self.bot.act_PRIVMSG(prefix.nick, "Your balance is: %s %s" % (amount, cmd.args[0].upper()))
def handle_withdraw(self, args, prefix, trailing, cmd):
usage = ".withdraw <currency> <amount>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==2:
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: usage: .getbal BTC 0.035")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".getbal: '%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])
# 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(prefix.nick, ".withdraw: You need to set a withdraw address before withdrawing. Try .setaddr")
return
# fetch RPC and check balance
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s"%cmd.args[0].lower())
balance = 0.0
client = rpc.getRpc(cmd.args[0].lower())
balance = client.getBal(walletname)
withdrawamount = float(cmd.args[1])
if balance < withdrawamount or withdrawamount<0:
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".withdraw: Withdrawing that much would put you below the reserve (%s %s)." % (client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".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(prefix.nick, ".withdraw: %s %s sent to %s. Transaction ID: %s"% (withdrawamount, client.name, withdrawaddr, txn))
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: Transaction create failed. Maybe the transaction was too large for the network? Try a smaller increment.")
def handle_getaddr(self, args, prefix, trailing, cmd):
attr,login,rpc = self.getMods()
usage = ".getaddr <currency>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==1:
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: usage: .getaddr BTC")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, "Your %s deposit address is: %s" % (cmd.args[0].upper(), walletaddr))
def handle_curinfo(self, args, prefix, trailing, cmd):
attr,login,rpc = self.getMods()
usage = ".curinfo [<currency>]"
attr,login,rpc = self.getMods()
# Check for args
if len(cmd.args)==0:
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".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(prefix.nick, ".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,login,rpc = self.getMods()
currency = currency.lower()
if attr.getKey(username, "cryptowallet-account-%s"%currency)==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:
walletName = attr.getKey(username, "cryptowallet-account-%s"%currency)
wallet = rpc.getRpc(currency.lower())
address = wallet.getAcctAddr(walletName)
attr.setKey(username, "cryptowallet-depoaddr-%s"%currency, address)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
cmd = self.bot.messageHasCommand(".setaddr", trailing)
if cmd:
self.handle_setaddr(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".getbal", trailing)
if cmd:
self.handle_getbal(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".withdraw", trailing)
if cmd:
self.handle_withdraw(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".getaddr", trailing)
if cmd:
self.handle_getaddr(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".curinfo", trailing)
if cmd:
self.handle_curinfo(args, prefix, trailing, cmd)
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def getMods(self):
return (self.bot.getBestModuleForService("attributes"), self.bot.getBestModuleForService("login"), self.bot.getBestModuleForService("bitcoinrpc"))
def handle_setaddr(self, args, prefix, trailing, cmd):
usage = ".setaddr <currency> <address>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==2:
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".setaddr: usage: .setaddr BTC 1xyWx6X5EABprhe3s9XduNxLn5NCtpSNB")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".setaddr: '%s' appears to be an invalid address." % (cmd.args[1]))
return
# Just make sure they have a wallet
self.checkUserHasWallet(prefix.nick, cmd.args[0])
# Set their address
attr.setKey(prefix.nick, "cryptowallet-%s-address"%cmd.args[0].lower(), cmd.args[1])
self.bot.act_PRIVMSG(prefix.nick, ".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>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".getbal: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==1:
self.bot.act_PRIVMSG(prefix.nick, ".getbal: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".getbal: usage: .getbal BTC")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".getbal: '%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])
# fetch RPC and tell them the balance
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s"%cmd.args[0].lower())
amount = 0.0
if walletname:
client = rpc.getRpc(cmd.args[0].lower())
amount = client.getBal(walletname)
self.bot.act_PRIVMSG(prefix.nick, "Your balance is: %s %s" % (amount, cmd.args[0].upper()))
def handle_withdraw(self, args, prefix, trailing, cmd):
usage = ".withdraw <currency> <amount>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==2:
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: usage: .getbal BTC 0.035")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".getbal: '%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])
# 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(prefix.nick, ".withdraw: You need to set a withdraw address before withdrawing. Try .setaddr")
return
# fetch RPC and check balance
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s"%cmd.args[0].lower())
balance = 0.0
client = rpc.getRpc(cmd.args[0].lower())
balance = client.getBal(walletname)
withdrawamount = float(cmd.args[1])
if balance < withdrawamount or withdrawamount<0:
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".withdraw: Withdrawing that much would put you below the reserve (%s %s)." % (client.reserve, cmd.args[0].upper()))
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".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(prefix.nick, ".withdraw: %s %s sent to %s. Transaction ID: %s"% (withdrawamount, client.name, withdrawaddr, txn))
else:
self.bot.act_PRIVMSG(prefix.nick, ".withdraw: Transaction create failed. Maybe the transaction was too large for the network? Try a smaller increment.")
def handle_getaddr(self, args, prefix, trailing, cmd):
attr,login,rpc = self.getMods()
usage = ".getaddr <currency>"
attr,login,rpc = self.getMods()
# Check login
if not login.check(prefix.nick, prefix.hostname):
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: Please .login to use this command.")
return
# Check for args
if not len(cmd.args)==1:
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: usage: %s" % usage)
self.bot.act_PRIVMSG(prefix.nick, ".getaddr: usage: .getaddr BTC")
return
# Check if currency is known
if not rpc.isSupported(cmd.args[0]):
supportedStr = ', '.join(rpc.getSupported())
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, "Your %s deposit address is: %s" % (cmd.args[0].upper(), walletaddr))
def handle_curinfo(self, args, prefix, trailing, cmd):
attr,login,rpc = self.getMods()
usage = ".curinfo [<currency>]"
attr,login,rpc = self.getMods()
# Check for args
if len(cmd.args)==0:
self.bot.act_PRIVMSG(prefix.nick, ".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(prefix.nick, ".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(prefix.nick, ".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,login,rpc = self.getMods()
currency = currency.lower()
if attr.getKey(username, "cryptowallet-account-%s"%currency)==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:
walletName = attr.getKey(username, "cryptowallet-account-%s"%currency)
wallet = rpc.getRpc(currency.lower())
address = wallet.getAcctAddr(walletName)
attr.setKey(username, "cryptowallet-depoaddr-%s"%currency, address)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
cmd = self.bot.messageHasCommand(".setaddr", trailing)
if cmd:
self.handle_setaddr(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".getbal", trailing)
if cmd:
self.handle_getbal(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".withdraw", trailing)
if cmd:
self.handle_withdraw(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".getaddr", trailing)
if cmd:
self.handle_getaddr(args, prefix, trailing, cmd)
cmd = self.bot.messageHasCommand(".curinfo", trailing)
if cmd:
self.handle_curinfo(args, prefix, trailing, cmd)
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: CryptoWalletRPC
:synopsis: Module capable of operating bitcoind-style RPC. Provided as a service.
:synopsis: Module capable of operating bitcoind-style RPC. Provided as a service.
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -14,120 +14,120 @@ from threading import Thread
from time import sleep
class CryptoWalletRPC(ModuleBase):
def __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
def getRpc(self, currencyAbbr):
# Return the rpc for the currency requested
# self.getRpc("LTC") -> returns a litecoin rpc instance
currencyAbbr = currencyAbbr.lower()
if currencyAbbr in self.rpcservices:
return self.rpcservices[currencyAbbr]
return None
def getSupported(self):
# return a list of (appreviatons of) supported currencies
return list(self.rpcservices.keys())
def isSupported(self, abbr):
# true/false if currency is supported
supported = self.getSupported()
return abbr.lower() in supported
def getInfo(self, abbr):
# return the coin's info from config
if self.isSupported(abbr):
return self.config["types"][abbr.upper()]
def __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
def getRpc(self, currencyAbbr):
# Return the rpc for the currency requested
# self.getRpc("LTC") -> returns a litecoin rpc instance
currencyAbbr = currencyAbbr.lower()
if currencyAbbr in self.rpcservices:
return self.rpcservices[currencyAbbr]
return None
def getSupported(self):
# return a list of (appreviatons of) supported currencies
return list(self.rpcservices.keys())
def isSupported(self, abbr):
# true/false if currency is supported
supported = self.getSupported()
return abbr.lower() in supported
def getInfo(self, abbr):
# return the coin's info from config
if self.isSupported(abbr):
return self.config["types"][abbr.upper()]
class BitcoinRPC:
def __init__(self, parent, name, host, port, username, password, precision, reserve):
# Store info and connect
self.master = parent
self.name = name
self.host = host
self.port = port
self.username = username
self.password = password
self.precision = precision
self.reserve = reserve
self.log = self.master.log
# AuthServiceProxy (json client) stored here
self.con = None
# Connect
Thread(target=self.ping).start()
def getBal(self, acct):
# get a balance of an address or an account
return self.getAcctBal(acct)
def getAcctAddr(self, acct):
# returns the address for an account. creates if necessary
self.ping()
addrs = self.con.getaddressesbyaccount(acct)
if len(addrs)==0:
return self.con.getnewaddress(acct)
return addrs[0]
def getAcctBal(self, acct):
# returns an account's balance
self.ping()
return float(self.con.getbalance(acct))
def canMove(self, fromAcct, toAcct, amount):
# true or false if fromAcct can afford to give toAcct an amount of coins
balfrom = self.getAcctBal(fromAcct)
return balfrom >= amount
def move(self, fromAcct, toAcct, amount):
# move coins from one account to another
self.ping()
if self.canMove(fromAcct, toAcct, amount):
return self.con.move(fromAcct, toAcct, amount)
return False
def send(self, fromAcct, toAddr, amount):
# send coins to an external addr
self.ping()
if self.canMove(fromAcct, toAddr, amount):
return self.con.sendfrom(fromAcct, toAddr, amount)
return False
def checkPrecision(self, amount):
return amount == round(amount, self.precision)
def ping(self):
# internal. test connection and connect if necessary
try:
self.con.getinfo()
except:
self.connect()
def connect(self):
# internal. connect to the service
self.log.debug("CryptoWalletRPC: %s: Connecting to %s:%s" % (self.name, self.host,self.port))
try:
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.username, self.password, self.host, self.port))
except Exception as e:
self.log.debug("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" % (self.name, self.host, self.port, str(e)))
return
self.log.debug("CryptoWalletRPC: %s: Connected to %s:%s" % (self.name, self.host, self.port))
def __init__(self, parent, name, host, port, username, password, precision, reserve):
# Store info and connect
self.master = parent
self.name = name
self.host = host
self.port = port
self.username = username
self.password = password
self.precision = precision
self.reserve = reserve
self.log = self.master.log
# AuthServiceProxy (json client) stored here
self.con = None
# Connect
Thread(target=self.ping).start()
def getBal(self, acct):
# get a balance of an address or an account
return self.getAcctBal(acct)
def getAcctAddr(self, acct):
# returns the address for an account. creates if necessary
self.ping()
addrs = self.con.getaddressesbyaccount(acct)
if len(addrs)==0:
return self.con.getnewaddress(acct)
return addrs[0]
def getAcctBal(self, acct):
# returns an account's balance
self.ping()
return float(self.con.getbalance(acct))
def canMove(self, fromAcct, toAcct, amount):
# true or false if fromAcct can afford to give toAcct an amount of coins
balfrom = self.getAcctBal(fromAcct)
return balfrom >= amount
def move(self, fromAcct, toAcct, amount):
# move coins from one account to another
self.ping()
if self.canMove(fromAcct, toAcct, amount):
return self.con.move(fromAcct, toAcct, amount)
return False
def send(self, fromAcct, toAddr, amount):
# send coins to an external addr
self.ping()
if self.canMove(fromAcct, toAddr, amount):
return self.con.sendfrom(fromAcct, toAddr, amount)
return False
def checkPrecision(self, amount):
return amount == round(amount, self.precision)
def ping(self):
# internal. test connection and connect if necessary
try:
self.con.getinfo()
except:
self.connect()
def connect(self):
# internal. connect to the service
self.log.debug("CryptoWalletRPC: %s: Connecting to %s:%s" % (self.name, self.host,self.port))
try:
self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.username, self.password, self.host, self.port))
except Exception as e:
self.log.debug("CryptoWalletRPC: %s: Could not connect to %s:%s: %s" % (self.name, self.host, self.port, str(e)))
return
self.log.debug("CryptoWalletRPC: %s: Connected to %s:%s" % (self.name, self.host, self.port))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: DogeDice
:synopsis: Module to provide a game for gambling Dogecoin
:synopsis: Module to provide a game for gambling Dogecoin
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -16,307 +16,307 @@ 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
self.doge = self.bot.getBestModuleForService("dogerpc")
# Dict of #channel -> game object
self.games = {}
def gotMsg(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
# Ignore messages from users not logged in
loggedinfrom = self.attr.getKey(prefixObj.nick, "loggedinfrom")
if loggedinfrom==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"]) ):
self.games[args[0]]=gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
else:
# Private message
#self.games[args[0].gotPrivMsg(args, prefix, trailing)
pass
else:
# Ignore potential spoofing
pass
def removeGame(self, channel):
del self.games[channel]
def ondisable(self):
self.log.info("DogeDice: Unload requested, ending games...")
while len(self.games)>0:
first = list(self.games.keys())[0]
self.games[first].gameover()
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
self.doge = self.bot.getBestModuleForService("dogerpc")
# Dict of #channel -> game object
self.games = {}
def gotMsg(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
# Ignore messages from users not logged in
loggedinfrom = self.attr.getKey(prefixObj.nick, "loggedinfrom")
if loggedinfrom==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"]) ):
self.games[args[0]]=gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
else:
# Private message
#self.games[args[0].gotPrivMsg(args, prefix, trailing)
pass
else:
# Ignore potential spoofing
pass
def removeGame(self, channel):
del self.games[channel]
def ondisable(self):
self.log.info("DogeDice: Unload requested, ending games...")
while len(self.games)>0:
first = list(self.games.keys())[0]
self.games[first].gameover()
class gameObj:
def __init__(self, master, channel):
self.master = master
self.channel = channel
# Game state
# 0 = waiting for players
# - advertise self?
# - players must be registered and have enough doge for current bet
# 1 = enough players, countdown
# - Last warning to pull out
# 2 = locked in / game setup
# - Move doge from player's wallets to table wallet. kick players if they can't afford
# 3 = start of a round
# - Each player's turn to roll
# 4 = determine winner, move doge
# - if > 10 doge, house fee?
self.step = 0
# Bet amount
self.bet = 0.0
# players list
self.players = []
# min players
self.minPlayers = 2
# max players
self.maxPlayers = 4
# Lobby countdown timer
self.startCountdownTimer = None
# pre-result timer
self.endgameResultTimer = None
# in-game timeout
self.playTimeout = None
# Wallet for this game
self.walletName = None
def getPlayer(self, nick):
for player in self.players:
if player.nick == nick:
return player
return None
def gotPrivMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
def gotMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
if self.step == 0 or self.step == 1:
# Join game
cmd = self.master.bot.messageHasCommand(".join", trailing)
if cmd:
if len(self.players)-1 < self.maxPlayers:
if self.getPlayer(prefix.nick)==None:
userWallet = self.master.attr.getKey(prefix.nick, "dogeaccountname")
if userWallet == 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:
# require an amount
if len(cmd.args)==1:
# Check if they have enough coins
try:
bet = float(cmd.args[0])
except:
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"]))
return
if balance>=bet:
newPlayer = playerObj(self, prefix.nick)
newPlayer.dogeWalletName = userWallet
self.players.append(newPlayer)
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))
else:
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:
newPlayer = playerObj(self, prefix.nick)
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:
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))
else:
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))
else:
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:
self.master.bot.act_PRIVMSG(self.channel, "%s: You're not in the game." % (prefix.nick))
else:
self.removePlayer(prefix.nick)
self.master.bot.act_PRIVMSG(self.channel, "%s: You have left the game!" % (prefix.nick))
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.step = 0
elif self.step == 2:
pass
elif self.step == 3:
# Ignore cmds from people outside the game
player = self.getPlayer(prefix.nick)
if not player:
return
# handle a .roll
cmd = self.master.bot.messageHasCommand(".roll", trailing)
if cmd and not player.hasRolled:
roll1 = random.randint(1,6)
roll2 = random.randint(1,6)
self.master.bot.act_PRIVMSG(self.channel, "%s rolls %s and %s!" % (prefix.nick, roll1, roll2))
player.hasRolled = True
player.rollValue = roll1+roll2
# Check if all players have rolled
for player in self.players:
if not player.hasRolled:
return
# start endgame timer
self.step = 4
self.endgameResultTimer = Timer(2, self.endgameResults)
self.endgameResultTimer.start()
elif self.step == 4:
pass
#senderIsOp = self.master.attr.getKey(prefix.nick, "op")=="yes"
def clearTimer(self, timer):
if timer:
timer.cancel()
timer = None
def removePlayer(self, playerNick):
pos = -1
for i in range(0, len(self.players)):
if self.players[i].nick == playerNick:
pos = i
break
if pos >= 0:
self.players.pop(pos)
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)
self.startCountdownTimer.start()
self.step = 1
def lobbyCountdownDone(self):
self.step = 2
self.master.bot.act_PRIVMSG(self.channel, "Collecting DOGE and starting game.. Type .roll !")
# Make a wallet for this game
self.walletName = "DogeDice-"+self.channel
# Generate an address to 'create' a wallet
self.master.doge.getAcctAddr(self.walletName)
# Verify and move funds from each player
for player in self.players:
playerBalance = self.master.doge.getAcctBal(player.dogeWalletName)
if playerBalance < self.bet:
self.master.bot.act_PRIVMSG(self.channel, "%s was dropped from the game!")
self.removePlayer(player.nick)
if len(self.players) <= 1:
self.master.bot.act_PRIVMSG(self.channel, "1 or players left - game over!")
self.resetGame()
return
# Take doges
for player in self.players:
self.master.doge.move(player.dogeWalletName, self.walletName, self.bet)
# Pre-game setup (nothing !)
# Accept game commands
self.step = 3
# Start play timeout
self.playTimeout = Timer(30, self.gamePlayTimeoutExpired)
self.playTimeout.start()
def gamePlayTimeoutExpired(self):
# Time out - return doges
self.master.bot.act_PRIVMSG(self.channel, "Time expired! Returning all doges.")
if self.step == 3:
# In game step. Refund doges
for player in self.players:
self.master.doge.move(self.walletName, player.dogeWalletName, self.bet)
self.resetGame()
def endgameResults(self):
maxRollNames = []
maxRollValue = 0
for player in self.players:
if player.rollValue > maxRollValue:
maxRollNames = []
maxRollNames.append(player.nick)
maxRollValue = player.rollValue
if player.rollValue == maxRollValue:
if not player.nick in maxRollNames:
maxRollNames.append(player.nick)
pot = self.master.doge.getAcctBal(self.walletName)
DOGEeachDec = pot/len(maxRollNames)
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))
else:
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:
player = self.getPlayer(nick)
self.master.doge.move(self.walletName, player.dogeWalletName, DOGEeach)
# the end!
self.resetGame()
def resetGame(self):
self.clearTimer(self.startCountdownTimer)
self.startCountdownTimer = None
self.clearTimer(self.endgameResultTimer)
self.endgameResultTimer = None
self.clearTimer(self.playTimeout)
self.playTimeout = None
self.master.removeGame(self.channel)
def gameover(self):
self.gamePlayTimeoutExpired()
def __init__(self, master, channel):
self.master = master
self.channel = channel
# Game state
# 0 = waiting for players
# - advertise self?
# - players must be registered and have enough doge for current bet
# 1 = enough players, countdown
# - Last warning to pull out
# 2 = locked in / game setup
# - Move doge from player's wallets to table wallet. kick players if they can't afford
# 3 = start of a round
# - Each player's turn to roll
# 4 = determine winner, move doge
# - if > 10 doge, house fee?
self.step = 0
# Bet amount
self.bet = 0.0
# players list
self.players = []
# min players
self.minPlayers = 2
# max players
self.maxPlayers = 4
# Lobby countdown timer
self.startCountdownTimer = None
# pre-result timer
self.endgameResultTimer = None
# in-game timeout
self.playTimeout = None
# Wallet for this game
self.walletName = None
def getPlayer(self, nick):
for player in self.players:
if player.nick == nick:
return player
return None
def gotPrivMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
def gotMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
if self.step == 0 or self.step == 1:
# Join game
cmd = self.master.bot.messageHasCommand(".join", trailing)
if cmd:
if len(self.players)-1 < self.maxPlayers:
if self.getPlayer(prefix.nick)==None:
userWallet = self.master.attr.getKey(prefix.nick, "dogeaccountname")
if userWallet == 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:
# require an amount
if len(cmd.args)==1:
# Check if they have enough coins
try:
bet = float(cmd.args[0])
except:
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"]))
return
if balance>=bet:
newPlayer = playerObj(self, prefix.nick)
newPlayer.dogeWalletName = userWallet
self.players.append(newPlayer)
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))
else:
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:
newPlayer = playerObj(self, prefix.nick)
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:
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))
else:
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))
else:
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:
self.master.bot.act_PRIVMSG(self.channel, "%s: You're not in the game." % (prefix.nick))
else:
self.removePlayer(prefix.nick)
self.master.bot.act_PRIVMSG(self.channel, "%s: You have left the game!" % (prefix.nick))
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.step = 0
elif self.step == 2:
pass
elif self.step == 3:
# Ignore cmds from people outside the game
player = self.getPlayer(prefix.nick)
if not player:
return
# handle a .roll
cmd = self.master.bot.messageHasCommand(".roll", trailing)
if cmd and not player.hasRolled:
roll1 = random.randint(1,6)
roll2 = random.randint(1,6)
self.master.bot.act_PRIVMSG(self.channel, "%s rolls %s and %s!" % (prefix.nick, roll1, roll2))
player.hasRolled = True
player.rollValue = roll1+roll2
# Check if all players have rolled
for player in self.players:
if not player.hasRolled:
return
# start endgame timer
self.step = 4
self.endgameResultTimer = Timer(2, self.endgameResults)
self.endgameResultTimer.start()
elif self.step == 4:
pass
#senderIsOp = self.master.attr.getKey(prefix.nick, "op")=="yes"
def clearTimer(self, timer):
if timer:
timer.cancel()
timer = None
def removePlayer(self, playerNick):
pos = -1
for i in range(0, len(self.players)):
if self.players[i].nick == playerNick:
pos = i
break
if pos >= 0:
self.players.pop(pos)
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)
self.startCountdownTimer.start()
self.step = 1
def lobbyCountdownDone(self):
self.step = 2
self.master.bot.act_PRIVMSG(self.channel, "Collecting DOGE and starting game.. Type .roll !")
# Make a wallet for this game
self.walletName = "DogeDice-"+self.channel
# Generate an address to 'create' a wallet
self.master.doge.getAcctAddr(self.walletName)
# Verify and move funds from each player
for player in self.players:
playerBalance = self.master.doge.getAcctBal(player.dogeWalletName)
if playerBalance < self.bet:
self.master.bot.act_PRIVMSG(self.channel, "%s was dropped from the game!")
self.removePlayer(player.nick)
if len(self.players) <= 1:
self.master.bot.act_PRIVMSG(self.channel, "1 or players left - game over!")
self.resetGame()
return
# Take doges
for player in self.players:
self.master.doge.move(player.dogeWalletName, self.walletName, self.bet)
# Pre-game setup (nothing !)
# Accept game commands
self.step = 3
# Start play timeout
self.playTimeout = Timer(30, self.gamePlayTimeoutExpired)
self.playTimeout.start()
def gamePlayTimeoutExpired(self):
# Time out - return doges
self.master.bot.act_PRIVMSG(self.channel, "Time expired! Returning all doges.")
if self.step == 3:
# In game step. Refund doges
for player in self.players:
self.master.doge.move(self.walletName, player.dogeWalletName, self.bet)
self.resetGame()
def endgameResults(self):
maxRollNames = []
maxRollValue = 0
for player in self.players:
if player.rollValue > maxRollValue:
maxRollNames = []
maxRollNames.append(player.nick)
maxRollValue = player.rollValue
if player.rollValue == maxRollValue:
if not player.nick in maxRollNames:
maxRollNames.append(player.nick)
pot = self.master.doge.getAcctBal(self.walletName)
DOGEeachDec = pot/len(maxRollNames)
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))
else:
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:
player = self.getPlayer(nick)
self.master.doge.move(self.walletName, player.dogeWalletName, DOGEeach)
# the end!
self.resetGame()
def resetGame(self):
self.clearTimer(self.startCountdownTimer)
self.startCountdownTimer = None
self.clearTimer(self.endgameResultTimer)
self.endgameResultTimer = None
self.clearTimer(self.playTimeout)
self.playTimeout = None
self.master.removeGame(self.channel)
def gameover(self):
self.gamePlayTimeoutExpired()
class playerObj:
def __init__(self, game, nick):
self.game = game
self.nick = nick
# Save the player's wallet name
self.dogeWalletName = None
# Set to true after they roll
self.hasRolled = False
# Sum of their dice
self.rollValue = None
def __init__(self, game, nick):
self.game = game
self.nick = nick
# Save the player's wallet name
self.dogeWalletName = None
# Set to true after they roll
self.hasRolled = False
# Sum of their dice
self.rollValue = None

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: DogeWallet
:synopsis: Module to provide a Dogecoin wallet
:synopsis: Module to provide a Dogecoin wallet
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,161 +12,161 @@ import time
import hashlib
class DogeWallet(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
# Load attribute storage
self.attr = self.bot.getBestModuleForService("attributes")
# Load doge RPC
self.doge = self.bot.getBestModuleForService("dogerpc")
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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\"")
else:
oldpass = self.attr.getKey(prefix.nick, "password")
if oldpass == 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])
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.")
cmd = self.bot.messageHasCommand(".setdogeaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==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])
# if they don't have a wallet name, we'll make one now
if self.attr.getKey(prefix.nick, "dogeaccountname")==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\"")
cmd = self.bot.messageHasCommand(".getdogebal", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
amount = 0.0
if walletname:
amount = self.doge.getBal(walletname)
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: Your balance is: %s DOGE" % amount)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: usage: \".getdogebal password\"")
cmd = self.bot.messageHasCommand(".withdrawdoge", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
useraddr = self.attr.getKey(prefix.nick, "dogeaddr")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a password with .setpass")
elif useraddr==None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a withdraw address .setdogeaddr")
else:
if len(cmd.args)==2:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
walletbal = self.doge.getBal(walletname)
desiredAmount = float(cmd.args[1])
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))
else:
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))
#################
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\" - ")
cmd = self.bot.messageHasCommand(".getdepositaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
addr = self.doge.getAcctAddr(walletname)
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: Your deposit address is: %s" % addr)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: incorrect password.")
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:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
self.attr.setKey(prefix.nick, "loggedinfrom", prefix.hostname)
self.bot.act_PRIVMSG(prefix.nick, ".login: You have been logged in from: %s" % prefix.hostname)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: usage: \".login password\"")
cmd = self.bot.messageHasCommand(".logout", trailing)
if cmd:
loggedin = self.attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
self.attr.setKey(prefix.nick, "loggedinfrom", None)
self.bot.act_PRIVMSG(prefix.nick, ".logout: You have been logged out.")
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
# Load attribute storage
self.attr = self.bot.getBestModuleForService("attributes")
# Load doge RPC
self.doge = self.bot.getBestModuleForService("dogerpc")
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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\"")
else:
oldpass = self.attr.getKey(prefix.nick, "password")
if oldpass == 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])
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.")
cmd = self.bot.messageHasCommand(".setdogeaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==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])
# if they don't have a wallet name, we'll make one now
if self.attr.getKey(prefix.nick, "dogeaccountname")==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\"")
cmd = self.bot.messageHasCommand(".getdogebal", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
amount = 0.0
if walletname:
amount = self.doge.getBal(walletname)
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: Your balance is: %s DOGE" % amount)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdogebal: usage: \".getdogebal password\"")
cmd = self.bot.messageHasCommand(".withdrawdoge", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
useraddr = self.attr.getKey(prefix.nick, "dogeaddr")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a password with .setpass")
elif useraddr==None:
self.bot.act_PRIVMSG(prefix.nick, ".withdrawdoge: You must first set a withdraw address .setdogeaddr")
else:
if len(cmd.args)==2:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
walletbal = self.doge.getBal(walletname)
desiredAmount = float(cmd.args[1])
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))
else:
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))
#################
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\" - ")
cmd = self.bot.messageHasCommand(".getdepositaddr", trailing)
if cmd:
userpw = self.attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
walletname = self.attr.getKey(prefix.nick, "dogeaccountname")
addr = self.doge.getAcctAddr(walletname)
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: Your deposit address is: %s" % addr)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".getdepositaddr: incorrect password.")
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:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
self.attr.setKey(prefix.nick, "loggedinfrom", prefix.hostname)
self.bot.act_PRIVMSG(prefix.nick, ".login: You have been logged in from: %s" % prefix.hostname)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: usage: \".login password\"")
cmd = self.bot.messageHasCommand(".logout", trailing)
if cmd:
loggedin = self.attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
self.attr.setKey(prefix.nick, "loggedinfrom", None)
self.bot.act_PRIVMSG(prefix.nick, ".logout: You have been logged out.")
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()

View File

@ -1,6 +1,6 @@
"""
.. module:: Error
:synopsis: Module to deliberately cause an error for testing handling.
:synopsis: Module to deliberately cause an error for testing handling.
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -10,19 +10,19 @@
from pyircbot.modulebase import ModuleBase,ModuleHook
class Error(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks=[ModuleHook("PRIVMSG", self.error)]
def error(self, args, prefix, trailing):
"""If the message recieved from IRC has the string "error" in it, cause a ZeroDivisionError
:param args: IRC args received
:type args: list
:param prefix: IRC prefix of sender
:type prefix: str
:param trailing: IRC message body
:type trailing: str"""
if "error" in trailing:
print(10/0)
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks=[ModuleHook("PRIVMSG", self.error)]
def error(self, args, prefix, trailing):
"""If the message recieved from IRC has the string "error" in it, cause a ZeroDivisionError
:param args: IRC args received
:type args: list
:param prefix: IRC prefix of sender
:type prefix: str
:param trailing: IRC message body
:type trailing: str"""
if "error" in trailing:
print(10/0)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: GameBase
:synopsis: A codebase for making IRC games
:synopsis: A codebase for making IRC games
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -14,59 +14,59 @@ import time
from threading import Timer
class GameBase(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
self.doge = self.bot.getBestModuleForService("dogerpc")
# Dict of #channel -> game object
self.games = {}
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?
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"]) ):
self.games[args[0]]=gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
else:
# Private message
#self.games[args[0]].gotPrivMsg(args, prefix, trailing)
pass
def ondisable(self):
self.log.info("GameBase: Unload requested, ending games...")
for game in self.games:
self.games[game].gameover()
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
self.doge = self.bot.getBestModuleForService("dogerpc")
# Dict of #channel -> game object
self.games = {}
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?
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"]) ):
self.games[args[0]]=gameObj(self, args[0])
# Channel message
self.games[args[0]].gotMsg(args, prefix, trailing)
else:
# Private message
#self.games[args[0]].gotPrivMsg(args, prefix, trailing)
pass
def ondisable(self):
self.log.info("GameBase: Unload requested, ending games...")
for game in self.games:
self.games[game].gameover()
class gameObj:
def __init__(self, master, channel):
self.master = master
self.channel = channel
def gotPrivMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
def gotMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
#senderIsOp = self.master.attr.getKey(prefix.nick, "op")=="yes"
def gameover(self):
pass
def __init__(self, master, channel):
self.master = master
self.channel = channel
def gotPrivMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
def gotMsg(self, args, prefix, trailing):
prefix = self.master.bot.decodePrefix(prefix)
pass
#senderIsOp = self.master.attr.getKey(prefix.nick, "op")=="yes"
def gameover(self):
pass
class playerObj:
def __init__(self, game, nick):
self.game = game
self.nick = nick
def __init__(self, game, nick):
self.game = game
self.nick = nick

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Inventory
:synopsis: Lets the bot hold random items
:synopsis: Lets the bot hold random items
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,97 +11,97 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
from datetime import datetime
class Inventory(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Inventory: Could not find a valid sqlite service provider")
else:
self.log.info("Inventory: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("inventory.db")
if not self.db.tableExists("inventory"):
self.log.info("Inventory: Creating table: inventory")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `inventory` (
`id` INTEGER PRIMARY KEY,
`date` INTEGER,
`donor` varchar(64),
`item` varchar(64)
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.checkInv)]
def checkInv(self, args, prefix, trailing):
if not args[0][0]=="#":
return
prefixObj = self.bot.decodePrefix(prefix)
cmd = self.bot.messageHasCommand([".have"], trailing, True)
if cmd:
if len(cmd.args)<1:
return
adjective = None
if cmd.args[0] in self.config["adjectives"]:
cmd.args_str = cmd.args_str[len(cmd.args[0]):].strip()
adjective = cmd.args[0]
newItem = cmd.args_str
if self.has_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)})
else:
self.bot.act_PRIVMSG(args[0], self.config["recv_msg"] %
{"item":newItem, "adjective":"these " if newItem[-1:]=="s" else "this "})
cmd = self.bot.messageHasCommand([".inventory", ".inv"], trailing)
if cmd:
inv = self.getinventory()
if len(inv)==0:
self.bot.act_PRIVMSG(args[0], self.config["inv_msg"] % {"itemlist":"nothing!"})
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,)) #
row = c.fetchone()
c.close()
return row["num"]>0
def add_item(self, donor, itemName):
dropped = []
c = self.db.query("SELECT * FROM `inventory` ORDER BY RANDOM() LIMIT %s,1000000" % self.config["limit"])
while True:
row = c.fetchone()
if row == None:
break
dropped.append(row["item"])
self.db.query("DELETE FROM `inventory` WHERE `id`=?", (row["id"],)).close()
c.close()
self.db.query("INSERT INTO `inventory` (`date`, `donor`, `item`) VALUES (?, ?, ?)",
(int(datetime.now().timestamp()), donor, itemName)).close()
return dropped
def getinventory(self):
inv = []
c = self.db.query("SELECT * FROM `inventory`")
while True:
row = c.fetchone()
if row == None:
break
inv.append(row["item"])
c.close()
return inv
def ondisable(self):
self.db.close()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Inventory: Could not find a valid sqlite service provider")
else:
self.log.info("Inventory: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("inventory.db")
if not self.db.tableExists("inventory"):
self.log.info("Inventory: Creating table: inventory")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `inventory` (
`id` INTEGER PRIMARY KEY,
`date` INTEGER,
`donor` varchar(64),
`item` varchar(64)
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.checkInv)]
def checkInv(self, args, prefix, trailing):
if not args[0][0]=="#":
return
prefixObj = self.bot.decodePrefix(prefix)
cmd = self.bot.messageHasCommand([".have"], trailing, True)
if cmd:
if len(cmd.args)<1:
return
adjective = None
if cmd.args[0] in self.config["adjectives"]:
cmd.args_str = cmd.args_str[len(cmd.args[0]):].strip()
adjective = cmd.args[0]
newItem = cmd.args_str
if self.has_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)})
else:
self.bot.act_PRIVMSG(args[0], self.config["recv_msg"] %
{"item":newItem, "adjective":"these " if newItem[-1:]=="s" else "this "})
cmd = self.bot.messageHasCommand([".inventory", ".inv"], trailing)
if cmd:
inv = self.getinventory()
if len(inv)==0:
self.bot.act_PRIVMSG(args[0], self.config["inv_msg"] % {"itemlist":"nothing!"})
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,)) #
row = c.fetchone()
c.close()
return row["num"]>0
def add_item(self, donor, itemName):
dropped = []
c = self.db.query("SELECT * FROM `inventory` ORDER BY RANDOM() LIMIT %s,1000000" % self.config["limit"])
while True:
row = c.fetchone()
if row == None:
break
dropped.append(row["item"])
self.db.query("DELETE FROM `inventory` WHERE `id`=?", (row["id"],)).close()
c.close()
self.db.query("INSERT INTO `inventory` (`date`, `donor`, `item`) VALUES (?, ?, ?)",
(int(datetime.now().timestamp()), donor, itemName)).close()
return dropped
def getinventory(self):
inv = []
c = self.db.query("SELECT * FROM `inventory`")
while True:
row = c.fetchone()
if row == None:
break
inv.append(row["item"])
c.close()
return inv
def ondisable(self):
self.db.close()

View File

@ -2,7 +2,7 @@
"""
.. module::LMGTFY
:synopsis: LMGTFY
:synopsis: LMGTFY
.. moduleauthor::Nick Krichevsky <nick@ollien.com>
"""
@ -12,27 +12,27 @@ 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)
self.hooks.append(ModuleHook("PRIVMSG", self.handleMessage))
self.bot = bot
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName)
self.hooks.append(ModuleHook("PRIVMSG", self.handleMessage))
self.bot = bot
def handleMessage(self, args, prefix, trailing):
channel = args[0]
prefix = self.bot.decodePrefix(prefix)
if self.bot.messageHasCommand(".lmgtfy", trailing):
message = trailing.split(" ")[1:]
link = self.createLink(message)
self.bot.act_PRIVMSG(channel, "%s: %s" % (prefix.nick, link))
def createLink(self, message):
finalUrl = BASE_URL
if type(message) == str:
message = message.split(" ")
def handleMessage(self, args, prefix, trailing):
channel = args[0]
prefix = self.bot.decodePrefix(prefix)
if self.bot.messageHasCommand(".lmgtfy", trailing):
message = trailing.split(" ")[1:]
link = self.createLink(message)
self.bot.act_PRIVMSG(channel, "%s: %s" % (prefix.nick, link))
def createLink(self, message):
finalUrl = BASE_URL
if type(message) == str:
message = message.split(" ")
for word in message:
finalUrl += urllib.parse.quote(word)
if word != message[-1]:
finalUrl+="+"
for word in message:
finalUrl += urllib.parse.quote(word)
if word != message[-1]:
finalUrl+="+"
return finalUrl
return finalUrl

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: MySQL
:synopsis: Module providing a mysql type service
:synopsis: Module providing a mysql type service
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,108 +11,108 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
import sys
try:
import MySQLdb #python 2.x
import MySQLdb #python 2.x
except:
import pymysql as MySQLdb #python 3.x
import pymysql as MySQLdb #python 3.x
class MySQL(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["mysql"]
self.loadConfig()
self.connection = self.getConnection()
def getConnection(self):
return Connection(self)
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["mysql"]
self.loadConfig()
self.connection = self.getConnection()
def getConnection(self):
return Connection(self)
class Connection:
def __init__(self, master):
self.config = master.config
self.log = master.log
self._connect()
# Check if the table requested exists
def tableExists(self, tablename):
c = self.getCursor()
c.execute("SHOW TABLES;")
tables = c.fetchall()
if len(tables)==0:
return False;
key = list(tables[0].keys())[0]
for table in tables:
if table[key]==tablename:
return True;
return False
def query(self, queryText, args=()):
"""Execute a MySQL query and return the cursor
:param queryText: the mysql query as a string, using '%s' for token replacement
:type queryText: str
:param args: arguments to be escaped into the query
:type args: tuple
:returns: cursor -- the sql cursor"""
c = self.getCursor()
if len(args)==0:
c.execute(queryText)
else:
c.execute(queryText, args)
return c
# Returns a cusor object, after checking for connectivity
def getCursor(self):
self.ensureConnected()
if sys.version_info > (3,0):
c = self.connection.cursor(MySQLdb.cursors.DictCursor)
else:
c = self.connection.cursor(cursorclass=MySQLdb.cursors.DictCursor)
c.execute("USE `%s`;" % self.config["database"])
return c
def escape(self, s):
"""Escape a string using the mysql server
:param s: the string to escape
:type s: str
:returns: str -- the escaped string"""
self.ensureConnected()
return self.connection.escape_string(s)
def ensureConnected(self):
try:
self.connection.ping()
except:
try:
self.connection.close()
except:
pass
del self.connection
self._connect()
def ondisable(self):
self.connection.close()
# 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.log.info("MySQL: Connected.")
self.connection.autocommit(True)
c = None
if sys.version_info > (3,0):
c = self.connection.cursor(MySQLdb.cursors.DictCursor)
else:
c = self.connection.cursor(cursorclass=MySQLdb.cursors.DictCursor)
c.execute("SHOW DATABASES")
dblist = c.fetchall()
found = False
for row in dblist:
if row["Database"]==self.config["database"]:
found = True
if not found:
c.execute("CREATE DATABASE `%s`;" % self.config["database"])
c.execute("USE `%s`;" % self.config["database"])
c.close()
def __init__(self, master):
self.config = master.config
self.log = master.log
self._connect()
# Check if the table requested exists
def tableExists(self, tablename):
c = self.getCursor()
c.execute("SHOW TABLES;")
tables = c.fetchall()
if len(tables)==0:
return False;
key = list(tables[0].keys())[0]
for table in tables:
if table[key]==tablename:
return True;
return False
def query(self, queryText, args=()):
"""Execute a MySQL query and return the cursor
:param queryText: the mysql query as a string, using '%s' for token replacement
:type queryText: str
:param args: arguments to be escaped into the query
:type args: tuple
:returns: cursor -- the sql cursor"""
c = self.getCursor()
if len(args)==0:
c.execute(queryText)
else:
c.execute(queryText, args)
return c
# Returns a cusor object, after checking for connectivity
def getCursor(self):
self.ensureConnected()
if sys.version_info > (3,0):
c = self.connection.cursor(MySQLdb.cursors.DictCursor)
else:
c = self.connection.cursor(cursorclass=MySQLdb.cursors.DictCursor)
c.execute("USE `%s`;" % self.config["database"])
return c
def escape(self, s):
"""Escape a string using the mysql server
:param s: the string to escape
:type s: str
:returns: str -- the escaped string"""
self.ensureConnected()
return self.connection.escape_string(s)
def ensureConnected(self):
try:
self.connection.ping()
except:
try:
self.connection.close()
except:
pass
del self.connection
self._connect()
def ondisable(self):
self.connection.close()
# 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.log.info("MySQL: Connected.")
self.connection.autocommit(True)
c = None
if sys.version_info > (3,0):
c = self.connection.cursor(MySQLdb.cursors.DictCursor)
else:
c = self.connection.cursor(cursorclass=MySQLdb.cursors.DictCursor)
c.execute("SHOW DATABASES")
dblist = c.fetchall()
found = False
for row in dblist:
if row["Database"]==self.config["database"]:
found = True
if not found:
c.execute("CREATE DATABASE `%s`;" % self.config["database"])
c.execute("USE `%s`;" % self.config["database"])
c.close()

View File

@ -1,6 +1,6 @@
"""
.. module:: NFLLive
:synopsis: Show upcoming NFL games and current scores.
:synopsis: Show upcoming NFL games and current scores.
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -13,213 +13,213 @@ from lxml import etree
from datetime import datetime,timedelta
class NFLLive(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.cache = None
self.cacheAge=0
self.hooks=[ModuleHook(["PRIVMSG"], self.nflitup)]
def nflitup(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
cmd = self.bot.messageHasCommand(".nfl", trailing)
if cmd:
games = self.getNflGamesCached()
msg = []
liveGames = []
gamesLaterToday = []
gamesToday = []
gamesUpcoming = []
gamesEarlierWeek = []
# sort games
for game in games["games"]:
if not game["time"]==None:
liveGames.append(game)
elif game["quarter"]=="P" and game["startdate"].day==datetime.now().day:
gamesLaterToday.append(game)
elif game["startdate"].day==datetime.now().day:
gamesToday.append(game)
elif game["startdate"].day > datetime.now().day:
gamesUpcoming.append(game)
else:
gamesEarlierWeek.append(game)
# create list of formatted games
liveGamesStr = []
for game in liveGames:
liveGamesStr.append(self.formatGameLive(game))
liveGamesStr = ", ".join(liveGamesStr)
gamesLaterTodayStr = []
for game in gamesLaterToday:
gamesLaterTodayStr.append(self.formatGameFuture(game))
gamesLaterTodayStr = ", ".join(gamesLaterTodayStr)
gamesTodayStr = []
for game in gamesToday:
gamesTodayStr.append(self.formatGamePast(game))
gamesTodayStr = ", ".join(gamesTodayStr)
gamesUpcomingStr = []
for game in gamesUpcoming:
gamesUpcomingStr.append(self.formatGameFuture(game))
gamesUpcomingStr = ", ".join(gamesUpcomingStr)
gamesEarlierWeekStr = []
for game in gamesEarlierWeek:
gamesEarlierWeekStr.append(self.formatGamePast(game))
gamesEarlierWeekStr = ", ".join(gamesEarlierWeekStr)
msgPieces = []
msgPieces.append("\x02NFL week %s\x02:" % (games["season"]["week"]))
# Depending on args build the respon pieces
if len(cmd.args)>0 and cmd.args[0]=="today":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesLaterTodayStr == "":
msgPieces.append("\x02Later today:\x02 %s" % gamesLaterTodayStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
elif len(cmd.args)>0 and cmd.args[0]=="live":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
elif len(cmd.args)>0 and cmd.args[0]=="scores":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
if not gamesEarlierWeekStr == "":
msgPieces.append("\x02Earlier this week: \x02 %s" % gamesEarlierWeekStr)
else:
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesLaterTodayStr == "":
msgPieces.append("\x02Later today:\x02 %s" % gamesLaterTodayStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
if not gamesEarlierWeekStr == "":
msgPieces.append("\x02Earlier this week: \x02 %s" % gamesEarlierWeekStr)
if not gamesUpcomingStr == "":
msgPieces.append("\x02Upcoming:\x02 %s" % gamesUpcomingStr)
# Collaspe the list into a repsonse string. Fix grammar
msg = ", ".join(msgPieces).replace(":, ", ": ")
# Nothing means there were probably no games
if len(msgPieces)==1:
msg = "No games!"
if len(msg)>0:
# The message can be long so chunk it into pieces splitting at commas
while len(msg)>0:
piece = msg[0:330]
msg = msg[330:]
while not piece[-1:]=="," and len(msg)>0:
piece+=msg[0:1]
msg = msg[1:]
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (prefix.nick, piece.strip()))
def formatGameLive(self, game):
c_vis = 3 if int(game["visitor_score"]) > int(game["home_score"]) else 4
c_home = 4 if int(game["visitor_score"]) > int(game["home_score"]) else 3
return "\x03%s%s(%s)\x03 @ \x03%s%s(%s)\x03 Q%s %s" % (
c_vis,
game["visitor"],
game["visitor_score"],
c_home,
game["home"],
game["home_score"],
game["quarter"],
game["time"]
)
def formatGameFuture(self, game):
return "\x02%s\x02@\x02%s\x02" % (
game["visitor"],
game["home"]
)
def formatGamePast(self, game):
c_vis = 3 if int(game["visitor_score"]) > int(game["home_score"]) else 4
c_home = 4 if int(game["visitor_score"]) > int(game["home_score"]) else 3
return "\x03%s%s(%s)\x03@\x03%s%s(%s)\x03" % (
c_vis,
game["visitor"],
game["visitor_score"],
c_home,
game["home"],
game["home_score"]
)
def getNflGamesCached(self):
if time()-self.cacheAge > self.config["cache"]:
self.cache = NFLLive.getNflGames()
self.cacheAge = time()
return self.cache
@staticmethod
def getNflGames():
result = {}
# Fetch NFL information as XML
nflxml = get("http://www.nfl.com/liveupdate/scorestrip/ss.xml?random=1413140448433")
doc = etree.fromstring(nflxml.content)
games = doc.xpath("/ss/gms")[0]
result["season"]={
"week":games.attrib["w"],
"year":games.attrib["y"],
"type":NFLLive.translateSeasonType(games.attrib["t"]), # R for regular season, probably P for pre (?)
"gameday":int(games.attrib["gd"]), # 1 or 0 for gameday or not (?)
"bph":games.attrib["bph"] # not sure
}
result["games"]=[]
for game in games.getchildren():
gameblob = {
"home":game.attrib["h"],
"home_name":game.attrib["hnn"],
"home_score":game.attrib["hs"],
"visitor":game.attrib["v"],
"visitor_name":game.attrib["vnn"],
"visitor_score":game.attrib["vs"],
"gametype":game.attrib["gt"], # REGular season, probably P for preseason (?)
"quarter":game.attrib["q"], # P if not started, 1-4, F is finished
"time":game.attrib["k"] if "k" in game.attrib else None,
"id":game.attrib["eid"],
"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.
}
# Add 4 more hours to make it GMT
gameblob["startdate_gmt"]=gameblob["startdate"]+timedelta(hours=4)
gameblob["nfl_link"]="http://www.nfl.com/gamecenter/%s/%s/%s%s/%s@%s" % (
gameblob["id"],
result["season"]["year"],
gameblob["gametype"],
result["season"]["week"],
gameblob["visitor_name"],
gameblob["home_name"])
result["games"].append(gameblob)
return result
@staticmethod
def translateSeasonType(season):
if season=="R":
return "Regular"
if season=="P":
return "Pre"
return season
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.cache = None
self.cacheAge=0
self.hooks=[ModuleHook(["PRIVMSG"], self.nflitup)]
def nflitup(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
replyTo = prefixObj.nick if not "#" in args[0] else args[0]
cmd = self.bot.messageHasCommand(".nfl", trailing)
if cmd:
games = self.getNflGamesCached()
msg = []
liveGames = []
gamesLaterToday = []
gamesToday = []
gamesUpcoming = []
gamesEarlierWeek = []
# sort games
for game in games["games"]:
if not game["time"]==None:
liveGames.append(game)
elif game["quarter"]=="P" and game["startdate"].day==datetime.now().day:
gamesLaterToday.append(game)
elif game["startdate"].day==datetime.now().day:
gamesToday.append(game)
elif game["startdate"].day > datetime.now().day:
gamesUpcoming.append(game)
else:
gamesEarlierWeek.append(game)
# create list of formatted games
liveGamesStr = []
for game in liveGames:
liveGamesStr.append(self.formatGameLive(game))
liveGamesStr = ", ".join(liveGamesStr)
gamesLaterTodayStr = []
for game in gamesLaterToday:
gamesLaterTodayStr.append(self.formatGameFuture(game))
gamesLaterTodayStr = ", ".join(gamesLaterTodayStr)
gamesTodayStr = []
for game in gamesToday:
gamesTodayStr.append(self.formatGamePast(game))
gamesTodayStr = ", ".join(gamesTodayStr)
gamesUpcomingStr = []
for game in gamesUpcoming:
gamesUpcomingStr.append(self.formatGameFuture(game))
gamesUpcomingStr = ", ".join(gamesUpcomingStr)
gamesEarlierWeekStr = []
for game in gamesEarlierWeek:
gamesEarlierWeekStr.append(self.formatGamePast(game))
gamesEarlierWeekStr = ", ".join(gamesEarlierWeekStr)
msgPieces = []
msgPieces.append("\x02NFL week %s\x02:" % (games["season"]["week"]))
# Depending on args build the respon pieces
if len(cmd.args)>0 and cmd.args[0]=="today":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesLaterTodayStr == "":
msgPieces.append("\x02Later today:\x02 %s" % gamesLaterTodayStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
elif len(cmd.args)>0 and cmd.args[0]=="live":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
elif len(cmd.args)>0 and cmd.args[0]=="scores":
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
if not gamesEarlierWeekStr == "":
msgPieces.append("\x02Earlier this week: \x02 %s" % gamesEarlierWeekStr)
else:
if not liveGamesStr == "":
msgPieces.append("\x02Playing now:\x02 %s" % liveGamesStr)
if not gamesLaterTodayStr == "":
msgPieces.append("\x02Later today:\x02 %s" % gamesLaterTodayStr)
if not gamesTodayStr == "":
msgPieces.append("\x02Earlier today:\x02 %s" % gamesTodayStr)
if not gamesEarlierWeekStr == "":
msgPieces.append("\x02Earlier this week: \x02 %s" % gamesEarlierWeekStr)
if not gamesUpcomingStr == "":
msgPieces.append("\x02Upcoming:\x02 %s" % gamesUpcomingStr)
# Collaspe the list into a repsonse string. Fix grammar
msg = ", ".join(msgPieces).replace(":, ", ": ")
# Nothing means there were probably no games
if len(msgPieces)==1:
msg = "No games!"
if len(msg)>0:
# The message can be long so chunk it into pieces splitting at commas
while len(msg)>0:
piece = msg[0:330]
msg = msg[330:]
while not piece[-1:]=="," and len(msg)>0:
piece+=msg[0:1]
msg = msg[1:]
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (prefix.nick, piece.strip()))
def formatGameLive(self, game):
c_vis = 3 if int(game["visitor_score"]) > int(game["home_score"]) else 4
c_home = 4 if int(game["visitor_score"]) > int(game["home_score"]) else 3
return "\x03%s%s(%s)\x03 @ \x03%s%s(%s)\x03 Q%s %s" % (
c_vis,
game["visitor"],
game["visitor_score"],
c_home,
game["home"],
game["home_score"],
game["quarter"],
game["time"]
)
def formatGameFuture(self, game):
return "\x02%s\x02@\x02%s\x02" % (
game["visitor"],
game["home"]
)
def formatGamePast(self, game):
c_vis = 3 if int(game["visitor_score"]) > int(game["home_score"]) else 4
c_home = 4 if int(game["visitor_score"]) > int(game["home_score"]) else 3
return "\x03%s%s(%s)\x03@\x03%s%s(%s)\x03" % (
c_vis,
game["visitor"],
game["visitor_score"],
c_home,
game["home"],
game["home_score"]
)
def getNflGamesCached(self):
if time()-self.cacheAge > self.config["cache"]:
self.cache = NFLLive.getNflGames()
self.cacheAge = time()
return self.cache
@staticmethod
def getNflGames():
result = {}
# Fetch NFL information as XML
nflxml = get("http://www.nfl.com/liveupdate/scorestrip/ss.xml?random=1413140448433")
doc = etree.fromstring(nflxml.content)
games = doc.xpath("/ss/gms")[0]
result["season"]={
"week":games.attrib["w"],
"year":games.attrib["y"],
"type":NFLLive.translateSeasonType(games.attrib["t"]), # R for regular season, probably P for pre (?)
"gameday":int(games.attrib["gd"]), # 1 or 0 for gameday or not (?)
"bph":games.attrib["bph"] # not sure
}
result["games"]=[]
for game in games.getchildren():
gameblob = {
"home":game.attrib["h"],
"home_name":game.attrib["hnn"],
"home_score":game.attrib["hs"],
"visitor":game.attrib["v"],
"visitor_name":game.attrib["vnn"],
"visitor_score":game.attrib["vs"],
"gametype":game.attrib["gt"], # REGular season, probably P for preseason (?)
"quarter":game.attrib["q"], # P if not started, 1-4, F is finished
"time":game.attrib["k"] if "k" in game.attrib else None,
"id":game.attrib["eid"],
"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.
}
# Add 4 more hours to make it GMT
gameblob["startdate_gmt"]=gameblob["startdate"]+timedelta(hours=4)
gameblob["nfl_link"]="http://www.nfl.com/gamecenter/%s/%s/%s%s/%s@%s" % (
gameblob["id"],
result["season"]["year"],
gameblob["gametype"],
result["season"]["week"],
gameblob["visitor_name"],
gameblob["home_name"])
result["games"].append(gameblob)
return result
@staticmethod
def translateSeasonType(season):
if season=="R":
return "Regular"
if season=="P":
return "Pre"
return season

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: NickUser
:synopsis: A module providing a simple login/logout account service
:synopsis: A module providing a simple login/logout account service
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,80 +12,80 @@ import time
import hashlib
class NickUser(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
self.services=["login"]
def check(self, nick, hostname):
attr = self.bot.getBestModuleForService("attributes")
loggedin = attr.getKey(nick, "loggedinfrom")
if hostname==loggedin:
return True
return False
def ondisable(self):
pass
# TODO: log out all users
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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\"")
else:
attr = self.bot.getBestModuleForService("attributes")
oldpass = attr.getKey(prefix.nick, "password")
if oldpass == 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])
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.")
cmd = self.bot.messageHasCommand(".login", trailing)
if cmd:
attr = self.bot.getBestModuleForService("attributes")
userpw = attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
attr.setKey(prefix.nick, "loggedinfrom", prefix.hostname)
self.bot.act_PRIVMSG(prefix.nick, ".login: You have been logged in from: %s" % prefix.hostname)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: usage: \".login password\"")
cmd = self.bot.messageHasCommand(".logout", trailing)
if cmd:
attr = self.bot.getBestModuleForService("attributes")
loggedin = attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
attr.setKey(prefix.nick, "loggedinfrom", None)
self.bot.act_PRIVMSG(prefix.nick, ".logout: You have been logged out.")
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.gotmsg)]
self.services=["login"]
def check(self, nick, hostname):
attr = self.bot.getBestModuleForService("attributes")
loggedin = attr.getKey(nick, "loggedinfrom")
if hostname==loggedin:
return True
return False
def ondisable(self):
pass
# TODO: log out all users
def gotmsg(self, args, prefix, trailing):
channel = args[0]
if channel[0] == "#":
# Ignore channel messages
pass
else:
self.handlePm(args, prefix, trailing)
def handlePm(self, args, prefix, trailing):
prefix = self.bot.decodePrefix(prefix)
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\"")
else:
attr = self.bot.getBestModuleForService("attributes")
oldpass = attr.getKey(prefix.nick, "password")
if oldpass == 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])
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.")
cmd = self.bot.messageHasCommand(".login", trailing)
if cmd:
attr = self.bot.getBestModuleForService("attributes")
userpw = attr.getKey(prefix.nick, "password")
if userpw==None:
self.bot.act_PRIVMSG(prefix.nick, ".login: You must first set a password with .setpass")
else:
if len(cmd.args)==1:
if userpw == cmd.args[0]:
#################
attr.setKey(prefix.nick, "loggedinfrom", prefix.hostname)
self.bot.act_PRIVMSG(prefix.nick, ".login: You have been logged in from: %s" % prefix.hostname)
#################
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: incorrect password.")
else:
self.bot.act_PRIVMSG(prefix.nick, ".login: usage: \".login password\"")
cmd = self.bot.messageHasCommand(".logout", trailing)
if cmd:
attr = self.bot.getBestModuleForService("attributes")
loggedin = attr.getKey(prefix.nick, "loggedinfrom")
if loggedin == None:
self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
else:
attr.setKey(prefix.nick, "loggedinfrom", None)
self.bot.act_PRIVMSG(prefix.nick, ".logout: You have been logged out.")
def md5(self, data):
m = hashlib.md5()
m.update(data.encode("ascii"))
return m.hexdigest()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: PingResponder
:synopsis: Module to repsond to irc server PING requests
:synopsis: Module to repsond to irc server PING requests
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -10,11 +10,11 @@
from pyircbot.modulebase import ModuleBase,ModuleHook
class PingResponder(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PING", self.pingrespond)]
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 __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PING", self.pingrespond)]
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))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: RandQuote
:synopsis: Log a configurable number of messages and pull up random ones on command
:synopsis: Log a configurable number of messages and pull up random ones on command
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,57 +11,57 @@ from pyircbot.modulebase import ModuleBase,ModuleHook
from datetime import datetime
class RandQuote(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("RandQuote: Could not find a valid sqlite service provider")
else:
self.log.info("RandQuote: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("randquote.db")
if not self.db.tableExists("chat"):
self.log.info("RandQuote: Creating table: chat")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `chat` (
`id` INTEGER PRIMARY KEY,
`date` INTEGER,
`sender` varchar(64),
`message` varchar(2048)
) ;""")
c.close()
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;")
row = c.fetchone()
c.close()
if row:
self.bot.act_PRIVMSG(args[0], "<%s> %s" % (row["sender"], row["message"],))
def logquote(self, args, prefix, trailing):
if not args[0][0]=="#":
return
prefixObj = self.bot.decodePrefix(prefix)
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()
if not row:
break
self.db.query("DELETE FROM `chat` WHERE id=?", (row["id"],)).close()
c.close()
def ondisable(self):
self.db.close()
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("RandQuote: Could not find a valid sqlite service provider")
else:
self.log.info("RandQuote: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("randquote.db")
if not self.db.tableExists("chat"):
self.log.info("RandQuote: Creating table: chat")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `chat` (
`id` INTEGER PRIMARY KEY,
`date` INTEGER,
`sender` varchar(64),
`message` varchar(2048)
) ;""")
c.close()
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;")
row = c.fetchone()
c.close()
if row:
self.bot.act_PRIVMSG(args[0], "<%s> %s" % (row["sender"], row["message"],))
def logquote(self, args, prefix, trailing):
if not args[0][0]=="#":
return
prefixObj = self.bot.decodePrefix(prefix)
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()
if not row:
break
self.db.query("DELETE FROM `chat` WHERE id=?", (row["id"],)).close()
c.close()
def ondisable(self):
self.db.close()

View File

@ -1,6 +1,6 @@
"""
.. module:: Remind
:synopsis: A module to support reminders
:synopsis: A module to support reminders
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -14,262 +14,262 @@ import re
import pytz
class Remind(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Remind: Could not find a valid sqlite service provider")
else:
self.log.info("Remind: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("remind.db")
if not self.db.tableExists("reminders"):
self.log.info("Remind: Creating table: reminders")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `reminders` (
`id` INTEGER PRIMARY KEY,
`sender` varchar(64),
`senderch` varchar(64),
`when` timestamp,
`message` varchar(2048)
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.remindin),ModuleHook("PRIVMSG", self.remindat)]
self.disabled = False
# Start monitor thread
self.t = Thread(target=self.monitor_thread)
self.t.daemon=True
self.t.start()
def monitor_thread(self):
while True:
sleep(self.config["precision"])
if self.disabled:
break
self.monitor()
def monitor(self):
remindPeople = self.db.query("SELECT * FROM `reminders` WHERE `when` < ?", (datetime.now(),))
reminders = remindPeople.fetchall()
remindPeople.close()
byrecip = {}
for reminder in reminders:
if not reminder["sender"] in byrecip:
byrecip[reminder["sender"]]=[]
byrecip[reminder["sender"]].append(reminder)
reminders_bych = {}
for recip in byrecip:
reminders_pm = []
for reminder in byrecip[recip]:
if reminder["senderch"]=="":
reminders_pm.append(reminder)
else:
if not reminder["senderch"] in reminders_bych:
reminders_bych[reminder["senderch"]] = []
reminders_bych[reminder["senderch"]].append(reminder)
self.sendReminders(reminders_pm, recip, recip)
for channel in reminders_bych:
channelpms_bysender = {}
for chreminder in reminders_bych[channel]:
if not chreminder["sender"] in channelpms_bysender:
channelpms_bysender[chreminder["sender"]]=[]
channelpms_bysender[chreminder["sender"]].append(chreminder)
for recip in channelpms_bysender:
self.sendReminders(channelpms_bysender[recip], channel, recip)
# Delete now that it's sent
for item in reminders:
self.db.query("DELETE FROM `reminders` WHERE `id`=?", (item["id"],)).close()
def sendReminders(self, reminders, target, nick):
" Send a set of reminders of the same recipient, to them. Collapse down into one message."
reminder_str = []
for reminder in reminders:
reminder_str.append(reminder["message"])
reminder_str = ", ".join(reminder_str)
if len(reminder_str)>0:
self.bot.act_PRIVMSG(target, "%s: Reminder: %s" % (nick, reminder_str))
def ondisable(self):
self.disabled = True
def remindat(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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)
if cmd:
regex = re.compile(r'(\d+):(\d+)(?::(\d+))?([^\s\d]+)? (.*)')
match = regex.match(cmd.args_str)
try:
hour, minute, second, tz, message = match.groups()
message = message.strip()
assert not message == ""
hour = int(hour)
minute = int(minute)
if not second == 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)
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:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
self.bot.act_PRIVMSG(replyTo, "%s: I don't recognize the timezone '%s'." % (prefixObj.nick, tz))
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
remindAt = remindAt.replace(hour=hour).replace(minute=minute).replace(microsecond=0)
# Set seconds
if second == 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:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
self.bot.act_PRIVMSG(replyTo, "%s: I don't recognize the timezone '%s'." % (prefixObj.nick, tz))
return
remindAt = remindAt.astimezone(pytz.timezone(self.config["mytimezone"])).replace(tzinfo=None)
# Advance it a day if the time would have been earlier today
while remindAt<now:
remindAt += timedelta(days=1)
timediff = remindAt-datetime.now()
#self.bot.act_PRIVMSG(replyTo, "Time: %s" % str(remindAt))
#self.bot.act_PRIVMSG(replyTo, "Diff: %s" % (timediff))
# Save the reminder
c = self.db.query("INSERT INTO `reminders` (`sender`, `senderch`, `when`, `message`) VALUES (?, ?, ?, ?)", (
prefixObj.nick,
args[0] if "#" in args[0] else "",
remindAt,
message
))
c.close()
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))
@staticmethod
def is_dst(tz):
now = pytz.utc.localize(datetime.utcnow())
return now.astimezone(tz).dst() != timedelta(0)
@staticmethod
def translateZoneStr(zonestr):
translations = {
"EDT":"US/Eastern",
"PDT":"America/Los_Angeles"
}
if zonestr in translations:
return translations[zonestr]
else:
return zonestr
def remindin(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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))
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))
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]))
return
delaySeconds+=(Remind.scaling[match[1]] * int(match[0]))
remindAt = datetime.now()+timedelta(seconds=delaySeconds)
self.db.query("INSERT INTO `reminders` (`sender`, `senderch`, `when`, `message`) VALUES (?, ?, ?, ?)", (
prefixObj.nick,
args[0] if "#" in args[0] else "",
remindAt,
cmd.args_str[len(cmd.args[0]):].strip()
)).close()
hours = int(delaySeconds/60/60)
minutes = int((delaySeconds-(hours*60*60))/60)
self.bot.act_PRIVMSG(replyTo, "%s: Ok, talk to you in approx %sh%sm" % (prefixObj.nick, hours,minutes))
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Remind: Could not find a valid sqlite service provider")
else:
self.log.info("Remind: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("remind.db")
if not self.db.tableExists("reminders"):
self.log.info("Remind: Creating table: reminders")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `reminders` (
`id` INTEGER PRIMARY KEY,
`sender` varchar(64),
`senderch` varchar(64),
`when` timestamp,
`message` varchar(2048)
) ;""")
c.close()
self.hooks=[ModuleHook("PRIVMSG", self.remindin),ModuleHook("PRIVMSG", self.remindat)]
self.disabled = False
# Start monitor thread
self.t = Thread(target=self.monitor_thread)
self.t.daemon=True
self.t.start()
def monitor_thread(self):
while True:
sleep(self.config["precision"])
if self.disabled:
break
self.monitor()
def monitor(self):
remindPeople = self.db.query("SELECT * FROM `reminders` WHERE `when` < ?", (datetime.now(),))
reminders = remindPeople.fetchall()
remindPeople.close()
byrecip = {}
for reminder in reminders:
if not reminder["sender"] in byrecip:
byrecip[reminder["sender"]]=[]
byrecip[reminder["sender"]].append(reminder)
reminders_bych = {}
for recip in byrecip:
reminders_pm = []
for reminder in byrecip[recip]:
if reminder["senderch"]=="":
reminders_pm.append(reminder)
else:
if not reminder["senderch"] in reminders_bych:
reminders_bych[reminder["senderch"]] = []
reminders_bych[reminder["senderch"]].append(reminder)
self.sendReminders(reminders_pm, recip, recip)
for channel in reminders_bych:
channelpms_bysender = {}
for chreminder in reminders_bych[channel]:
if not chreminder["sender"] in channelpms_bysender:
channelpms_bysender[chreminder["sender"]]=[]
channelpms_bysender[chreminder["sender"]].append(chreminder)
for recip in channelpms_bysender:
self.sendReminders(channelpms_bysender[recip], channel, recip)
# Delete now that it's sent
for item in reminders:
self.db.query("DELETE FROM `reminders` WHERE `id`=?", (item["id"],)).close()
def sendReminders(self, reminders, target, nick):
" Send a set of reminders of the same recipient, to them. Collapse down into one message."
reminder_str = []
for reminder in reminders:
reminder_str.append(reminder["message"])
reminder_str = ", ".join(reminder_str)
if len(reminder_str)>0:
self.bot.act_PRIVMSG(target, "%s: Reminder: %s" % (nick, reminder_str))
def ondisable(self):
self.disabled = True
def remindat(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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)
if cmd:
regex = re.compile(r'(\d+):(\d+)(?::(\d+))?([^\s\d]+)? (.*)')
match = regex.match(cmd.args_str)
try:
hour, minute, second, tz, message = match.groups()
message = message.strip()
assert not message == ""
hour = int(hour)
minute = int(minute)
if not second == 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)
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:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
self.bot.act_PRIVMSG(replyTo, "%s: I don't recognize the timezone '%s'." % (prefixObj.nick, tz))
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
remindAt = remindAt.replace(hour=hour).replace(minute=minute).replace(microsecond=0)
# Set seconds
if second == 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:
try:
theirzone = pytz.timezone(Remind.translateZoneStr(tz))
except:
self.bot.act_PRIVMSG(replyTo, "%s: I don't recognize the timezone '%s'." % (prefixObj.nick, tz))
return
remindAt = remindAt.astimezone(pytz.timezone(self.config["mytimezone"])).replace(tzinfo=None)
# Advance it a day if the time would have been earlier today
while remindAt<now:
remindAt += timedelta(days=1)
timediff = remindAt-datetime.now()
#self.bot.act_PRIVMSG(replyTo, "Time: %s" % str(remindAt))
#self.bot.act_PRIVMSG(replyTo, "Diff: %s" % (timediff))
# Save the reminder
c = self.db.query("INSERT INTO `reminders` (`sender`, `senderch`, `when`, `message`) VALUES (?, ?, ?, ?)", (
prefixObj.nick,
args[0] if "#" in args[0] else "",
remindAt,
message
))
c.close()
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))
@staticmethod
def is_dst(tz):
now = pytz.utc.localize(datetime.utcnow())
return now.astimezone(tz).dst() != timedelta(0)
@staticmethod
def translateZoneStr(zonestr):
translations = {
"EDT":"US/Eastern",
"PDT":"America/Los_Angeles"
}
if zonestr in translations:
return translations[zonestr]
else:
return zonestr
def remindin(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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))
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))
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]))
return
delaySeconds+=(Remind.scaling[match[1]] * int(match[0]))
remindAt = datetime.now()+timedelta(seconds=delaySeconds)
self.db.query("INSERT INTO `reminders` (`sender`, `senderch`, `when`, `message`) VALUES (?, ?, ?, ?)", (
prefixObj.nick,
args[0] if "#" in args[0] else "",
remindAt,
cmd.args_str[len(cmd.args[0]):].strip()
)).close()
hours = int(delaySeconds/60/60)
minutes = int((delaySeconds-(hours*60*60))/60)
self.bot.act_PRIVMSG(replyTo, "%s: Ok, talk to you in approx %sh%sm" % (prefixObj.nick, hours,minutes))
scaling = {
"years": 365.25 * 24 * 3600,
"year": 365.25 * 24 * 3600,
"yrs": 365.25 * 24 * 3600,
"y": 365.25 * 24 * 3600,
"months": 29.53059 * 24 * 3600,
"month": 29.53059 * 24 * 3600,
"mo": 29.53059 * 24 * 3600,
"weeks": 7 * 24 * 3600,
"week": 7 * 24 * 3600,
"wks": 7 * 24 * 3600,
"wk": 7 * 24 * 3600,
"w": 7 * 24 * 3600,
"days": 24 * 3600,
"day": 24 * 3600,
"d": 24 * 3600,
"hours": 3600,
"hour": 3600,
"hrs": 3600,
"hr": 3600,
"h": 3600,
"minutes": 60,
"minute": 60,
"mins": 60,
"min": 60,
"m": 60,
"seconds": 1,
"second": 1,
"secs": 1,
"sec": 1,
"s": 1,
}
scaling = {
"years": 365.25 * 24 * 3600,
"year": 365.25 * 24 * 3600,
"yrs": 365.25 * 24 * 3600,
"y": 365.25 * 24 * 3600,
"months": 29.53059 * 24 * 3600,
"month": 29.53059 * 24 * 3600,
"mo": 29.53059 * 24 * 3600,
"weeks": 7 * 24 * 3600,
"week": 7 * 24 * 3600,
"wks": 7 * 24 * 3600,
"wk": 7 * 24 * 3600,
"w": 7 * 24 * 3600,
"days": 24 * 3600,
"day": 24 * 3600,
"d": 24 * 3600,
"hours": 3600,
"hour": 3600,
"hrs": 3600,
"hr": 3600,
"h": 3600,
"minutes": 60,
"minute": 60,
"mins": 60,
"min": 60,
"m": 60,
"seconds": 1,
"second": 1,
"secs": 1,
"sec": 1,
"s": 1,
}

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: SQLite
:synopsis: Module providing a sqlite type service
:synopsis: Module providing a sqlite type service
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,78 +12,78 @@ import sys
import sqlite3
class SQLite(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["sqlite"]
self.loadConfig()
def opendb(self, dbname):
return Connection(self, dbname)
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[]
self.services=["sqlite"]
self.loadConfig()
def opendb(self, dbname):
return Connection(self, dbname)
class Connection:
def __init__(self, master, dbname):
self.master = master
self.log = master.log
self.dbname = dbname
self.connection = None
self._connect()
# Check if the table requested exists
def tableExists(self, tablename):
c = self.getCursor()
c.execute("SELECT * FROM SQLITE_MASTER WHERE `type`='table' AND `name`=?", (tablename,))
tables = c.fetchall()
if len(tables)==0:
return False;
return True
@staticmethod
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
def __init__(self, master, dbname):
self.master = master
self.log = master.log
self.dbname = dbname
self.connection = None
self._connect()
# Check if the table requested exists
def tableExists(self, tablename):
c = self.getCursor()
c.execute("SELECT * FROM SQLITE_MASTER WHERE `type`='table' AND `name`=?", (tablename,))
tables = c.fetchall()
if len(tables)==0:
return False;
return True
@staticmethod
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
def query(self, queryText, args=()):
"""Execute a Sqlite query and return the cursor
:param queryText: the sqlite query as a string, using '%s' for token replacement
:type queryText: str
:param args: arguments to be escaped into the query
:type args: tuple
:returns: cursor -- the sql cursor"""
c = self.getCursor()
if len(args)==0:
c.execute(queryText)
else:
c.execute(queryText, args)
return c
# Returns a cusor object, after checking for connectivity
def getCursor(self):
c=self.connection.cursor()
return c
def escape(self, s):
raise NotImplementedError
def ondisable(self):
self.connection.close()
# 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("Sqlite: opening database %s" % self.master.getFilePath(self.dbname))
self.connection = sqlite3.connect(self.master.getFilePath(self.dbname), check_same_thread=False)
self.connection.row_factory = Connection.dict_factory
self.connection.isolation_level = None
self.log.info("Sqlite: Connected.")
# Test the connection
c = self.connection.cursor()
derp=c.execute("SELECT * FROM SQLITE_MASTER")
c.close()
def close(self):
self.connection.close()
def query(self, queryText, args=()):
"""Execute a Sqlite query and return the cursor
:param queryText: the sqlite query as a string, using '%s' for token replacement
:type queryText: str
:param args: arguments to be escaped into the query
:type args: tuple
:returns: cursor -- the sql cursor"""
c = self.getCursor()
if len(args)==0:
c.execute(queryText)
else:
c.execute(queryText, args)
return c
# Returns a cusor object, after checking for connectivity
def getCursor(self):
c=self.connection.cursor()
return c
def escape(self, s):
raise NotImplementedError
def ondisable(self):
self.connection.close()
# 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("Sqlite: opening database %s" % self.master.getFilePath(self.dbname))
self.connection = sqlite3.connect(self.master.getFilePath(self.dbname), check_same_thread=False)
self.connection.row_factory = Connection.dict_factory
self.connection.isolation_level = None
self.log.info("Sqlite: Connected.")
# Test the connection
c = self.connection.cursor()
derp=c.execute("SELECT * FROM SQLITE_MASTER")
c.close()
def close(self):
self.connection.close()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Seen
:synopsis: Provides !seen <username>
:synopsis: Provides !seen <username>
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,61 +12,61 @@ 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()
# check if our table exists
c.execute("SELECT * FROM SQLITE_MASTER WHERE `type`='table' AND `name`='seen'")
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`))");
self.x = "asdf"
def lastSeen(self, args, prefix, trailing):
# using a message to update last seen, also, the .seen query
prefixObj = self.bot.decodePrefix(prefix)
nick = prefixObj.nick
sql=self.getSql()
c = sql.cursor()
# update or add the user's row
datest=str( time.time()+(int(self.config["add_hours"])*60*60))
c.execute("REPLACE INTO `seen` (`nick`, `date`) VALUES (?, ?)", (nick.lower(), datest ))
#self.log.info("Seen: %s on %s" % (nick.lower(), datest))
sql.commit()
if trailing.startswith(".seen"):
cmdargs = trailing.split(" ");
# query the DB for the user
if len(cmdargs)>=2:
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"]));
else:
self.bot.act_PRIVMSG(args[0], "Sorry, I haven't seen %s!" % cmdargs[1])
c.close()
def getSql(self):
# return a SQL reference to the database
path = self.getFilePath('database.sql3')
sql = sqlite3.connect(path);
sql.row_factory = self.dict_factory
return sql
def dict_factory(self, cursor, row):
# because Lists suck for database results
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
def test(self, arg):
print("TEST: %s" % arg)
print("self.x = %s" % self.x)
return arg
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()
# check if our table exists
c.execute("SELECT * FROM SQLITE_MASTER WHERE `type`='table' AND `name`='seen'")
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`))");
self.x = "asdf"
def lastSeen(self, args, prefix, trailing):
# using a message to update last seen, also, the .seen query
prefixObj = self.bot.decodePrefix(prefix)
nick = prefixObj.nick
sql=self.getSql()
c = sql.cursor()
# update or add the user's row
datest=str( time.time()+(int(self.config["add_hours"])*60*60))
c.execute("REPLACE INTO `seen` (`nick`, `date`) VALUES (?, ?)", (nick.lower(), datest ))
#self.log.info("Seen: %s on %s" % (nick.lower(), datest))
sql.commit()
if trailing.startswith(".seen"):
cmdargs = trailing.split(" ");
# query the DB for the user
if len(cmdargs)>=2:
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"]));
else:
self.bot.act_PRIVMSG(args[0], "Sorry, I haven't seen %s!" % cmdargs[1])
c.close()
def getSql(self):
# return a SQL reference to the database
path = self.getFilePath('database.sql3')
sql = sqlite3.connect(path);
sql.row_factory = self.dict_factory
return sql
def dict_factory(self, cursor, row):
# because Lists suck for database results
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
def test(self, arg):
print("TEST: %s" % arg)
print("self.x = %s" % self.x)
return arg

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Services
:synopsis: Provides the ability to configure a nickname, password, channel auto-join
:synopsis: Provides the ability to configure a nickname, password, channel auto-join
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,54 +11,54 @@ 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.loadConfig()
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"])
def nickTaken(self, args, prefix, trailing):
"""Hook that responds to 433, meaning our nick is taken"""
if self.config["ident"]["ghost"]:
self.do_ghost = True
self.current_nick+=1
if self.current_nick >= len(self.config["user"]["nick"]):
self.log.critical("Ran out of usernames while selecting backup username!")
return
self.bot.act_NICK(self.config["user"]["nick"][self.current_nick])
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.loadConfig()
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"])
def nickTaken(self, args, prefix, trailing):
"""Hook that responds to 433, meaning our nick is taken"""
if self.config["ident"]["ghost"]:
self.do_ghost = True
self.current_nick+=1
if self.current_nick >= len(self.config["user"]["nick"]):
self.log.critical("Ran out of usernames while selecting backup username!")
return
self.bot.act_NICK(self.config["user"]["nick"][self.current_nick])
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"]})
sleep(2)
self.bot.act_NICK(self.config["user"]["nick"][0])
self.do_initservices()
def invited(self, args, prefix, trailing):
"""Hook responding to INVITE channel invitations"""
if trailing.lower() in self.config["privatechannels"]["list"]:
self.log.info("Invited to %s, joining" % trailing)
self.bot.act_JOIN(trailing)
def do_initservices(self):
"""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"]})
" join plain channels "
for channel in self.config["channels"]:
self.log.info("Joining %s" % channel)
self.bot.act_JOIN(channel)
" 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})
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"]})
sleep(2)
self.bot.act_NICK(self.config["user"]["nick"][0])
self.do_initservices()
def invited(self, args, prefix, trailing):
"""Hook responding to INVITE channel invitations"""
if trailing.lower() in self.config["privatechannels"]["list"]:
self.log.info("Invited to %s, joining" % trailing)
self.bot.act_JOIN(trailing)
def do_initservices(self):
"""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"]})
" join plain channels "
for channel in self.config["channels"]:
self.log.info("Joining %s" % channel)
self.bot.act_JOIN(channel)
" 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})

View File

@ -1,6 +1,6 @@
"""
.. module:: Tell
:synopsis: Deliver a message to a user when they're next seen
:synopsis: Deliver a message to a user when they're next seen
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -11,186 +11,186 @@ import datetime
from time import mktime
class Tell(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Tell: Could not find a valid sqlite service provider")
else:
self.log.info("Tell: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("tell.db")
if not self.db.tableExists("tells"):
self.log.info("Remind: Creating table: tells")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `tells` (
`id` INTEGER PRIMARY KEY,
`sender` varchar(64),
`channel` varchar(64),
`when` INTEGER,
`recip` varchar(64),
`message` varchar(2048)
) ;""").close()
# Purge expired tells
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),
ModuleHook(["PRIVMSG"], self.tellcmds)
]
def showtell(self, args, prefix, trailing):
#print("%s - %s - %s" % (args, prefix, trailing))
prefix = self.bot.decodePrefix(prefix)
# Look for tells for this person
c = self.db.query("SELECT * FROM `tells` WHERE `recip`=?", (prefix.nick,))
tells = c.fetchall()
c.close()
for tell in tells:
agostr = Tell.timesince(datetime.datetime.fromtimestamp(tell["when"]))
recip = None
if tell["channel"]=="":
recip = prefix.nick
else:
recip = tell["channel"]
self.bot.act_PRIVMSG(recip, "%s: %s said %s ago: %s" % (
prefix.nick,
tell["sender"],
agostr,
tell["message"]
))
# Delete
self.db.query("DELETE FROM `tells` WHERE `id`=?", (tell["id"],))
def tellcmds(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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)
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)
return
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()
self.bot.act_PRIVMSG(replyTo, "%s: I'll pass that along." % prefixObj.nick)
# Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of Django nor the names of its contributors may be used
# to endorse or promote products derived from this software without
# specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@staticmethod
def timesince(d, now=None):
"""
Takes two datetime objects and returns the time between d and now
as a nicely formatted string, e.g. "10 minutes". If d occurs after now,
then "0 minutes" is returned.
Units used are years, months, weeks, days, hours, and minutes.
Seconds and microseconds are ignored. Up to two adjacent units will be
displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
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'))
)
# Convert int or float (unix epoch) to datetime.datetime for comparison
if isinstance(d, int) or isinstance(d, float):
d = datetime.datetime.fromtimestamp(d)
# Convert datetime.date to datetime.datetime for comparison.
if not isinstance(d, datetime.datetime):
d = datetime.datetime(d.year, d.month, d.day)
if now and not isinstance(now, datetime.datetime):
now = datetime.datetime(now.year, now.month, now.day)
if not now:
now = datetime.datetime.now()
# ignore microsecond part of 'd' since we removed it from 'now'
delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
since = delta.days * 24 * 60 * 60 + delta.seconds
if since <= 0:
# d is in the future compared to now, stop processing.
return u'0 ' + 'minutes'
for i, (seconds, name) in enumerate(chunks):
count = since // seconds
if count != 0:
break
if count == 1:
s = '%(number)d %(type)s' % {'number': count, 'type': name[0]}
else:
s = '%(number)d %(type)s' % {'number': count, 'type': name[1]}
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]
count2 = (since - (seconds * count)) // seconds2
if count2 != 0:
if count2 == 1:
s += ', %d %s' % (count2, name2[0])
else:
s += ', %d %s' % (count2, name2[1])
return s
@staticmethod
def timeuntil(d, now=None):
"""
Like timesince, but returns a string measuring the time until
the given time.
"""
if not now:
now = datetime.datetime.now()
return timesince(now, d)
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.db = None
serviceProviders = self.bot.getmodulesbyservice("sqlite")
if len(serviceProviders)==0:
self.log.error("Tell: Could not find a valid sqlite service provider")
else:
self.log.info("Tell: Selecting sqlite service provider: %s" % serviceProviders[0])
self.db = serviceProviders[0].opendb("tell.db")
if not self.db.tableExists("tells"):
self.log.info("Remind: Creating table: tells")
c = self.db.query("""CREATE TABLE IF NOT EXISTS `tells` (
`id` INTEGER PRIMARY KEY,
`sender` varchar(64),
`channel` varchar(64),
`when` INTEGER,
`recip` varchar(64),
`message` varchar(2048)
) ;""").close()
# Purge expired tells
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),
ModuleHook(["PRIVMSG"], self.tellcmds)
]
def showtell(self, args, prefix, trailing):
#print("%s - %s - %s" % (args, prefix, trailing))
prefix = self.bot.decodePrefix(prefix)
# Look for tells for this person
c = self.db.query("SELECT * FROM `tells` WHERE `recip`=?", (prefix.nick,))
tells = c.fetchall()
c.close()
for tell in tells:
agostr = Tell.timesince(datetime.datetime.fromtimestamp(tell["when"]))
recip = None
if tell["channel"]=="":
recip = prefix.nick
else:
recip = tell["channel"]
self.bot.act_PRIVMSG(recip, "%s: %s said %s ago: %s" % (
prefix.nick,
tell["sender"],
agostr,
tell["message"]
))
# Delete
self.db.query("DELETE FROM `tells` WHERE `id`=?", (tell["id"],))
def tellcmds(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
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)
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)
return
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()
self.bot.act_PRIVMSG(replyTo, "%s: I'll pass that along." % prefixObj.nick)
# Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of Django nor the names of its contributors may be used
# to endorse or promote products derived from this software without
# specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@staticmethod
def timesince(d, now=None):
"""
Takes two datetime objects and returns the time between d and now
as a nicely formatted string, e.g. "10 minutes". If d occurs after now,
then "0 minutes" is returned.
Units used are years, months, weeks, days, hours, and minutes.
Seconds and microseconds are ignored. Up to two adjacent units will be
displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
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'))
)
# Convert int or float (unix epoch) to datetime.datetime for comparison
if isinstance(d, int) or isinstance(d, float):
d = datetime.datetime.fromtimestamp(d)
# Convert datetime.date to datetime.datetime for comparison.
if not isinstance(d, datetime.datetime):
d = datetime.datetime(d.year, d.month, d.day)
if now and not isinstance(now, datetime.datetime):
now = datetime.datetime(now.year, now.month, now.day)
if not now:
now = datetime.datetime.now()
# ignore microsecond part of 'd' since we removed it from 'now'
delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
since = delta.days * 24 * 60 * 60 + delta.seconds
if since <= 0:
# d is in the future compared to now, stop processing.
return u'0 ' + 'minutes'
for i, (seconds, name) in enumerate(chunks):
count = since // seconds
if count != 0:
break
if count == 1:
s = '%(number)d %(type)s' % {'number': count, 'type': name[0]}
else:
s = '%(number)d %(type)s' % {'number': count, 'type': name[1]}
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]
count2 = (since - (seconds * count)) // seconds2
if count2 != 0:
if count2 == 1:
s += ', %d %s' % (count2, name2[0])
else:
s += ', %d %s' % (count2, name2[1])
return s
@staticmethod
def timeuntil(d, now=None):
"""
Like timesince, but returns a string measuring the time until
the given time.
"""
if not now:
now = datetime.datetime.now()
return timesince(now, d)

View File

@ -2,7 +2,7 @@
"""
.. module::TextCDC
:synopsis: Text Chrisdotcode, right now.
:synopsis: Text Chrisdotcode, right now.
.. moduleauthor::Nick Krichevsky <nick@ollien.com>
"""
@ -14,98 +14,98 @@ 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 __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:
self.timer.cancel()
def ondisable(self):
if self.timer != None:
self.timer.cancel()
def handleMessage(self, args, prefix, trailing):
channel = args[0]
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.")
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.quit()
self.bot.act_PRIVMSG(channel, "Message sent.")
except Exception as e:
self.bot.log.error(str(e))
self.bot.act_PRIVMSG(channel, "An SMTP Error has Occured")
def handleMessage(self, args, prefix, trailing):
channel = args[0]
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.")
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.quit()
self.bot.act_PRIVMSG(channel, "Message sent.")
except Exception as e:
self.bot.log.error(str(e))
self.bot.act_PRIVMSG(channel, "An SMTP Error has Occured")
def setupIMAP(self):
imapObj = None
if self.config["account"]["imap"]["ssl"]:
imapObj = imaplib.IMAP4_SSL(self.config["account"]["imap"]["host"], self.config["account"]["imap"]["port"])
else:
imapObj = imaplib.IMAP4(self.config["account"]["imap"]["host"], self.config["account"]["imap"]["port"])
imapObj.login(self.config["account"]["auth"]["username"], self.config["account"]["auth"]["password"])
resp = imapObj.select("INBOX")
if resp[0] == "OK":
return imapObj
else:
return None
def setupIMAP(self):
imapObj = None
if self.config["account"]["imap"]["ssl"]:
imapObj = imaplib.IMAP4_SSL(self.config["account"]["imap"]["host"], self.config["account"]["imap"]["port"])
else:
imapObj = imaplib.IMAP4(self.config["account"]["imap"]["host"], self.config["account"]["imap"]["port"])
imapObj.login(self.config["account"]["auth"]["username"], self.config["account"]["auth"]["password"])
resp = imapObj.select("INBOX")
if resp[0] == "OK":
return imapObj
else:
return None
def setupSMTP(self):
smtpObj = None
if self.config["account"]["smtp"]["ssl"]:
smtpObj = smtplib.SMTP_SSL(self.config["account"]["smtp"]["host"], self.config["account"]["smtp"]["port"])
else:
smtpObj = smtplib.SMTP_SSL(self.config["account"]["smtp"]["host"], self.config["account"]["smtp"]["port"])
if self.config["account"]["smtp"]["authentication"]:
resp = smtpObj.login(self.config["account"]["auth"]["username"], self.config["account"]["auth"]["password"])
if resp[0] == 235:
return smtpObj
else:
return None
else:
resp = smtpObj.connect()
if resp[0] == 220:
return smtpObj
else:
return None
def setupTimer(self):
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:
imapObj = self.setupIMAP()
for person in people:
emailAddr = people[person]["email-addr"]
result = imapObj.search(None, "(FROM \"%s\")" % emailAddr)
if (result[0] == "OK"):
messageIds = result[1][0].decode("utf-8")
if len(messageIds) > 0:
messageIds = messageIds.split(" ")
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()
for channel in channels:
bot.act_PRIVMSG(channel, "Message from %s: %s" % (person, messageText))
imapObj.store(messageId, "+FLAGS", "\\Deleted")
else:
raise Exception("SMTP Error. Status was %s, expected OK" % message[0])
imapObj.logout()
self.setupTimer()
except Exception as e:
if imapObj != None:
imapObj.logout()
self.setupTimer()
raise e
def setupSMTP(self):
smtpObj = None
if self.config["account"]["smtp"]["ssl"]:
smtpObj = smtplib.SMTP_SSL(self.config["account"]["smtp"]["host"], self.config["account"]["smtp"]["port"])
else:
smtpObj = smtplib.SMTP_SSL(self.config["account"]["smtp"]["host"], self.config["account"]["smtp"]["port"])
if self.config["account"]["smtp"]["authentication"]:
resp = smtpObj.login(self.config["account"]["auth"]["username"], self.config["account"]["auth"]["password"])
if resp[0] == 235:
return smtpObj
else:
return None
else:
resp = smtpObj.connect()
if resp[0] == 220:
return smtpObj
else:
return None
def setupTimer(self):
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:
imapObj = self.setupIMAP()
for person in people:
emailAddr = people[person]["email-addr"]
result = imapObj.search(None, "(FROM \"%s\")" % emailAddr)
if (result[0] == "OK"):
messageIds = result[1][0].decode("utf-8")
if len(messageIds) > 0:
messageIds = messageIds.split(" ")
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()
for channel in channels:
bot.act_PRIVMSG(channel, "Message from %s: %s" % (person, messageText))
imapObj.store(messageId, "+FLAGS", "\\Deleted")
else:
raise Exception("SMTP Error. Status was %s, expected OK" % message[0])
imapObj.logout()
self.setupTimer()
except Exception as e:
if imapObj != None:
imapObj.logout()
self.setupTimer()
raise e

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Urban
:synopsis: Lookup from urban dictionary
:synopsis: Lookup from urban dictionary
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,24 +12,24 @@ import json
from requests import get
class Urban(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.urban)]
def urban(self, args, prefix, trailing):
cmd = self.bot.messageHasCommand(".urban", trailing)
if not cmd:
cmd = self.bot.messageHasCommand(".u", trailing)
if cmd and args[0][0:1]=="#":
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"]
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']))
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.urban)]
def urban(self, args, prefix, trailing):
cmd = self.bot.messageHasCommand(".urban", trailing)
if not cmd:
cmd = self.bot.messageHasCommand(".u", trailing)
if cmd and args[0][0:1]=="#":
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"]
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']))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
.. module:: Weather
:synopsis: Fetch weather by location string
:synopsis: Fetch weather by location string
.. moduleauthor:: Dave Pedu <dave@davepedu.com>
@ -12,206 +12,206 @@ from requests import get
from urllib.parse import urlencode
class Weather(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
assert not "get an API key" in self.config["apikey"]
self.login = self.bot.getBestModuleForService("login")
try:
assert not self.login == 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:
self.log.error("Weather: An 'attributes' service is required")
return
self.hooks=[ModuleHook("PRIVMSG", self.weather)]
def weather(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
fromWho = prefixObj.nick
replyTo = args[0] if "#" in args[0] else fromWho
hasUnit = self.attr.get(fromWho, "weather-unit")
if hasUnit:
hasUnit = hasUnit.upper()
cmd = self.bot.messageHasCommand([".w", ".weather"], trailing)
if cmd:
if len(cmd.args_str)>0:
self.send_weather(replyTo, fromWho, cmd.args_str, hasUnit)
return
weatherZip = self.attr.get(fromWho, "weather-zip")
if weatherZip == None:
self.bot.act_PRIVMSG(replyTo, "%s: you must set a location with .setloc" % (fromWho,))
return
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (fromWho, self.getWeather(weatherZip, hasUnit)))
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")
return
weatherLoc = cmd.args_str
try:
result = self.getWeather(weatherLoc)
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)))
return
except LocationException as le:
self.bot.act_PRIVMSG(fromWho, "'%s': location not found" % weatherLoc)
return
if not self.login.check(prefixObj.nick, prefixObj.hostname):
self.bot.act_PRIVMSG(fromWho, ".setloc: you need to be logged in to do that (try .login)")
return
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:
self.bot.act_PRIVMSG(fromWho, "Tip: choose C or F with .wunit <C/F>")
cmd = self.bot.messageHasCommand(".wunit", trailing)
if cmd and not args[0]=="#":
unit = None
try:
assert cmd.args[0].lower() in ['c', 'f']
unit = cmd.args[0]
except:
pass
if unit == None:
self.bot.act_PRIVMSG(fromWho, ".wunit: set your preferred temperature unit to C or F")
return
if not self.login.check(prefixObj.nick, prefixObj.hostname):
self.bot.act_PRIVMSG(fromWho, ".wunit: you need to be logged in to do that (try .login)")
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())
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)))
except LocationException as le:
self.bot.act_PRIVMSG(target, "'%s': location not found" % location)
def alternates_to_str(self, alternates):
pieces = []
for item in alternates:
item_pieces = []
for key in ["name", "state", "country_name"]:
if key in item and len(item[key].strip()):
item_pieces.append(item[key])
pieces.append(', '.join(item_pieces))
return ' -- '.join(pieces)
def getWeather(self, zipcode, unit=None):
if unit==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()
if "results" in data["response"]:
raise LocationNotSpecificException(data["response"]["results"])
if "error" in data["response"] and data["response"]["error"]["type"]=="querynotfound":
raise LocationException
# Build 5day
fiveday = ""
for item in data["forecast"]["simpleforecast"]["forecastday"][1:6]:
fiveday += "%(day)s %(icon)s %(low)s-%(high)s°%(unit)s" % {
"unit":unit.upper(),
"high":item["high"]["fahrenheit" if unit=="f" else "celsius"],
"low":item["low"]["fahrenheit" if unit=="f" else "celsius"],
"icon":self.icon2emoji(item["icon"]),
"day":item["date"]["weekday_short"]
}
fiveday=fiveday[0:-3]
# 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"]
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" % {
"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"]),
"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
}
def shorten_windstr(self, windstr):
if "gusting" in windstr:
return "Gusting"
if "calm" in windstr:
return "Calm"
if "from the" in windstr.lower():
return "Varying"
return windstr[0:12]
def icon2emoji(self,icon):
if "partlycloudy" in icon or "mostlycloudy" in icon:
return "⛅️"
elif "cloudy" in icon:
return "☁️"
elif "rain" in icon:
return "💧"
elif "clear" in icon:
return "☀️"
elif "snow" in icon:
return "❄️"
else:
return "(%s)" % icon
def deg_to_arrow(self, deg):
if deg > 335 or deg < 0:
return ""
elif deg > 292:
return ""
elif deg > 247:
return ""
elif deg > 202:
return ""
elif deg > 157:
return ""
elif deg > 112:
return ""
elif deg > 67:
return ""
elif deg > 22:
return ""
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
assert not "get an API key" in self.config["apikey"]
self.login = self.bot.getBestModuleForService("login")
try:
assert not self.login == 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:
self.log.error("Weather: An 'attributes' service is required")
return
self.hooks=[ModuleHook("PRIVMSG", self.weather)]
def weather(self, args, prefix, trailing):
prefixObj = self.bot.decodePrefix(prefix)
fromWho = prefixObj.nick
replyTo = args[0] if "#" in args[0] else fromWho
hasUnit = self.attr.get(fromWho, "weather-unit")
if hasUnit:
hasUnit = hasUnit.upper()
cmd = self.bot.messageHasCommand([".w", ".weather"], trailing)
if cmd:
if len(cmd.args_str)>0:
self.send_weather(replyTo, fromWho, cmd.args_str, hasUnit)
return
weatherZip = self.attr.get(fromWho, "weather-zip")
if weatherZip == None:
self.bot.act_PRIVMSG(replyTo, "%s: you must set a location with .setloc" % (fromWho,))
return
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (fromWho, self.getWeather(weatherZip, hasUnit)))
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")
return
weatherLoc = cmd.args_str
try:
result = self.getWeather(weatherLoc)
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)))
return
except LocationException as le:
self.bot.act_PRIVMSG(fromWho, "'%s': location not found" % weatherLoc)
return
if not self.login.check(prefixObj.nick, prefixObj.hostname):
self.bot.act_PRIVMSG(fromWho, ".setloc: you need to be logged in to do that (try .login)")
return
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:
self.bot.act_PRIVMSG(fromWho, "Tip: choose C or F with .wunit <C/F>")
cmd = self.bot.messageHasCommand(".wunit", trailing)
if cmd and not args[0]=="#":
unit = None
try:
assert cmd.args[0].lower() in ['c', 'f']
unit = cmd.args[0]
except:
pass
if unit == None:
self.bot.act_PRIVMSG(fromWho, ".wunit: set your preferred temperature unit to C or F")
return
if not self.login.check(prefixObj.nick, prefixObj.hostname):
self.bot.act_PRIVMSG(fromWho, ".wunit: you need to be logged in to do that (try .login)")
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())
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)))
except LocationException as le:
self.bot.act_PRIVMSG(target, "'%s': location not found" % location)
def alternates_to_str(self, alternates):
pieces = []
for item in alternates:
item_pieces = []
for key in ["name", "state", "country_name"]:
if key in item and len(item[key].strip()):
item_pieces.append(item[key])
pieces.append(', '.join(item_pieces))
return ' -- '.join(pieces)
def getWeather(self, zipcode, unit=None):
if unit==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()
if "results" in data["response"]:
raise LocationNotSpecificException(data["response"]["results"])
if "error" in data["response"] and data["response"]["error"]["type"]=="querynotfound":
raise LocationException
# Build 5day
fiveday = ""
for item in data["forecast"]["simpleforecast"]["forecastday"][1:6]:
fiveday += "%(day)s %(icon)s %(low)s-%(high)s°%(unit)s" % {
"unit":unit.upper(),
"high":item["high"]["fahrenheit" if unit=="f" else "celsius"],
"low":item["low"]["fahrenheit" if unit=="f" else "celsius"],
"icon":self.icon2emoji(item["icon"]),
"day":item["date"]["weekday_short"]
}
fiveday=fiveday[0:-3]
# 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"]
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" % {
"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"]),
"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
}
def shorten_windstr(self, windstr):
if "gusting" in windstr:
return "Gusting"
if "calm" in windstr:
return "Calm"
if "from the" in windstr.lower():
return "Varying"
return windstr[0:12]
def icon2emoji(self,icon):
if "partlycloudy" in icon or "mostlycloudy" in icon:
return "⛅️"
elif "cloudy" in icon:
return "☁️"
elif "rain" in icon:
return "💧"
elif "clear" in icon:
return "☀️"
elif "snow" in icon:
return "❄️"
else:
return "(%s)" % icon
def deg_to_arrow(self, deg):
if deg > 335 or deg < 0:
return ""
elif deg > 292:
return ""
elif deg > 247:
return ""
elif deg > 202:
return ""
elif deg > 157:
return ""
elif deg > 112:
return ""
elif deg > 67:
return ""
elif deg > 22:
return ""
class LocationException(Exception):
pass
pass
class LocationNotSpecificException(LocationException):
def __init__(self, alternates):
self.alternates = alternates
pass
def __init__(self, alternates):
self.alternates = alternates
pass

View File

@ -1,6 +1,6 @@
"""
.. module:: Modules
:synopsis: Module containing the bot's modules
:synopsis: Module containing the bot's modules
.. moduleauthor:: Dave Pedu <dave@davepedu.com>

View File

@ -4,11 +4,11 @@ from setuptools import setup
__version__ = "4.0.0-r02"
setup(name='pyircbot',
version='4.0.0-r02',
description='A modular python irc bot',
url='http://gitlab.xmopx.net/dave/pyircbot3/tree/master',
author='dpedu',
author_email='dave@davepedu.com',
packages=['pyircbot', 'pyircbot.modules'],
scripts=['bin/pyircbot'],
zip_safe=False)
version='4.0.0-r02',
description='A modular python irc bot',
url='http://gitlab.xmopx.net/dave/pyircbot3/tree/master',
author='dpedu',
author_email='dave@davepedu.com',
packages=['pyircbot', 'pyircbot.modules'],
scripts=['bin/pyircbot'],
zip_safe=False)