comofas / comofas_twitterer.py

# -*- coding: utf-8 -*-

# Comofas - everyone deserves an answer from Yahoo!Answers and Twitter
# Yahoo!Answers and Twitter are trademarks from Yahoo! Inc and Twitter respectively.
#
#Copyright (C) 2008  Pedro Valente
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import urllib
import re
import simplejson
import sys
import logging
import cPickle as pickle
import os
import traceback

from twitter import twitter
from comofas_credentials import *
from comofas_settings import *


class ComofasTwitterer(object):
    """
    Esta classe cuida apenas formatar a resposta e mandar pro usuário via twitter
    """
    def __init__(self,twitter_connection=None):
        """
        o twitter_connection pode ser substituido por outra classe
        para executar testes offline.
        """
        self.twitter_connection = twitter_connection

        

        logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)

        if PICKLE_FILENAME in os.listdir('.'):
            self.picklefd = open(PICKLE_FILENAME,"rb")
            try:
                self.persisted_questions = pickle.load(self.picklefd)
            except EOFError:
                self.persisted_questions = []
            finally:
                self.picklefd.close()
        else:
            self.picklefd =open(PICKLE_FILENAME,'wb')
            pickle.dump(self.persisted_questions,self.picklefd)
            self.picklefd.close()
            self.picklefd =open(PICKLE_FILENAME,'wb')
            self.persisted_questions = pickle.load(self.picklefd)
            self.picklefd.close()
        
        

    def persist_questions(self):
        self.picklefd =open(PICKLE_FILENAME,"wb")
        pickle.dump(self.persisted_questions,self.picklefd)
        self.picklefd.close()


    def build_message(self,to_user, raw_answer):
        """
        este metodo:
        remove palavras que nao ficam bem no final da frase.
        limita o tamanho da frase
        """
        chars = 140
        msg = "@%s " % to_user
        chars = chars - len(msg)
        if len(raw_answer) < chars:
            return "%s%s" % (msg, raw_answer)
        last = 0
        for indice, c in enumerate(raw_answer):
            if indice > chars:
                break
            if c == " ":
                last = indice
        # Lista de palavras que não ficam bem no fim da frase.
        dispensaveis = ['e','a','o','de','da','do','na','no','para','pra','mas',
                        'em', u'até', 'se','que','como','porque', ',',':']
        a = raw_answer[:last].split()
        while a[-1] in dispensaveis:
            a.pop(-1)
        
        return "%s%s" % (msg, " ".join(a))

    def add_new_friends(self):
        added_friends = list()
        try:
            added_friends = self.twitter_connection.GetFriends()
            for friend in added_friends:
                if not self.last_users.has_key(friend.name) and friend.name != 'fasassim':
                    try:
                        self.twitter_connection.CreateFriendship(friend)
                        print "twitter.fasassim.following %s" % friend.name
                        self.last_users.pop(friend.name)
                    except:
                        print "cannot create friendship for " + friend.name
        except urllib2.HTTPError:
            logging.debug("answer exception:" + str(traceback.print_exc()))
        finally:
            self.last_users = dict()

    def post_tweets(self):
        """
        este metodo processa cada resposta e envia ao usuário
        faz isso com apenas 3 por vez
        """
        try:      
            contador_de_posts = 0
            
            fasassim_timeline =self.twitter_connection.GetUserTimeline(TWITTER_USERNAME)
            fasassim_updates = [ up.text for up in fasassim_timeline ]
          
            for question in self.persisted_questions:
                try:
                # Estabelece que a pergunta tenha uma resposta
                # Ignora o que ainda não foi processado
                    if question['answered'] == False:                
                        continue
                except KeyError:
                    continue
                
                try:
                    if question['twittered'] == True:
                        continue
                except KeyError:
                    question['twittered'] = False
                
                # Beleza, temos uma pergunta respondida e não tuitada.
                # Vamos em frente
                
                if contador_de_posts <= (NUMBER_OF_TWEETS - 1):
                    
                    to_user = question['from_user']
                    raw_answer = question['answer']['ChosenAnswer']
                    update = self.build_message(to_user, raw_answer)
                    
                    # Salvaguarda antes de mandar, vamos checar se nos últimos
                    # updates o fasassim já mandou um tweet idêntico.
                    # Se tiver mandado, aborta o post e atualiza a persistencia

                    if not update in fasassim_updates:
                        if not DEBUG:
                            status = self.twitter_connection.PostUpdate(update)
                    if not DEBUG: question['twittered'] = True
                    question['posted_tweet'] = update                    
                    contador_de_posts = contador_de_posts + 1
                    
                    if DEBUG: print update
                else:
                    if DEBUG: print "Fica para a próxima iteração"
            self.persist_questions()
                   
        except KeyboardInterrupt:
            self.persist_questions()
            sys.exit(1)
        

if __name__=='__main__':
    twitter_api = twitter.Api(username=TWITTER_USERNAME, password=TWITTER_PASSWORD)

    comofas = ComofasTwitterer(twitter_connection = twitter_api)
    comofas.post_tweets()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.