]> jfr.im git - irc/rizon/acid.git/blobdiff - pyva/pyva/src/main/python/internets/cmd_user.py
Pyva: Disable google commands. Add unshorten alias for expand. Closes #16 and #53
[irc/rizon/acid.git] / pyva / pyva / src / main / python / internets / cmd_user.py
index cff3cb4be4abcfe0dbfc197cf7539a5f2e5c47b1..2b687a5fcf3653149edbf5eb4b70f8af03a82cf4 100644 (file)
@@ -13,6 +13,40 @@ from api.quotes import FmlException
 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:
@@ -255,7 +289,18 @@ def command_calc(self, manager, opts, arg, channel, sender, userinfo):
                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:
@@ -278,6 +323,122 @@ def command_youtube_search(self, manager, opts, arg, channel, sender, userinfo):
                        '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)
@@ -345,7 +506,7 @@ def command_urbandictionary(self, manager, opts, arg, channel, sender, userinfo)
                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', ' / ')
@@ -566,8 +727,10 @@ def command_url_expand(self, manager, opts, arg, channel, sender, userinfo):
        
        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:
@@ -725,11 +888,11 @@ class UserCommandManager(CommandManager):
                        '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'),
@@ -754,6 +917,7 @@ class UserCommandManager(CommandManager):
                        
                        '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',
@@ -774,6 +938,14 @@ class UserCommandManager(CommandManager):
                        
                        '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', []),