Exemple #1
0
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
Exemple #2
0
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),
    ]
Exemple #3
0
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."
Exemple #4
0
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": []})
Exemple #5
0
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))
Exemple #6
0
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.")
Exemple #7
0
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)
Exemple #8
0
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))
Exemple #9
0
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)))
Exemple #10
0
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!")
Exemple #11
0
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!")
Exemple #12
0
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)
Exemple #13
0
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)),
    )
Exemple #14
0
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": []})
Exemple #15
0
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