Beispiel #1
0
def get_oauth_token(scopes):
	with open("keys.json") as f:
		keys = json.load(f)
	t = int(time.time())

	header = json.dumps({"alg":"RS256", "typ":"JWT"}).encode("utf-8")
	claim = json.dumps({
		"iss": keys["client_email"],
		"scope": " ".join(scopes),
		"aud": "https://accounts.google.com/o/oauth2/token",
		"iat": t,
		"exp": t+60*60,
	}).encode("utf-8")

	data = base64_encode(header) + b'.' + base64_encode(claim)

	key = RSA.importKey(keys["private_key"])
	h = SHA256.new(data)
	signer = PKCS1_v1_5.new(key)
	signature = signer.sign(h)

	jwt = (data + b'.' + base64_encode(signature)).decode("utf-8")

	data = {"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": jwt}

	ret = json.loads((yield from utils.http_request_coro("https://accounts.google.com/o/oauth2/token", data, "POST")))
	if "error" in ret:
		raise Exception(ret["error"])
	return ret
Beispiel #2
0
def get_display_name(nick):
	try:
		data = yield from utils.http_request_coro("https://api.twitch.tv/kraken/users/%s" % nick)
		data = json.loads(data)
		return data['display_name']
	except:
		return nick
Beispiel #3
0
def extract_new_channels(loop):
    data = yield from utils.http_request_coro(
        googlecalendar.EVENTS_URL % urllib.parse.quote(googlecalendar.CALENDAR_FAN),
        {"key": config["google_key"], "maxResults": 25000},
    )
    data = json.loads(data)

    channels = set()

    for event in data["items"]:
        if "location" in event:
            for token in event["location"].split():
                url = urllib.parse.urlparse(token)
                if url.scheme == "":
                    url = urllib.parse.urlparse("https://" + token)
                if url.netloc in {"www.twitch.tv", "twitch.tv"}:
                    try:
                        channel = url.path.split("/")[1].lower()
                    except IndexError:
                        continue
                    channels.add(channel)

    follows = yield from twitch.get_follows_channels()
    old_channels = {channel["channel"]["name"] for channel in follows}
    old_channels.add(config["channel"])

    yield from asyncio.gather(
        *map(twitch.follow_channel, channels.difference(old_channels)), loop=loop, return_exceptions=True
    )
Beispiel #4
0
def get_videos(channel=None, offset=0, limit=10, broadcasts=False, hls=False):
    channel = channel or config["channel"]
    data = yield from utils.http_request_coro(
        "https://api.twitch.tv/kraken/channels/%s/videos" % channel,
        data={"offset": offset, "limit": limit, "broadcasts": "true" if broadcasts else "false", "hls": hls},
    )
    return json.loads(data)["videos"]
Beispiel #5
0
def unfollow_channel(target, user=None):
    if user is None:
        user = config["username"]
    headers = {"Authorization": "OAuth %s" % storage.data["twitch_oauth"][user]}
    yield from utils.http_request_coro(
        "https://api.twitch.tv/kraken/users/%s/follows/channels/%s" % (user, target), method="DELETE", headers=headers
    )
Beispiel #6
0
def follow_channel(target, user=None):
	if user is None:
		user = config["username"]
	headers = {
		"Authorization": "OAuth %s" % storage.data['twitch_oauth'][user],
	}
	yield from utils.http_request_coro("https://api.twitch.tv/kraken/users/%s/follows/channels/%s" % (user, target),
									data={"notifications": "false"}, method="PUT", headers=headers)
Beispiel #7
0
def get_follows_channels(username=None):
	if username is None:
		username = config["username"]
	url = "https://api.twitch.tv/kraken/users/%s/follows/channels" % username
	follows = []
	total = 1
	while len(follows) < total:
		data = yield from utils.http_request_coro(url)
		data = json.loads(data)
		total = data["_total"]
		follows += data["follows"]
		url = data["_links"]["next"]
	return follows
Beispiel #8
0
def get_streams_followed(username=None):
    if username is None:
        username = config["username"]
    url = "https://api.twitch.tv/kraken/streams/followed"
    headers = {"Authorization": "OAuth %s" % storage.data["twitch_oauth"][username]}
    streams = []
    total = 1
    while len(streams) < total:
        data = yield from utils.http_request_coro(url, headers=headers)
        data = json.loads(data)
        total = data["_total"]
        streams += data["streams"]
        url = data["_links"]["next"]
    return streams
Beispiel #9
0
def get_twitch_emotes_undocumented():
	# This endpoint is not documented, however `/chat/emoticons` might be deprecated soon.
	data = yield from utils.http_request_coro("https://api.twitch.tv/kraken/chat/emoticon_images")
	data = json.loads(data)["emoticons"]
	emotesets = {}
	for emote in data:
		regex = emote["code"]
		regex = regex.replace(r"\&lt\;", "<").replace(r"\&gt\;", ">").replace(r"\&quot\;", '"').replace(r"\&amp\;", "&")
		if re_just_words.match(regex):
			regex = r"\b%s\b" % regex
		emotesets.setdefault(emote["emoticon_set"], {})[emote["code"]] = {
			"regex": re.compile("(%s)" % regex),
			"html": '<img src="https://static-cdn.jtvnw.net/emoticons/v1/%s/1.0" alt="{0}" title="{0}">' % emote["id"]
		}
	return emotesets
Beispiel #10
0
def add_rows_to_spreadsheet(spreadsheet, rows):
	token = yield from 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((yield from utils.http_request_coro(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:
		raise Exception("List feed missing.")
	list_feed = xml.dom.minidom.parseString((yield from utils.http_request_coro(list_feed, headers=headers)))
	post_url = find_schema(list_feed, "http://schemas.google.com/g/2005#post")
	if post_url is None:
		raise Exception("POST URL missing.")

	for row in rows:
		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")
		for column, value in row:
			root.appendChild(new_field(doc, column, value))

		headers["Content-Type"] = "application/atom+xml"
		yield from utils.http_request_coro(post_url, headers=headers, data=doc.toxml(), method="POST")
Beispiel #11
0
def get_subscribers(channel=None, count=5, offset=None, latest=True):
    if channel is None:
        channel = config["channel"]
    if channel not in storage.data["twitch_oauth"]:
        return None
    headers = {"Authorization": "OAuth %s" % storage.data["twitch_oauth"][channel]}
    data = {"limit": count, "direction": "desc" if latest else "asc"}
    if offset is not None:
        data["offset"] = offset
    res = yield from utils.http_request_coro(
        "https://api.twitch.tv/kraken/channels/%s/subscriptions" % channel, headers=headers, data=data
    )
    subscriber_data = json.loads(res)
    return [
        (sub["user"]["display_name"], sub["user"].get("logo"), sub["created_at"])
        for sub in subscriber_data["subscriptions"]
    ]
Beispiel #12
0
def get_twitch_emotes():
	data = yield from utils.http_request_coro("https://api.twitch.tv/kraken/chat/emoticons")
	data = json.loads(data)['emoticons']
	emotesets = {}
	for emote in data:
		regex = emote['regex']
		if regex == r"\:-?[\\/]": # Don't match :/ inside URLs
			regex = r"\:-?[\\/](?![\\/])"
		regex = regex.replace(r"\&lt\;", "<").replace(r"\&gt\;", ">").replace(r"\&quot\;", '"').replace(r"\&amp\;", "&")
		if re_just_words.match(regex):
			regex = r"\b%s\b" % regex
		regex = re.compile("(%s)" % regex)
		for image in emote['images']:
			html = '<img src="%s" width="%d" height="%d" alt="{0}" title="{0}">' % (image['url'], image['width'], image['height'])
			emotesets.setdefault(image.get("emoticon_set"), {})[emote['regex']] = {
				"regex": regex,
				"html": html,
			}
	return emotesets
Beispiel #13
0
def get_subscribers(channel=None, count=5, offset=None, latest=True):
	if channel is None:
		channel = config['channel']
	if channel not in storage.data['twitch_oauth']:
		return None
	headers = {
		"Authorization": "OAuth %s" % storage.data['twitch_oauth'][channel],
	}
	data = {
		"limit": count,
		"direction": "desc" if latest else "asc",
	}
	if offset is not None:
		data['offset'] = offset
	res = yield from utils.http_request_coro("https://api.twitch.tv/kraken/channels/%s/subscriptions" % channel, headers=headers, data=data)
	subscriber_data = json.loads(res)
	return [
		(sub['user']['display_name'], sub['user'].get('logo'), sub['created_at'])
		for sub in subscriber_data['subscriptions']
	]