def privmsg(self, targ, text, priority = None): Logger.log("c", self.instance + ": %s <- %s " % (targ, text)) for i in xrange(0, len(text), 350): if priority: Irc.instance_send(self.instance, ("PRIVMSG", targ, text[i:i+350]), priority = priority) else: Irc.instance_send(self.instance, ("PRIVMSG", targ, text[i:i+350]))
def tip(req, arg): """%tip <target> <amount> - Sends 'amount' coins to the specified nickname. Nickname can be suffixed with @ and an account name, if you want to make sure you are tipping the correct person""" if len(arg) < 2: return req.reply(gethelp("tip")) to = arg[0] acct, toacct = Irc.account_names([req.nick, target_nick(to)]) if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") if not toacct: if toacct == None: return req.reply_private(target_nick(to) + " is not online") else: return req.reply_private(target_nick(to) + " is not identified with freenode services") if not target_verify(to, toacct): return req.reply_private("Account name mismatch") try: amount = parse_amount(arg[1], acct) except ValueError as e: return req.reply_private(str(e)) token = Logger.token() try: Transactions.tip(token, acct, toacct, amount) if Irc.equal_nicks(req.nick, req.target): req.reply("Done [%s]" % (token)) else: req.say(" %s tipped BITB%i to %s! (to claim /msg Beaner help) [%s]" % (req.nick, amount, target_nick(to), token)) req.privmsg(target_nick(to), "%s has tipped you BITB%i (to claim /msg Beaner help) [%s]" % (req.nick, amount, token), priority = 10) except Transactions.NotEnoughMoney: req.reply_private("You tried to tip BITB%i but you only have BITB%i" % (amount, Transactions.balance(acct)))
def send(self, *args): print(self.nick + ": " + Irc.compile(*args)) t = self.lastsend - time.time() + 0.25 if t > 0: time.sleep(t) self.connection.sendall(Irc.compile(*args) + "\n") self.lastsend = time.time()
def _help(req, arg): """%help - list of commands; %help <command> - help for specific command""" if len(arg): h = gethelp(arg[0]) if h: req.reply(h) else: if not Irc.equal_nicks(req.target, req.nick): return req.reply("I'm Doger, an IRC dogecoin tipbot. For more info do /msg Doger help") acct = Irc.account_names([req.nick])[0] if acct: ident = "you're identified as \2" + acct + "\2" else: ident = "you're not identified" req.say( "I'm Doger, I'm an IRC dogecoin tipbot. To get help about a specific command, say \2%help <command>\2 Commands: %tip %balance %withdraw %deposit %mtip %donate %help".replace( "%", Config.config["prefix"] ) ) req.say( ( "Note that to receive or send tips you should be identified with freenode services (%s). Please consider donating with %%donate. For any support questions, including those related to lost coins, join ##doger" % (ident) ).replace("%", Config.config["prefix"]) )
def tip(req, arg): """%tip <target> <amount> - Sends 'amount' coins to the specified nickname""" if len(arg) < 2: return req.reply(gethelp("tip")) to = arg[0] acct, toacct = Irc.account_names([req.nick, to]) if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") if not toacct: if toacct == None: return req.reply_private(to + " is not online") else: return req.reply_private(to + " is not identified with freenode services") try: amount = parse_amount(arg[1], acct) except ValueError as e: return req.reply_private(str(e)) token = Logger.token() try: Transactions.tip(token, acct, toacct, amount) if Irc.equal_nicks(req.nick, req.target): req.reply("Done [%s]" % (token)) else: req.say("Such %s tipped much Ɖ%i to %s! (to claim /msg Doger help) [%s]" % (req.nick, amount, to, token)) req.privmsg(to, "Such %s has tipped you Ɖ%i (to claim /msg Doger help) [%s]" % (req.nick, amount, token), priority = 10) except Transactions.NotEnoughMoney: req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (amount, Transactions.balance(acct)))
def main(args): global irc listener = Listener(IRC_RESTART, restartIRCHook) getEventManager().addListener(listener) host = args[1] port = int(args[2]) channel = args[3] if channel[0] != '#': channel = '#' + channel getEventManager().start() irc = Irc(host, port, channel) while running: try: i = raw_input() if i == "quit" or i == "exit": irc.disconnect() getEventManager().stop() break except KeyboardInterrupt: irc.disconnect() getEventManager().stop() break time.sleep(1) sys.exit()
def tip(req, arg): """%tip <target> <amount> - Sends 'amount' coins to the specified nickname""" if len(arg) < 2: return req.reply("%tip <target> <amount>") to = arg[0] acct, toacct = Irc.account_names([req.nick, to]) if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if not toacct: if toacct == None: return req.reply_private(to + " is not online") else: return req.reply_private(to + " is not identified with freenode services") try: amount = int(arg[1]) if amount <= 0: raise ValueError() amount = min(amount, 1000000000000) except ValueError as e: req.reply_private(repr(arg[1]) + " - invalid amount") return None with Logger.token() as token: try: Transactions.tip(acct, toacct, amount) token.log("t", "acct:%s tipped %d to acct:%s(%d)" % (acct, amount, toacct, Transactions.balance(toacct))) if Irc.equal_nicks(req.nick, req.target): req.reply("Done [%s]" % (token.id)) else: req.say("Such %s tipped much Ɖ%i to %s! (to claim /msg Doger help) [%s]" % (req.nick, amount, to, token.id)) Irc.instance_send(req.instance, "PRIVMSG", to, "Such %s has tipped you Ɖ%i (to claim /msg Doger help) [%s]" % (req.nick, amount, token.id)) except Transactions.NotEnoughMoney: req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (amount, Transactions.balance(acct)))
def mtip(req, arg): """%mtip <targ1> <amt1> [<targ2> <amt2> ...] - Send multiple tips at once""" if not len(arg) or len(arg) % 2: return req.reply("%mtip <targ1> <amt1> [<targ2> <amt2> ...]") acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") for i in range(0, len(arg), 2): try: if int(arg[i + 1]) <= 0: raise ValueError() except ValueError as e: req.reply_private(repr(arg[i + 1]) + " - invalid amount") return None targets = [] amounts = [] total = 0 for i in range(0, len(arg), 2): target = arg[i] amount = int(arg[i + 1]) amount = min(amount, 1000000000000) found = False for i in range(len(targets)): if Irc.equal_nicks(targets[i], target): amounts[i] += amount total += amount found = True break if not found: targets.append(target) amounts.append(amount) total += amount balance = Transactions.balance(acct) if total > balance: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, balance)) accounts = Irc.account_names(targets) totip = {} failed = "" tipped = "" for i in range(len(targets)): if accounts[i]: totip[accounts[i]] = amounts[i] tipped += " %s %d" % (targets[i], amounts[i]) elif accounts[i] == None: failed += " %s (offline)" % (targets[i]) else: failed += " %s (unidentified)" % (targets[i]) with Logger.token() as token: try: Transactions.tip_multiple(acct, totip) token.log("t", "acct:%s mtipped: %s" % (acct, repr(totip))) tipped += " [%s]" % (token.id) except Transactions.NotEnoughMoney: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, Transactions.balance(acct))) output = "Tipped:" + tipped if len(failed): output += " Failed:" + failed req.reply(output)
def mtip(req, arg): """%mtip <targ1> <amt1> [<targ2> <amt2> ...] - Send multiple tips at once""" if not len(arg) or len(arg) % 2: return req.reply(gethelp("mtip")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") for i in range(0, len(arg), 2): try: arg[i + 1] = parse_amount(arg[i + 1], acct) except ValueError as e: return req.reply_private(str(e)) targets = [] amounts = [] total = 0 for i in range(0, len(arg), 2): target = arg[i] amount = arg[i + 1] found = False for i in range(len(targets)): if Irc.equal_nicks(targets[i], target): amounts[i] += amount total += amount found = True break if not found: targets.append(target) amounts.append(amount) total += amount balance = Transactions.balance(acct) if total > balance: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, balance)) accounts = Irc.account_names([target_nick(target) for target in targets]) totip = {} failed = "" tipped = "" for i in range(len(targets)): if accounts[i] == None: failed += " %s (offline)" % (target_nick(targets[i])) elif accounts[i] == False: failed += " %s (unidentified)" % (target_nick(targets[i])) elif not target_verify(targets[i], accounts[i]): failed += " %s (mismatch)" % (targets[i]) else: totip[accounts[i]] = totip.get(accounts[i], 0) + amounts[i] tipped += " %s %d" % (target_nick(targets[i]), amounts[i]) token = Logger.token() try: Transactions.tip_multiple(token, acct, totip) tipped += " [%s]" % (token) except Transactions.NotEnoughMoney: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, Transactions.balance(acct))) output = "Tipped:" + tipped if len(failed): output += " Failed:" + failed req.reply(output)
def main(args): global irc config = ConfigParser.ConfigParser() if (sys.argv != 2): cfile = "bot.conf" else: cfile = args[1] listener = Listener(IRC_RESTART, restartIRCHook) getEventManager().addListener(listener) __import__("plugins.logger") try: config.readfp(open(cfile)) except: print "Error loading configuration file:", sys.exc_info()[1] sys.exit(1) host = config.get("main", "host") port = config.get("main", "port") channels = config.get("main", "channels") nick = config.get("main", "nick") print "Host: ", host print "Port: ", port print "Channels: ", channels channels = channels.split(",") port = int(port) for i in range(len(channels)): if channels[i][0] != '#': channels[i] = '#' + channels[i] getEventManager().start() irc = Irc(host, port, channels, nick) while running: try: i = raw_input() if i == "quit" or i == "exit": irc.disconnect() getEventManager().stop() break except KeyboardInterrupt: irc.disconnect() getEventManager().stop() break time.sleep(1) sys.exit()
def message(serv, source, target, text): host = Irc.get_host(source) Commands.Tracking.activity(source,target,serv) if target != serv.nick and source == '[email protected]' and 'tipped' in text and 'to dogesoak' in text.lower(): try: usr = text.split()[1] req = Request(serv, target, usr) val = int(text.split('much ',1)[1][2:].split(' ',1)[0]) try: Commands.soak(req,[str(val)]) except: req.say('An error occurred.') #req.serv.send('PRIVMSG','Doger','tip ') except: print 'soaker error' if Commands.lreq and target == serv.nick and source.split('!',1)[0] == 'Doger': Commands.balancerepl(text) if text[0] == '!' or target == serv.nick: if serv.is_ignored(host): print(serv.nick + ": (ignored) <" + Irc.get_nickname(source) + "> " + text) return print(serv.nick + ": <" + Irc.get_nickname(source) + "> " + text) t = time.time() score = serv.flood_score.get(host, (t, 0)) score = max(score[1] + score[0] - t, 0) + 4 if score > 40 and not serv.is_admin(source): serv.ignore(host, 240) serv.send("PRIVMSG", Irc.get_nickname(source), "You're sending commands too quickly. Your host is ignored for 240 seconds") return serv.flood_score[host] = (t, score) if text[0] == '!': text = text[1:] src = Irc.get_nickname(source) if target == serv.nick: reply = src else: reply = target if text.find(" ") == -1: command = text args = [] else: command, args = text.split(" ", 1) args = args.split(" ") if command[0] != '_': cmd = Commands.commands.get(command.lower(), None) if not cmd.__doc__ or cmd.__doc__.find("admin") == -1 or serv.is_admin(source): if cmd: req = Request(serv, reply, source) try: ret = cmd(req, args) except Exception as e: type, value, tb = sys.exc_info() traceback.print_tb(tb) req.reply(repr(e))
def _nick(instance, source, newnick): nick = Irc.get_nickname(source) for channel in Global.account_cache: if nick in Global.account_cache[channel]: Global.account_cache[channel][newnick] = Global.account_cache[channel][nick] Logger.log("w", "%s -> %s in %s" % (nick, newnick, channel)) del Global.account_cache[channel][nick]
def withdraw(req, arg): """%withdraw <address> [amount] - Sends 'amount' coins to the specified dogecoin address. If no amount specified, sends the whole balance""" if len(arg) == 0: return req.reply("%withdraw <address> [amount]") acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if len(arg) == 1: amount = max(Transactions.balance(acct) - 1, 1) else: try: amount = int(arg[1]) if amount <= 0: raise ValueError() amount = min(amount, 1000000000000) except ValueError as e: req.reply_private(repr(arg[1]) + " - invalid amount") return None to = arg[0] if not Transactions.verify_address(to): return req.reply_private(to + " doesn't seem to be a valid dogecoin address") with Logger.token() as token: try: tx = Transactions.withdraw(acct, to, amount) token.log("t", "acct:%s withdrew %d, TX id is %s (acct:%s(%d))" % (acct, amount, tx, acct, Transactions.balance(acct))) req.reply("Coins have been sent, see http://dogechain.info/tx/%s [%s]" % (tx, token.id)) except Transactions.NotEnoughMoney: req.reply_private("You tried to withdraw Ɖ%i (+Ɖ1 TX fee) but you only have Ɖ%i" % (amount, Transactions.balance(acct))) except Transactions.InsufficientFunds: token.log("te", "acct:%s tried to withdraw %d" % (acct, amount)) req.reply("Something went wrong, report this to mniip [%s]" % (token.id))
def donate(req, arg): """%donate <amount> - Donate 'amount' coins to the developers of this bot""" if len(arg) < 1: return req.reply(gethelp("donate")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") toacct = "mniip" if arg[0] == "all": arg[0] = str(Transactions.balance(acct)) try: amount = float(arg[0]) if math.isnan(amount): raise ValueError except ValueError as e: return req.reply_private(repr(arg[0]) + " - invalid amount") if amount > 1e12: return req.reply_private(repr(arg[0]) + " - invalid amount (value too large)") if amount < 1: return req.reply_private(repr(arg[0]) + " - invalid amount (should be 1 or more)") if not int(amount) == amount: return req.reply_private(repr(arg[0]) + " - invalid amount (should be integer)") amount = int(amount) token = Logger.token() try: Transactions.tip(token, acct, toacct, amount) req.reply("Donated Ɖ%i [%s]" % (amount, token)) req.privmsg(toacct, "Such %s donated Ɖ%i [%s]" % (req.nick, amount, token), priority = 10) except Transactions.NotEnoughMoney: req.reply_private("You tried to donate Ɖ%i but you only have Ɖ%i" % (amount, Transactions.balance(acct)))
def withdraw(req, arg): """%withdraw <address> [amount] - Sends 'amount' coins to the specified dogecoin address. If no amount specified, sends the whole balance""" if len(arg) == 0: return req.reply(gethelp("withdraw")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") if len(arg) == 1: amount = max(Transactions.balance(acct) - 1, 1) else: try: amount = parse_amount(arg[1], acct, all_offset = -1) except ValueError as e: return req.reply_private(str(e)) to = arg[0] if not Transactions.verify_address(to): return req.reply_private(to + " doesn't seem to be a valid dogecoin address") token = Logger.token() try: tx = Transactions.withdraw(token, acct, to, amount) req.reply("Coins have been sent, see http://dogechain.info/tx/%s [%s]" % (tx, token)) except Transactions.NotEnoughMoney: req.reply_private("You tried to withdraw Ɖ%i (+Ɖ1 TX fee) but you only have Ɖ%i" % (amount, Transactions.balance(acct))) except Transactions.InsufficientFunds: req.reply("Something went wrong, report this to mniip [%s]" % (token)) Logger.irclog("InsufficientFunds while executing '%s' from '%s'" % (req.text, req.nick))
def message(instance, source, target, text): host = Irc.get_host(source) if text == "\x01VERSION\x01": p = subprocess.Popen(["git", "rev-parse", "HEAD"], stdout = subprocess.PIPE) hash, _ = p.communicate() hash = hash.strip() p = subprocess.Popen(["git", "diff", "--quiet"]) changes = p.wait() if changes: hash += "[+]" version = "Doger by mniip, version " + hash Irc.instance_send(instance, "NOTICE", Irc.get_nickname(source), "\x01VERSION " + version + "\x01") elif text[0] == '%' or target == instance: if Irc.is_ignored(host): Logger.log("c", instance + ": %s <%s ignored> %s " % (target, Irc.get_nickname(source), text)) return Logger.log("c", instance + ": %s <%s> %s " % (target, Irc.get_nickname(source), text)) t = time.time() score = Global.flood_score.get(host, (t, 0)) score = max(score[1] + score[0] - t, 0) + 10 if score > 80 and not Irc.is_admin(source): Logger.log("c", instance + ": Ignoring " + source) #Irc.ignore(host, 240) #Irc.instance_send(instance, "PRIVMSG", Irc.get_nickname(source), "You're sending commands too quickly. Your host is ignored for 240 seconds") #return Global.flood_score[host] = (t, score) if text[0] == '%': text = text[1:] src = Irc.get_nickname(source) if target == instance: reply = src else: reply = target if text.find(" ") == -1: command = text args = [] else: command, args = text.split(" ", 1) args = [a for a in args.split(" ") if len(a) > 0] if command[0] != '_': cmd = Commands.commands.get(command.lower(), None) if not cmd.__doc__ or cmd.__doc__.find("admin") == -1 or Irc.is_admin(source): if cmd: req = Request(instance, reply, source, text) t = threading.Thread(target = run_command, args = (cmd, req, args)) t.start()
def account(instance, source, account): if account == "*": account = False nick = Irc.get_nickname(source) for channel in Global.account_cache: if nick in Global.account_cache[channel]: Global.account_cache[channel][nick] = account Logger.log("w", "Propagating %s=%s into %s" % (nick, account, channel))
def deposit(req, _): """%deposit - Displays your deposit address""" acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") req.reply_private( "To deposit, send coins to %s (transactions will be credited after %d confirmations)" % (Transactions.deposit_address(acct), Config.config["confirmations"]) )
def part(instance, source, channel, *_): nick = Irc.get_nickname(source) if nick == instance: del Global.account_cache[channel] Logger.log("w", "Removing cache for " + channel) return if nick in Global.account_cache[channel]: del Global.account_cache[channel][nick] Logger.log("w", "Removing %s from %s" % (nick, channel))
def read(self): if len(self.unseen): return self.unseen.pop(0) while self.buffer.find('\n') == -1: data = self.connection.recv(4096) self.buffer += data line, self.buffer = self.buffer.split('\n', 1) print(line) return Irc.parse(line.rstrip('\r'))
def _help(req, arg): """%help - list of commands; %help <command> - help for specific command""" if len(arg): if arg[0][0] == '%': name = arg[0][1:] else: name = arg[0] cmd = commands.get(name, None) if cmd and cmd.__doc__: req.reply(cmd.__doc__.split("\n")[0]) else: if not Irc.equal_nicks(req.target, req.nick): return req.reply("I'm Doger, an IRC dogecoin tipbot. For more info do /msg Doger help") acct = Irc.account_names([req.nick])[0] if acct: ident = "you're identified as \2" + acct + "\2" else: ident = "you're not identified" req.say("I'm Doger, I'm an IRC dogecoin tipbot. To get help about a specific command, say \2%help <command>\2 Commands: %tip %balance %withdraw %deposit %mtip %donate %help") req.say("Note that to receive or send tips you should be identified with freenode services (%s). For any support questions, including those related to lost coins, join ##doger" % (ident))
def balance(req, _): """%balance - Displays your confirmed and unconfirmed balance""" acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") confirmed = Transactions.balance(acct) pending = Transactions.balance_unconfirmed(acct) if pending: req.reply("Your balance is Ɖ%i (+Ɖ%i unconfirmed)" % (confirmed, pending)) else: req.reply("Your balance is Ɖ%i" % (confirmed))
def join(instance, source, channel, account, _): if account == "*": account = False nick = Irc.get_nickname(source) with Global.account_lock: if nick == instance: Global.account_cache[channel] = {} Global.account_cache[channel][nick] = account for channel in Global.account_cache: if nick in Global.account_cache[channel]: Global.account_cache[channel][nick] = account Logger.log("w", "Propagating %s=%s into %s" % (nick, account, channel))
def whois_end(instance, _, __, target, ___): try: nick, q = Global.instances[instance].whois_queue.get(False) if Irc.equal_nicks(target, nick): Logger.log("w", instance + ": WHOIS of " + target + " is " + repr(Global.instances[instance].lastwhois)) q.put(Global.instances[instance].lastwhois, True) else: Logger.log("we", instance + ": WHOIS reply for " + target + " but queued " + nick + " returning None") q.put(None, True) Global.instances[instance].lastwhois = None Global.instances[instance].whois_queue.task_done() except Queue.Empty: Logger.log("we", instance + ": WHOIS reply for " + target + " but nothing queued")
def quit(instance, source, _): nick = Irc.get_nickname(source) if nick == instance: chans = [] for channel in Global.account_cache: if nick in Global.account_cache[channel]: chans.append(channel) for channel in chans: del Global.account_cache[channel] Logger.log("w", "Removing cache for " + channel) return for channel in Global.account_cache: if nick in Global.account_cache[channel]: del Global.account_cache[channel][nick] Logger.log("w", "Removing %s from %s" % (nick, channel))
def _as(req, arg): """ admin""" _, target, text = req.text.split(" ", 2) if target[0] == '@': Global.account_cache[""] = {"@": target[1:]} target = "@" if text.find(" ") == -1: command = text args = [] else: command, args = text.split(" ", 1) args = [a for a in args.split(" ") if len(a) > 0] if command[0] != '_': cmd = commands.get(command.lower(), None) if not cmd.__doc__ or cmd.__doc__.find("admin") == -1 or Irc.is_admin(source): if cmd: req = Hooks.FakeRequest(req, target, text) Hooks.run_command(cmd, req, args)
def donate(req, arg): """%donate <amount> - Donate 'amount' coins to help fund the server Doger is running on""" if len(arg) < 1: return req.reply(gethelp("donate")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") toacct = "@DONATIONS" try: amount = parse_amount(arg[0], acct) except ValueError as e: return req.reply_private(str(e)) token = Logger.token() try: Transactions.tip(token, acct, toacct, amount) req.reply("Donated Ɖ%i, thank you very much for your donation [%s]" % (amount, token)) except Transactions.NotEnoughMoney: req.reply_private("You tried to donate Ɖ%i but you only have Ɖ%i" % (amount, Transactions.balance(acct)))
def donate(req, arg): if len(arg) < 1: return req.reply("%donate <amount>") acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") toacct = "@DONATIONS" try: amount = int(arg[0]) if amount <= 0: raise ValueError() amount = min(amount, 1000000000000) except ValueError as e: req.reply_private(repr(arg[0]) + " - invalid amount") return None with Logger.token() as token: try: Transactions.tip(acct, toacct, amount) token.log("t", "acct:%s tipped %d to acct:%s(%d)" % (acct, amount, toacct, Transactions.balance(toacct))) req.reply("Done [%s]" % (token.id)) except Transactions.NotEnoughMoney: req.reply_private("You tried to donate Ɖ%i but you only have Ɖ%i" % (amount, Transactions.balance(acct)))
def message(instance, source, target, text): host = Irc.get_host(source) if text == "\x01VERSION\x01": p = subprocess.Popen(["git", "rev-parse", "HEAD"], stdout=subprocess.PIPE) hash, _ = p.communicate() hash = hash.strip() p = subprocess.Popen(["git", "diff", "--quiet"]) changes = p.wait() if changes: hash += "[+]" version = "Doger by mniip, version " + hash Irc.instance_send(instance, ("NOTICE", Irc.get_nickname(source), "\x01VERSION " + version + "\x01"), priority=20) else: commandline = None if target == instance: commandline = text if text[0] == Config.config["prefix"]: commandline = text[1:] if commandline: if Irc.is_ignored(host): Logger.log( "c", instance + ": %s <%s ignored> %s " % (target, Irc.get_nickname(source), text)) return Logger.log( "c", instance + ": %s <%s> %s " % (target, Irc.get_nickname(source), text)) if Config.config.get("ignore", None): t = time.time() score = Global.flood_score.get(host, (t, 0)) score = max(score[1] + score[0] - t, 0) + Config.config["ignore"]["cost"] if score > Config.config["ignore"][ "limit"] and not Irc.is_admin(source): Logger.log("c", instance + ": Ignoring " + host) Irc.ignore(host, Config.config["ignore"]["timeout"]) Irc.instance_send(instance, ( "PRIVMSG", Irc.get_nickname(source), "You're sending commands too quickly. Your host is ignored for 240 seconds" )) return Global.flood_score[host] = (t, score) src = Irc.get_nickname(source) if target == instance: reply = src else: reply = target if commandline.find(" ") == -1: command = commandline args = [] else: command, args = commandline.split(" ", 1) args = [a for a in args.split(" ") if len(a) > 0] if command[0] != '_': cmd = Commands.commands.get(command.lower(), None) if not cmd.__doc__ or cmd.__doc__.find( "admin") == -1 or Irc.is_admin(source): if cmd: req = Request(instance, reply, source, commandline) t = threading.Thread(target=run_command, args=(cmd, req, args)) t.start()
def __init__(self, serv, target, source): self.serv = serv self.target = target self.source = source self.nick = Irc.get_nickname(source)
import socket, errno, time, sys, traceback, threading import Global, Config, Irc, Logger Logger.log("m", "Started Doger") for instance in Config.config["instances"]: Global.manager_queue.put(("Spawn", instance)) Irc.manager() Logger.log("me", "Manager returned")
def end_of_motd(instance, *_): Global.instances[instance].can_send.set() Logger.log("c", instance + ": End of motd, joining " + " ".join(Config.config["instances"][instance])) for channel in Config.config["instances"][instance]: Irc.instance_send(instance, ("JOIN", channel))
def authenticate(instance, _, data): if data == "+": load = Config.config["account"] + "\0" + Config.config["account"] + "\0" + Config.config["password"] Irc.instance_send(instance, ("AUTHENTICATE", load.encode("base64").rstrip("\n")), lock = False)
def mtip(req, arg): """%mtip <targ1> <amt1> [<targ2> <amt2> ...] - Send multiple tips at once""" if not len(arg) or len(arg) % 2: return req.reply(gethelp("mtip")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private( "You are not identified with freenode services (see /msg NickServ help)" ) if Transactions.lock(acct): return req.reply_private("Your account is currently locked") for i in range(0, len(arg), 2): try: arg[i + 1] = parse_amount(arg[i + 1], acct) except ValueError as e: return req.reply_private(str(e)) targets = [] amounts = [] total = 0 for i in range(0, len(arg), 2): target = arg[i] amount = arg[i + 1] found = False for i in range(len(targets)): if Irc.equal_nicks(targets[i], target): amounts[i] += amount total += amount found = True break if not found: targets.append(target) amounts.append(amount) total += amount balance = Transactions.balance(acct) if total > balance: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, balance)) accounts = Irc.account_names([target_nick(target) for target in targets]) totip = {} failed = "" tipped = "" for i in range(len(targets)): if accounts[i] == None: failed += " %s (offline)" % (target_nick(targets[i])) elif accounts[i] == False: failed += " %s (unidentified)" % (target_nick(targets[i])) elif not target_verify(targets[i], accounts[i]): failed += " %s (mismatch)" % (targets[i]) else: totip[accounts[i]] = totip.get(accounts[i], 0) + amounts[i] tipped += " %s %d" % (target_nick(targets[i]), amounts[i]) token = Logger.token() try: Transactions.tip_multiple(token, acct, totip) tipped += " [%s]" % (token) except Transactions.NotEnoughMoney: return req.reply_private("You tried to tip Ɖ%i but you only have Ɖ%i" % (total, Transactions.balance(acct))) output = "Tipped:" + tipped if len(failed): output += " Failed:" + failed req.reply(output)
def admin(req, arg): """ admin""" if len(arg): command = arg[0] arg = arg[1:] if command == "reload": for mod in arg: reload(sys.modules[mod]) req.reply("Reloaded") elif command == "exec" and Config.config.get("enable_exec", None): exec(" ".join(arg).replace("$", "\n")) elif command == "ignore": Irc.ignore(arg[0], int(arg[1])) req.reply("Ignored") elif command == "die": for instance in Global.instances: Global.manager_queue.put(("Disconnect", instance)) Global.manager_queue.join() Blocknotify.stop() Global.manager_queue.put(("Die",)) elif command == "restart": for instance in Global.instances: Global.manager_queue.put(("Disconnect", instance)) Global.manager_queue.join() Blocknotify.stop() os.execv(sys.executable, [sys.executable] + sys.argv) elif command == "manager": for cmd in arg: Global.manager_queue.put(cmd.split("$")) req.reply("Sent") elif command == "raw": Irc.instance_send(req.instance, eval(" ".join(arg))) elif command == "config": if arg[0] == "save": os.rename("Config.py", "Config.py.bak") with open("Config.py", "w") as f: f.write("config = " + pprint.pformat(Config.config) + "\n") req.reply("Done") elif arg[0] == "del": exec("del Config.config " + " ".join(arg[1:])) req.reply("Done") else: try: req.reply(repr(eval("Config.config " + " ".join(arg)))) except SyntaxError: exec("Config.config " + " ".join(arg)) req.reply("Done") elif command == "join": Irc.instance_send(req.instance, ("JOIN", arg[0]), priority = 0.1) elif command == "part": Irc.instance_send(req.instance, ("PART", arg[0]), priority = 0.1) elif command == "caches": acsize = 0 accached = 0 with Global.account_lock: for channel in Global.account_cache: for user in Global.account_cache[channel]: acsize += 1 if Global.account_cache[channel][user] != None: accached += 1 acchannels = len(Global.account_cache) whois = " OK" whoisok = True for instance in Global.instances: tasks = Global.instances[instance].whois_queue.unfinished_tasks if tasks: if whoisok: whois = "" whoisok = False whois += " %s:%d!" % (instance, tasks) req.reply("Account caches: %d user-channels (%d cached) in %d channels; Whois queues:%s" % (acsize, accached, acchannels, whois)) elif command == "channels": inss = "" for instance in Global.instances: chans = [] with Global.account_lock: for channel in Global.account_cache: if instance in Global.account_cache[channel]: chans.append(channel) inss += " %s:%s" % (instance, ",".join(chans)) req.reply("Instances:" + inss) elif command == "balances": database, dogecoind = Transactions.balances() req.reply("Dogecoind: %.8f; Database: %.8f" % (dogecoind, database)) elif command == "blocks": info, hashd = Transactions.get_info() hashb = Transactions.lastblock req.reply("Best block: " + hashd + ", Last tx block: " + hashb + ", Blocks: " + str(info.blocks) + ", Testnet: " + str(info.testnet)) elif command == "lock": if len(arg) > 1: if arg[1] == "on": Transactions.lock(arg[0], True) elif arg[1] == "off": Transactions.lock(arg[0], False) req.reply("Done") elif len(arg): req.reply("locked" if Transactions.lock(arg[0]) else "not locked")
def ping(instance, *_): Irc.instance_send(instance, ("PONG", ), priority=0)
def __init__(self, instance, target, source, text): self.instance = instance self.target = target self.source = source self.nick = Irc.get_nickname(source) self.text = text
import socket, errno, time, sys, traceback, threading sys.dont_write_bytecode = True import Global, Config, Irc, Logger Logger.log("m", "Started Beaner") for instance in Config.config["instances"]: Global.manager_queue.put(("Spawn", instance)) Global.manager_queue.put(("Signal", )) Irc.manager() Logger.log("me", "Manager returned")
def target_verify(target, accname): s = target.split("@", 1) if len(s) == 2: return Irc.equal_nicks(s[1], accname) else: return True
def admin(req, arg): """ admin""" if len(arg): command = arg[0] arg = arg[1:] if command == "reload": for mod in arg: reload(sys.modules[mod]) req.reply("Reloaded") elif command == "exec" and Config.config.get("enable_exec", None): try: exec(" ".join(arg).replace("$", "\n")) except Exception as e: type, value, tb = sys.exc_info() Logger.log("ce", "ERROR in " + req.instance + " : " + req.text) Logger.log("ce", repr(e)) Logger.log("ce", "".join(traceback.format_tb(tb))) req.reply(repr(e)) req.reply("".join(traceback.format_tb(tb)).replace("\n", " || ")) del tb elif command == "ignore": Irc.ignore(arg[0], int(arg[1])) req.reply("Ignored") elif command == "die": for instance in Global.instances: Global.manager_queue.put(("Disconnect", instance)) Global.manager_queue.join() Blocknotify.stop() Global.manager_queue.put(("Die",)) elif command == "restart": for instance in Global.instances: Global.manager_queue.put(("Disconnect", instance)) Global.manager_queue.join() Blocknotify.stop() os.execv(sys.executable, [sys.executable] + sys.argv) elif command == "manager": for cmd in arg: Global.manager_queue.put(cmd.split("$")) req.reply("Sent") elif command == "raw": Irc.instance_send(req.instance, eval(" ".join(arg))) elif command == "config": if arg[0] == "save": os.rename("Config.py", "Config.py.bak") with open("Config.py", "w") as f: f.write("config = " + pprint.pformat(Config.config) + "\n") req.reply("Done") elif arg[0] == "del": exec("del Config.config " + " ".join(arg[1:])) req.reply("Done") else: try: req.reply(repr(eval("Config.config " + " ".join(arg)))) except SyntaxError: exec("Config.config " + " ".join(arg)) req.reply("Done") elif command == "join": Irc.instance_send(req.instance, ("JOIN", arg[0]), priority = 0.1) elif command == "part": Irc.instance_send(req.instance, ("PART", arg[0]), priority = 0.1) elif command == "caches": acsize = 0 accached = 0 with Global.account_lock: for channel in Global.account_cache: for user in Global.account_cache[channel]: acsize += 1 if Global.account_cache[channel][user] != None: accached += 1 acchannels = len(Global.account_cache) whois = " OK" whoisok = True for instance in Global.instances: tasks = Global.instances[instance].whois_queue.unfinished_tasks if tasks: if whoisok: whois = "" whoisok = False whois += " %s:%d!" % (instance, tasks) req.reply("Account caches: %d user-channels (%d cached) in %d channels; Whois queues:%s" % (acsize, accached, acchannels, whois)) elif command == "channels": inss = "" for instance in Global.instances: chans = [] with Global.account_lock: for channel in Global.account_cache: if instance in Global.account_cache[channel]: chans.append(channel) inss += " %s:%s" % (instance, ",".join(chans)) req.reply("Instances:" + inss) elif command == "balances": database, dogecoind = Transactions.balances() req.reply("Dogecoind: %.8f; Database: %.8f" % (dogecoind, database)) elif command == "blocks": info, hashd = Transactions.get_info() hashb = Transactions.lastblock.encode("ascii") req.reply("Best block: " + hashd + ", Last tx block: " + hashb + ", Blocks: " + str(info.blocks) + ", Testnet: " + str(info.testnet)) elif command == "lock": if len(arg) > 1: if arg[1] == "on": Transactions.lock(arg[0], True) elif arg[1] == "off": Transactions.lock(arg[0], False) req.reply("Done") elif len(arg): req.reply("locked" if Transactions.lock(arg[0]) else "not locked") elif command == "ping": t = time.time() Irc.account_names(["."]) pingtime = time.time() - t acc = Irc.account_names([req.nick])[0] t = time.time() Transactions.balance(acc) dbreadtime = time.time() - t t = time.time() Transactions.lock(acc, False) dbwritetime = time.time() - t t = time.time() Transactions.ping() rpctime = time.time() - t req.reply("Ping: %f, DB read: %f, DB write: %f, RPC: %f" % (pingtime, dbreadtime, dbwritetime, rpctime))
def deposit(req, _): """%deposit - Displays your deposit address""" acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") req.reply_private("To deposit, send coins to %s (transactions will be credited after %d confirmations)" % (Transactions.deposit_address(acct), Config.config["confirmations"]))
def soak(req, arg): """%soak <amt> [minutes] - Sends each active user an equal share of soaked amount""" if not len(arg) or len(arg) % 1: return req.reply(gethelp("soak")) acct = Irc.account_names([req.nick])[0] if not acct: return req.reply_private("You are not identified with freenode services (see /msg NickServ help)") if Transactions.lock(acct): return req.reply_private("Your account is currently locked") for i in range(0, len(arg), 1): try: arg[i] = parse_amount(arg[i], acct) except ValueError as e: return req.reply_private(str(e)) activeseconds = 600 if len(arg) > 1: activeseconds = int(arg[1]) * 60 if activeseconds < 60: activeseconds = 600 elif activeseconds > 86400: activeseconds = 86400 curtime = time.time() targets = [] targetnicks = [] failed = "" for oneactive in Global.account_cache[req.target].keys(): try: curactivetime = curtime - Global.active_list[req.target][oneactive] except: curactivetime = -1 # if not found default to expired target = oneactive if target != None and target != acct and target != req.nick and target != req.instance and target not in targets and not is_soak_ignored(target) and curactivetime > 0 and curactivetime < activeseconds: targets.append(target) if Irc.getacctnick(target) and not Global.acctnick_list[target] == None: targetnicks.append(str(Global.acctnick_list[target])) else: targetnicks.append(str(target)) MinActive = 1 if len(targets) < MinActive: return req.reply("This place seems dead. (Maybe try specifying more minutes..)") accounts = Irc.account_names(targetnicks) failedcount = 0 # we need a count of how many will fail to do calculations so pre-loop list for i in range(len(accounts)): if not accounts[i] or accounts[i] == None: Global.account_cache.setdefault(req.target, {})[targetnicks[i]] = None failedcount += 1 scraps = 0 amount = int(arg[0] / (len(targets) - failedcount)) total = (len(targets) - failedcount) * amount scraps = int(arg[0]) - total if scraps <= 0: scraps = 0 balance = Transactions.balance(acct) if total <= 0: return req.reply("Unable to soak (Not enough to go around, Ɖ%d Minimum)" % (len(targets) - failedcount)) if total + scraps > balance: return req.reply_private("You tried to soak %.0f %s but you only have %.0f %s" % (total+scraps, Config.config["coinab"], balance, Config.config["coinab"])) totip = {} tipped = "" for i in range(len(accounts)): if accounts[i]: totip[accounts[i]] = amount tipped += " %s" % (targetnicks[i]) elif accounts[i] == None: failed += " %s (o)" % (targetnicks[i]) else: failed += " %s (u)" % (targetnicks[i]) # special case where bot isn't included in soak but there are scraps if req.instance not in accounts and scraps > 0: totip[req.instance] = scraps tipped += " %s (%d scraps)" % (req.instance, scraps) token = Logger.token() try: Transactions.tip_multiple(token, acct, totip) except Transactions.NotEnoughMoney: return req.reply_private("You tried to soak %.0f %s but you only have %.0f %s" % (total, Config.config["coinab"], Transactions.balance(acct), Config.config["coinab"])) output = "%s is soaking %d users with %d %s:" % (req.nick, len(targets), amount, Config.config["coinab"]) tippednicks = tipped.strip().split(" ") # only show nicks if not too many active, if large enough total (default 1 to always show or change), if nick list changed or if enough time has passed if len(tippednicks) > 100 or total + scraps < 1 or ((acct in Global.nicks_last_shown and Global.nicks_last_shown[acct] == tipped) and (acct+":last" in Global.nicks_last_shown and curtime < Global.nicks_last_shown[acct+":last"] + 600)): output += " (See previous nick list ) [%s]" % (token) else: for onetipped in tippednicks: if onetipped: if len(output) < 250: output += " " + onetipped else: req.reply(output) output = " " + onetipped Global.nicks_last_shown[acct] = tipped Global.nicks_last_shown[acct+":last"] = curtime req.say(output) Logger.log("c","SOAK %s %s skipped: %s" % (token, repr(targetnicks), repr(failed)))
def names(instance, _, __, eq, channel, names): names = names.split(" ") with Global.account_lock: for n in names: n = Irc.strip_nickname(n) Global.account_cache[channel][n] = None
def sasl_success(instance, _, data, __): Logger.log("c", "Finished authentication") Irc.instance_send(instance, ("CAP", "END"), lock=False) Irc.instance_send(instance, ("CAP", "REQ", "extended-join account-notify"), lock=False)
def cap(instance, _, __, ___, caps): if caps.rstrip(" ") == "sasl": Irc.instance_send(instance, ("AUTHENTICATE", "PLAIN"), lock=False)
def irclog(text): if Config.config.get("irclog", None): for i in xrange(0, len(text), 350): Irc.instance_send(Config.config["irclog"][0], ("PRIVMSG", Config.config["irclog"][1], text[i:i+350]), priority = 0)
def message(instance, source, target, text): host = Irc.get_host(source) text = Irc.strip_colours(text) if text == "\x01VERSION\x01": p = subprocess.Popen(["git", "rev-parse", "HEAD"], stdout = subprocess.PIPE) hash, _ = p.communicate() hash = hash.strip() p = subprocess.Popen(["git", "diff", "--quiet"]) changes = p.wait() if changes: hash += "[+]" version = "Rogerer by TheHoliestRoger, version " + hash Irc.instance_send(instance, ("NOTICE", Irc.get_nickname(source, text), "\x01VERSION " + version + "\x01"), priority = 20) else: commandline = None altnick = Irc.get_nickname(source, text, altnick=True) if any(x.lower() in str(source).lower() for x in Config.config["bridgebotnicks"]) and ">" in str(text): text = text.split("> ", 1)[1] nick = Irc.get_nickname(source, text) if target == instance: commandline = text if len(text) > 1 and text[0] == Config.config["prefix"]: commandline = text[1:] elif ( len(Global.response_read_timers) > 0 and (target != instance or Irc.is_super_admin(source)) and ( nick in Global.response_read_timers or ("@roger_that" in Global.response_read_timers and target in Config.config["welcome_channels"]))): if nick not in Global.response_read_timers and "@roger_that" in Global.response_read_timers: theReadTimer = "@roger_that" auto_or_text = text time_multiplier = (60*60) else: theReadTimer = nick auto_or_text = "auto" time_multiplier = (60) t = time.time() if Global.response_read_timers[theReadTimer]["time"] + 90 > t: commandline = "%s %s" % (Global.response_read_timers[theReadTimer]["cmd"], text) elif Global.response_read_timers[theReadTimer]["time"] + (10*time_multiplier) > t: commandline = "%s %s" % (Global.response_read_timers[theReadTimer]["cmd"], auto_or_text) Logger.log("c", "%s: timer expired (auto) for: %s on: %s, cmd: %s" % ( instance, nick, theReadTimer, Global.response_read_timers[theReadTimer]["cmd"])) else: commandline = "%s end-game" % (Global.response_read_timers[theReadTimer]["cmd"]) Logger.log("c", "%s: timer expired (ended) for: %s on: %s, cmd: %s" % ( instance, nick, theReadTimer, Global.response_read_timers[theReadTimer]["cmd"])) # Track & update last time user talked in channel (ignore PM to bot for activity purposes) if target.startswith('#'): with Global.active_lock: if not target in Global.active_list.keys(): Global.active_list[target] = {} Global.active_list[target][nick] = time.time() if commandline: if Irc.is_ignored(host) and not Irc.is_super_admin(source): Logger.log("c", instance + ": %s <%s ignored> %s " % (target, nick, text)) return Logger.log("c", instance + ": %s <%s> %s " % (target, nick, text)) if Config.config.get("ignore", None): t = time.time() score = Global.flood_score.get(host, (t, 0)) score = max(score[1] + score[0] - t, 0) + Config.config["ignore"]["cost"] if score > Config.config["ignore"]["limit"] and not Irc.is_admin(source): Logger.log("c", instance + ": Ignoring " + host) Irc.ignore(host, Config.config["ignore"]["timeout"]) Irc.instance_send(instance, ("PRIVMSG", nick, "You're sending commands too quickly. Your host is ignored for 240 seconds")) return Global.flood_score[host] = (t, score) src = nick if target == instance: reply = src else: reply = target commandline = commandline.rstrip(" \t") if commandline.find(" ") == -1: command = commandline args = [] else: command, args = commandline.split(" ", 1) args = [a for a in args.split(" ") if len(a) > 0] if command[0] != '_': cmd = Commands.commands.get(command.lower(), None) if cmd == None: cmd = Games.games.get(command.lower(), None) if not cmd.__doc__ or cmd.__doc__.find("admin") == -1 or Irc.is_admin(source): if cmd: req = Request(instance, reply, source, altnick, commandline, command.lower()) t = threading.Thread(target = run_command, args = (cmd, req, args)) t.start()
def ping(instance, source, *args): Irc.instance_send(instance, tuple(("PONG", ) + args), priority=0, lock=False)