Exemplo n.º 1
0
class Turpial:
    '''Inicio de Turpial'''
    def __init__(self):
        parser = OptionParser()
        parser.add_option('-d', '--debug', dest='debug', action='store_true',
            help='Debug Mode', default=False)
        parser.add_option('-i', '--interface', dest='interface',
            help='Select interface to use. (cmd|gtk)', default='gtk')
        parser.add_option('-c', '--clean', dest='clean', action='store_true',
            help='Clean all bytecodes', default=False)
        parser.add_option('--test', dest='test', action='store_true',
            help='Test mode. Only load timeline', default=False)
        
        (options, _) = parser.parse_args()
        
        self.config = None
        self.global_cfg = ConfigApp()
        self.profile = None
        self.remember = False
        self.testmode = options.test
        
        if options.debug: 
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)
        self.log = logging.getLogger('Controller')
        
        if options.clean:
            self.__clean()
            self.signout()
            
        self.interface = options.interface
        #if options.interface == 'gtk2':
        #    self.ui = gtk2_ui_main.Main(self)
        if options.interface == 'gtk+':
            self.ui = _GTK(self, extend=True)
        elif options.interface == 'gtk':
            self.ui = _GTK(self)
        else:
            print 'No existe tal interfaz. Saliendo...'
            sys.exit(-1)
        
        self.httpserv = HTTPServices()
        self.api = TurpialAPI()
        
        self.log.debug('Iniciando Turpial')
        self.httpserv.start()
        self.api.start()
        self.api.change_api_url(self.global_cfg.read('Proxy', 'url'))
        
        if self.testmode:
            self.log.debug('Modo Pruebas Activado')
            
        self.ui.show_login(self.global_cfg)
        self.ui.main_loop()
        
    def __clean(self):
        '''Limpieza de ficheros .pyc y .pyo'''
        self.log.debug("Limpiando la casa...")
        i = 0
        for root, dirs, files in os.walk('.'):
            for f in files:
                path = os.path.join(root, f)
                if path.endswith('.pyc') or path.endswith('.pyo'): 
                    self.log.debug("Borrado %s" % path)
                    os.remove(path)
            
    def __validate_signin(self, val):
        '''Chequeo de inicio de sesion'''
        if val.has_key('error'):
            self.ui.cancel_login(val['error'])
        else:
            self.profile = val
            self.ui.update_user_profile(val)
            self.ui.show_main(self.config, self.global_cfg, val)
            
            self._update_timeline()
            if self.testmode: return
            self._update_replies()
            self._update_directs()
            self._update_favorites()
            self._update_rate_limits()
            
    def __validate_credentials(self, val):
        '''Chequeo de credenciales'''
        if val.has_key('error'):
            self.ui.cancel_login(val['error'])
        else:
            self.profile = val
            self.config = ConfigHandler(val['screen_name'])
            if self.remember:
                self.global_cfg.write('Login', 'username', self.api.username)
                self.global_cfg.write('Login', 'password',
                                      base64.b64encode(self.api.password))
            else:
                self.global_cfg.write('Login', 'username', '')
                self.global_cfg.write('Login', 'password', '')
            self.httpserv.update_img_dir(self.config.imgdir)
            self.httpserv.set_credentials(self.api.username, self.api.password)
            
            auth = self.config.read_section('Auth')
            if self.api.has_oauth_support():
                self.api.start_oauth(auth, self.ui.show_oauth_pin_request,
                                     self.__signin_done)
            else:
                self.api.is_oauth = False
                self.__signin_done(None, None, None)
    
    def __done_follow(self, friends, profile, user, follow):
        self.ui.update_user_profile(profile)
        self.ui.update_friends(friends)
        self.ui.update_follow(user, follow)
        #self.ui.update_timeline(friends)
        
    def __direct_done(self, tweet):
        self.ui.tweet_done(tweet)
        
    def __tweet_done(self, tweet):
        if tweet:
            self.profile['statuses_count'] += 1
            self.ui.update_user_profile(self.profile)
        self.ui.tweet_done(tweet)
        
    def __signin_done(self, key, secret, verifier):
        '''Inicio de sesion finalizado'''
        if key is not None:
            self.config.write('Auth', 'oauth-key', key)
        if secret is not None:
            self.config.write('Auth', 'oauth-secret', secret)
        if verifier is not None:
            self.config.write('Auth', 'oauth-verifier', verifier)
        
        self.api.muted_users = self.config.load_muted_list()
        
        self.ui.show_main(self.config, self.global_cfg, self.profile)
        self._update_timeline()
        if self.testmode: return
        self._update_replies()
        self._update_directs()
        self._update_rate_limits()
        self._update_favorites()
        self._update_friends()
        
    def _update_timeline(self):
        '''Actualizar linea de tiempo'''
        self.ui.start_updating_timeline()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_timeline(self.ui.update_timeline, tweets)
        
    def _update_replies(self):
        '''Actualizar numero de respuestas'''
        self.ui.start_updating_replies()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_replies(self.ui.update_replies, tweets)
        
    def _update_directs(self):
        '''Actualizar mensajes directos'''
        self.ui.start_updating_directs()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_directs(self.ui.update_directs, tweets)
        
    def _update_favorites(self):
        '''Actualizar favoritos'''
        self.api.update_favorites(self.ui.update_favorites)
    
    def _update_rate_limits(self):
        self.api.update_rate_limits(self.ui.update_rate_limits)
        
    def _update_friends(self):
        '''Actualizar amigos'''
        self.api.get_friends(self.ui.update_friends)
        
    def signin(self, username, password):
        self.config = ConfigHandler(username)
        self.api.auth(username, password, self.__validate_signin)
        
    def signin_oauth(self, username, password, remember):
        self.remember = remember
        self.api.auth(username, password, self.__validate_credentials)
        
    def auth_token(self, pin):
        self.api.authorize_oauth_token(pin, self.__signin_done)
        
    def signout(self):
        '''Finalizar sesion'''
        self.save_muted_list()
        self.log.debug('Desconectando')
        exit(0)
        #self.httpserv.quit()
        #if self.profile: 
        #    self.api.end_session()
        #else:
        #    self.api.quit()
    
    def update_status(self, text, reply_id=None):
        if text.startswith('D '):
            self.api.update_status(text, reply_id, self.__direct_done)
        else:
            self.api.update_status(text, reply_id, self.__tweet_done)
        
    def destroy_status(self, tweet_id):
        self.api.destroy_status(tweet_id, self.ui.after_destroy)
        
    def set_favorite(self, tweet_id):
        self.api.set_favorite(tweet_id, self.ui.update_favorites)
        
    def unset_favorite(self, tweet_id):
        self.api.unset_favorite(tweet_id, self.ui.update_favorites)
    
    def retweet(self, tweet_id):
        self.api.retweet(tweet_id, self.ui.tweet_changed)
    
    def follow(self, user):
        self.api.follow(user, self.__done_follow)
        
    def unfollow(self, user):
        self.api.unfollow(user, self.__done_follow)
        
    def update_profile(self, new_name, new_url, new_bio, new_location):
        self.api.update_profile(new_name, new_url, new_bio, new_location,
            self.ui.update_user_profile)
    
    def in_reply_to(self, twt_id):
        self.api.in_reply_to(twt_id, self.ui.update_in_reply_to)
        
    def get_conversation(self, twt_id):
        self.api.get_conversation(twt_id, self.ui.update_conversation)
        
    def mute(self, user):
        self.ui.start_updating_timeline()
        self.api.mute(user, self.ui.update_timeline)
        
    def short_url(self, text, callback):
        service = self.config.read('Services', 'shorten-url')
        self.httpserv.short_url(service, text, callback)
    
    def download_user_pic(self, user, pic_url, callback):
        self.httpserv.download_pic(user, pic_url, callback)
        
    def upload_pic(self, path, callback):
        service = self.config.read('Services', 'upload-pic')
        self.httpserv.upload_pic(service, path, callback)
        
    def search_topic(self, query):
        self.ui.start_search()
        self.api.search_topic(query, self.ui.update_search_topics)
        
    def get_popup_info(self, tweet_id, user):
        if tweet_id in self.api.to_fav:
            return {'busy': 'Marcando favorito...'}
        elif tweet_id in self.api.to_unfav:
            return {'busy': 'Desmarcando favorito...'}
        elif tweet_id in self.api.to_del:
            return {'busy': 'Borrando...'}
            
        rtn = {}
        if self.api.friendsloaded:
            rtn['friend'] = self.api.is_friend(user)

        rtn['fav'] = self.api.is_fav(tweet_id)
        rtn['own'] = (self.profile['screen_name'] == user)
        
        return rtn
        
    def save_config(self, config, update):
        self.config.save(config)
        if update:
            self.ui.update_config(self.config)
            
    def save_global_config(self, config):
        self.global_cfg.save(config)
        
    def save_muted_list(self):
        if self.config:
            self.config.save_muted_list(self.api.muted_users)
        
    def get_muted_list(self):
        return self.api.get_muted_list()
            
    def update_muted(self, muted_users):
        self.ui.start_updating_timeline()
        timeline = self.api.mute(muted_users, self.ui.update_timeline)
        
    def destroy_direct(self, tweet_id):
        self.api.destroy_direct(tweet_id, self.ui.after_destroy)
        
    def get_friends(self):
        return self.api.get_single_friends_list()
Exemplo n.º 2
0
class Turpial:
    """Inicio de Turpial"""

    def __init__(self):
        ui_avail = "("
        for ui in INTERFACES:
            ui_avail += ui + "|"
        ui_avail = ui_avail[:-1] + ")"
        default_ui = INTERFACES[1] if len(INTERFACES) > 1 else ""

        parser = OptionParser()
        parser.add_option(
            "-d",
            "--debug",
            dest="debug",
            action="store_true",
            help="show debug info in shell during execution",
            default=False,
        )
        parser.add_option(
            "-i", "--interface", dest="interface", help="select interface to use %s" % ui_avail, default=default_ui
        )
        parser.add_option("-c", "--clean", dest="clean", action="store_true", help="clean all bytecodes", default=False)
        parser.add_option(
            "-s", "--save-credentials", dest="save", action="store_true", help="save user credentials", default=False
        )
        parser.add_option(
            "--version", dest="version", action="store_true", help="show the version of Turpial and exit", default=False
        )
        parser.add_option(
            "--test", dest="test", action="store_true", help="only load timeline and friends", default=False
        )
        parser.add_option(
            "--no-sound", dest="no_sound", action="store_true", help="disable the sounds module", default=False
        )
        parser.add_option(
            "--no-notif", dest="no_notif", action="store_true", help="disable the notifications module", default=False
        )

        (options, args) = parser.parse_args()

        self.config = None
        self.global_cfg = ConfigApp()
        self.protocol_cfg = {}
        self.profile = None
        self.testmode = options.test
        self.interface = options.interface
        self.no_sound = options.no_sound
        self.no_notif = options.no_notif
        self.httpserv = None
        self.api = None
        self.version = self.global_cfg.read("App", "version")

        for p in PROTOCOLS:
            self.protocol_cfg[p] = ConfigProtocol(p)

        if options.debug or options.clean:
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)
        self.log = logging.getLogger("Controller")

        if options.clean:
            self.__clean()
            sys.exit(0)

        if options.version:
            print "Turpial v%s" % self.version
            print "Python v%X" % sys.hexversion
            sys.exit(0)

        if options.save:
            try:
                self.__save_credentials()
            except KeyboardInterrupt:
                self.log.debug("Interceptado Keyboard Interrupt")
            sys.exit(0)

        self.interface = options.interface
        if options.interface == "gtk+" and ("gtk+" in INTERFACES):
            self.ui = _GTK(self, extend=True)
        elif options.interface == "gtk" and ("gtk" in INTERFACES):
            self.ui = _GTK(self)
        elif options.interface == "cmd" and ("cmd" in INTERFACES):
            self.ui = _CMD(self, args)
        else:
            print "No existe una interfaz válida. Las interfaces válidas son: %s" % INTERFACES
            print "Saliendo..."
            sys.exit(-1)

        self.httpserv = HTTPServices()
        self.api = TurpialAPI()

        self.log.debug("Iniciando Turpial v%s" % self.version)
        if self.interface != "cmd":
            self.httpserv.start()
        self.api.start()
        self.api.change_api_url(self.global_cfg.read("Proxy", "url"))

        if self.testmode:
            self.log.debug("Modo Pruebas Activado")

        self.ui.show_login()
        try:
            self.ui.main_loop()
        except KeyboardInterrupt:
            self.log.debug("Interceptado Keyboard Interrupt")
            self.ui.main_quit()

    def __clean(self):
        """Limpieza de ficheros .pyc y .pyo"""
        self.log.debug("Limpiando la casa...")
        path = os.path.join(os.path.dirname(__file__))
        i = 0
        for root, dirs, files in os.walk(path):
            for f in files:
                path = os.path.join(root, f)
                if path.endswith(".pyc") or path.endswith(".pyo"):
                    self.log.debug("Borrado %s" % path)
                    os.remove(path)

    def __save_credentials(self):
        print "This assistant will allow you store your credentials"
        print "Available protocols"
        print "==================="
        for i in range(len(PROTOCOLS)):
            print "%d - %s" % (i, PROTOCOLS[i])

        while 1:
            protocol = int(raw_input("Select protocol: "))
            if protocol <= len(PROTOCOLS):
                break
            else:
                print "Invalid protocol, please try again"

        user, passwd, rem = self.get_remembered(protocol)
        if user != "" and passwd != "":
            delete = raw_input("Delete your current credentials (%s)? [Y/n/q]: " % user)
            if delete == "" or delete.lower() == "y":
                self.remember(pro=protocol, rem=False)
                return
            elif delete.lower() == "q":
                return

        user = raw_input("User: "******"Password: "******"Retype password: "******"Password mismatch, please try again"
        self.remember(user, passwd, protocol, True)
        print "Credentials saved successfully"

    def __validate_credentials(self, val, key, secret, protocol):
        """Chequeo de credenciales"""
        if val.type == "error":
            self.ui.cancel_login(val.errmsg)
        elif val.type == "profile":
            self.profile = val.items
            self.config = ConfigHandler(self.profile.username, protocol)
            self.config.initialize()

            self.current_protocol = protocol
            self.httpserv.update_img_dir(self.config.imgdir)
            self.httpserv.set_credentials(self.profile.username, self.profile.password, self.api.protocol.http)

            self.__signin_done(key, secret, val)

    def __done_follow(self, response):
        user = response.items[1]
        follow = response.items[2]

        if response.type == "error":
            msg = response.errmsg % user
            self.ui.following_error(msg, follow)
        elif response.type == "mixed":
            self.profile = response.items[0]
            self.ui.update_user_profile(self.profile)
            self.ui.update_follow(user, follow)

    def __direct_done(self, status):
        self.ui.tweet_done(status)

    def __tweet_done(self, status):
        if status:
            self.profile.statuses_count += 1
            self.ui.update_user_profile(self.profile)
        self.ui.tweet_done(status)

    def __signin_done(self, key, secret, resp_profile):
        """Inicio de sesion finalizado"""

        # TODO: Llenar con el resto de listas
        self.lists = {
            "timeline": MicroBloggingList("timeline", "", _("Timeline"), _("tweet"), _("tweets")),
            "replies": MicroBloggingList("replies", "", _("Replies"), _("mention"), _("mentions")),
            "directs": MicroBloggingList("directs", "", _("Directs"), _("direct"), _("directs")),
            "sent": MicroBloggingList("sent", "", _("My Tweets"), _("tweet"), _("tweets")),
        }

        if self.interface != "cmd":
            plists = self.api.get_lists()
            for ls in plists:
                self.lists[str(ls.id)] = MicroBloggingList(str(ls.id), ls.user, ls.name, _("tweet"), _("tweets"))

        # Evita que la aplicación reviente si se borra una lista por fuera
        try:
            column1 = self.lists[self.config.read("Columns", "column1")]
        except KeyError:
            self.log.debug("La lista %s no existe. Se carga el Timeline" % self.config.read("Columns", "column1"))
            column1 = self.lists["timeline"]

        try:
            column2 = self.lists[self.config.read("Columns", "column2")]
        except KeyError:
            self.log.debug("La lista %s no existe. Se carga el Timeline" % self.config.read("Columns", "column2"))
            column2 = self.lists["timeline"]

        try:
            column3 = self.lists[self.config.read("Columns", "column3")]
        except KeyError:
            self.log.debug("La lista %s no existe. Se carga el Timeline" % self.config.read("Columns", "column3"))
            column3 = self.lists["timeline"]

        self.viewed_cols = [column1, column2, column3]

        self.api.protocol.muted_users = self.config.load_muted_list()
        self.ui.set_lists(self.lists, self.viewed_cols)
        self.ui.show_main(self.config, self.global_cfg, resp_profile)

        if self.interface == "cmd":
            return

        self._update_column1()
        if self.testmode:
            self._update_rate_limits()
            self._update_friends()
            return
        self._update_column2()
        self._update_column3()
        self._update_rate_limits()
        self._update_favorites()
        self._update_friends()

    def _update_column1(self):
        """Actualizar columna 1"""
        self.ui.start_updating_column1()
        count = int(self.config.read("General", "num-tweets"))
        column = self.viewed_cols[0]
        self.api.update_column(self.ui.update_column1, count, column)

    def _update_column2(self):
        """Actualizar columna 2"""
        self.ui.start_updating_column2()
        count = int(self.config.read("General", "num-tweets"))
        column = self.viewed_cols[1]
        self.api.update_column(self.ui.update_column2, count, column)

    def _update_column3(self):
        """Actualizar columna 3"""
        self.ui.start_updating_column3()
        count = int(self.config.read("General", "num-tweets"))
        column = self.viewed_cols[2]
        self.api.update_column(self.ui.update_column3, count, column)

    def _update_favorites(self):
        """Actualizar favoritos"""
        self.api.update_favorites(self.ui.update_favorites)

    def _update_rate_limits(self):
        self.api.update_rate_limits(self.ui.update_rate_limits)

    def _update_friends(self):
        """Actualizar amigos"""
        self.api.get_friends()

    def get_remembered(self, index):
        protocol = PROTOCOLS[index]
        us = self.protocol_cfg[protocol].read("Login", "username")
        pw = self.protocol_cfg[protocol].read("Login", "password")
        try:
            if us != "" and pw != "":
                a = base64.b64decode(pw)
                b = a[1:-1]
                c = base64.b32decode(b)
                d = c[1:-1]
                e = base64.b16decode(d)
                pwd = e[0 : len(us)] + e[len(us) :]
                return us, pwd, True
            else:
                return us, pw, False
        except TypeError:
            self.protocol_cfg[protocol].write("Login", "username", "")
            self.protocol_cfg[protocol].write("Login", "password", "")
            return "", "", False

    def remember(self, us="", pw="", pro=0, rem=False):
        protocol = PROTOCOLS[pro]
        if not rem:
            self.protocol_cfg[protocol].write("Login", "username", "")
            self.protocol_cfg[protocol].write("Login", "password", "")
            return

        a = base64.b16encode(pw)
        b = us[0] + a + ("%s" % us[-1])
        c = base64.b32encode(b)
        d = ("%s" % us[-1]) + c + us[0]
        e = base64.b64encode(d)
        pwd = e[0 : len(us)] + e[len(us) :]

        self.protocol_cfg[protocol].write("Login", "username", us)
        self.protocol_cfg[protocol].write("Login", "password", pwd)

    def signin(self, username, password, protocol):
        config = ConfigHandler(username, protocol)
        config.initialize_failsafe()
        auth = config.read_section("Auth")
        self.api.auth(username, password, auth, protocol, self.__validate_credentials)

    def signout(self):
        """Finalizar sesion"""
        self.save_muted_list()
        self.log.debug("Desconectando")
        if self.httpserv and self.interface != "cmd":
            self.httpserv.quit()
            self.httpserv.join(0)
        if self.api:
            self.api.quit()
            if self.interface != "cmd":
                self.api.join(0)
        sys.exit(0)

    def update_status(self, text, reply_id=None):
        if text.startswith("D "):
            self.api.update_status(text, reply_id, self.__direct_done)
        else:
            self.api.update_status(text, reply_id, self.__tweet_done)

    def destroy_status(self, id):
        self.api.destroy_status(id, self.ui.after_destroy_status)

    def set_favorite(self, id):
        self.api.set_favorite(id, self.ui.tweet_changed)

    def unset_favorite(self, id):
        self.api.unset_favorite(id, self.ui.tweet_changed)

    def repeat(self, id):
        self.api.repeat(id, self.__tweet_done)

    def follow(self, user):
        self.api.follow(user, self.__done_follow)

    def unfollow(self, user):
        self.api.unfollow(user, self.__done_follow)

    def update_profile(self, new_name, new_url, new_bio, new_location):
        self.api.update_profile(new_name, new_url, new_bio, new_location, self.ui.update_user_profile)

    def in_reply_to(self, id):
        self.api.in_reply_to(id, self.ui.update_in_reply_to)

    def get_conversation(self, id):
        self.api.get_conversation(id, self.ui.update_conversation)

    def mute(self, users):
        self.api.mute(users, self.ui.tweet_changed)

    def short_url(self, text, callback):
        service = self.config.read("Services", "shorten-url")
        self.httpserv.short_url(service, text, callback)

    def download_user_pic(self, user, pic_url, callback):
        self.httpserv.download_pic(user, pic_url, callback)

    def upload_pic(self, path, message, callback):
        service = self.config.read("Services", "upload-pic")
        self.httpserv.upload_pic(service, path, message, callback)

    def search(self, query):
        self.ui.start_search()
        self.api.search(query, self.ui.update_search)

    def get_popup_info(self, tweet_id, user):
        if self.api.is_marked_to_fav(tweet_id):
            return {"marking_fav": True}
        elif self.api.is_marked_to_unfav(tweet_id):
            return {"unmarking_fav": True}
        elif self.api.is_marked_to_del(tweet_id):
            return {"deleting": True}

        rtn = {}
        if self.api.friends_loaded():
            rtn["friend"] = self.api.is_friend(user)

        rtn["fav"] = self.api.is_fav(tweet_id)

        return rtn

    def save_config(self, config, update):
        self.config.save(config)
        if update:
            self.ui.update_config(self.config)

    def save_global_config(self, config):
        self.global_cfg.save(config)

    def save_muted_list(self):
        if self.config:
            self.config.save_muted_list(self.api.protocol.muted_users)

    def get_muted_list(self):
        return self.api.get_muted_list()

    def destroy_direct(self, id):
        self.api.destroy_direct(id, self.ui.after_destroy_direct)

    def get_friends(self):
        return self.api.get_single_friends_list()

    def get_hashtags_url(self):
        return self.api.protocol.tags_url

    def get_groups_url(self):
        return self.api.protocol.groups_url

    # FIXME: Debería pasarse como parámetro el protocolo
    def get_profiles_url(self):
        return self.api.protocol.profiles_url

    def get_viewed_columns(self):
        return self.viewed_cols

    def change_column(self, index, new_id):
        print "change_column", self.lists.keys(), index, new_id
        if self.lists.has_key(new_id):
            self.viewed_cols[index] = self.lists[new_id]
            if index == 0:
                self._update_column1()
            elif index == 1:
                self._update_column2()
            elif index == 2:
                self._update_column3()
        else:
            self.ui.set_column_item(index, reset=True)
            self.log.debug("Error: la columna %s no existe" % new_id)

    def is_friend(self, user):
        return self.api.is_friend(user)
Exemplo n.º 3
0
class Turpial:
    '''Inicio de Turpial'''
    def __init__(self):
        parser = OptionParser()
        parser.add_option('-d',
                          '--debug',
                          dest='debug',
                          action='store_true',
                          help='Debug Mode',
                          default=False)
        parser.add_option('-i',
                          '--interface',
                          dest='interface',
                          help='Select interface to use. (cmd|gtk)',
                          default='gtk')
        parser.add_option('-c',
                          '--clean',
                          dest='clean',
                          action='store_true',
                          help='Clean all bytecodes',
                          default=False)
        parser.add_option('--test',
                          dest='test',
                          action='store_true',
                          help='Test mode. Only load timeline',
                          default=False)

        (options, _) = parser.parse_args()

        self.config = None
        self.global_cfg = ConfigApp()
        self.profile = None
        self.remember = False
        self.testmode = options.test
        self.httpserv = None
        self.api = None

        if options.debug:
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)
        self.log = logging.getLogger('Controller')

        if options.clean:
            self.__clean()
            self.signout()

        self.interface = options.interface
        if options.interface == 'gtk+':
            self.ui = _GTK(self, extend=True)
        elif options.interface == 'gtk':
            self.ui = _GTK(self)
        else:
            print 'No existe tal interfaz. Saliendo...'
            sys.exit(-1)

        self.httpserv = HTTPServices()
        self.api = TurpialAPI()

        self.log.debug('Iniciando Turpial')
        self.httpserv.start()
        self.api.start()
        self.api.change_api_url(self.global_cfg.read('Proxy', 'url'))

        if self.testmode:
            self.log.debug('Modo Pruebas Activado')

        self.ui.show_login(self.global_cfg)
        self.ui.main_loop()

    def __clean(self):
        '''Limpieza de ficheros .pyc y .pyo'''
        self.log.debug("Limpiando la casa...")
        i = 0
        for root, dirs, files in os.walk('.'):
            for f in files:
                path = os.path.join(root, f)
                if path.endswith('.pyc') or path.endswith('.pyo'):
                    self.log.debug("Borrado %s" % path)
                    os.remove(path)

    def __validate_signin(self, val):
        '''Chequeo de inicio de sesion'''
        if val.has_key('error'):
            self.ui.cancel_login(val['error'])
        else:
            self.profile = val
            self.ui.update_user_profile(val)
            self.ui.show_main(self.config, self.global_cfg, val)

            self._update_timeline()
            if self.testmode: return
            self._update_replies()
            self._update_directs()
            self._update_favorites()
            self._update_rate_limits()

    def __validate_credentials(self, val):
        '''Chequeo de credenciales'''
        if val.has_key('error'):
            self.ui.cancel_login(val['error'])
        else:
            if self.api.has_oauth_support():
                self.api.validate_credentials(self.__signin_done)
            else:
                self.api.is_oauth = False
                self.__signin_done(None, None, None)

    def __done_follow(self, friends, profile, user, follow):
        self.ui.update_user_profile(profile)
        self.ui.update_friends(friends)
        self.ui.update_follow(user, follow)
        #self.ui.update_timeline(friends)

    def __direct_done(self, tweet):
        self.ui.tweet_done(tweet)

    def __tweet_done(self, tweet):
        if tweet:
            self.profile['statuses_count'] += 1
            self.ui.update_user_profile(self.profile)
        self.ui.tweet_done(tweet)

    def __signin_done(self, val):
        '''Inicio de sesion finalizado'''
        if val.has_key('error'):
            self.ui.cancel_login(val['error'])
        else:
            self.profile = val
            self.config = ConfigHandler(val['screen_name'])
            if self.remember:
                self.global_cfg.write('Login', 'username', self.api.username)
                self.global_cfg.write('Login', 'password',
                                      base64.b64encode(self.api.password))
            else:
                self.global_cfg.write('Login', 'username', '')
                self.global_cfg.write('Login', 'password', '')

            self.httpserv.update_img_dir(self.config.imgdir)
            self.httpserv.set_credentials(self.api.username, self.api.password)

            self.api.muted_users = self.config.load_muted_list()

            self.ui.show_main(self.config, self.global_cfg, self.profile)
            self._update_timeline()
            if self.testmode: return
            self._update_replies()
            self._update_directs()
            self._update_rate_limits()
            self._update_favorites()
            self._update_friends()

    def _update_timeline(self):
        '''Actualizar linea de tiempo'''
        self.ui.start_updating_timeline()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_timeline(self.ui.update_timeline, tweets)

    def _update_replies(self):
        '''Actualizar numero de respuestas'''
        self.ui.start_updating_replies()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_replies(self.ui.update_replies, tweets)

    def _update_directs(self):
        '''Actualizar mensajes directos'''
        self.ui.start_updating_directs()
        tweets = int(self.config.read('General', 'num-tweets'))
        self.api.update_directs(self.ui.update_directs, tweets)

    def _update_favorites(self):
        '''Actualizar favoritos'''
        self.api.update_favorites(self.ui.update_favorites)

    def _update_rate_limits(self):
        self.api.update_rate_limits(self.ui.update_rate_limits)

    def _update_friends(self):
        '''Actualizar amigos'''
        self.api.get_friends(self.ui.update_friends)

    def signin(self, username, password):
        self.config = ConfigHandler(username)
        self.api.auth(username, password, self.__validate_signin)

    def signin_oauth(self, username, password, remember):
        self.remember = remember
        self.api.auth(username, password, self.__validate_credentials)

    def auth_token(self, pin):
        self.api.authorize_oauth_token(pin, self.__signin_done)

    def signout(self):
        '''Finalizar sesion'''
        self.save_muted_list()
        self.log.debug('Desconectando')
        if self.httpserv:
            self.httpserv.quit()
            self.httpserv.join()
        if self.api:
            self.api.quit()
            self.api.join()
        sys.exit(0)

    def update_status(self, text, reply_id=None):
        if text.startswith('D '):
            self.api.update_status(text, reply_id, self.__direct_done)
        else:
            self.api.update_status(text, reply_id, self.__tweet_done)

    def destroy_status(self, tweet_id):
        self.api.destroy_status(tweet_id, self.ui.after_destroy)

    def set_favorite(self, tweet_id):
        self.api.set_favorite(tweet_id, self.ui.update_favorites)

    def unset_favorite(self, tweet_id):
        self.api.unset_favorite(tweet_id, self.ui.update_favorites)

    def retweet(self, tweet_id):
        self.api.retweet(tweet_id, self.ui.tweet_changed)

    def follow(self, user):
        self.api.follow(user, self.__done_follow)

    def unfollow(self, user):
        self.api.unfollow(user, self.__done_follow)

    def update_profile(self, new_name, new_url, new_bio, new_location):
        self.api.update_profile(new_name, new_url, new_bio, new_location,
                                self.ui.update_user_profile)

    def in_reply_to(self, twt_id):
        self.api.in_reply_to(twt_id, self.ui.update_in_reply_to)

    def get_conversation(self, twt_id):
        self.api.get_conversation(twt_id, self.ui.update_conversation)

    def mute(self, user):
        self.ui.start_updating_timeline()
        self.api.mute(user, self.ui.update_timeline)

    def short_url(self, text, callback):
        service = self.config.read('Services', 'shorten-url')
        self.httpserv.short_url(service, text, callback)

    def download_user_pic(self, user, pic_url, callback):
        self.httpserv.download_pic(user, pic_url, callback)

    def upload_pic(self, path, callback):
        service = self.config.read('Services', 'upload-pic')
        self.httpserv.upload_pic(service, path, callback)

    def search_topic(self, query):
        self.ui.start_search()
        self.api.search_topic(query, self.ui.update_search_topics)

    def get_popup_info(self, tweet_id, user):
        if tweet_id in self.api.to_fav:
            return {'busy': 'Marcando favorito...'}
        elif tweet_id in self.api.to_unfav:
            return {'busy': 'Desmarcando favorito...'}
        elif tweet_id in self.api.to_del:
            return {'busy': 'Borrando...'}

        rtn = {}
        if self.api.friendsloaded:
            rtn['friend'] = self.api.is_friend(user)

        rtn['fav'] = self.api.is_fav(tweet_id)
        rtn['own'] = (self.profile['screen_name'] == user)

        return rtn

    def save_config(self, config, update):
        self.config.save(config)
        if update:
            self.ui.update_config(self.config)

    def save_global_config(self, config):
        self.global_cfg.save(config)

    def save_muted_list(self):
        if self.config:
            self.config.save_muted_list(self.api.muted_users)

    def get_muted_list(self):
        return self.api.get_muted_list()

    def update_muted(self, muted_users):
        self.ui.start_updating_timeline()
        timeline = self.api.mute(muted_users, self.ui.update_timeline)

    def destroy_direct(self, tweet_id):
        self.api.destroy_direct(tweet_id, self.ui.after_destroy)

    def get_friends(self):
        return self.api.get_single_friends_list()
Exemplo n.º 4
0
class Turpial:
    '''Inicio de Turpial'''
    def __init__(self):
        ui_avail = '('
        for ui in INTERFACES:
            ui_avail += ui + '|'
        ui_avail = ui_avail[:-1] + ')'
        default_ui = INTERFACES[1] if len(INTERFACES) > 1 else ''
        
        parser = OptionParser()
        parser.add_option('-d', '--debug', dest='debug', action='store_true',
            help='show debug info in shell during execution', default=False)
        parser.add_option('-i', '--interface', dest='interface',
            help='select interface to use %s' % ui_avail, default=default_ui)
        parser.add_option('-c', '--clean', dest='clean', action='store_true',
            help='clean all bytecodes', default=False)
        parser.add_option('-s', '--save-credentials', dest='save', action='store_true',
            help='save user credentials', default=False)
        parser.add_option('--version', dest='version', action='store_true',
            help='show the version of Turpial and exit', default=False)
        parser.add_option('--test', dest='test', action='store_true',
            help='only load timeline and friends', default=False)
        parser.add_option('--no-sound', dest='no_sound', action='store_true',
            help='disable the sounds module', default=False)
        parser.add_option('--no-notif', dest='no_notif', action='store_true',
            help='disable the notifications module', default=False)
        
        (options, args) = parser.parse_args()
        
        self.config = None
        self.global_cfg = ConfigApp()
        self.protocol_cfg = {}
        self.profile = None
        self.testmode = options.test
        self.interface = options.interface
        self.no_sound = options.no_sound
        self.no_notif = options.no_notif
        self.httpserv = None
        self.api = None
        self.version = self.global_cfg.read('App', 'version')
        
        for p in PROTOCOLS:
            self.protocol_cfg[p] = ConfigProtocol(p)
        
        if options.debug or options.clean: 
            logging.basicConfig(level=logging.DEBUG)
        else:
            logging.basicConfig(level=logging.INFO)
        self.log = logging.getLogger('Controller')
        
        if options.clean:
            self.__clean()
            sys.exit(0)
            
        if options.version:
            print "Turpial v%s" % self.version
            print "Python v%X" % sys.hexversion
            sys.exit(0)
            
        if options.save:
            try:
                self.__save_credentials()
            except KeyboardInterrupt:
                self.log.debug('Interceptado Keyboard Interrupt')
            sys.exit(0)
            
        self.interface = options.interface
        if options.interface == 'gtk+' and ('gtk+' in INTERFACES):
            self.ui = _GTK(self, extend=True)
        elif options.interface == 'gtk' and ('gtk' in INTERFACES):
            self.ui = _GTK(self)
        elif options.interface == 'cmd' and ('cmd' in INTERFACES):
            self.ui = _CMD(self, args)
        else:
            print 'No existe una interfaz válida. Las interfaces válidas son: %s' % INTERFACES
            print 'Saliendo...'
            sys.exit(-1)
        
        self.httpserv = HTTPServices()
        self.api = TurpialAPI()
        
        self.log.debug('Iniciando Turpial v%s' % self.version)
        if self.interface  != 'cmd':
            self.httpserv.start()
        self.api.start()
        self.api.change_api_url(self.global_cfg.read('Proxy', 'url'))
        
        if self.testmode:
            self.log.debug('Modo Pruebas Activado')
            
        self.ui.show_login()
        try:
            self.ui.main_loop()
        except KeyboardInterrupt:
            self.log.debug('Interceptado Keyboard Interrupt')
            self.ui.main_quit()
        
    def __clean(self):
        '''Limpieza de ficheros .pyc y .pyo'''
        self.log.debug("Limpiando la casa...")
        path = os.path.join(os.path.dirname(__file__))
        i = 0
        for root, dirs, files in os.walk(path):
            for f in files:
                path = os.path.join(root, f)
                if path.endswith('.pyc') or path.endswith('.pyo'): 
                    self.log.debug("Borrado %s" % path)
                    os.remove(path)
            
    def __save_credentials(self):
        print "This assistant will allow you store your credentials"
        print "Available protocols"
        print "==================="
        for i in range(len(PROTOCOLS)):
            print "%d - %s" % (i, PROTOCOLS[i])
        
        while 1:
            protocol = int(raw_input("Select protocol: "))
            if protocol <= len(PROTOCOLS):
                break
            else:
                print "Invalid protocol, please try again"
        
        user, passwd, rem = self.get_remembered(protocol)
        if user != '' and passwd != '':
            delete = raw_input("Delete your current credentials (%s)? [Y/n/q]: " %
                user)
            if delete == '' or delete.lower() == 'y':
                self.remember(pro=protocol, rem=False)
                return
            elif delete.lower() == 'q':
                return
        
        user = raw_input("User: "******"Password: "******"Retype password: "******"Password mismatch, please try again"
        self.remember(user, passwd, protocol, True)
        print "Credentials saved successfully"
        
    def __validate_credentials(self, val):
        '''Chequeo de credenciales'''
        if val.type == 'error':
            self.ui.cancel_login(val.errmsg)
        elif val.type == 'profile':
            self.profile = val.items
            self.config = ConfigHandler(self.profile.username, self.current_protocol)
            self.config.initialize()
            
            if self.tmp_key is not None:
                self.config.write('Auth', 'oauth-key', self.tmp_key)
            if self.tmp_secret is not None:
                self.config.write('Auth', 'oauth-secret', self.tmp_secret)
            if self.tmp_verifier is not None:
                self.config.write('Auth', 'oauth-verifier', self.tmp_verifier)
            
            self.httpserv.update_img_dir(self.config.imgdir)
            self.httpserv.set_credentials(self.profile.username, 
                self.profile.password, self.api.protocol.http)
            
            self.__signin_done()
        
    def __validate_token(self, val):
        if val.type == 'auth-done':
            token = val.items
            self.__save_oauth_token(token.key, token.secret, token.verifier)
        elif val.type == 'auth-token':
            self.ui.show_oauth_pin_request(val.items)
        
    def __save_oauth_token(self, key, secret, verifier):
        self.tmp_key = key
        self.tmp_secret = secret
        self.tmp_verifier = verifier
        auth = self.config.read_section('Auth')
        self.api.auth(self.tmp_username, self.tmp_passwd, auth, 
            self.__validate_credentials)
        
    def __done_follow(self, response):
        user = response.items[1]
        follow = response.items[2]
        
        if response.type == 'error':
            msg = response.errmsg % user
            self.ui.following_error(msg, follow)
        elif response.type == 'mixed':
            self.profile = response.items[0]
            self.ui.update_user_profile(self.profile)
            self.ui.update_follow(user, follow)
        
    def __direct_done(self, status):
        self.ui.tweet_done(status)
        
    def __tweet_done(self, status):
        if status:
            self.profile.statuses_count += 1
            self.ui.update_user_profile(self.profile)
        self.ui.tweet_done(status)
        
    def __signin_done(self):
        '''Inicio de sesion finalizado'''
        resp_profile = self.profile
            
        # TODO: Llenar con el resto de listas
        self.lists = {
            'timeline': MicroBloggingList('timeline', '', _('Timeline'),
                _('tweet'), _('tweets')),
            'replies': MicroBloggingList('replies', '', _('Replies'),
                _('mention'), _('mentions')),
            'directs': MicroBloggingList('directs', '', _('Directs'),
                _('direct'), _('directs')),
            'sent': MicroBloggingList('sent', '', _('My Tweets'), 
                _('tweet'), _('tweets')),
        }
        
        if self.interface  != 'cmd':
            plists = self.api.get_lists()
            for ls in plists:
                self.lists[str(ls.id)] = MicroBloggingList(str(ls.id), ls.user, 
                    ls.name, _('tweet'), _('tweets'))
        
        # Evita que la aplicación reviente si se borra una lista por fuera
        try:
            column1 = self.lists[self.config.read('Columns', 'column1')]
        except KeyError:
            self.log.debug('La lista %s no existe. Se carga el Timeline' % 
                self.config.read('Columns', 'column1'))
            column1 = self.lists['timeline']
        
        try:
            column2 = self.lists[self.config.read('Columns', 'column2')]
        except KeyError:
            self.log.debug('La lista %s no existe. Se carga el Timeline' % 
                self.config.read('Columns', 'column2'))
            column2 = self.lists['timeline']
            
        try:
            column3 = self.lists[self.config.read('Columns', 'column3')]
        except KeyError:
            self.log.debug('La lista %s no existe. Se carga el Timeline' % 
                self.config.read('Columns', 'column3'))
            column3 = self.lists['timeline']
            
        self.viewed_cols = [column1, column2, column3]
        
        self.api.protocol.muted_users = self.config.load_muted_list()
        self.api.protocol.filtered_terms = self.config.load_filtered_list()
        self.ui.set_lists(self.lists, self.viewed_cols)
        self.ui.show_main(self.config, self.global_cfg, resp_profile)
        
        if self.interface  == 'cmd':
            return
        
        self._update_column1()
        if self.testmode:
            self._update_rate_limits()
            self._update_friends()
            return
        self._update_column2()
        self._update_column3()
        self._update_rate_limits()
        self._update_favorites()
        self._update_friends()
        
    def _update_column1(self):
        '''Actualizar columna 1'''
        self.ui.start_updating_column1()
        count = int(self.config.read('General', 'num-tweets'))
        column = self.viewed_cols[0]
        self.api.update_column(self.ui.update_column1, count, column)
        
    def _update_column2(self):
        '''Actualizar columna 2'''
        self.ui.start_updating_column2()
        count = int(self.config.read('General', 'num-tweets'))
        column = self.viewed_cols[1]
        self.api.update_column(self.ui.update_column2, count, column)
        
    def _update_column3(self):
        '''Actualizar columna 3'''
        self.ui.start_updating_column3()
        count = int(self.config.read('General', 'num-tweets'))
        column = self.viewed_cols[2]
        self.api.update_column(self.ui.update_column3, count, column)
        
    def _update_favorites(self):
        '''Actualizar favoritos'''
        self.api.update_favorites(self.ui.update_favorites)
    
    def _update_rate_limits(self):
        self.api.update_rate_limits(self.ui.update_rate_limits)
        
    def _update_friends(self):
        '''Actualizar amigos'''
        self.api.get_friends()
    
    def get_remembered(self, index):
        protocol = PROTOCOLS[index]
        us = self.protocol_cfg[protocol].read('Login', 'username')
        pw = self.protocol_cfg[protocol].read('Login', 'password')
        au = self.global_cfg.read('Startup', 'autologin')
        try:
            if au == 'on':
                auto = True
            else:
                auto = False
            if us != '' and pw != '':
                a = base64.b64decode(pw)
                b = a[1:-1]
                c = base64.b32decode(b)
                d = c[1:-1]
                e = base64.b16decode(d)
                pwd = e[0:len(us)]+ e[len(us):]
                return us, pwd, True, auto
            else:
                return us, pw, False, False
        except TypeError:
            self.protocol_cfg[protocol].write('Login', 'username','')
            self.protocol_cfg[protocol].write('Login', 'password','')
            self.global_cfg.write('Startup', 'autologin', 'off')
            return '', '', False, False
        
    def remember(self, us='', pw='', pro=0, rem=False, auto=False):
        protocol = PROTOCOLS[pro]
        if not rem:
            self.protocol_cfg[protocol].write('Login', 'username', '')
            self.protocol_cfg[protocol].write('Login', 'password', '')
            return
            
        a = base64.b16encode(pw)
        b = us[0] + a + ('%s' % us[-1])
        c = base64.b32encode(b)
        d = ('%s' % us[-1]) + c + us[0]
        e = base64.b64encode(d)
        pwd = e[0:len(us)]+ e[len(us):]
        
        self.protocol_cfg[protocol].write('Login', 'username', us)
        self.protocol_cfg[protocol].write('Login', 'password', pwd)
        if auto:
            self.global_cfg.write('Startup', 'autologin', 'on')
        else:
            self.global_cfg.write('Startup', 'autologin', 'off')
            
    def signin(self, username, password, protocol):
        self.config = ConfigHandler(username, protocol)
        self.config.initialize_failsafe()
        auth = self.config.read_section('Auth')
        self.tmp_username = username
        self.tmp_passwd = password
        self.current_protocol = protocol
        self.api.start_oauth(auth, protocol, self.__validate_token)
    
    def auth_token(self, pin):
        print 'PIN', pin
        self.api.authorize_oauth_token(pin, self.__save_oauth_token)
        
    def signout(self):
        '''Finalizar sesion'''
        self.save_muted_list()
        self.save_filtered_list()
        self.log.debug('Desconectando')
        if self.httpserv and self.interface  != 'cmd':
            self.httpserv.quit()
            self.httpserv.join(0)
        if self.api: 
            self.api.quit()
            if self.interface  != 'cmd':
                self.api.join(0)
        sys.exit(0)
    
    def update_status(self, text, reply_id=None):
        if text.startswith('D '):
            self.api.update_status(text, reply_id, self.__direct_done)
        else:
            self.api.update_status(text, reply_id, self.__tweet_done)
        
    def destroy_status(self, id):
        self.api.destroy_status(id, self.ui.after_destroy_status)
        
    def set_favorite(self, id):
        self.api.set_favorite(id, self.ui.tweet_changed)
        
    def unset_favorite(self, id):
        self.api.unset_favorite(id, self.ui.tweet_changed)
    
    def repeat(self, id):
        self.api.repeat(id, self.__tweet_done)
    
    def follow(self, user):
        self.api.follow(user, self.__done_follow)
        
    def unfollow(self, user):
        self.api.unfollow(user, self.__done_follow)
        
    def update_profile(self, new_name, new_url, new_bio, new_location):
        self.api.update_profile(new_name, new_url, new_bio, new_location,
            self.ui.update_user_profile)
    
    def in_reply_to(self, id):
        self.api.in_reply_to(id, self.ui.update_in_reply_to)
        
    def get_conversation(self, id):
        self.api.get_conversation(id, self.ui.update_conversation)
    
    def mute(self, users):
        self.api.mute(users, self.ui.tweet_changed)

    def filter_term(self, term):
        self.api.filter_term(term, self.ui.tweet_changed)
    
    def short_url(self, text, callback):
        service = self.config.read('Services', 'shorten-url')
        self.httpserv.short_url(service, text, callback)

    def expand_url(self, url, callback):
        self.httpserv.expand_url(url, callback)
    
    def download_user_pic(self, user, pic_url, callback):
        self.httpserv.download_pic(user, pic_url, callback)
        
    def upload_pic(self, path, message, callback):
        service = self.config.read('Services', 'upload-pic')
        self.httpserv.upload_pic(service, path, message, callback)
        
    def search(self, query):
        self.ui.start_search()
        self.api.search(query, self.ui.update_search)
        
    def get_popup_info(self, tweet_id, user):
        if self.api.is_marked_to_fav(tweet_id):
            return {'marking_fav': True}
        elif self.api.is_marked_to_unfav(tweet_id):
            return {'unmarking_fav': True}
        elif self.api.is_marked_to_del(tweet_id):
            return {'deleting': True}
            
        rtn = {}
        if self.api.friends_loaded():
            rtn['friend'] = self.api.is_friend(user)

        rtn['fav'] = self.api.is_fav(tweet_id)
        
        return rtn
        
    def save_config(self, config, update):
        self.config.save(config)
        if update:
            self.ui.update_config(self.config)
            
    def save_global_config(self, config):
        self.global_cfg.save(config)
        
    def save_muted_list(self):
        if self.config:
            self.config.save_muted_list(self.api.protocol.muted_users)
        
    def get_muted_list(self):
        return self.api.get_muted_list()
        
    def save_filtered_list(self):
        if self.config:
            self.config.save_filtered_list(self.api.protocol.filtered_terms)
        
    def get_filtered_list(self):
        return self.api.get_filtered_list()

    def destroy_direct(self, id):
        self.api.destroy_direct(id, self.ui.after_destroy_direct)
        
    def get_friends(self):
        return self.api.get_single_friends_list()
        
    def get_hashtags_url(self):
        return self.api.protocol.tags_url
        
    def get_groups_url(self):
        return self.api.protocol.groups_url
        
    # FIXME: Debería pasarse como parámetro el protocolo
    def get_profiles_url(self):
        return self.api.protocol.profiles_url
        
    def get_viewed_columns(self):
        return self.viewed_cols
        
    def change_column(self, index, new_id):
        print 'change_column', self.lists.keys(), index, new_id
        if self.lists.has_key(new_id):
            self.viewed_cols[index] = self.lists[new_id]
            if index == 0:
                self.ui.home.timeline.clear()
                self._update_column1()
            elif index == 1:
                self.ui.home.replies.clear()
                self._update_column2()
            elif index == 2:
                self.ui.home.direct.clear()
                self._update_column3()
        else:
            self.ui.set_column_item(index, reset=True)
            self.log.debug('Error: la columna %s no existe' % new_id)
            
    def is_friend(self, user):
        return self.api.is_friend(user)