File size: 9,809 Bytes
dd9cc55
f3b1ac7
aeb2715
3251884
 
7384c00
 
 
e6a37ce
 
 
 
 
7384c00
 
 
 
 
 
 
e6a37ce
 
 
7384c00
 
5083bb3
7384c00
 
e6a37ce
 
 
 
 
 
 
 
 
 
7384c00
e6a37ce
7384c00
e6a37ce
 
 
 
 
 
 
 
 
 
7384c00
 
 
 
 
 
 
 
 
3251884
5083bb3
 
e6a37ce
 
5083bb3
e6a37ce
 
5083bb3
 
 
 
 
 
 
3251884
5083bb3
 
 
 
e6a37ce
5083bb3
e6a37ce
3251884
5083bb3
e6a37ce
fb0b40b
e6a37ce
 
5083bb3
 
 
 
 
81a43fe
5083bb3
 
 
 
 
 
 
81a43fe
5083bb3
dd9cc55
e6a37ce
 
 
 
9f422c2
e6a37ce
 
 
 
 
 
f5949bf
5083bb3
e6a37ce
 
 
5083bb3
 
e6a37ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5083bb3
 
 
e6a37ce
f3b1ac7
 
5083bb3
f3b1ac7
 
 
5083bb3
3251884
5083bb3
 
 
 
f3b1ac7
 
 
 
 
 
 
 
 
5083bb3
 
 
 
 
 
 
 
 
7384c00
e6a37ce
 
5083bb3
 
 
7384c00
5083bb3
 
e6a37ce
5083bb3
 
 
 
 
 
 
 
 
 
e6a37ce
 
5083bb3
 
 
 
 
 
 
 
 
 
e6a37ce
7384c00
5083bb3
7384c00
e6a37ce
7384c00
 
e6a37ce
3251884
 
e6a37ce
3251884
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6a37ce
3251884
 
 
 
 
 
 
 
 
 
e6a37ce
aeb2715
5083bb3
 
e6a37ce
 
5083bb3
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
import tweepy
from transformers import pipeline, GPT2LMHeadModel, GPT2Tokenizer, AutoModelForSequenceClassification, AutoTokenizer
import os
import streamlit as st
from datetime import datetime
import time
from tenacity import retry, stop_after_attempt, wait_exponential

def debug_print(message):
    """Função para imprimir mensagens de debug tanto no console quanto no Streamlit"""
    print(message)
    st.text(message)

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=4, max=10),
    retry=lambda e: isinstance(e, tweepy.errors.TooManyRequests)
)
def fetch_tweets(client, query, tweet_fields):
    try:
        debug_print(f"Iniciando busca com query: {query}")
        debug_print(f"Campos solicitados: {tweet_fields}")
        
        tweets = client.search_recent_tweets(
            query=query,
            max_results=10,
            tweet_fields=tweet_fields
        )
        
        if tweets is None:
            debug_print("Nenhum resultado retornado da API")
            return None
            
        if not hasattr(tweets, 'data'):
            debug_print("Resposta não contém dados")
            return None
            
        debug_print(f"Tweets encontrados: {len(tweets.data) if tweets.data else 0}")
        return tweets
        
    except tweepy.errors.TooManyRequests as e:
        debug_print(f"Rate limit atingido: {str(e)}")
        raise e
    except tweepy.errors.TwitterServerError as e:
        debug_print(f"Erro do servidor Twitter: {str(e)}")
        raise e
    except tweepy.errors.BadRequest as e:
        debug_print(f"Erro na requisição: {str(e)}")
        raise e
    except Exception as e:
        debug_print(f"Erro inesperado na busca: {str(e)}")
        raise e

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=4, max=10),
    retry=lambda e: isinstance(e, tweepy.errors.TooManyRequests)
)
def post_tweet(api, text):
    return api.update_status(status=text)

def main():
    try:
        st.title("Análise de Sentimentos - BBB25")
        
        # Verificar variáveis de ambiente
        debug_print("Verificando variáveis de ambiente...")
        
        required_vars = [
            'TWITTER_API_KEY',
            'TWITTER_API_SECRET_KEY',
            'TWITTER_ACCESS_TOKEN',
            'TWITTER_ACCESS_TOKEN_SECRET',
            'TWITTER_BEARER_TOKEN'
        ]

        missing_vars = []
        for var in required_vars:
            if os.getenv(var) is None:
                missing_vars.append(var)
                debug_print(f"Erro: A variável de ambiente '{var}' não está definida.")
            else:
                debug_print(f"{var} carregada com sucesso.")

        if missing_vars:
            raise ValueError(f"Variáveis de ambiente faltando: {', '.join(missing_vars)}")

        debug_print("Iniciando autenticação com Twitter...")
        
        # Autenticação com Twitter para leitura
        client = tweepy.Client(
            bearer_token=os.getenv('TWITTER_BEARER_TOKEN'),
            wait_on_rate_limit=True
        )

        # Autenticação com Twitter para postagem
        auth = tweepy.OAuth1UserHandler(
            os.getenv('TWITTER_API_KEY'),
            os.getenv('TWITTER_API_SECRET_KEY'),
            os.getenv('TWITTER_ACCESS_TOKEN'),
            os.getenv('TWITTER_ACCESS_TOKEN_SECRET')
        )

        api = tweepy.API(auth, wait_on_rate_limit=True)

        # Vamos testar a autenticação com uma query simples
        debug_print("Testando autenticação...")
        try:
            test_query = "test"
            test_response = client.search_recent_tweets(query=test_query, max_results=10)
            debug_print("Teste de autenticação bem sucedido")
        except Exception as e:
            debug_print(f"Erro no teste de autenticação: {str(e)}")
            raise e

        # Query principal
        query = 'BBB25 lang:pt -is:retweet -is:reply'
        tweet_fields = ['text', 'created_at', 'lang', 'public_metrics']
        
        debug_print("Iniciando busca principal de tweets...")
        
        with st.spinner('Buscando tweets...'):
            tweets = fetch_tweets(client, query, tweet_fields)
            
            if tweets is None:
                st.error("Não foi possível obter tweets")
                return
            
            if not tweets.data:
                st.warning("Nenhum tweet encontrado com os critérios especificados")
                debug_print("Busca retornou vazia")
                return
            
            debug_print(f"Encontrados {len(tweets.data)} tweets")
            
            # Mostrar alguns tweets encontrados para debug
            st.subheader("Tweets encontrados (preview):")
            for i, tweet in enumerate(tweets.data[:3]):
                st.text(f"Tweet {i+1}: {tweet.text[:100]}...")

        # Análise de sentimentos
        with st.spinner('Analisando sentimentos...'):
            debug_print("Iniciando análise de sentimentos...")
            
            # Inicializando o pipeline com modelo em português
            sentiment_pipeline = pipeline(
                "sentiment-analysis",
                model="pierreguillou/bert-base-cased-gs-sentiment-pt",
                tokenizer="pierreguillou/bert-base-cased-gs-sentiment-pt"
            )
            
            sentiments = []
            for tweet in tweets.data:
                if hasattr(tweet, 'lang') and tweet.lang == 'pt':
                    result = sentiment_pipeline(tweet.text)
                    # Mapeando os resultados para positive/negative/neutral
                    label = result[0]['label']
                    if label == 'POSITIVE':
                        sentiments.append('positive')
                    elif label == 'NEGATIVE':
                        sentiments.append('negative')
                    else:
                        sentiments.append('neutral')
                    debug_print(f"Sentimento analisado: {label}")
                    
            time.sleep(1)
                
        # Calcular taxas
        if sentiments:
            positive = sentiments.count('positive')
            negative = sentiments.count('negative')
            neutral = sentiments.count('neutral')
            total = len(sentiments)
            
            debug_print(f"Total de sentimentos analisados: {total}")
            
            positive_ratio = positive / total
            negative_ratio = negative / total
            neutral_ratio = neutral / total
            
            # Gerar mensagem com IA
            with st.spinner('Gerando novo tweet...'):
                debug_print("Iniciando geração de texto...")
                tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
                model = GPT2LMHeadModel.from_pretrained('gpt2')
                
                if positive_ratio > 0.6:
                    prompt = "Write an exciting tweet about BBB25 with a positive tone in Portuguese."
                elif negative_ratio > 0.6:
                    prompt = "Write an informative tweet about BBB25 with a neutral tone in Portuguese."
                else:
                    prompt = "Write a buzzing tweet about BBB25 with an engaging tone in Portuguese."
                
                debug_print(f"Usando prompt: {prompt}")
                
                input_ids = tokenizer.encode(prompt, return_tensors='pt')
                outputs = model.generate(
                    input_ids,
                    max_length=25,
                    do_sample=True,
                    pad_token_id=tokenizer.eos_token_id
                )
                
                generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
                generated_text = generated_text[:280]
                debug_print(f"Texto gerado: {generated_text}")
            
            # Postar tweet
            with st.spinner('Postando tweet...'):
                debug_print("Tentando postar tweet...")
                post_tweet(api, generated_text)
                st.success("Tweet postado com sucesso!")
                debug_print("Tweet postado com sucesso")
            
            # Interface Streamlit
            st.title("Resultados da Análise")
            
            # Mostrar estatísticas
            col1, col2, col3 = st.columns(3)
            with col1:
                st.metric("Sentimento Positivo", f"{positive_ratio:.1%}")
            with col2:
                st.metric("Sentimento Neutro", f"{neutral_ratio:.1%}")
            with col3:
                st.metric("Sentimento Negativo", f"{negative_ratio:.1%}")
            
            # Mostrar tweet gerado
            st.subheader("Tweet Gerado e Postado")
            st.write(generated_text)
            
            # Logging
            debug_print("Salvando log...")
            log_entry = {
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'positive_ratio': positive_ratio,
                'negative_ratio': negative_ratio,
                'neutral_ratio': neutral_ratio,
                'tweet': generated_text
            }
            
            with open('posting_log.txt', 'a') as f:
                f.write(f"{str(log_entry)}\n")
            debug_print("Log salvo com sucesso")

    except Exception as e:
        st.error(f"Erro: {str(e)}")
        debug_print(f"Erro fatal: {str(e)}")
        raise e

    finally:
        st.markdown("---")
        st.markdown(
            """
            <div style='text-align: center'>
                <small>Desenvolvido com ❤️ usando Streamlit e Transformers</small>
            </div>
            """,
            unsafe_allow_html=True
        )

if __name__ == "__main__":
    main()