Source

comofas / comofas_answers.py

Full commit
# -*- 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.

from pynswers.Answers import Answers

import urllib
import urllib2
import string
import random
import re
import simplejson
import sys
import logging
import cPickle as pickle
import os
import traceback

from comofas_credentials import *
from comofas_settings import *

class ComofasAnswers(object):
    """
    Esta classe encontra a resposta e atualiza o arquivo de persistencia com as respostas
    """
    def __init__(self, answers_connection=None):
    
        self.answers_connection = answers_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 clean_text(self,txt):
        """
        vou falar o obvio: este metodo limpa o texto
        """
        pergunta = string.lower(txt)
        
        #pergunta = re.sub('#\w+',' ', txt)
        pergunta = re.sub('@\w+',' ', pergunta)

        pergunta = pergunta.replace(KEYWORD,' ')
        
        s=string.find(pergunta,'http://')
        if s != -1:
            t = string.find(pergunta[s+7:], " ")
            pergunta = string.replace(pergunta,pergunta[s:t+s+7],' ')

        replacements = [(u'é','e'),(u'á','a'),(u'í','i'),(u'ó','o'),(u'ú','u'),(u'â','a'),(u'ê','e'),(u'ô','o'),(u'ã','a'),(u'õ','o'),(u'ç','c')]

        for a, b in replacements:
            pergunta = pergunta.replace(a, b)
        for punct in string.punctuation:
            pergunta = pergunta.replace(punct, ' ')

        pergunta = re.sub('\n',' ', pergunta)
        pergunta = re.sub('\s\s',' ', pergunta)

        pergunta = string.joinfields(pergunta.split(), ' OR ')

        return pergunta.encode("utf-8")

    def nao_entendi(self,usuario):
        """
        este metodo pede que o usuario pergunte de outra forma
        """
        nao_entendi_lista=[u"Não entendi mt bem, vc poderia me explicar?",u"Vc poderia explicar melhor?", u"Hã? Repete aí, mas fala diferente."]
        mensagem = self.build_message(to_user=usuario, raw_answer=nao_entendi_lista[random.randint(0,len(nao_entendi_lista)-1)])
        status = "sem status"
        try:
            status = self.twitter_connection.PostUpdate(mensagem)
        except urllib2.HTTPError:
            logging.debug("answer exception:" + str(traceback.print_exc()))
        print '-' * 50
        print "twitter.fasassim(nao entendi) postUpdate: %s - status:%s" % (mensagem,status)

    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','se','que','como','porque']
        a = raw_answer[:last].split()
        while a[-1] in dispensaveis:
            a.pop(-1)
        return "%s%s" % (msg, " ".join(a))

    
    def answer_tweets(self):
        """
        este metodo busca as perguntas do twitter, limpa o texto e processa a
        resposta para cada pergunta UMA única vez

        """
        try:
            for question in self.persisted_questions:
                #Detecta se a pergunta já foi respondida
                try:
                    if question['answered'] == True:                
                        continue
                except KeyError:
                    question['answered'] = False
                cleaned_question = self.clean_text(question['text'])                
                
                try:
                    answer = self.answers_connection.questionSearch({'query':cleaned_question, 'search_in':'question', 'region': REGION, 'type':'resolved', 'results':'1'})
                except urllib2.HTTPError:
                    logging.debug("answer exception:" + str(traceback.print_exc()))
                    continue
                try:    
                    question['answered'] = True
                    question['answer'] = answer[0]
                    question['twittered'] = False
                    
                    if DEBUG: print question                   

                except IndexError:
                    logging.debug("answer exception:" + str(traceback.print_exc()))
                    continue
            self.persist_questions()

        except KeyboardInterrupt:
            self.persist_questions()
            sys.exit(1)


if __name__=='__main__':
    answers = Answers()
    answers.appid = answers_appid

    comofas = ComofasAnswers(answers_connection = answers)
    comofas.answer_tweets()