from api.weather import WeatherException
from api.steam import SteamException
+import pyva_net_rizon_acid_core_User as User
+
+RE_YT_PATTERN = re.compile(
+ "(?:www\\.|m\\.)?(?:(?:youtube\\.com/(?:watch)?(?:[?&][a-z]+=[a-z_]+)?(?:[?&]v=))"
+ "|(?:youtu\\.be\\/))([a-zA-Z0-9-_]+)")
+
+
+def onPrivmsg_regex_youtube(self, source, target, message):
+ userinfo = User.findUser(source)
+ myself = User.findUser(self.nick)
+
+ sender = userinfo['nick']
+ channel = target
+
+ yt_links = RE_YT_PATTERN.findall(message)
+
+ if yt_links and self.google._check_link_eligibility(channel, yt_links[0]):
+ try:
+ video = self.google.yt_video(yt_links[0], userip=userinfo['ip'] if userinfo['ip'] != '0' else None)
+ except:
+ # Silently die
+ return
+ self.msg(channel, "@sep @bYouTube@b %(title)s @sep (%(duration)s) @sep @bViews@b %(views)s @sep "\
+ "@bRating@b @c3@b[+]@b %(liked)s likes @c4@b[-]@b %(disliked)s dislikes @sep" % {
+ 'title': video['title'],
+ 'duration': '%s' % format_hms(video['duration']),
+ 'views': format_thousand(video['view_count']),
+ 'liked': format_thousand(video['liked']),
+ 'disliked': format_thousand(video['disliked'])
+ })
+ else:
+ return True
+
+
def get_citystate_from_zipcode(self, zipcode):
"""Return [city,state] for the given U.S. zip code (if database has been imported)"""
try:
if result is None:
self.msg(channel, '[W|A] Invalid input.')
else:
- self.msg(channel, u'[W|A] {r[0]} = {r[1]}'.format(r=result))
+ resultLines = result[0].splitlines(True) if result[1] is None else result[1].splitlines(True)
+ lines = len(resultLines) # number of lines
+ maxLineLength = max([len(x) for x in resultLines]) # max length of lines
+
+ tosend = u'[W|A] {r[0]}'.format(r=result) # default to always show the first part
+ if result[1] is not None:
+ tosend += u' = {r[1]}'.format(r=result)
+
+ if lines > self.output_limit or maxLineLength > self.max_line_length:
+ self.notice(sender, tosend)
+ else:
+ self.msg(channel, tosend)
def command_youtube_search(self, manager, opts, arg, channel, sender, userinfo):
try:
'disliked': format_thousand(res['disliked']) if res['disliked'] else 0
})
+def command_twitch(self, manager, opts, arg, channel, sender, userinfo):
+ MAX_RESULTS = 5
+ expr, sep, res_num = arg.partition('/')
+ arg = expr.strip()
+ try:
+ if 'stream' in opts:
+ if arg.strip(): # search for a particular stream
+ [total, streams] = self.twitch.search_stream(arg)
+ if not total:
+ self.errormsg(channel, u"No results found.")
+ return
+ if res_num:
+ s = streams[int(res_num)-1]
+ self.msg(channel, (u"@sep Game @b{s[game]}@b @sep has status @b{s[status]}@b on channel @u{s[chan]}@u, " +
+ u"which has {s[views]} views and {s[followers]} followers @sep Link: {s[url]} @sep").format(s=s))
+ return
+ i = 1
+ for s in streams:
+ if i > MAX_RESULTS: break
+ self.msg(channel, (u"@sep [{i}/{total}] Game @b{s[game]}@b @sep has status @b{s[status]}@b on channel @u{s[chan]}@u, " +
+ u"which has {s[views]} views and {s[followers]} followers @sep Link: {s[url]} @sep").format(i=i, total=total, s=s))
+ i += 1
+ self.notice(sender, "To view a particular result, type: @b.tw -s {} /@unumber@u@b".format(arg.replace('+', ' ')))
+ else: # list top streams
+ streams = self.twitch.get_streams()
+ if res_num:
+ s = streams[int(res_num)-1]
+ self.msg(channel, (u"@sep Game @b{s[game]}@b @sep has a stream created on {s[created_at]} that has " +
+ u"{s[viewers]} viewers @sep Related channel: @b{s[channel]}@b @sep").format(s=s))
+ return
+ i = 1
+ total = len(streams)
+ for s in streams:
+ if i > MAX_RESULTS: break
+ self.msg(channel, (u"@sep [{i}/{total}] Game @b{s[game]}@b @sep has a stream created on {s[created_at]} that has " +
+ u"{s[viewers]} viewers @sep Related channel: @b{s[channel]}@b @sep").format(s=s, i=i, total=total))
+ i += 1
+ self.notice(sender, u"To view a particular result, type: @b.tw -s /@unumber@u@b")
+
+ elif 'channel' in opts:
+ videos = self.twitch.get_channel(arg.strip())
+ if videos:
+ if res_num:
+ v = videos[int(res_num)-1]
+ self.msg(channel, u"@sep @b{v[title]}@b @sep with {v[views]} views @sep Link: {v[url]} @sep".format(v=v))
+ return
+ self.msg(channel, "@sep Videos in channel @b{}@b @sep".format(arg))
+ i = 1
+ total = len(videos)
+ for v in videos:
+ if i > MAX_RESULTS: break
+ self.msg(channel, "@sep [{i}/{total}] @b{v[title]}@b @sep with {v[views]} views @sep Link: {v[url]} @sep"
+ .format(v=v, i=i, total=total))
+ i += 1
+ self.notice(sender, "To view a particular result, type: @b.tw -c {} /@unumber@u@b".format(arg.replace('+', ' ')))
+ else:
+ self.errormsg(channel, "Channel @b{}@b does not exit.".format(arg))
+
+ elif 'game' in opts:
+ games = self.twitch.search_games(arg)
+ if not games:
+ self.errormsg(channel, "Game @b{}@b does not exit.".format(arg))
+ return
+ if res_num:
+ g = games[int(res_num)-1]
+ self.msg(channel, (u"@sep @b{g[name]}@b @sep ranked @b{g[popularity]}@b in popularity @sep " +
+ u"http://www.twitch.tv/search?query={g[name2]} @sep").format(g=g))
+ return
+ self.msg(channel, "Results for @b{}@b".format(arg.replace('+', ' ')))
+ i = 1
+ total = len(games)
+ for g in games:
+ if i > MAX_RESULTS: break
+ self.msg(channel, (u"@sep [{i}/{total}] @b{g[name]}@b @sep ranked @b{g[popularity]}@b in popularity @sep " +
+ u"http://www.twitch.tv/search?query={g[name2]} @sep").format(i=i, g=g, total=total))
+ i += 1
+ self.notice(sender, "To view a particular result, type: @b.tw -g {} /@unumber@u@b".format(arg.replace('+', ' ')))
+
+ elif 'team' in opts:
+ if arg.strip(): # search for a particular team
+ t = self.twitch.get_team(arg)
+ if t:
+ self.msg(channel, (u"@sep Team @u{t[name]}@u @sep called @b{t[display_name]}@b @sep was created " +
+ u"on {t[created_at]} @sep Info: {t[info]} @sep").format(t=t))
+ else:
+ self.errormsg(channel, "Team @b{}@b does not exist.".format(arg))
+ else: # list top teams
+ teams = self.twitch.get_teams()
+ if not teams:
+ self.errormsg(channel, u"No teams exist.")
+ return
+ if res_num:
+ t = teams[int(res_num)-1]
+ self.msg(channel, (u"@sep Team @u{t[name]}@u @sep called @b{t[display_name]}@b @sep was created " +
+ u"on {t[created_at]} @sep Info: {t[info]} @sep").format(t=t))
+ return
+ i = 1
+ total = len(teams)
+ for t in teams:
+ if i > MAX_RESULTS: break
+ self.msg(channel, (u"@sep [{i}/{total}] Team @u{t[name]}@u @sep called @b{t[display_name]}@b @sep was created " +
+ u"on {t[created_at]} @sep Info: {t[info]} @sep").format(t=t, i=i, total=total))
+ i += 1
+ self.notice(sender, u"To view a particular result, type: @b.tw -t /@unumber@u@b")
+
+ elif 'video' in opts:
+ self.msg(channel, "@sep http://www.twitch.tv/search?query={} @sep".format(arg.replace(' ', '+')))
+
+ else:
+ self.notice(sender, u"Type: @b.help twitch@b for the twitch.tv bot command syntax.")
+ except ValueError:
+ self.errormsg(channel, u"What's after the slash must be an integer number.")
+ except IndexError:
+ self.errormsg(channel, u"No result with that number exists.")
+
+
def command_dictionary(self, manager, opts, arg, channel, sender, userinfo):
try:
results = self.wordnik.definition(arg)
else:
for num, entry in enumerate(res['list'], 1):
if num == 4:
- self.notice(sender, 'To view a single definition with a related example, type: @b.u %s /def_number@b. For more definitions, visit: %s' % (expr, res['list'][0]['permalink']))
+ self.notice(sender, u'To view a single definition with a related example, type: @b.u %s /def_number@b. For more definitions, visit: %s' % (expr, res['list'][0]['permalink']))
break
definition = entry['definition'].replace('\r\n', ' / ').replace('\n', ' / ')
if 'error' in reply:
self.errormsg(channel, reply['error'])
+ elif not reply['long-url']:
+ self.msg(channel, '@sep @bLong URL@b URL does not redirect')
else:
- self.msg(channel, '@sep @bLong URL@b {reply[long-url]} @sep @bContent-type@b {reply[content-type]} @sep'.format(reply=reply))
+ self.msg(channel, '@sep @bLong URL@b {reply[long-url]} @sep'.format(reply=reply))
def command_idlerpg(self, manager, opts, arg, channel, sender, userinfo):
try:
'u': 'urbandictionary',
'urbandictionary': (command_urbandictionary, ARG_YES, 'Search for a definition on Urban Dictionary', [], 'word'),
- 'g': 'google',
- 'google': (command_google_search, ARG_YES, 'Search for something on Google', [], 'google_search'),
+ # 'g': 'google',
+ # 'google': (command_google_search, ARG_YES, 'Search for something on Google', [], 'google_search'),
- 'gi': 'google_image',
- 'google_image': (command_google_image_search, ARG_YES, 'Search for images via Google Image', [], 'google_image_search'),
+ # 'gi': 'google_image',
+ # 'google_image': (command_google_image_search, ARG_YES, 'Search for images via Google Image', [], 'google_image_search'),
't': 'translate',
'translate': (command_bing_translate, ARG_YES, 'Translate something from a language to another', [], 'from to text'),
'shorten': (command_url_shorten, ARG_YES, 'Shortens a URL using http://j.mp', [], 'long_url'),
+ 'unshorten': 'expand',
'expand': (command_url_expand, ARG_YES, 'Expands a shortened URL using http://longurl.org', [], 'shortened_url'),
'irpg': 'idlerpg',
'regsteam': 'register_steam',
'register_steam': (command_register_steam, ARG_YES, 'Registers your Steam user ID', [], 'steamid'),
+
+ 'tw': 'twitch',
+ 'twitch': (command_twitch, ARG_OPT, 'Displays information about twitch.tv streams/games/channels/teams', [
+ ('stream', '-s', 'searches for a particular stream, or displays the top streams if no argument provided', {'action': 'store_true'}, ARG_OPT),
+ ('channel', '-c', 'lists the top videos of a particular channel on twitch.tv', {'action': 'store_true'}, ARG_YES),
+ ('game', '-g', 'searches for a game on twitch.tv', {'action': 'store_true'}, ARG_YES),
+ ('video', '-v', 'allows you to search the twitch.tv site for a video', {'action': 'store_true'}, ARG_YES),
+ ('team', '-t', 'displays the info of a particular stream on twitch.tv, or or displays the top teams if no argument provided', {'action': 'store_true'}, ARG_OPT)]),
'info': (command_internets_info, ARG_NO|ARG_OFFLINE, 'Displays version and author information', []),
'help': (command_internets_help, ARG_OPT|ARG_OFFLINE, 'Displays available commands and their usage', []),