def _parseWeather(json): if "current_observation" not in json: return "No weather for this location could be found at this moment. Try again later." cond = json["current_observation"] tempC = cond["temp_c"] tempF = cond["temp_f"] feelslikeC = cond["feelslike_c"] feelslikeF = cond["feelslike_f"] description = cond["weather"] humidity = cond["relative_humidity"] winddir = cond["wind_dir"] windspeedMiles = cond["wind_mph"] windspeedMs = round(cond["wind_kph"] / 3.6, 1) stationID = cond["station_id"] feelslikeStr = "" if abs(float(tempC) - float(feelslikeC)) > 3.0: feelslikeStr = "(feels like {}°C / {}°F) ".format( feelslikeC, feelslikeF) if len(cond["estimated"]) > 0: latestUpdateStr = cond["estimated"]["description"] else: latestUpdate = (timestamp(now()) - int(cond["observation_epoch"])) / 60 latestUpdateStr = "Latest Update: {}".format("{} minute(s) ago".format(latestUpdate) if latestUpdate > 0 \ else "just now") return "Temp: {}°C / {}°F {}| Weather: {} | Humidity: {} | Wind Speed: {} m/s / {} mph | " \ "Wind Direction: {} | Station ID: {} | {}.".format(tempC, tempF, feelslikeStr, description, humidity, windspeedMs, windspeedMiles, winddir, stationID, latestUpdateStr)
def _processTells(self, server, source, nick): if networkName(self.bot, server) not in self.tells: return chanTells = [] pmTells = [] for tell in self.tells[networkName(self.bot, server)][:]: if not any( fnmatch(nick.lower(), r) for r in tell["to"].split("/")): continue if now() < tell["datetoreceive"]: continue if tell["source"][0] in self.bot.servers[ server].supportHelper.chanTypes and len(chanTells) < 3: if tell["source"] == source: chanTells.append(tell) self.tells[networkName(self.bot, server)].remove(tell) elif tell["source"][0] not in self.bot.servers[ server].supportHelper.chanTypes: pmTells.append(tell) self.tells[networkName(self.bot, server)].remove(tell) for tell in chanTells: self.replyPRIVMSG(server, source, self._parseTell(nick, tell)) for tell in pmTells: self.replyPRIVMSG(server, nick, self._parseTell(nick, tell)) if len(chanTells) > 0 or len(pmTells) > 0: self.bot.storage["tells"] = self.tells
def checkEvents(self): for network in self.subscriptions: if network not in self.events: continue try: server = [x for x in self.bot.servers.itervalues() if x.supportHelper.network == network][0].name except IndexError: # We're not currently connected to this network continue sources = [x for x in self.subscriptions[network] if x in self.bot.servers[server].channels or x in self.bot.servers[server].users] if len(sources) == 0: continue # Only fire events if there's a channel or user to fire them at events = [] for i in range(0, len(self.events[network])): event = self.events[network][i] if event["date"] < now() and event["fired"] == False: events.append(event) self.events[network][i]["fired"] = True if len(events) == 0: continue self.bot.storage["events"] = self.events for source in sources: for event in events: m = "{}'s event {!r} is happening right now!".format(event["user"], event["event"]) self.replyPRIVMSG(server, source, m)
def __init__(self, configFile): self.config = Config(configFile) self.connectionFactory = HeufyBotFactory(self) self.log = None self.moduleHandler = ModuleHandler(self) self.servers = {} self.storage = None self.storageSync = None self.startTime = now()
def __init__(self, configFile): self.config = Config(configFile) self.connectionFactory = HeufyBotFactory(self) self.log = None self.moduleHandler = ModuleHandler(self) self.servers = {} self.storage = None self.storageSync = None self.startTime = now()
def handleCTCP(self, server, source, user, message): if not self.bot.moduleHandler.useModuleOnServer(self.name, server): return if message.upper() == "PING" or message.upper().startswith("PING "): self.sendCTCPReply(server, user.nick, "PING", message[5:]) elif message.upper() == "VERSION": self.sendCTCPReply(server, user.nick, "VERSION", "PyHeufyBot v{} / {}".format(__version__, platform())) elif message.upper() == "TIME": self.sendCTCPReply(server, user.nick, "TIME", strftimeWithTimezone(now())) elif message.upper() == "SOURCE": self.sendCTCPReply(server, user.nick, "SOURCE", "https://github.com/Heufneutje/PyHeufyBot/")
def _handleTOPIC(self, nick, ident, host, params): if params[0] not in self.connection.channels: self._logWarning("Received TOPIC message for unknown channel {}.".format(params[0])) return channel = self.connection.channels[params[0]] if nick not in self.connection.users: # A user that's not in the channel can change the topic so let's make a temporary user. user = IRCUser(nick, ident, host) else: user = self.connection.users[nick] oldTopic = channel.topic channel.topic = params[1] channel.topicSetter = user.fullUserPrefix() channel.topicTimestamp = timeutils.timestamp(timeutils.now()) self.moduleHandler.runGenericAction("changetopic", self.connection.name, channel, user, oldTopic, params[1])
def handleCTCP(self, server, source, user, message): if not self.bot.moduleHandler.useModuleOnServer(self.name, server): return if message.upper() == "PING" or message.upper().startswith("PING "): self.sendCTCPReply(server, user.nick, "PING", message[5:]) elif message.upper() == "VERSION": self.sendCTCPReply( server, user.nick, "VERSION", "PyHeufyBot v{} / {}".format(__version__, platform())) elif message.upper() == "TIME": self.sendCTCPReply(server, user.nick, "TIME", strftimeWithTimezone(now())) elif message.upper() == "SOURCE": self.sendCTCPReply(server, user.nick, "SOURCE", "https://github.com/Heufneutje/PyHeufyBot/")
def _getTime(self, lat, lon): currentTime = timestamp(now()) params = { "location": "{},{}".format(lat, lon), "timestamp": currentTime } result = self.bot.moduleHandler.runActionUntilValue("fetch-url", self.timeBaseURL, params) if not result: return "No time for this location could be found at this moment. Try again later." timeJSON = result.json() if timeJSON["status"] != "OK": if "error_message" in timeJSON: return timeJSON["error_message"] else: return "An unknown error occurred while requesting the time." resultDate = datetime.fromtimestamp(currentTime + int(timeJSON["dstOffset"]) + int(timeJSON["rawOffset"])) properDay = self._getProperDay(resultDate.day) formattedTime = resultDate.strftime("%H:%M (%I:%M %p) on %A, " + properDay + " of %B, %Y") return "Timezone: {} | Local time is {}".format(timeJSON["timeZoneName"], formattedTime)
def _handleTOPIC(self, nick, ident, host, params): if params[0] not in self.connection.channels: self._logWarning( "Received TOPIC message for unknown channel {}.".format( params[0])) return channel = self.connection.channels[params[0]] if nick not in self.connection.users: # A user that's not in the channel can change the topic so let's make a temporary user. user = IRCUser(nick, ident, host) else: user = self.connection.users[nick] oldTopic = channel.topic channel.topic = params[1] channel.topicSetter = user.fullUserPrefix() channel.topicTimestamp = timeutils.timestamp(timeutils.now()) self.moduleHandler.runGenericAction("changetopic", self.connection.name, channel, user, oldTopic, params[1])
def _processTells(self, server, source, nick): if networkName(self.bot, server) not in self.tells: return chanTells = [] pmTells = [] for tell in self.tells[networkName(self.bot, server)][:]: if not any(fnmatch(nick.lower(), r) for r in tell["to"].split("/")): continue if now() < tell["datetoreceive"]: continue if tell["source"][0] in self.bot.servers[server].supportHelper.chanTypes and len(chanTells) < 3: if tell["source"] == source: chanTells.append(tell) self.tells[networkName(self.bot, server)].remove(tell) elif tell["source"][0] not in self.bot.servers[server].supportHelper.chanTypes: pmTells.append(tell) self.tells[networkName(self.bot, server)].remove(tell) for tell in chanTells: self.replyPRIVMSG(server, source, self._parseTell(nick, tell)) for tell in pmTells: self.replyPRIVMSG(server, nick, self._parseTell(nick, tell)) if len(chanTells) > 0 or len(pmTells) > 0: self.bot.storage["tells"] = self.tells
def execute(self, server, source, command, params, data): start = strftimeWithTimezone(self.bot.startTime) delta = timeDeltaString(now(), self.bot.startTime) self.replyPRIVMSG(server, source, "I have been up since {} ({}).".format(start, delta))
def _parseTell(self, nick, tell): return "{}: {} < From {} ({} ago).".format(nick, tell["body"], tell["from"], timeDeltaString(now(), tell["date"]))
def execute(self, server, source, command, params, data): if command == "tell" or command == "tellafter": if len(params) == 0 or len(params) == 1: self.replyPRIVMSG(server, source, "Tell who?") return elif len(params) == 1 and command == "tellafter": self.replyPRIVMSG(server, source, "Tell it when?") return elif len(params) == 1 or len(params) == 2 and command == "tellafter": self.replyPRIVMSG(server, source, "Tell {} what?".format(params[0])) return sentTells = [] if command == "tellafter": try: date = datetime.strptime(params[1], "%Y-%m-%d") except ValueError: date = now() + durationToTimedelta(params[1]) else: date = now() for recep in params[0].split("&"): if recep.lower() == self.bot.servers[server].nick.lower(): self.replyPRIVMSG(server, source, "Thanks for telling me that, {}.".format(data["user"].nick)) continue message = { "to": recep.lower(), "body": " ".join(params[1:]) if command == "tell" else " ".join(params[2:]), "date": now(), "datetoreceive": date, "from": data["user"].nick, "source": source if source[0] in self.bot.servers[server].supportHelper.chanTypes else "PM" } if networkName(self.bot, server) not in self.tells: self.tells[networkName(self.bot, server)] = [] self.tells[networkName(self.bot, server)].append(message) sentTells.append(recep.replace("/", " or ")) if len(sentTells) > 0: if command == "tellafter": m = "Okay, I'll tell {} that when they speak after {}.".format("&".join(sentTells), strftimeWithTimezone(date)) else: m = "Okay, I'll tell {} that next time they speak.".format("&".join(sentTells)) self.replyPRIVMSG(server, source, m) self.bot.storage["tells"] = self.tells elif command == "stells": if networkName(self.bot, server) not in self.tells: return tells = [] for tell in self.tells[networkName(self.bot, server)]: if tell["from"].lower() == data["user"].nick.lower(): tells.append(self._parseSentTell(tell)) if len(tells) > 0: for tell in tells: self.replyNOTICE(server, data["user"].nick, tell) else: self.replyNOTICE(server, data["user"].nick, "No undelivered messages sent by you were found.") elif command == "rtell": if len(params) == 0: self.replyPRIVMSG(server, source, "Remove what?") return if networkName(self.bot, server) not in self.tells: self.replyNOTICE(server, data["user"].nick, "No tells matching {!r} were found.".format(params[0])) return tells = [x for x in self.tells[networkName(self.bot, server)] if x["from"].lower() == data[ "user"].nick.lower()] for tell in tells: if re.search(" ".join(params), tell["body"], re.IGNORECASE): self.tells[networkName(self.bot, server)].remove(tell) self.bot.storage["tells"] = self.tells m = "Message {!r} was removed from the message database.".format(self._parseSentTell(tell)) self.replyNOTICE(server, data["user"].nick, m) break else: self.replyNOTICE(server, data["user"].nick, "No tells matching {!r} were found.".format(params[0]))
def _parseTell(self, nick, tell): return "{}: {} < From {} ({} ago).".format( nick, tell["body"], tell["from"], timeDeltaString(now(), tell["date"]))
def execute(self, server, source, command, params, data): start = strftimeWithTimezone(self.bot.startTime) delta = timeDeltaString(now(), self.bot.startTime) self.replyPRIVMSG(server, source, "I have been up since {} ({}).".format(start, delta))
def execute(self, server, source, command, params, data): if networkName(self.bot, server) not in self.events: self.events[networkName(self.bot, server)] = [] if command == "event": if len(params) == 0: self.replyPRIVMSG(server, source, "Add what event?") return try: date = datetime.strptime(" ".join(params[0:2]), "%Y-%m-%d %H:%M") eventOffset = 2 if len(params) < 3: self.replyPRIVMSG(server, source, "Add what event?") return except ValueError: try: date = datetime.strptime(params[0], "%Y-%m-%d") eventOffset = 1 if len(params) < 2: self.replyPRIVMSG(server, source, "Add what event?") return except ValueError: e = "The date format you specified is invalid. The format is yyyy-MM-dd or yyyy-MM-dd HH:mm." self.replyPRIVMSG(server, source, e) return event = { "event": " ".join(params[eventOffset:]), "date": date, "user": data["user"].nick, "fired": True if date < now() else False } self.events[networkName(self.bot, server)].append(event) self.bot.storage["events"] = self.events m = "Event {!r} on date {} was added to the events database!".format(event["event"], strftimeWithTimezone(date)) self.replyPRIVMSG(server, source, m) elif command == "timetill": if len(params) == 0: self.replyPRIVMSG(server, source, "You didn't specify an event") return events = [x for x in self.events[networkName(self.bot, server)] if x["date"] > now()] events.sort(key=lambda item: item["date"]) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): m = "{}'s event {!r} will occur in {}.".format(event["user"], event["event"], timeDeltaString( event["date"], now())) self.replyPRIVMSG(server, source, m) break else: m = "No events matching {!r} were found in the events database.".format(" ".join(params)) self.replyPRIVMSG(server, source, m) elif command == "timesince": if len(params) == 0: self.replyPRIVMSG(server, source, "You didn't specify an event") return events = [x for x in self.events[networkName(self.bot, server)] if x["date"] < now()] events.sort(key=lambda item: item["date"], reverse=True) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): m = "{}'s event {!r} occurred {} ago.".format(event["user"], event["event"], timeDeltaString( now(), event["date"])) self.replyPRIVMSG(server, source, m) break else: m = "No events matching {!r} were found in the events database.".format(" ".join(params)) self.replyPRIVMSG(server, source, m) elif command == "dateof": if len(params) == 0: self.replyPRIVMSG(server, source, "You didn't specify an event") return events = [x for x in self.events[networkName(self.bot, server)] if x["date"] > now()] events.sort(key=lambda item: item["date"]) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): m = "{}'s event {!r} will occur on {}.".format(event["user"], event["event"], strftimeWithTimezone(event["date"])) self.replyPRIVMSG(server, source, m) break else: events = [x for x in self.events[networkName(self.bot, server)] if x["date"] < now()] events.sort(key=lambda item: item["date"], reverse=True) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): m = "{}'s event {!r} occurred on {}.".format(event["user"], event["event"], strftimeWithTimezone(event["date"])) self.replyPRIVMSG(server, source, m) break else: m = "No events matching {!r} were found in the events database.".format(" ".join(params)) self.replyPRIVMSG(server, source, m) elif command == "events": if len(params) == 0 or not isNumber(params[0]): days = 7 else: days = int(params[0]) if int(params[0]) < 365 else 365 events = [x for x in self.events[networkName(self.bot, server)] if x["date"] > now() and x[ "date"] <= now() + timedelta(days)] dayString = "" if days == 1 else "s" if len(events) > 0: events.sort(key=lambda item: item["date"]) eventNames = [x["event"] for x in events] m = "Events occurring in the next {} day{}: {}.".format(days, dayString, ", ".join(eventNames)) else: m = "No events are occurring in the next {} day{}.".format(days, dayString) self.replyPRIVMSG(server, source, m) elif command == "revent": if len(params) == 0: self.replyPRIVMSG(server, source, "You didn't specify an event") return events = [x for x in self.events[networkName(self.bot, server)] if x["date"] > now()] events.sort(key=lambda item: item["date"]) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): self.events[networkName(self.bot, server)].remove(event) self.bot.storage["events"] = self.events m = "{}'s event {!r} with date {} has been removed from the events database.".format( event["user"], event["event"], strftimeWithTimezone(event["date"])) self.replyPRIVMSG(server, source, m) break else: events = [x for x in self.events[networkName(self.bot, server)] if x["date"] < now() and x[ "user"].lower() == data["user"].nick.lower()] events.sort(key=lambda item: item["date"], reverse=True) for event in events: if re.search(" ".join(params), event["event"], re.IGNORECASE): self.events[networkName(self.bot, server)].remove(event) self.bot.storage["events"] = self.events m = "{}'s event {!r} with date {} has been removed from the events database.".format( event["user"], event["event"], strftimeWithTimezone(event["date"])) self.replyPRIVMSG(server, source, m) break else: m = "No events matching {!r} by you were found in the events database.".format(" ".join(params)) self.replyPRIVMSG(server, source, m) elif command == "subevent" or command == "unsubevent": if networkName(self.bot, server) not in self.subscriptions: self.subscriptions[networkName(self.bot, server)] = [] src = source if "channel" in data else data["user"].nick subAction = command == "subevent" self._handleSubscription(server, src, subAction)
def execute(self, server, source, command, params, data): if command == "tell" or command == "tellafter": if len(params) == 0 or len(params) == 1: self.replyPRIVMSG(server, source, "Tell who?") return elif len(params) == 1 and command == "tellafter": self.replyPRIVMSG(server, source, "Tell it when?") return elif len(params ) == 1 or len(params) == 2 and command == "tellafter": self.replyPRIVMSG(server, source, "Tell {} what?".format(params[0])) return sentTells = [] if command == "tellafter": try: date = datetime.strptime(params[1], "%Y-%m-%d") except ValueError: date = now() + durationToTimedelta(params[1]) else: date = now() for recep in params[0].split("&"): if recep.lower() == self.bot.servers[server].nick.lower(): self.replyPRIVMSG( server, source, "Thanks for telling me that, {}.".format( data["user"].nick)) continue message = { "to": recep.lower(), "body": " ".join(params[1:]) if command == "tell" else " ".join(params[2:]), "date": now(), "datetoreceive": date, "from": data["user"].nick, "source": source if source[0] in self.bot.servers[server].supportHelper.chanTypes else "PM" } if networkName(self.bot, server) not in self.tells: self.tells[networkName(self.bot, server)] = [] self.tells[networkName(self.bot, server)].append(message) sentTells.append(recep.replace("/", " or ")) if len(sentTells) > 0: if command == "tellafter": m = "Okay, I'll tell {} that when they speak after {}.".format( "&".join(sentTells), strftimeWithTimezone(date)) else: m = "Okay, I'll tell {} that next time they speak.".format( "&".join(sentTells)) self.replyPRIVMSG(server, source, m) self.bot.storage["tells"] = self.tells elif command == "stells": if networkName(self.bot, server) not in self.tells: return tells = [] for tell in self.tells[networkName(self.bot, server)]: if tell["from"].lower() == data["user"].nick.lower(): tells.append(self._parseSentTell(tell)) if len(tells) > 0: for tell in tells: self.replyNOTICE(server, data["user"].nick, tell) else: self.replyNOTICE( server, data["user"].nick, "No undelivered messages sent by you were found.") elif command == "rtell": if len(params) == 0: self.replyPRIVMSG(server, source, "Remove what?") return if networkName(self.bot, server) not in self.tells: self.replyNOTICE( server, data["user"].nick, "No tells matching {!r} were found.".format(params[0])) return tells = [ x for x in self.tells[networkName(self.bot, server)] if x["from"].lower() == data["user"].nick.lower() ] for tell in tells: if re.search(" ".join(params), tell["body"], re.IGNORECASE): self.tells[networkName(self.bot, server)].remove(tell) self.bot.storage["tells"] = self.tells m = "Message {!r} was removed from the message database.".format( self._parseSentTell(tell)) self.replyNOTICE(server, data["user"].nick, m) break else: self.replyNOTICE( server, data["user"].nick, "No tells matching {!r} were found.".format(params[0]))