@@ -0,0 +1,2696 @@
+# -*- coding: utf-8 -*-%0A%0A%22%22%22%0A:mod:%60gygax.modules.gatherer%60 --- Module to track live channels on twitch.tv%0A============================================================================%0A%22%22%22%0A%0Aimport codecs%0Aimport collections%0Aimport json%0Afrom urllib import parse, request%0A%0Afrom gygax import irc%0A%0Adef check_channels(*channels):%0A    url = %22https://api.twitch.tv/kraken/streams%22%0A    mime = %22application/vnd.twitchtv.v2+json%22%0A%0A    # In the future we might want to use pagination, but currently 100 channels%0A    # is more than enough.%0A    params = parse.urlencode(%7B%22channel%22: %22,%22.join(channels), %22limit%22: %22100%22%7D)%0A%0A    req = request.Request(%22%7B%7D?%7B%7D%22.format(url, params))%0A    req.add_header(%22Accept%22, mime)%0A    with request.urlopen(req) as f:%0A        utf8 = codecs.getreader(%22utf-8%22)%0A        data = json.load(utf8(f))%0A%0A    # Return a dict from an online channel's name to the channel's metadata.%0A    results = %7B%7D%0A    for stream in data%5B%22streams%22%5D:%0A        results%5Bstream%5B%22channel%22%5D%5B%22name%22%5D%5D = stream%5B%22channel%22%5D%0A    return results%0A%0Adef format_metadata(metadata):%0A    return %22%7B%7D (%7B%7D) is online with status: %7B%7D%22.format(%0A            metadata%5B%22name%22%5D, metadata%5B%22url%22%5D, metadata%5B%22status%22%5D)%0A%0Adef twitch(bot, sender, text):%0A    words = text.split()%0A    if not len(words):%0A        bot.reply(%22missing command, use one of: check, follow, unfollow%22)%0A        return%0A%0A    command = words%5B0%5D%0A    args = words%5B1:%5D%0A    if not len(args):%0A        bot.reply(%22missing channel names%22)%0A        return%0A%0A    if command == %22check%22:%0A        results = check_channels(*args)%0A        for channel in args:%0A            if channel in results:%0A                bot.reply(format_metadata(results%5Bchannel%5D))%0A            else:%0A                bot.reply(%22%7B%7D is offline%22.format(channel))%0A%0A    elif command == %22follow%22:%0A        nick, _, _ = irc.split_name(sender)%0A        for channel in args:%0A            watchdog._following%5Bchannel%5D.add(nick)%0A        bot.reply(%22done%22)%0A%0A    elif command == %22unfollow%22:%0A        nick, _, _ = irc.split_name(sender)%0A        for channel in args:%0A            watchdog._following%5Bchannel%5D.remove(nick)%0A        bot.reply(%22done%22)%0A%0A    else:%0A        bot.reply(%22unknown command%22)%0Atwitch.command = %22.twitch%22%0A%0Adef watchdog(bot):%0A    if len(watchdog._following):%0A        online = check_channels(*watchdog._following.keys())%0A        for channel in online:%0A            if channel not in watchdog._last_online:%0A                for target in watchdog._following%5Bchannel%5D:%0A                    bot.message(target, format_metadata(online%5Bchannel%5D))%0A        watchdog._last_online = set(online.keys())%0A# FIXME: Make _following persistent.%0Awatchdog._following = collections.defaultdict(set)%0Awatchdog._last_online = set()%0Awatchdog.tick = 1%0A

Implement module for following the online status of twitch streams.