modernize module system: 5.0.0
This commit is contained in:
parent
5b68793f4f
commit
d55e111767
@ -6,8 +6,8 @@ Quick start
|
||||
-----------
|
||||
|
||||
* Install: `python3 setup.py install`
|
||||
* Configure: `cd examples ; vim config.json data/config/Services.json`
|
||||
* Run: `pyircbot -c config.json`
|
||||
* Configure: `vim examples/config.json examples/data/config/Services.json`
|
||||
* Run: `pyircbot -c examples/config.json`
|
||||
|
||||
Running in docker
|
||||
-----------------
|
||||
|
131
bin/pubsubbot
Executable file
131
bin/pubsubbot
Executable file
@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
from contextlib import closing
|
||||
from argparse import ArgumentParser
|
||||
from json import loads, load
|
||||
from msgbus.client import MsgbusSubClient
|
||||
import pyircbot
|
||||
import traceback
|
||||
from pyircbot.pyircbot import PrimitiveBot
|
||||
from pyircbot.irccore import IRCEvent, UserPrefix
|
||||
from json import dumps
|
||||
|
||||
|
||||
# IRCEvent = namedtuple("IRCEvent", "command args prefix trailing")
|
||||
# UserPrefix = namedtuple("UserPrefix", "nick username hostname")
|
||||
# ServerPrefix = namedtuple("ServerPrefix", "hostname")
|
||||
|
||||
|
||||
class PyIRCBotSub(PrimitiveBot):
|
||||
def __init__(self, name, host, port, config):
|
||||
super().__init__(config)
|
||||
self.name = name
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.client = None # PubSub socket
|
||||
|
||||
def run(self):
|
||||
# Connect to msgbus and loop through messages
|
||||
with closing(MsgbusSubClient(self.host, self.port)) as self.client:
|
||||
self.client.sub("pyircbot_privmsg")#TODO More of these
|
||||
while True:
|
||||
try:
|
||||
channel, body = self.client.recv()
|
||||
self.process_line(channel, body)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
|
||||
def process_line(self, channel, body):
|
||||
name, rest = body.split(" ", 1)
|
||||
if name != self.name:
|
||||
return
|
||||
|
||||
# pyircbot_privmsg default
|
||||
# [["#jesusandhacking"], "xMopxShell", "test", {"prefix": ["xMopxShell", "~xMopxShel", "192.95.23.134"]}]
|
||||
args, sender, trailing, extras = loads(rest)
|
||||
nick, username, hostname = extras["prefix"]
|
||||
|
||||
msg = IRCEvent("PRIVMSG",
|
||||
args,
|
||||
UserPrefix(nick,
|
||||
username,
|
||||
hostname),
|
||||
trailing)
|
||||
|
||||
for module_name, module in self.moduleInstances.items():
|
||||
for hook in module.irchooks:
|
||||
validation = hook.validator(msg, self)
|
||||
if validation:
|
||||
hook.method(msg, validation)
|
||||
|
||||
# client.pub("pyircbot_send", "default privmsg {}".format(dumps([channel, "{}: pong".format(sender)])))
|
||||
|
||||
" Filesystem Methods "
|
||||
def getConfigPath(self, moduleName):
|
||||
"""Return the absolute path for a module's config file
|
||||
|
||||
:param moduleName: the module who's config file we want
|
||||
:type moduleName: str"""
|
||||
|
||||
basepath = "%s/config/%s" % (self.botconfig["bot"]["datadir"], moduleName)
|
||||
|
||||
if os.path.exists("%s.json" % basepath):
|
||||
return "%s.json" % basepath
|
||||
return None
|
||||
|
||||
def getDataPath(self, moduleName):
|
||||
"""Return the absolute path for a module's data dir
|
||||
|
||||
:param moduleName: the module who's data dir we want
|
||||
:type moduleName: str"""
|
||||
module_dir = os.path.join(self.botconfig["bot"]["datadir"], "data", moduleName)
|
||||
if not os.path.exists(module_dir):
|
||||
os.mkdir(module_dir)
|
||||
return module_dir
|
||||
|
||||
" IRC methods "
|
||||
def act_PRIVMSG(self, towho, message):
|
||||
"""Use the `/msg` command
|
||||
|
||||
:param towho: the target #channel or user's name
|
||||
:type towho: str
|
||||
:param message: the message to send
|
||||
:type message: str"""
|
||||
# self.sendRaw("PRIVMSG %s :%s" % (towho, message))
|
||||
self.client.pub("pyircbot_send", "{} {} {}".format(self.name, "privmsg", dumps([towho, message])))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
|
||||
log = logging.getLogger('main')
|
||||
|
||||
# parse command line args
|
||||
parser = ArgumentParser(description="Run pyircbot plugins behind a pubsub client")
|
||||
parser.add_argument("-c", "--config", help="Pyircbot config file")
|
||||
parser.add_argument("-s", "--server", default="localhost", help="Msgbus server address")
|
||||
parser.add_argument("-p", "--port", default=7100, type=int, help="Msgbus server port")
|
||||
parser.add_argument("-n", "--name", default="default", help="bot name")
|
||||
parser.add_argument("--debug", action="store_true", help="")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
log.debug(args)
|
||||
|
||||
# Load config
|
||||
with open(args.config) as f:
|
||||
config = load(f)
|
||||
|
||||
bot = PyIRCBotSub(args.name, args.server, int(args.port), config)
|
||||
|
||||
# Load modules in config
|
||||
sys.path.append(os.path.dirname(pyircbot.__file__) + "/modules/")
|
||||
for modulename in config["modules"]:
|
||||
print("Load: ", modulename)
|
||||
bot.loadmodule(modulename)
|
||||
|
||||
bot.run()
|
||||
|
@ -3,6 +3,7 @@ import sys
|
||||
import logging
|
||||
import signal
|
||||
from argparse import ArgumentParser
|
||||
from pyircbot.common import load
|
||||
from pyircbot import PyIRCBot
|
||||
from json import loads
|
||||
|
||||
@ -30,7 +31,7 @@ if __name__ == "__main__":
|
||||
log.critical("No bot config file specified (-c). Exiting.")
|
||||
sys.exit(1)
|
||||
|
||||
botconfig = loads(sys.stdin.read()) if args.config == "-" else PyIRCBot.load(args.config)
|
||||
botconfig = loads(sys.stdin.read()) if args.config == "-" else load(args.config)
|
||||
|
||||
log.debug(botconfig)
|
||||
|
||||
|
@ -13,6 +13,7 @@ Contents:
|
||||
modules/_modules.rst
|
||||
rpc/_rpc.rst
|
||||
module_guide/_module_guide.rst
|
||||
module_guide/_pubsub_mode.rst
|
||||
changelog.rst
|
||||
|
||||
More Information
|
||||
|
@ -74,6 +74,8 @@ Prefix may also be a ``ServerPrefix`` object, if the hook is for an IRC method
|
||||
that interacts with the server directly, such as PING. It would have the
|
||||
properties ``event.prefix.hostname`` and ``event.prefix.str``.
|
||||
|
||||
There are more hook-like decorators. See @regex and @command.
|
||||
|
||||
Since the module described above echos messages, let's do that:
|
||||
|
||||
.. code-block:: python
|
||||
@ -134,30 +136,6 @@ In usage:
|
||||
4:40:17 PM <Beefpile> test
|
||||
4:40:17 PM <derpbot420> test
|
||||
|
||||
New Style Module Hooks
|
||||
----------------------
|
||||
|
||||
Instead of receiving the values of the IRC event a module is responding to in
|
||||
3 separate arguments, hooks can receive them as one object. The hook system
|
||||
will automatically determine which argument style to use.
|
||||
|
||||
The reason for this change is to eliminate some unnecessary code in modules.
|
||||
Any module that looks at a user's nick or hostname may find itself doing
|
||||
something like this in every hook:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def saynick(self, args, prefix, trailing):
|
||||
prefixObj = self.bot.decodePrefix(prefix)
|
||||
self.bot.act_PRIVMSG(args[0], "Hello, %s. You are connecting from %s" % (prefixObj.nick, prefixObj.hostname))
|
||||
|
||||
With the new style, one line can be eliminated, as the passed ``IRCEvent``
|
||||
event has the prefix already parsed:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def saynick(self, event):
|
||||
self.bot.act_PRIVMSG(event.args[0], "Hello, %s. You are connecting from %s" % (event.prefix.nick, event.prefix.hostname))
|
||||
|
||||
Advanced Usage
|
||||
==============
|
||||
|
31
docs/module_guide/_pubsub_mode.rst
Normal file
31
docs/module_guide/_pubsub_mode.rst
Normal file
@ -0,0 +1,31 @@
|
||||
***********
|
||||
PubSub Mode
|
||||
***********
|
||||
|
||||
The PubSubClient module provides a ZeroMQ-based PubSub remote control capability to pyircbot. Well, what if you could
|
||||
also run pyircbot modules as a client of the pubsub bus? Look no further!
|
||||
|
||||
Obviously, the :py:class:`pyircbot.modules.PubSubClient.PubSubClient` module should be enabled. Take note of the `name`
|
||||
parameter (which may be left at the default "default").
|
||||
|
||||
The so-called footless (as opposed to headless, as the bot's head is the IRC client connection) client needs only a
|
||||
small set of bootstrap modules:
|
||||
|
||||
- PingResponder (:py:class:`pyircbot.modules.PingResponder.PingResponder`)
|
||||
- Services (:py:class:`pyircbot.modules.Services.Services`)
|
||||
- PubSubClient (:py:class:`pyircbot.modules.PubSubClient.PubSubClient`)
|
||||
|
||||
Launch the bot and let it connect to the msgbus server.
|
||||
|
||||
Next, create a config identical to that of a normal pyircbot, but with any modules desired enabled. Also, read the
|
||||
`--help` text for the `pubsubbot` program. Launch the `pubsubbot` process:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pubsubbot -c config-sub.json --name <name>
|
||||
|
||||
After connecting to the message bus, `pubsubbot` will be hosting any configured modules. It can be exited and restarted
|
||||
any time without affecting the IRC client connection!
|
||||
|
||||
For a module to support running in this mode, it must use only methods described in the Module Developers Guide. Using
|
||||
APIs outside of this - while not discouraged - will definitely break compatibility.
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"bot":{
|
||||
"datadir":"./data/",
|
||||
"datadir":"./examples/data/",
|
||||
"rpcbind":"0.0.0.0",
|
||||
"rpcport":1876,
|
||||
"usermodules": [ "./data/modules/" ]
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"limit": 25,
|
||||
"recv_msg": "Oh, thanks, I'll keep %(adjective)s%(item)s safe",
|
||||
"inv_msg": "\u0000\u0001ACTION is carrying %(itemlist)s\u0000\u0001",
|
||||
"swap_msg": "\u0000\u0001ACTION takes %(adjective)s%(recv_item)s but drops %(drop_item)s\u0000\u0010",
|
||||
"inv_msg": "\u0001ACTION is carrying %(itemlist)s\u0001",
|
||||
"swap_msg": "\u0001ACTION takes %(adjective)s%(recv_item)s but drops %(drop_item)s\u0010",
|
||||
"dupe_msg": "No thanks, I've already got %(item)s",
|
||||
"adjectives": [
|
||||
"some",
|
||||
@ -10,4 +10,4 @@
|
||||
"an",
|
||||
"these"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
pyircbot --config config.json
|
@ -1,5 +1,10 @@
|
||||
from time import time
|
||||
from math import floor
|
||||
from json import load as json_load
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
ParsedCommand = namedtuple("ParsedCommand", "command args args_str message")
|
||||
|
||||
|
||||
class burstbucket(object):
|
||||
@ -39,3 +44,63 @@ class burstbucket(object):
|
||||
self.bucket -= 1
|
||||
return 0
|
||||
return self.bucket_period - since_fill
|
||||
|
||||
|
||||
def messageHasCommand(command, message, requireArgs=False):
|
||||
"""Check if a message has a command with or without args in it
|
||||
|
||||
:param command: the command string to look for, like !ban. If a list is passed, the first match is returned.
|
||||
:type command: str or list
|
||||
:param message: the message string to look in, like "!ban Lil_Mac"
|
||||
:type message: str
|
||||
:param requireArgs: if true, only validate if the command use has any amount of trailing text
|
||||
:type requireArgs: bool"""
|
||||
|
||||
if not type(command) == list:
|
||||
command = [command]
|
||||
for item in command:
|
||||
cmd = messageHasCommandSingle(item, message, requireArgs)
|
||||
if cmd:
|
||||
return cmd
|
||||
return False
|
||||
|
||||
|
||||
def messageHasCommandSingle(command, message, requireArgs=False):
|
||||
# Check if the message at least starts with the command
|
||||
messageBeginning = message[0:len(command)]
|
||||
if messageBeginning != command:
|
||||
return False
|
||||
# Make sure it's not a subset of a longer command (ie .meme being set off by .memes)
|
||||
subsetCheck = message[len(command):len(command) + 1]
|
||||
if subsetCheck != " " and subsetCheck != "":
|
||||
return False
|
||||
|
||||
# We've got the command! Do we need args?
|
||||
argsStart = len(command)
|
||||
args = ""
|
||||
if argsStart > 0:
|
||||
args = message[argsStart + 1:].strip()
|
||||
|
||||
if requireArgs and args == '':
|
||||
return False
|
||||
|
||||
# Verified! Return the set.
|
||||
return ParsedCommand(command,
|
||||
args.split(" ") if args else [],
|
||||
args,
|
||||
message)
|
||||
|
||||
|
||||
def load(filepath):
|
||||
"""Return an object from the passed filepath
|
||||
|
||||
:param filepath: path to a json file. filename must end with .json
|
||||
:type filepath: str
|
||||
:Returns: | dict
|
||||
"""
|
||||
|
||||
if filepath.endswith(".json"):
|
||||
with open(filepath, 'r') as f:
|
||||
return json_load(f)
|
||||
else:
|
||||
raise Exception("Unknown config format")
|
||||
|
@ -172,6 +172,7 @@ class IRCCore(object):
|
||||
def initHooks(self):
|
||||
"""Defines hooks that modules can listen for events of"""
|
||||
self.hooks = [
|
||||
'_ALL',
|
||||
'_CONNECT',
|
||||
'_DISCONNECT',
|
||||
'_RECV',
|
||||
@ -222,7 +223,7 @@ class IRCCore(object):
|
||||
:type prefix: str
|
||||
:param trailing: data payload of the command
|
||||
:type trailing: str"""
|
||||
for hook in self.hookcalls[command]:
|
||||
for hook in self.hookcalls["_ALL"] + self.hookcalls[command]:
|
||||
try:
|
||||
if len(getargspec(hook).args) == 2:
|
||||
hook(IRCCore.packetAsObject(command, args, prefix, trailing))
|
||||
|
@ -9,7 +9,8 @@
|
||||
import re
|
||||
import os
|
||||
import logging
|
||||
from .pyircbot import PyIRCBot
|
||||
from .common import load as pload
|
||||
from .common import messageHasCommand
|
||||
|
||||
|
||||
class ModuleBase:
|
||||
@ -28,9 +29,6 @@ class ModuleBase:
|
||||
self.bot = bot
|
||||
"""Reference to the master PyIRCBot object"""
|
||||
|
||||
self.hooks = []
|
||||
"""Low-level protocol hooks this module has"""
|
||||
|
||||
self.irchooks = []
|
||||
"""IRC Hooks this module has"""
|
||||
|
||||
@ -73,7 +71,7 @@ class ModuleBase:
|
||||
if not self.config:
|
||||
configPath = self.getConfigPath()
|
||||
if configPath is not None:
|
||||
self.config = PyIRCBot.load(configPath)
|
||||
self.config = pload(configPath)
|
||||
|
||||
def onenable(self):
|
||||
"""Called when the module is enabled"""
|
||||
@ -228,7 +226,7 @@ class command(hook):
|
||||
"""
|
||||
if not super().validate(msg, bot):
|
||||
return False
|
||||
if not self.allow_private and msg.args[0] == "#":
|
||||
if msg.args[0][0] != "#" and not self.allow_private:
|
||||
return False
|
||||
for keyword in self.keywords:
|
||||
single = self._validate_one(msg, keyword)
|
||||
@ -238,7 +236,7 @@ class command(hook):
|
||||
|
||||
def _validate_one(self, msg, keyword):
|
||||
with_prefix = "{}{}".format(self.prefix, keyword)
|
||||
return PyIRCBot.messageHasCommand(with_prefix, msg.trailing, requireArgs=self.require_args)
|
||||
return messageHasCommand(with_prefix, msg.trailing, requireArgs=self.require_args)
|
||||
|
||||
|
||||
class regex(hook):
|
||||
|
@ -13,7 +13,6 @@ from pyircbot.modulebase import ModuleBase
|
||||
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")
|
||||
|
@ -13,7 +13,6 @@ from pyircbot.modulebase import ModuleBase
|
||||
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")
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
from decimal import Decimal
|
||||
from requests import get
|
||||
from time import time
|
||||
|
||||
@ -18,25 +20,23 @@ class BitcoinPrice(ModuleBase):
|
||||
self.cache = None
|
||||
self.cacheAge = 0
|
||||
|
||||
self.hooks = [
|
||||
ModuleHook(["PRIVMSG"], self.btc)
|
||||
]
|
||||
@info("btc retrieve the current price of bitcoin", cmds=["btc"])
|
||||
@command("btc", "bitcoin")
|
||||
def btc(self, msg, cmd):
|
||||
replyTo = msg.prefix.nick if "#" not in msg.args[0] else msg.args[0]
|
||||
|
||||
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'])
|
||||
))
|
||||
data = self.getApi()
|
||||
self.bot.act_PRIVMSG(replyTo, "%s: %s" % (
|
||||
msg.prefix.nick,
|
||||
"\x02\x0307Bitcoin:\x03\x02 \x0307${price:.2f}\x0f - "
|
||||
"24h change: \x0307${change:.2f}\x0f - "
|
||||
"24h volume: \x0307${volume:.0f}M\x0f".format(price=Decimal(data["price_usd"]),
|
||||
change=Decimal(data["percent_change_24h"]),
|
||||
volume=Decimal(data["24h_volume_usd"]) / 10**6)
|
||||
))
|
||||
|
||||
def getApi(self):
|
||||
if self.cache is None or time() - self.cacheAge > self.config["cache"]:
|
||||
self.cache = get("https://btc-e.com/api/2/btc_usd/ticker").json()
|
||||
self.cache = get("https://api.coinmarketcap.com/v1/ticker/bitcoin/").json()[0]
|
||||
self.cacheAge = time()
|
||||
return self.cache
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook, MissingDependancyException, regex, command
|
||||
from pyircbot.modulebase import ModuleBase, MissingDependancyException, regex, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
import datetime
|
||||
import time
|
||||
@ -93,12 +93,13 @@ class Calc(ModuleBase):
|
||||
|
||||
if word and changeit:
|
||||
# Add a new calc or delete
|
||||
if self.config["allowDelete"] and not value:
|
||||
result = self.deleteCalc(channel, word)
|
||||
if result:
|
||||
self.bot.act_PRIVMSG(channel, "Calc deleted, %s." % sender)
|
||||
else:
|
||||
self.bot.act_PRIVMSG(channel, "Sorry %s, I don't know what '%s' is." % (sender, word))
|
||||
if not value:
|
||||
if self.config["allowDelete"]:
|
||||
result = self.deleteCalc(channel, word)
|
||||
if result:
|
||||
self.bot.act_PRIVMSG(channel, "Calc deleted, %s." % sender)
|
||||
else:
|
||||
self.bot.act_PRIVMSG(channel, "Sorry %s, I don't know what '%s' is." % (sender, word))
|
||||
else:
|
||||
if self.config["delaySubmit"] > 0 and self.timeSince(channel, "add") < self.config["delaySubmit"]:
|
||||
self.bot.act_PRIVMSG(channel, self.remainingToStr(self.config["delaySubmit"],
|
||||
|
@ -15,7 +15,6 @@ from threading import Thread
|
||||
class CryptoWalletRPC(ModuleBase):
|
||||
def __init__(self, bot, moduleName):
|
||||
ModuleBase.__init__(self, bot, moduleName)
|
||||
self.hooks = []
|
||||
self.services = ["bitcoinrpc"]
|
||||
self.rpcservices = {}
|
||||
self.loadrpcservices()
|
||||
|
@ -14,7 +14,6 @@ from bitcoinrpc.authproxy import AuthServiceProxy
|
||||
class DogeRPC(ModuleBase):
|
||||
def __init__(self, bot, moduleName):
|
||||
ModuleBase.__init__(self, bot, moduleName)
|
||||
self.hooks = []
|
||||
self.services = ["dogerpc"]
|
||||
self.rpc = DogeController(self)
|
||||
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
import time
|
||||
import json
|
||||
import random
|
||||
@ -18,7 +19,6 @@ import os
|
||||
class DuckHunt(ModuleBase):
|
||||
def __init__(self, bot, moduleName):
|
||||
ModuleBase.__init__(self, bot, moduleName)
|
||||
self.hooks = [ModuleHook("PRIVMSG", self.hunt)]
|
||||
|
||||
self.jsonPath = self.getFilePath("scores.json")
|
||||
|
||||
@ -29,109 +29,103 @@ class DuckHunt(ModuleBase):
|
||||
|
||||
self.startHunt()
|
||||
|
||||
def hunt(self, args, prefix, trailing):
|
||||
prefixObj = self.bot.decodePrefix(prefix)
|
||||
fromWho = prefixObj.nick
|
||||
@info("huntscore show your duckhunt score", cmds=["huntscore"])
|
||||
@command("huntscore", allow_private=True)
|
||||
def hunt(self, msg, cmd):
|
||||
scores = self.loadScores()
|
||||
fromWho = msg.prefix.nick
|
||||
if fromWho not in scores:
|
||||
self.bot.act_PRIVMSG(fromWho, "You have no points :(")
|
||||
else:
|
||||
scores = scores[fromWho]
|
||||
kills = 0
|
||||
runts = 0
|
||||
prime = 0
|
||||
weight = 0.0
|
||||
shots = 0
|
||||
misses = 0
|
||||
for kill in scores:
|
||||
if kill["prime"]:
|
||||
prime += 1
|
||||
if kill["runt"]:
|
||||
runts += 1
|
||||
kills += 1
|
||||
weight += kill["weight"]
|
||||
shots += 1
|
||||
shots += kill["misses"]
|
||||
misses += kill["misses"]
|
||||
|
||||
cmd = self.bot.messageHasCommand("!huntscore", trailing, False)
|
||||
if cmd:
|
||||
scores = self.loadScores()
|
||||
if fromWho not in scores:
|
||||
self.bot.act_PRIVMSG(fromWho, "You have no points :(")
|
||||
self.bot.act_PRIVMSG(fromWho, "You've shot %s %s for a total weight of %s lbs." %
|
||||
(kills, self.config["animalSpeciesPlural"], weight))
|
||||
self.bot.act_PRIVMSG(fromWho, "%s prime catches, %s runts, %s bullets used and %s misses." %
|
||||
(prime, runts, shots, misses))
|
||||
# self.bot.act_PRIVMSG(fromWho, "More info & highscores: http://duckhunt.xmopx.net/")
|
||||
|
||||
@info("shoot shoot active targets", cmds=["shoot"])
|
||||
@command("shoot")
|
||||
def cmd_shoot(self, msg, args):
|
||||
if self.isDuckOut:
|
||||
fromWho = msg.prefix.nick
|
||||
|
||||
if fromWho not in self.misses:
|
||||
self.misses[fromWho] = 0
|
||||
|
||||
shotIn = round(time.time() - self.outStart, 2)
|
||||
|
||||
if random.randint(0, 100) <= self.config["missChance"]:
|
||||
self.bot.act_PRIVMSG(self.config["activeChannel"], "%s fires after %s seconds and misses!" %
|
||||
(fromWho, shotIn))
|
||||
self.misses[fromWho] += 1
|
||||
return
|
||||
|
||||
self.isDuckOut = False
|
||||
|
||||
bagged = {
|
||||
"species": self.config["animalSpecies"],
|
||||
"gender": "M" if random.randint(0, 1) == 1 else "F",
|
||||
"time": shotIn,
|
||||
"prime": False,
|
||||
"runt": False,
|
||||
"weight": 0.0,
|
||||
"date": time.time(),
|
||||
"misses": self.misses[fromWho]
|
||||
}
|
||||
|
||||
message = "%s %s " % (fromWho, "bags")
|
||||
|
||||
if random.randint(0, 100) <= self.config["primeChance"]:
|
||||
bagged["prime"] = True
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightMax"], self.config["weightFat"])
|
||||
message += "a prime catch, a "
|
||||
elif random.randint(0, 100) <= self.config["runtChance"]:
|
||||
bagged["runt"] = True
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightRunt"], self.config["weightMin"])
|
||||
message += "a runt of a catch, a "
|
||||
else:
|
||||
scores = scores[fromWho]
|
||||
kills = 0
|
||||
runts = 0
|
||||
prime = 0
|
||||
weight = 0.0
|
||||
shots = 0
|
||||
misses = 0
|
||||
for kill in scores:
|
||||
if kill["prime"]:
|
||||
prime += 1
|
||||
if kill["runt"]:
|
||||
runts += 1
|
||||
kills += 1
|
||||
weight += kill["weight"]
|
||||
shots += 1
|
||||
shots += kill["misses"]
|
||||
misses += kill["misses"]
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightMin"], self.config["weightMax"])
|
||||
message += "a "
|
||||
|
||||
self.bot.act_PRIVMSG(fromWho, "You've shot %s %s for a total weight of %s lbs." %
|
||||
(kills, self.config["animalSpeciesPlural"], weight))
|
||||
self.bot.act_PRIVMSG(fromWho, "%s prime catches, %s runts, %s bullets used and %s misses." %
|
||||
(prime, runts, shots, misses))
|
||||
# self.bot.act_PRIVMSG(fromWho, "More info & highscores: http://duckhunt.xmopx.net/")
|
||||
self.log.info("DuckHunt: %s used !huntscore" % fromWho)
|
||||
return
|
||||
message += "%s lb " % (bagged["weight"])
|
||||
if bagged["gender"] == "M":
|
||||
message += self.config["animalNameMale"] + " "
|
||||
else:
|
||||
message += self.config["animalNameFemale"] + " "
|
||||
|
||||
# Channel only
|
||||
if not args[0][0] == "#":
|
||||
return
|
||||
message += "in %s seconds!" % shotIn
|
||||
self.bot.act_PRIVMSG(self.config["activeChannel"], message)
|
||||
|
||||
cmd = self.bot.messageHasCommand("!shoot", trailing, False)
|
||||
if cmd:
|
||||
if self.isDuckOut:
|
||||
self.addKillFor(fromWho, bagged)
|
||||
|
||||
if fromWho not in self.misses:
|
||||
self.misses[fromWho] = 0
|
||||
self.misses = {}
|
||||
|
||||
shotIn = round(time.time() - self.outStart, 2)
|
||||
|
||||
if random.randint(0, 100) <= self.config["missChance"]:
|
||||
self.bot.act_PRIVMSG(self.config["activeChannel"], "%s fires after %s seconds and misses!" %
|
||||
(fromWho, shotIn))
|
||||
self.misses[fromWho] += 1
|
||||
return
|
||||
|
||||
self.isDuckOut = False
|
||||
|
||||
bagged = {
|
||||
"species": self.config["animalSpecies"],
|
||||
"gender": "M" if random.randint(0, 1) == 1 else "F",
|
||||
"time": shotIn,
|
||||
"prime": False,
|
||||
"runt": False,
|
||||
"weight": 0.0,
|
||||
"date": time.time(),
|
||||
"misses": self.misses[fromWho]
|
||||
}
|
||||
|
||||
message = "%s %s " % (fromWho, "bags")
|
||||
|
||||
if random.randint(0, 100) <= self.config["primeChance"]:
|
||||
bagged["prime"] = True
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightMax"], self.config["weightFat"])
|
||||
message += "a prime catch, a "
|
||||
elif random.randint(0, 100) <= self.config["runtChance"]:
|
||||
bagged["runt"] = True
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightRunt"], self.config["weightMin"])
|
||||
message += "a runt of a catch, a "
|
||||
else:
|
||||
bagged["weight"] = self.getRandWeight(self.config["weightMin"], self.config["weightMax"])
|
||||
message += "a "
|
||||
|
||||
message += "%s lb " % (bagged["weight"])
|
||||
if bagged["gender"] == "M":
|
||||
message += self.config["animalNameMale"] + " "
|
||||
else:
|
||||
message += self.config["animalNameFemale"] + " "
|
||||
|
||||
message += "in %s seconds!" % shotIn
|
||||
self.bot.act_PRIVMSG(self.config["activeChannel"], message)
|
||||
|
||||
self.addKillFor(fromWho, bagged)
|
||||
|
||||
self.misses = {}
|
||||
|
||||
self.startHunt()
|
||||
self.startHunt()
|
||||
|
||||
def startHunt(self):
|
||||
" Creates a timer that waits a certain amount of time then sends out a bird \\_o< quack"
|
||||
delay = self.config["delayMin"] + random.randint(0, self.config["delayMax"] - self.config["delayMin"])
|
||||
self.timer = Timer(delay, self.duckOut)
|
||||
self.timer.start()
|
||||
print("DuckHunt: Sending out animal in %s seconds" % delay)
|
||||
self.log.info(" Sending out animal in %s seconds" % delay)
|
||||
|
||||
def duckOut(self):
|
||||
self.isDuckOut = True
|
||||
@ -143,12 +137,6 @@ class DuckHunt(ModuleBase):
|
||||
weight = float(weight) * random.random()
|
||||
return round(weight + minW, 2)
|
||||
|
||||
def getScoreFor(self, playername):
|
||||
return 1
|
||||
|
||||
def getScoresFor(self, playername):
|
||||
return 1
|
||||
|
||||
def addKillFor(self, playername, kill):
|
||||
scores = self.loadScores()
|
||||
if scores is None:
|
||||
|
@ -7,14 +7,14 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
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 not serviceProviders:
|
||||
@ -33,42 +33,38 @@ class Inventory(ModuleBase):
|
||||
) ;""")
|
||||
c.close()
|
||||
|
||||
self.hooks = [ModuleHook("PRIVMSG", self.checkInv)]
|
||||
|
||||
def checkInv(self, args, prefix, trailing):
|
||||
if not args[0][0] == "#":
|
||||
@info("have <item> give the bot an item", cmds=["have"])
|
||||
@command("have")
|
||||
def checkInv(self, msg, cmd):
|
||||
if len(cmd.args) < 1:
|
||||
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
|
||||
adjective = None
|
||||
newItem = cmd.args_str
|
||||
if cmd.args[0] in self.config["adjectives"]:
|
||||
newItem = cmd.args_str[len(cmd.args[0]):].strip()
|
||||
adjective = cmd.args[0]
|
||||
|
||||
if self.has_item(newItem):
|
||||
self.bot.act_PRIVMSG(args[0], self.config["dupe_msg"] % {"item": newItem})
|
||||
return
|
||||
if self.has_item(newItem):
|
||||
self.bot.act_PRIVMSG(msg.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 "})
|
||||
dropped = self.add_item(msg.prefix.nick, newItem)
|
||||
if len(dropped) > 0:
|
||||
self.bot.act_PRIVMSG(msg.args[0], self.config["swap_msg"] %
|
||||
{"adjective": (adjective + " ") if adjective else "",
|
||||
"recv_item": newItem, "drop_item": ", ".join(dropped)})
|
||||
else:
|
||||
self.bot.act_PRIVMSG(msg.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)})
|
||||
@info("inventory show the bot's inventory", cmds=["inventory", "inv"])
|
||||
@command("inventory", "inv")
|
||||
def cmd_inv(self, msg, cmd):
|
||||
inv = self.getinventory()
|
||||
if len(inv) == 0:
|
||||
self.bot.act_PRIVMSG(msg.args[0], self.config["inv_msg"] % {"itemlist": "nothing!"})
|
||||
else:
|
||||
self.bot.act_PRIVMSG(msg.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,))
|
||||
|
@ -7,24 +7,20 @@
|
||||
"""
|
||||
|
||||
import urllib.parse
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
|
||||
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 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))
|
||||
@info("lmgtfy <term> display a condescending internet query", cmds=["lmgtfy"])
|
||||
@command("lmgtfy", require_args=True)
|
||||
def handleMessage(self, msg, cmd):
|
||||
message = msg.trailing.split(" ")[1:]
|
||||
link = self.createLink(message)
|
||||
self.bot.act_PRIVMSG(msg.args[0], "%s: %s" % (msg.prefix.nick, link))
|
||||
|
||||
def createLink(self, message):
|
||||
finalUrl = BASE_URL
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, hook
|
||||
from requests import get
|
||||
import re
|
||||
import time
|
||||
@ -22,16 +22,14 @@ class LinkTitler(ModuleBase):
|
||||
def __init__(self, bot, moduleName):
|
||||
ModuleBase.__init__(self, bot, moduleName)
|
||||
self.REQUEST_SIZE_LIMIT = 10 * 1024
|
||||
self.hooks = [ModuleHook("PRIVMSG", self.searches)]
|
||||
|
||||
def searches(self, args, prefix, trailing):
|
||||
t = Thread(target=self.doLinkTitle, args=(args, prefix, trailing))
|
||||
@hook("PRIVMSG")
|
||||
def searches(self, msg, cmd):
|
||||
t = Thread(target=self.doLinkTitle, args=(msg.args, msg.prefix.nick, msg.trailing))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def doLinkTitle(self, args, prefix, trailing):
|
||||
sender = self.bot.decodePrefix(prefix)
|
||||
|
||||
def doLinkTitle(self, args, sender, trailing):
|
||||
# Youtube
|
||||
matches = re.compile(r'(?:youtube.*?(?:v=|/v/)|youtu\.be/|yooouuutuuube.*?id=)([-_a-z0-9]+)', re.I) \
|
||||
.findall(trailing)
|
||||
@ -67,7 +65,7 @@ class LinkTitler(ModuleBase):
|
||||
"domain": submission.domain,
|
||||
"nsfw": "[NSFW]" if submission.over_18 else "",
|
||||
"points": submission.ups,
|
||||
"percent": "%s%%" % int(submission.upvote_ratio *100),
|
||||
"percent": "%s%%" % int(submission.upvote_ratio * 100),
|
||||
"comments": submission.num_comments,
|
||||
"author": submission.author.name,
|
||||
"date": datetime.datetime.fromtimestamp(submission.created).strftime("%Y.%m.%d")
|
||||
@ -98,11 +96,11 @@ class LinkTitler(ModuleBase):
|
||||
# Fetch HTML title
|
||||
title = self.url_htmltitle(match[0])
|
||||
if title:
|
||||
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02" % (sender.nick, title))
|
||||
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02" % (sender, title))
|
||||
else:
|
||||
# Unknown types, just print type and size
|
||||
self.bot.act_PRIVMSG(args[0], "%s: \x02%s\x02, %s" %
|
||||
(sender.nick, headers["Content-Type"],
|
||||
(sender, headers["Content-Type"],
|
||||
self.nicesize(int(headers["Content-Length"])) if
|
||||
"Content-Length" in headers else "unknown size"))
|
||||
|
||||
|
@ -34,8 +34,16 @@ class info(object):
|
||||
self.commands = cmds or []
|
||||
|
||||
def __call__(self, func):
|
||||
setattr(func, "irchelp", self.docstring)
|
||||
setattr(func, "irchelpc", self.commands)
|
||||
if hasattr(func, "irchelp"):
|
||||
func.irchelp.append(self.docstring)
|
||||
else:
|
||||
setattr(func, "irchelp", [self.docstring])
|
||||
|
||||
if hasattr(func, "irchelpc"):
|
||||
func.irchelpc.append(self.commands)
|
||||
else:
|
||||
setattr(func, "irchelpc", [self.commands])
|
||||
|
||||
return func
|
||||
|
||||
|
||||
@ -77,5 +85,6 @@ class ModInfo(ModuleBase):
|
||||
for attr_name in dir(module):
|
||||
attr = getattr(module, attr_name)
|
||||
if callable(attr) and hasattr(attr, "irchelp"):
|
||||
yield (modname, module, getattr(attr, "irchelp"), getattr(attr, "irchelpc"), )
|
||||
for cmdhelp, cmdaliases in zip(getattr(attr, "irchelp"), getattr(attr, "irchelpc")):
|
||||
yield (modname, module, cmdhelp, cmdaliases, )
|
||||
raise StopIteration()
|
||||
|
@ -19,7 +19,6 @@ except:
|
||||
class MySQL(ModuleBase):
|
||||
def __init__(self, bot, moduleName):
|
||||
ModuleBase.__init__(self, bot, moduleName)
|
||||
self.hooks = []
|
||||
self.services = ["mysql"]
|
||||
self.connection = self.getConnection()
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
from pyircbot.modulebase import ModuleBase, command
|
||||
from pyircbot.modules.ModInfo import info
|
||||
from time import time
|
||||
from requests import get
|
||||
from lxml import etree
|
||||
@ -19,112 +20,107 @@ class NFLLive(ModuleBase):
|
||||
self.cache = None
|
||||
self.cacheAge = 0
|
||||
|
||||
self.hooks = [ModuleHook(["PRIVMSG"], self.nflitup)]
|
||||
@info("nfl show nfl schedule & score", cmds=["nfl"])
|
||||
@command("nfl")
|
||||
def nflitup(self, message, cmd):
|
||||
games = self.getNflGamesCached()
|
||||
msg = []
|
||||
|
||||
def nflitup(self, args, prefix, trailing):
|
||||
prefix = self.bot.decodePrefix(prefix)
|
||||
replyTo = prefix.nick if "#" not in args[0] else args[0]
|
||||
liveGames = []
|
||||
gamesLaterToday = []
|
||||
gamesToday = []
|
||||
gamesUpcoming = []
|
||||
gamesEarlierWeek = []
|
||||
|
||||
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 game["time"] is not 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)
|
||||
# sort games
|
||||
for game in games["games"]:
|
||||
if game["time"] is not 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:
|
||||
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)
|
||||
gamesEarlierWeek.append(game)
|
||||
|
||||
# Collaspe the list into a repsonse string. Fix grammar
|
||||
msg = ", ".join(msgPieces).replace(":, ", ": ")
|
||||
# create list of formatted games
|
||||
liveGamesStr = []
|
||||
for game in liveGames:
|
||||
liveGamesStr.append(self.formatGameLive(game))
|
||||
liveGamesStr = ", ".join(liveGamesStr)
|
||||
|
||||
# Nothing means there were probably no games
|
||||
if len(msgPieces) == 1:
|
||||
msg = "No games!"
|
||||
gamesLaterTodayStr = []
|
||||
for game in gamesLaterToday:
|
||||
gamesLaterTodayStr.append(self.formatGameFuture(game))
|
||||
gamesLaterTodayStr = ", ".join(gamesLaterTodayStr)
|
||||
|
||||
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()))
|
||||
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(message.args[0], "%s: %s" % (message.prefix.nick, piece.strip()))
|
||||
|
||||
def formatGameLive(self, game):
|
||||
c_vis = 3 if int(game["visitor_score"]) > int(game["home_score"]) else 4
|
||||
|
@ -7,14 +7,14 @@
|
||||
|
||||
"""
|
||||
|
||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
||||
import hashlib
|
||||
from pyircbot.modulebase import ModuleBase, hook
|
||||
from pyircbot.common import messageHasCommand
|
||||
from pyircbot.modules.ModInfo import info
|
||||
|
||||
|
||||
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):
|
||||
@ -28,17 +28,19 @@ class NickUser(ModuleBase):
|
||||
pass
|
||||
# TODO: log out all users
|
||||
|
||||
def gotmsg(self, args, prefix, trailing):
|
||||
channel = args[0]
|
||||
if channel[0] == "#":
|
||||
@hook("PRIVMSG")
|
||||
def gotmsg(self, msg, cmd):
|
||||
if msg.args[0][0] == "#":
|
||||
# Ignore channel messages
|
||||
pass
|
||||
return
|
||||
else:
|
||||
self.handlePm(args, prefix, trailing)
|
||||
|