#!/usr/bin/python3 -u import socket import ssl import sys import os from time import sleep import launch import threading import re import json import requests from datetime import datetime, timedelta import konfuzius import fml import string import random from nslookup import nslookup import rss version = "v0.9" # IRC settings host = "" port = nick = "huan" password = "" chan = "" fefe_chans = [""] # fml endpoint fml_url = "http://www.fmylife.com/random" # Chat colors b = "\x0312" c = "\x0311" y = "\x038" r = "\x034" g = "\x033" # global variable for the socket, see connect() irc = None # Currency API def get_exchange(): url = "https://www.bitstamp.net/api/v2/ticker/eurusd" try: r = requests.get(url) data = json.loads(r.text) return float(data["last"]) except: pass def calc_currency(curr, value): eurusd = get_exchange() if curr == "eur": rate = value * eurusd return rate elif curr == "usd": rate = value / eurusd return rate else: raise Exception("wrong input") def safeexit(): sys.exit(0) def connect(host, port): global irc print("Connecting to "+host+":"+str(port)) context = ssl.create_default_context() with socket.create_connection((host, port), timeout=180) as sock: irc = context.wrap_socket(sock, server_hostname=host) def sendRaw(data): irc.send(bytes(data, "UTF-8")) def register(nick, host): print("Registering User...") sendRaw("USER "+nick+" "+host+" "+nick+" "+nick+"\n") def name(nick): print("Setting Nickname to "+nick) sendRaw("NICK "+nick+"\n") def auth(nick, password): print("Authenticating...") sendRaw("PRIVMSG NickServ :IDENTIFY "+nick+" "+password+"\n") def join(chan): print("Joining channel "+chan) try: sendRaw("JOIN "+chan+"\n") except Exception as err: print("Failed! "+str(err)) def mode(nick): print("Setting modes +B-x") sendRaw("MODE "+nick+" +B-x\n") def part(chan): print("Leaving channel "+chan) try: sendRaw("PART "+chan+"\n") except Exception as err: print(err) def say(chan, msg): try: sendRaw("PRIVMSG "+chan+" :"+msg+"\n") print("OK") except Exception as err: print("Error: "+str(err)) def raw(msg): try: sendRaw(msg+"\n") print("OK") except Exception as err: print("Error"+str(err)) def me(chan, msg): try: sendRaw("PRIVMSG "+chan+" :\u0001ACTION "+msg+"\u0001\n") except Exception as err: print("Error: "+str(err)) def getData(): raw = irc.recv(4096) if not raw: print("Connection lost!") sys.exit(0) try: data = raw.decode("UTF-8") except: try: data = raw.decode("latin-1") except: data = "Broken encoding" return data def getMessage(): data = getData() rawMsg = data.strip("\r\n") return rawMsg def getRocket(): rocket, mission, delta = launch.next_launch() rstring = "%sNext rocket: %s%s %s| %s%s %s| %s%s" % (b, y, rocket, b, y, mission, b, y, delta) return rstring def yon(): from random import choice answer = choice(['y', 'n']) return answer def is_registered(username): try: sendRaw("WHOIS "+str(username)+"\n") user_info = getMessage() regex = r"330 "+str(re.escape(nick))+" "+str(re.escape(username))+" \S+ :is logged in as" matches = re.finditer(regex, user_info, re.MULTILINE) for match in matches: acc_name = match.group(0).split()[3] return acc_name except Exception as err: print("Error getting user account! - "+str(err)) return None def hour_min(td): return td.seconds//3600, (td.seconds//60)%60 def give_rep(user, orig_user, giver, reason, channel): print("Give rep action: target-user "+str(user)+" - username "+str(orig_user)+" - giver "+str(giver)+" - reason "+str(reason)) data = json.load(open("rep.json")) date = datetime.now() stamp = datetime.strftime(date, "%Y-%m-%d %H:%M:%S") delay = timedelta(hours=4) if giver in data["users"]: last_give = datetime.strptime(data["users"][giver]["last_given"], "%Y-%m-%d %H:%M:%S") delta = date - last_give again = delay - delta ah, am = hour_min(again) if delta <= delay: if ah != 0: say(channel, "You can give rep again in "+str(ah)+" hours and "+str(am)+" minutes.") return else: say(channel, "You can give rep again in "+str(am)+" minutes.") return else: data["users"][giver]["last_given"] = stamp else: data["users"][giver] = {"rep": 0, "last_given": stamp, "reason": "None"} if user in data["users"]: data["users"][user]["rep"] += 1 data["users"][user]["reason"] = str(reason) else: data["users"][user] = {"rep": 1, "last_given": "1990-01-01 00:00:00", "reason": str(reason)} say(channel, "Reputation of "+orig_user+": "+str(data["users"][user]["rep"])) data["last_update"] = stamp json.dump(data, open("rep.json", "w")) def get_rep(user): data = json.load(open("rep.json")) if user in data["users"]: rep = data["users"][user]["rep"] reason = data["users"][user]["reason"] else: rep = 0 reason = "None" return [str(rep), str(reason)] def notice(user, msg): sendRaw("NOTICE "+user+" :"+msg+"\n") print("sent notice to "+user+" with message: "+msg) def ping(msg): sendRaw("PONG :"+msg+"\n") def start(host, port, nick, password, chans): connect(host, port) sleep(2) register(nick, host) sleep(2) name(nick) sleep(6) auth(nick, password) sleep(2) mode(nick) sleep(2) for chan in chans: join(chan) sleep(2) def command_loop(): while True: try: data = getData() ircmsg = data.strip("\n\r") if ircmsg.find("PING :") != -1: pingstring = ircmsg.strip("PING :") ping(pingstring) if ircmsg.find("ERROR :Closing link") != -1: print("Error. Lost Connection. Giving up!") os._exit(1) break if ircmsg.find(" PRIVMSG ") != -1: ircnick = ircmsg.split("!")[0][1:] channel = ircmsg.split(" PRIVMSG ", 1)[-1].split(" :", 1)[0] msg = ircmsg.split(channel+" :", 1)[1] if channel == nick: print("direct message received") if msg == "\x01VERSION\x01": print("got ctcp version request") notice(ircnick, "\x01VERSION HuanBot (fork of BertBot) "+version+"\x01") elif msg.startswith("\x01PING"): print("got ctcp ping request") pingstring = msg.split()[1] notice(ircnick, "\x01PING "+pingstring+"\x01") continue if msg == ".hello": say(channel, "Hello "+ircnick) elif msg == ".help": print("sending help") say(channel, "available commands: .nextrocket, .slap, .mate, .hello, .jn, .rep, .konfuzius, .fml, .eurusd, .usdeur, .nslookup") elif msg == ".nextrocket": try: print("found Rocket command\nRequesting next rocketlaunch...") response = getRocket() say(channel, response) except: print("Error getting next rocketlaunch") say(channel, "Error contacting LaunchLibrary API") elif msg.startswith(".slap"): try: slapname = msg.split()[1] print("slapping "+slapname) say(channel, ircnick+" slaps "+slapname+" around a bit with a large trout") except Exception as err: print(err) elif msg.startswith(".mate"): try: try: user = msg.split()[1] print("schenke mate an "+user+" aus") me(channel, "reicht "+user+" eine eiskalte Mate. Prost du scheiss Hipster.") except: print("schenke mate an "+ircnick+" aus") me(channel, "reicht "+ircnick+" eine eiskalte Mate. Prost du scheiss Hipster.") except Exception as err: print(err) elif msg.startswith(".eurusd"): try: value = float(msg.split()[1]) rate = calc_currency("eur", value) say(channel, "USD: {0:.2f}".format(rate)) except Exception as err: say(channel, "could not get data") print(err) elif msg.startswith(".usdeur"): try: value = float(msg.split()[1]) rate = calc_currency("usd", value) say(channel, "EUR: {0:.2f}".format(rate)) except Exception as err: say(channel, "could not get data") print(err) elif msg.startswith(".jn"): choose = yon() try: print("choose "+choose+" for "+ircnick) if choose == "y": say(channel, ircnick+": "+g+"Ja") else: say(channel, ircnick+": "+r+"Nein") except Exception as err: print(err) elif msg.startswith(".rep"): try: user = msg.split(" ", 2)[1] print("got rep message from "+str(ircnick)+" for "+str(user)) try: reason = msg.split(" ", 2)[2] print("with reason "+str(reason)) except: reason = "None" print("with no reason") if user == ircnick: say(channel, "You can't give rep to yourself. Selfish little prick!") continue try: acc_name = is_registered(user) give_acc = is_registered(ircnick) print("found account name for "+str(user)+": "+str(acc_name)) if acc_name != None and give_acc != None: give_rep(acc_name, user, give_acc, reason, channel) elif give_acc == None: say(channel, "You are not registered!") continue else: say(channel, "invalid or not registered user") continue except Exception as err: print("Error in giving rep! - "+str(err)) except Exception as err: print("No rep user found! - "+str(err)) try: acc_name = is_registered(ircnick) if acc_name != None: rep_result = get_rep(acc_name) rep = rep_result[0] reason = rep_result[1] say(channel, "Your reputation: "+str(rep)+" - Last reason: "+str(reason)) else: say(channel, "You are not registered") continue except Exception as err: print("Error getting rep! - "+str(err)) elif msg.startswith(".konfuzius"): try: quote = konfuzius.random_quote() say(channel, b+"Konfuzius sagt: "+c+quote) except: say(channel, "Error :(") elif msg == ".quit": if ircnick == "jkhsjdhjs": say(channel, "Flying to mars...") print("got quit command. exiting...") part(channel) safeexit() else: say(channel, "You are not my master!") elif msg.startswith(".say"): if ircnick == "jkhsjdhjs": try: sayit = msg.split(" ", 1)[1] say(channel, str(sayit)) except: say(channel, "What should I say?") continue else: say(channel, "You are not my master!") elif msg.startswith(".debug"): if ircnick == "jkhsjdhjs": try: debugmsg = msg.split(" ", 1)[1] raw(debugmsg) except: say(channel, "What should I say?") continue else: say(channel, "You are not my master!") elif msg == ".fml": try: fml_string = fml.get_fml(fml_url) print("got fml command") say(channel, c+fml_string+b+" FML.") except Exception as err: print("Error getting URL title "+str(err)) elif msg.startswith(".nslookup"): try: msg_parts = msg.split(" ") try: nsdomain = msg_parts[1] except: say(channel, r+"You must specify a domain!") continue nstype = msg_parts[2:] if not nstype: nstype = ["AAAA", "A"] print("got nslookup command with domain: "+str(nsdomain)+" and type: "+str(nstype)) nsresult = nslookup(nsdomain, nstype) nslines = set(nsresult.split("\n")) for nsline in nslines: say(channel, y+" "+str(nsline)) except Exception as err: print("Error in nslookup - "+str(err)) #elif "i won't" in msg: # try: # say(channel, "blp") # except Exception as err: # print("could not blp - "+str(err)) except Exception as err: print(err) def fefe_check(): while True: try: fefe_result = rss.check() if not fefe_result == None: for chan in fefe_chans: say(chan, b+"Fefe sagt: "+c+str(fefe_result)) except Exception as err: print("Error in fefe module! - "+str(err)) sleep(300) class command_thread(threading.Thread): def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID def run(self): print("Starting Command Thread...") command_loop() class fefe_thread(threading.Thread): def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID def run(self): print("Starting fefe thread...") fefe_check() def main(): try: start(host, port, nick, password, set(join_chans + fefe_chans)) except Exception as err: print("FAIL: "+str(err)) sys.exit(1) thread_command = command_thread(1) #thread_fefe = fefe_thread(2) thread_command.start() #sleep(2) #thread_fefe.start() if __name__ == "__main__": main()