def get_next_event_text(calendar, after=None, include_current=None, tz=None, verbose=True): """ Build the actual human-readable response to the !next command. The tz parameter can override the timezone used to display the event times. This can be an actual timezone object, or a string timezone name. Defaults to moonbase time. """ if after is None: after = datetime.datetime.now(datetime.timezone.utc) if not tz: tz = config['timezone'] elif isinstance(tz, str): tz = tz.strip() try: tz = utils.get_timezone(tz) except pytz.exceptions.UnknownTimeZoneError: return "Unknown timezone: %s" % tz events = get_next_event(calendar, after=after, include_current=include_current) if not events: return "There don't seem to be any upcoming scheduled streams" strs = [] for i, ev in enumerate(events): if ev['location'] is not None: title = "%(title)s (%(location)s)" % ev else: title = ev['title'] # If several events are at the same time, just show the time once after all of them if i == len(events) - 1 or ev['start'] != events[i+1]['start']: if verbose: if ev['start'] < after: nice_duration = utils.nice_duration(after - ev['start'], 1) + " ago" else: nice_duration = utils.nice_duration(ev['start'] - after, 1) + " from now" strs.append("%s at %s (%s)" % (title, ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT), nice_duration)) else: strs.append("%s at %s" % (ev['title'], ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT))) else: strs.append(title if verbose else ev['title']) response = ', '.join(strs) if verbose: if calendar == CALENDAR_LRL: response = "Next scheduled stream: %s." % response elif calendar == CALENDAR_FAN: response = "Next scheduled fan stream: %s." % response return utils.shorten(response, 450) # For safety
def format_row(title, description, url, timestamp, nick): return [ ("SHOW", title), ("QUOTE or MOMENT", description), ("YOUTUBE VIDEO LINK", url), ("ROUGH TIME THEREIN", "before " + utils.nice_duration(timestamp, 0)), ("NOTES", "from chat user '%s'" % nick), ]
def uptime_msg(stream_info=None): if stream_info is None: stream_info = twitch.get_info() if stream_info and stream_info.get("stream_created_at"): start = dateutil.parser.parse(stream_info["stream_created_at"]) now = datetime.datetime.now(datetime.timezone.utc) return "The stream has been live for %s." % utils.nice_duration(now-start, 0) elif stream_info and stream_info.get('live'): return "Twitch won't tell me when the stream went live." else: return "The stream is not live."
def main(): if twitch.get_info()["live"]: print("Stream is live.") return highlights = send_bot_command("get_data", {"key": "staged_highlights"}) if argv.test: print("Staged highlights: %r" % highlights) if highlights is None: highlights = [] highlights = list(filter(lambda e: e is not None, map(twitch_lookup, highlights))) if highlights == []: return token = get_oauth_token(["https://spreadsheets.google.com/feeds"]) headers = {"Authorization": "%(token_type)s %(access_token)s" % token} url = "https://spreadsheets.google.com/feeds/worksheets/%s/private/full" % SPREADSHEET tree = xml.dom.minidom.parseString(utils.http_request(url, headers=headers)) worksheet = next(iter(tree.getElementsByTagName("entry"))) list_feed = find_schema(worksheet, "http://schemas.google.com/spreadsheets/2006#listfeed") if list_feed is None: print("List feed missing.") return list_feed = xml.dom.minidom.parseString(utils.http_request(list_feed, headers=headers)) post_url = find_schema(list_feed, "http://schemas.google.com/g/2005#post") if post_url is None: print("POST URL missing.") return for highlight in highlights: doc = xml.dom.minidom.getDOMImplementation().createDocument(None, "entry", None) root = doc.documentElement root.setAttribute("xmlns", "http://www.w3.org/2005/Atom") root.setAttribute("xmlns:gsx", "http://schemas.google.com/spreadsheets/2006/extended") root.appendChild(new_field(doc, "SHOW", highlight["title"])) root.appendChild(new_field(doc, "QUOTE or MOMENT", highlight["description"])) root.appendChild(new_field(doc, "YOUTUBE VIDEO LINK", highlight["url"])) root.appendChild(new_field(doc, "ROUGH TIME THEREIN", "before "+ utils.nice_duration(highlight["time"], 0))) root.appendChild(new_field(doc, "NOTES", "From chat user '%s'." % highlight["user"])) if argv.test: print("Command: %s" % doc.toxml()) else: headers["Content-Type"] = "application/atom+xml" utils.http_request(post_url, headers=headers, data=doc.toxml(), method="POST") if not argv.test: send_bot_command("set_data", {"key": "staged_highlights", "value": []})
def polls(lrrbot, conn, event, respond_to): """ Command: !polls Section: misc List all currently active polls. """ if lrrbot.polls == []: return conn.privmsg(respond_to, "No active polls.") now = time.time() messages = [] for end, title, poll_id, respond_to in lrrbot.polls: messages += ["%s (https://strawpoll.me/%s): %s from now" % (title, poll_id, utils.nice_duration(end - now, 1))] conn.privmsg(respond_to, utils.shorten("Active polls: " + "; ".join(messages), 450))
def uptime(lrrbot, conn, event, respond_to): """ Command: !uptime Section: info Post the duration the stream has been live. """ stream_info = twitch.get_info() if stream_info and stream_info.get("stream_created_at"): start = dateutil.parser.parse(stream_info["stream_created_at"]) now = datetime.datetime.now(datetime.timezone.utc) conn.privmsg(respond_to, "The stream has been live for %s" % utils.nice_duration(now-start, 0)) elif stream_info: conn.privmsg(respond_to, "Twitch won't tell me when the stream went live.") else: conn.privmsg(respond_to, "The stream is not live.")
def notifications(conn, cur, session): row_data = get_notifications(cur) for row in row_data: if row['time'] is None: row['duration'] = None else: row['duration'] = utils.nice_duration(datetime.datetime.now(row['time'].tzinfo) - row['time'], 2) row_data.reverse() if row_data: maxkey = row_data[0]['key'] else: cur.execute("SELECT MAX(notificationkey) FROM notification") maxkey = cur.fetchone()[0] if maxkey is None: maxkey = -1 return flask.render_template('notifications.html', row_data=row_data, maxkey=maxkey, session=session)
def polls(lrrbot, conn, event, respond_to): """ Command: !polls Section: misc List all currently active polls. """ if lrrbot.polls == []: return conn.privmsg(respond_to, "No active polls.") now = time.time() messages = [] for end, title, poll_id, respond_to in lrrbot.polls: messages += [ "%s (http://strawpoll.me/%s): %s from now" % (title, poll_id, utils.nice_duration(end - now, 1)) ] conn.privmsg(respond_to, utils.shorten("Active polls: " + "; ".join(messages), 450))
def new_poll(lrrbot, conn, event, respond_to, multi, timeout, poll_id, title, options): """ Command: !poll N http://strawpoll.me/ID Command: !poll N TITLE: OPTION1; OPTION2 Command: !multipoll N TITLE: OPTION1; OPTION2 Section: misc Start a new Strawpoll poll. Post results in N seconds. Multiple polls can be active at the same time. """ if poll_id is not None: url = "http://strawpoll.me/api/v2/polls/%s" % poll_id data = json.loads(utils.http_request(url)) title = data["title"] else: if title is None: title = "LoadingReadyLive poll" if ';' in options: options = [option.strip() for option in options.split(';')] elif ',' in options: options = [option.strip() for option in options.split(',')] else: options = options.split() data = json.dumps({ "options": options, "title": title, "multi": multi is not None }) response = utils.http_request( "http://strawpoll.me/api/v2/polls", data, "POST", headers={"Content-Type": "application/json"}) poll_id = json.loads(response)["id"] if timeout is not None: timeout = int(timeout) else: timeout = DEFAULT_TIMEOUT end = time.time() + int(timeout) lrrbot.polls += [(end, title, poll_id, respond_to)] conn.privmsg( respond_to, "New poll: %s (http://strawpoll.me/%s): %s from now" % (title, poll_id, utils.nice_duration(timeout, 1)))
def desertbus(lrrbot, conn, event, respond_to, timezone): if not timezone: timezone = config['timezone'] else: timezone = timezone.strip() try: timezone = utils.get_timezone(timezone) except pytz.exceptions.UnknownTimeZoneError: conn.privmsg(respond_to, "Unknown timezone: %s" % timezone) now = datetime.datetime.now(datetime.timezone.utc) if now < DESERTBUS_START: nice_duration = utils.nice_duration(DESERTBUS_START - now, 1) + " from now" conn.privmsg(respond_to, "Desert Bus for Hope will begin at %s (%s)" % (DESERTBUS_START.astimezone(timezone).strftime( googlecalendar.DISPLAY_FORMAT), nice_duration)) elif now < DESERTBUS_END: conn.privmsg(respond_to, "Desert Bus for Hope is currently live! Go watch it now at http://desertbus.org/live/") else: conn.privmsg(respond_to, "Desert Bus for Hope will return next year, start saving your donation money now!")
def notifications(conn, cur, session): row_data = get_notifications(cur) for row in row_data: if row['time'] is None: row['duration'] = None else: row['duration'] = utils.nice_duration( datetime.datetime.now(row['time'].tzinfo) - row['time'], 2) row_data.reverse() if row_data: maxkey = row_data[0]['key'] else: cur.execute("SELECT MAX(notificationkey) FROM notification") maxkey = cur.fetchone()[0] if maxkey is None: maxkey = -1 return flask.render_template('notifications.html', row_data=row_data, maxkey=maxkey, session=session)
def new_poll(lrrbot, conn, event, respond_to, multi, timeout, poll_id, title, options): """ Command: !poll N https://strawpoll.me/ID Command: !poll N TITLE: OPTION1; OPTION2 Command: !multipoll N TITLE: OPTION1; OPTION2 Section: misc Start a new Strawpoll poll. Post results in N seconds. Multiple polls can be active at the same time. """ if poll_id is not None: url = "https://strawpoll.me/api/v2/polls/%s" % poll_id data = json.loads(utils.http_request(url)) title = data["title"] else: if title is None: title = "LoadingReadyLive poll" if ";" in options: options = [option.strip() for option in options.split(";")] elif "," in options: options = [option.strip() for option in options.split(",")] else: options = options.split() data = json.dumps({"options": options, "title": title, "multi": multi is not None}) response = utils.http_request( "https://strawpoll.me/api/v2/polls", data, "POST", headers={"Content-Type": "application/json"} ) poll_id = json.loads(response)["id"] if timeout is not None: timeout = int(timeout) else: timeout = DEFAULT_TIMEOUT end = time.time() + int(timeout) lrrbot.polls += [(end, title, poll_id, respond_to)] conn.privmsg( respond_to, "New poll: %s (https://strawpoll.me/%s): %s from now" % (title, poll_id, utils.nice_duration(timeout, 1)), )
def main(): if twitch.get_info()["live"]: print("Stream is live.") return highlights = send_bot_command("get_data", {"key": "staged_highlights"}) if argv.test: print("Staged highlights: %r" % highlights) if highlights is None: highlights = [] highlights = list( filter(lambda e: e is not None, map(twitch_lookup, highlights))) if highlights == []: return token = get_oauth_token(["https://spreadsheets.google.com/feeds"]) headers = {"Authorization": "%(token_type)s %(access_token)s" % token} url = "https://spreadsheets.google.com/feeds/worksheets/%s/private/full" % SPREADSHEET tree = xml.dom.minidom.parseString(utils.http_request(url, headers=headers)) worksheet = next(iter(tree.getElementsByTagName("entry"))) list_feed = find_schema( worksheet, "http://schemas.google.com/spreadsheets/2006#listfeed") if list_feed is None: print("List feed missing.") return list_feed = xml.dom.minidom.parseString( utils.http_request(list_feed, headers=headers)) post_url = find_schema(list_feed, "http://schemas.google.com/g/2005#post") if post_url is None: print("POST URL missing.") return for highlight in highlights: doc = xml.dom.minidom.getDOMImplementation().createDocument( None, "entry", None) root = doc.documentElement root.setAttribute("xmlns", "http://www.w3.org/2005/Atom") root.setAttribute( "xmlns:gsx", "http://schemas.google.com/spreadsheets/2006/extended") root.appendChild(new_field(doc, "SHOW", highlight["title"])) root.appendChild( new_field(doc, "QUOTE or MOMENT", highlight["description"])) root.appendChild(new_field(doc, "YOUTUBE VIDEO LINK", highlight["url"])) root.appendChild( new_field(doc, "ROUGH TIME THEREIN", "before " + utils.nice_duration(highlight["time"], 0))) root.appendChild( new_field(doc, "NOTES", "From chat user '%s'." % highlight["user"])) if argv.test: print("Command: %s" % doc.toxml()) else: headers["Content-Type"] = "application/atom+xml" utils.http_request(post_url, headers=headers, data=doc.toxml(), method="POST") if not argv.test: send_bot_command("set_data", {"key": "staged_highlights", "value": []})
def get_next_event_text(calendar, after=None, include_current=None, tz=None, verbose=True): """ Build the actual human-readable response to the !next command. The tz parameter can override the timezone used to display the event times. This can be an actual timezone object, or a string timezone name. Defaults to moonbase time. """ if after is None: after = datetime.datetime.now(datetime.timezone.utc) if not tz: tz = config['timezone'] elif isinstance(tz, str): tz = tz.strip() try: tz = utils.get_timezone(tz) except pytz.exceptions.UnknownTimeZoneError: return "Unknown timezone: %s" % tz events = get_next_event(calendar, after=after, include_current=include_current) if not events: return "There don't seem to be any upcoming scheduled streams" strs = [] for i, ev in enumerate(events): # If several events are at the same time, just show the time once after all of them if i == len(events) - 1 or ev['start'] != events[i + 1]['start']: if verbose: if ev['location'] is not None: title = "%(title)s (%(location)s)" % ev else: title = ev['title'] if ev['start'] < after: nice_duration = utils.nice_duration( after - ev['start'], 1) + " ago" else: nice_duration = utils.nice_duration( ev['start'] - after, 1) + " from now" strs.append( "%s at %s (%s)" % (title, ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT), nice_duration)) else: strs.append( "%s at %s" % (ev['title'], ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT))) else: strs.append(ev['title']) response = ', '.join(strs) if verbose: if calendar == CALENDAR_LRL: response = "Next scheduled stream: " + response elif calendar == CALENDAR_FAN: response = "Next scheduled fan stream: " + response return utils.shorten(response, 450) # For safety