diff --git a/data/config/DogeDice.yml b/data/config/DogeDice.yml
deleted file mode 100644
index 28b01d0..0000000
--- a/data/config/DogeDice.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-minBet: .01
-lobbyIdleSeconds: 15
-channelWhitelistOn: True
-channelWhitelist:
- - test
\ No newline at end of file
diff --git a/data/config/DogeRPC.yml b/data/config/DogeRPC.yml
deleted file mode 100644
index 8939bf3..0000000
--- a/data/config/DogeRPC.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-host: 127.0.0.1
-username: root
-password: root
-port: 22555
\ No newline at end of file
diff --git a/data/config/DogeScramble.yml b/data/config/DogeScramble.yml
deleted file mode 100644
index 9754af9..0000000
--- a/data/config/DogeScramble.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-hintDelay: 15
-delayNext: 5
-maxHints: 5
-abortAfterNoGuesses: 2
-winAmount: 0.1
-categoryduration: 2
-decreaseFactor: 0.83
\ No newline at end of file
diff --git a/data/config/Scramble.yml b/data/config/Scramble.yml
index cbd5bc5..acb369b 100644
--- a/data/config/Scramble.yml
+++ b/data/config/Scramble.yml
@@ -1,5 +1,4 @@
hintDelay: 15
delayNext: 5
maxHints: 5
-abortAfterNoGuesses: 5
-decreaseFactor: 0.83
\ No newline at end of file
+abortAfterNoGuesses: 5
\ No newline at end of file
diff --git a/pyircbot/core/pyircbot.py b/pyircbot/core/pyircbot.py
index eb23b79..9856b9f 100644
--- a/pyircbot/core/pyircbot.py
+++ b/pyircbot/core/pyircbot.py
@@ -70,7 +70,17 @@ class PyIRCBot(asynchat.async_chat):
def found_terminator(self):
" A complete command was pushed through, so clear the buffer and process it."
- self.process_data(self.getBuf().decode("UTF-8"))
+ line = None
+ buf = self.getBuf()
+ try:
+ line = buf.decode("UTF-8")
+ except UnicodeDecodeError as ude:
+ self.log.error("found_terminator(): could not decode input as UTF-8")
+ self.log.error("found_terminator(): data: %s" % line)
+ self.log.error("found_terminator(): repr(data): %s" % repr(line))
+ self.log.error("found_terminator(): error: %s" % str(ude))
+ return
+ self.process_data(line)
def handle_close(self):
" called on socket shutdown "
diff --git a/pyircbot/core/rpc.py b/pyircbot/core/rpc.py
index 258250f..3a6edd1 100644
--- a/pyircbot/core/rpc.py
+++ b/pyircbot/core/rpc.py
@@ -17,36 +17,71 @@ class BotRPC(Thread):
self.server.register_function( self.unloadModule )
self.server.register_function( self.reloadModule )
self.server.register_function( self.redoModule )
- self.server.register_function( self.getTraceback )
+ self.server.register_function( self.getLoadedModules )
+ self.server.register_function( self.pluginCommand )
+ self.server.register_function( self.setPluginVar )
+ self.server.register_function( self.getPluginVar )
+
self.start()
def run(self):
self.server.serve()
-
def importModule(self, moduleName):
+ self.log.info("RPC: calling importModule(%s)"%moduleName)
return self.bot.importmodule(moduleName)
def deportModule(self, moduleName):
+ self.log.info("RPC: calling deportModule(%s)"%moduleName)
self.bot.deportmodule(moduleName)
def loadModule(self, moduleName):
+ self.log.info("RPC: calling loadModule(%s)"%moduleName)
return self.bot.loadmodule(moduleName)
def unloadModule(self, moduleName):
+ self.log.info("RPC: calling unloadModule(%s)"%moduleName)
self.bot.unloadmodule(moduleName)
def reloadModule(self, moduleName):
+ self.log.info("RPC: calling reloadModule(%s)"%moduleName)
self.bot.unloadmodule(moduleName)
return self.bot.loadmodule(moduleName)
def redoModule(self, moduleName):
+ self.log.info("RPC: calling redoModule(%s)"%moduleName)
return self.bot.redomodule(moduleName)
- def getTraceback(self):
- tb = str(traceback.format_exc())
- print(tb)
- return tb
+ def getLoadedModules(self):
+ self.log.info("RPC: calling getLoadedModules()")
+ return list(self.bot.moduleInstances.keys())
+ def pluginCommand(self, pluginName, methodName, argList):
+ plugin = self.bot.getmodulebyname(pluginName)
+ if not plugin:
+ return (False, "Plugin not found")
+ method = getattr(plugin, methodName)
+ if not method:
+ return (False, "Method not found")
+ self.log.info("RPC: calling %s.%s(%s)" % (pluginName, methodName, argList))
+ return (True, method(*argList))
+ def getPluginVar(self, pluginName, pluginVarName):
+ plugin = self.bot.getmodulebyname(pluginName)
+ if pluginName == "_core":
+ plugin = self.bot
+ if not plugin:
+ return (False, "Plugin not found")
+ self.log.info("RPC: getting %s.%s" % (pluginName, pluginVarName))
+ return (True, getattr(plugin, pluginVarName))
+ def setPluginVar(self, pluginName, pluginVarName, value):
+ plugin = self.bot.getmodulebyname(pluginName)
+ if pluginName == "_core":
+ plugin = self.bot
+ if not plugin:
+ return (False, "Plugin not found")
+ self.log.info("RPC: setting %s.%s = %s )" % (pluginName, pluginVarName, value))
+ setattr(plugin, pluginVarName, value)
+ return (True, "Var set")
+
diff --git a/pyircbot/modules/AttributeStorage.py b/pyircbot/modules/AttributeStorage.py
index cd4b671..c732747 100644
--- a/pyircbot/modules/AttributeStorage.py
+++ b/pyircbot/modules/AttributeStorage.py
@@ -47,6 +47,7 @@ class AttributeStorage(ModuleBase):
# self.getAttribute('xMopxShell', 'name')
# self.setAttribute('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):
c = self.db.connection.query("""SELECT
diff --git a/pyircbot/modules/DogeDice.py b/pyircbot/modules/DogeDice.py
deleted file mode 100644
index 80cc7a5..0000000
--- a/pyircbot/modules/DogeDice.py
+++ /dev/null
@@ -1,315 +0,0 @@
-#!/usr/bin/env python
-from modulebase import ModuleBase,ModuleHook
-import random
-import yaml
-import os
-import time
-import math
-import hashlib
-from threading import Timer
-
-class DogeDice(ModuleBase):
- def __init__(self, bot, moduleName):
- ModuleBase.__init__(self, bot, moduleName);
- self.hooks=[ModuleHook("PRIVMSG", self.gotMsg)]
- self.loadConfig()
- # Load attribute storage
- self.attr = self.bot.getBestModuleForService("attributes")
- # Load doge RPC
- 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.getAttribute(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.getAttribute(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.getAttribute(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
-
diff --git a/pyircbot/modules/DogeRPC.py b/pyircbot/modules/DogeRPC.py
deleted file mode 100644
index 16e4512..0000000
--- a/pyircbot/modules/DogeRPC.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-from modulebase import ModuleBase,ModuleHook
-from bitcoinrpc.authproxy import AuthServiceProxy
-
-class DogeRPC(ModuleBase):
- def __init__(self, bot, moduleName):
- ModuleBase.__init__(self, bot, moduleName);
- self.hooks=[]
- self.services=["dogerpc"]
- self.loadConfig()
- self.rpc = DogeController(self)
-
- 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.rpc.ping()
- addrs = self.rpc.con.getaddressesbyaccount(acct)
- if len(addrs)==0:
- return self.rpc.con.getnewaddress(acct)
- return addrs[0]
-
- def getAcctBal(self, acct):
- " returns an account's balance"
- self.rpc.ping()
- return float(self.rpc.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.rpc.ping()
- if self.canMove(fromAcct, toAcct, amount):
- return self.rpc.con.move(fromAcct, toAcct, amount)
- return False
-
- def send(self, fromAcct, toAddr, amount):
- " send coins to an external addr "
- self.rpc.ping()
- if self.canMove(fromAcct, toAddr, amount):
- return self.rpc.con.sendfrom(fromAcct, toAddr, amount)
- return False
-
-class DogeController:
- def __init__(self, master):
- self.config = master.config
- self.log = master.log
- self.con = None
- self.ping()
-
- def ping(self):
- try:
- self.con.getinfo()
- except:
- self.connect()
-
- def connect(self):
- self.log.debug("DogeRPC: Connecting to dogecoind")
- self.con = AuthServiceProxy("http://%s:%s@%s:%s" % (self.config["username"], self.config["password"], self.config["host"], self.config["port"]))
- self.con.getinfo()
- self.log.debug("DogeRPC: Connected to %s:%s" % (self.config["host"], self.config["port"]))
diff --git a/pyircbot/modules/DogeScramble.py b/pyircbot/modules/DogeScramble.py
deleted file mode 100644
index 44c923f..0000000
--- a/pyircbot/modules/DogeScramble.py
+++ /dev/null
@@ -1,258 +0,0 @@
-#!/usr/bin/env python
-from modulebase import ModuleBase,ModuleHook
-import random
-import yaml
-import os
-import time
-from threading import Timer
-
-class DogeScramble(ModuleBase):
- def __init__(self, bot, moduleName):
- ModuleBase.__init__(self, bot, moduleName);
- self.hooks=[ModuleHook("PRIVMSG", self.scramble)]
- self.loadConfig()
-
- # Load attribute storage
- self.attr = None
- serviceProviders = self.bot.getmodulesbyservice("attributes")
- if len(serviceProviders)==0:
- self.log.error("DogeScramble: Could not find a valid attributes service provider")
- else:
- self.log.info("DogeScramble: Selecting attributes service provider: %s" % serviceProviders[0])
- self.attr = serviceProviders[0]
-
- # Load doge RPC
- self.doge = self.bot.getBestModuleForService("dogerpc")
-
- # Per channel games
- self.games = {}
-
- def scramble(self, args, prefix, trailing):
- channel = args[0]
- if channel[0] == "#":
- # Ignore messages from users without a dogewallet password
- prefixObj = self.bot.decodePrefix(prefix)
- if self.attr.getAttribute(prefixObj.nick, "password")==None:
- return
- if not channel in self.games:
- self.games[channel]=scrambleGame(self, channel)
- self.games[channel].scramble(args, prefix, trailing)
- def ondisable(self):
- self.log.info("DogeScramble: Unload requested, ending games...")
- for game in self.games:
- self.games[game].gameover()
-
-class scrambleGame:
- def __init__(self, master, channel):
- self.master = master
- self.channel = channel
- # Running?
- self.running = False
- # Current word
- self.currentWord = None
- # Current word, scrambled
- self.scrambled = None
- # Online?
- self.scrambleOn = False
- # Count down to hints
- self.hintTimer = None
- # of hints given
- self.hintsGiven = 0
- # Cooldown between words
- self.nextTimer = None
- # How many guesses submitted this round
- self.guesses = 0;
- # How many games in a row where nobody guessed
- self.gamesWithoutGuesses = 0;
- # What file are we using
- self.category_file = None;
- # How many words in this category have been used?
- self.category_count = 0
- # How long between categories
- self.change_category_after_words = self.master.config["categoryduration"]
- # Should we change categories at the next pick?
- self.should_change_category = True
- # Holds the processed category name
- self.category_name = None
- # list of last picked words
- self.lastwords = []
- # name of last winner for decreasing return
- self.lastwinner = None
- self.lastwinvalue = 0
-
- self.delayHint = self.master.config["hintDelay"];
- self.delayNext = self.master.config["delayNext"];
- self.maxHints = self.master.config["maxHints"];
- self.abortAfterNoGuesses = self.master.config["abortAfterNoGuesses"];
-
- def gameover(self):
- self.clearTimers();
- self.running = False
- def clearTimers(self):
- self.clearTimer(self.nextTimer)
- self.clearTimer(self.hintTimer)
- def clearTimer(self, timer):
- if timer:
- timer.cancel()
- def scramble(self, args, prefix, trailing):
- prefix = self.master.bot.decodePrefix(prefix)
- sender = prefix.nick
-
- senderIsOp = self.master.attr.getAttribute(prefix.nick, "op")=="yes"
-
- cmd = self.master.bot.messageHasCommand(".scramble", trailing)
- if cmd and not self.running:
- #and senderIsOp
- self.running = True
- self.startScramble()
- return
- cmd = self.master.bot.messageHasCommand(".scrambleoff", trailing)
- if cmd and senderIsOp and self.running:
- self.gameover()
- self.running = False
- return
-
- if self.currentWord and trailing.strip().lower() == self.currentWord:
- # Get winner withdraw address
- useraddr = self.master.attr.getAttribute(prefix.nick, "dogeaddr")
- userwallet = self.master.attr.getAttribute(prefix.nick, "dogeaccountname")
-
- self.master.bot.act_PRIVMSG(self.channel, "%s got the word - %s!" % (sender, self.currentWord))
-
- if not useraddr:
- self.master.bot.act_PRIVMSG(self.channel, "%s: to win DOGE, you must set an wallet address by PMing me \".setdogeaddr\". Next word in %s seconds." % (prefix.nick, self.delayNext))
- else:
- winamount = float(self.master.config["winAmount"])
- if self.lastwinner == prefix.nick:
- winamount = self.lastwinvalue * self.master.config["decreaseFactor"]
- self.lastwinvalue = winamount
- self.lastwinner = prefix.nick
-
- self.master.bot.act_PRIVMSG(self.channel, "%s won %s DOGE! Next word in %s seconds." % (prefix.nick, round(winamount, 8), self.delayNext))
- self.master.doge.move('', userwallet, winamount)
-
- self.currentWord = None
- self.clearTimers()
- self.hintsGiven = 0
- self.nextTimer = Timer(self.delayNext, self.startNewWord)
- self.nextTimer.start()
- self.guesses=0
- self.category_count+=1
- self.master.log.debug("DogeScramble: category_count is: %s" % (self.category_count))
- if self.category_count >= self.change_category_after_words:
- self.should_change_category = True
- else:
- self.guesses+=1
-
- def startScramble(self):
- self.clearTimer(self.nextTimer)
- self.nextTimer = Timer(0, self.startNewWord)
- self.nextTimer.start()
-
- def startNewWord(self):
- self.currentWord = self.pickWord()
- self.scrambled = self.scrambleWord(self.currentWord)
- self.master.bot.act_PRIVMSG(self.channel, "[Category: %s] Unscramble this: %s " % (self.category_name, self.scrambled))
-
- self.clearTimer(self.hintTimer)
- self.hintTimer = Timer(self.delayHint, self.giveHint)
- self.hintTimer.start()
-
- def giveHint(self):
- self.hintsGiven+=1
-
- if self.hintsGiven>=len(self.currentWord) or self.hintsGiven > self.maxHints:
- self.abortWord()
- return
-
- blanks = ""
- for letter in list(self.currentWord):
- if letter == " ":
- blanks+=" "
- else:
- blanks+="_"
- partFromWord = self.currentWord[0:self.hintsGiven]
- partFromBlanks = blanks[self.hintsGiven:]
- hintstr = partFromWord+partFromBlanks
-
- self.master.bot.act_PRIVMSG(self.channel, "Hint: - %s" % (hintstr))
-
- self.clearTimer(self.hintTimer)
- self.hintTimer = Timer(self.delayHint, self.giveHint)
- self.hintTimer.start()
-
- def abortWord(self):
- cur = self.currentWord
- self.currentWord = None
- self.master.bot.act_PRIVMSG(self.channel, "Word expired - the answer was '%s'. Next word in %s seconds." % (cur, self.delayNext))
- self.hintsGiven = 0
- self.clearTimer(self.nextTimer)
-
- if self.guesses==0:
- self.gamesWithoutGuesses+=1
- if self.gamesWithoutGuesses >= self.abortAfterNoGuesses:
- self.master.bot.act_PRIVMSG(self.channel, "No one seems to be playing - type .scramble to start again.")
- self.gameover()
- return
- else:
- self.gamesWithoutGuesses=0
-
- self.nextTimer = Timer(self.delayNext, self.startNewWord)
- self.nextTimer.start()
-
- def catFileNameToStr(self, s):
- s=s.split(".")[0]
- s=s.replace("_", " ")
- return s.title()
-
- def pickWord(self):
- if self.should_change_category:
- # clear flags
- self.should_change_category = False
- self.category_count = 0
- # Get the path to word files dir
- dirpath = self.master.getFilePath("")
- # List dir
- files = os.listdir(dirpath)
- # choose a random file
- random.shuffle(files)
- self.category_file = files[0]
- self.category_name = self.catFileNameToStr(self.category_file)
- # Process the name & announce
- self.master.bot.act_PRIVMSG(self.channel, "The category is now: %s " % self.category_name)
- # count lines
- f = open(self.master.getFilePath(self.category_file), "r")
- lines = 0
- while True:
- lines+=1
- if f.readline() == "":
- break
- f.close()
- # change category
- picked = ""
- while picked == "" or picked in self.lastwords:
-
- skip = random.randint(0, lines)
- f = open(self.master.getFilePath(self.category_file), "r")
- while skip>=0:
- f.readline()
- skip-=1
- picked = f.readline().strip().lower()
- f.close()
-
- self.master.log.debug("DogeScramble: picked %s for %s" % (picked, self.channel))
- self.lastwords.append(picked)
- if len(self.lastwords) > 5:
- self.lastwords.pop(0)
- return picked
-
- def scrambleWord(self, word):
- scrambled = ""
- for subword in word.split(" "):
- scrambled+=self.scrambleIndividualWord(subword)+ " "
- return scrambled.strip()
-
- def scrambleIndividualWord(self, word):
- scrambled = list(word)
- random.shuffle(scrambled)
- return ''.join(scrambled).lower()
diff --git a/pyircbot/modules/DogeWallet.py b/pyircbot/modules/DogeWallet.py
deleted file mode 100644
index a70daf3..0000000
--- a/pyircbot/modules/DogeWallet.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env python
-from modulebase import ModuleBase,ModuleHook
-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.getAttribute(prefix.nick, "password")
- if oldpass == None:
- self.attr.setAttribute(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.setAttribute(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.getAttribute(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.setAttribute(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.getAttribute(prefix.nick, "dogeaccountname")==None:
- randName = self.md5(str(time.time()))[0:10]
- self.attr.setAttribute(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.getAttribute(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.getAttribute(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.getAttribute(prefix.nick, "password")
- useraddr = self.attr.getAttribute(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.getAttribute(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.getAttribute(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.getAttribute(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.getAttribute(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.setAttribute(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.getAttribute(prefix.nick, "loggedinfrom")
- if loggedin == None:
- self.bot.act_PRIVMSG(prefix.nick, ".logout: You must first be logged in")
- else:
- self.attr.setAttribute(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()
diff --git a/pyircbot/modules/NyanThread.py b/pyircbot/modules/NyanThread.py
new file mode 100644
index 0000000..d25a25f
--- /dev/null
+++ b/pyircbot/modules/NyanThread.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+from modulebase import ModuleBase,ModuleHook
+import re
+from time import time
+from urllib import request
+from bs4 import BeautifulSoup
+from bs4.element import Tag as bs_type_tag
+
+class NyanThread(ModuleBase):
+ def __init__(self, bot, moduleName):
+ ModuleBase.__init__(self, bot, moduleName);
+ self.hooks=[ModuleHook("PRIVMSG", self.check)]
+ self.lastrun = 0
+ self.pagepattern = re.compile(r'([0-9]+)')
+ self.messagepattern = re.compile(r'([^<]+)', flags=re.IGNORECASE)
+ self.linkmessage = re.compile(r'')
+
+ def check(self, args, prefix, trailing):
+ if not args[0][0]=="#":
+ return
+ cmd = self.bot.messageHasCommand(".story", trailing)
+ if cmd:
+ if time() - self.lastrun < 10:
+ return
+
+ self.log.info("Nyanthread: fetching story...")
+ prefixObj = self.bot.decodePrefix(prefix)
+ page = request.urlopen("https://bitcointalk.org/index.php?topic=403335").read()
+ pages = self.pagepattern.findall(page.decode("ISO-8859-1"))
+ lastpage = pages[-1]
+ lastpagelink = "https://bitcointalk.org/index.php?topic=403335.%s" % lastpage[0]
+ self.log.info("Nyanthread: last page is %s" % lastpagelink)
+ page = request.urlopen(lastpagelink).read()
+
+ bs = BeautifulSoup(page)
+
+ body = bs.find('div', id="bodyarea")
+ thread = body.find('form', id="quickModForm")
+ posttable = thread.find('table', class_="bordercolor")
+
+ postTrs = []
+ for item in posttable:
+ postTrs.append(item)
+
+ postTrs.reverse()
+
+ for item in postTrs:
+ if type(item) == bs_type_tag:
+ message = item.find('div', class_="post")
+ if message:
+ redContent = self.messagepattern.findall(message.decode_contents())
+ if len(redContent)>0:
+ linkmessage = self.linkmessage.findall(item.decode_contents())
+ lastpagelink = "https://bitcointalk.org/index.php?topic=403335.msg%s#msg%s"%(linkmessage[0][0],linkmessage[0][0])
+ if len(linkmessage)>75:
+ continue
+ self.bot.act_PRIVMSG(args[0], "%s: %s - %s" % (prefixObj.nick, redContent[0], lastpagelink))
+ self.lastrun = time()
+ return
+
+ self.bot.act_PRIVMSG(args[0], "%s: failed to read thread :(" % (prefixObj.nick))
+ self.lastrun = time()
+ return
diff --git a/pyircbot/modules/Seen.py b/pyircbot/modules/Seen.py
new file mode 100644
index 0000000..412c676
--- /dev/null
+++ b/pyircbot/modules/Seen.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+from modulebase import ModuleBase,ModuleHook
+import sqlite3
+import time
+
+class Seen(ModuleBase):
+ def __init__(self, bot, moduleName):
+ ModuleBase.__init__(self, bot, moduleName)
+ self.hooks=[ModuleHook("PRIVMSG", self.lastSeen)]
+ self.loadConfig()
+ # if the database doesnt exist, it will be created
+ sql = self.getSql()
+ c=sql.cursor()
+ # 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
+