@@ -4,7 +4,6 @@ use anda_engine::{
44 context:: AgentCtx , engine:: Engine , extension:: character:: CharacterAgent , rand_number,
55} ;
66use anda_lancedb:: knowledge:: KnowledgeStore ;
7- use log:: { debug, error, info} ;
87use std:: sync:: Arc ;
98use tokio:: {
109 sync:: RwLock ,
@@ -42,13 +41,13 @@ impl TwitterDaemon {
4241 }
4342
4443 pub async fn run ( & self , cancel_token : CancellationToken ) -> Result < ( ) , BoxError > {
45- info ! ( target: LOG_TARGET , "starting Twitter bot" ) ;
44+ log :: info!( target: LOG_TARGET , "starting Twitter bot" ) ;
4645
4746 loop {
4847 {
4948 let status = self . status . read ( ) . await ;
5049 if * status == ServiceStatus :: Stopped {
51- info ! ( target: LOG_TARGET , "Twitter task stopped" ) ;
50+ log :: info!( target: LOG_TARGET , "Twitter task stopped" ) ;
5251 tokio:: select! {
5352 _ = cancel_token. cancelled( ) => {
5453 return Ok ( ( ) ) ;
@@ -57,52 +56,47 @@ impl TwitterDaemon {
5756 }
5857 continue ;
5958 }
60- info ! ( target: LOG_TARGET , "run a Twitter task" ) ;
59+ log :: info!( target: LOG_TARGET , "run a Twitter task" ) ;
6160 // release read lock
6261 }
6362
64- match rand_number ( 0 ..=2 ) {
65- 0 => {
66- if let Err ( err) = self . post_new_tweet ( ) . await {
67- error ! ( target: LOG_TARGET , "post_new_tweet error: {err:?}" ) ;
68- }
69- }
70- 1 => {
71- if let Err ( err) = self . handle_home_timeline ( ) . await {
72- error ! ( target: LOG_TARGET , "handle_home_timeline error: {err:?}" ) ;
73- }
74- }
75- 2 => {
76- match self
77- . scraper
78- . search_tweets (
79- & format ! ( "@{}" , self . agent. character. username. clone( ) ) ,
80- 5 ,
81- SearchMode :: Latest ,
82- None ,
83- )
84- . await
85- {
86- Ok ( mentions) => {
87- for tweet in mentions. tweets {
88- if let Err ( err) = self . handle_mention ( tweet) . await {
89- error ! ( target: LOG_TARGET , "handle mention error: {err:?}" ) ;
90- }
91-
92- tokio:: select! {
93- _ = cancel_token. cancelled( ) => {
94- return Ok ( ( ) ) ;
95- } ,
96- _ = sleep( Duration :: from_secs( rand_number( 3 ..=10 ) ) ) => { } ,
97- }
98- }
63+ if let Err ( err) = self . handle_home_timeline ( ) . await {
64+ log:: error!( target: LOG_TARGET , "handle_home_timeline error: {err:?}" ) ;
65+ }
66+
67+ match self
68+ . scraper
69+ . search_tweets (
70+ & format ! ( "@{}" , self . agent. character. username. clone( ) ) ,
71+ 5 ,
72+ SearchMode :: Latest ,
73+ None ,
74+ )
75+ . await
76+ {
77+ Ok ( mentions) => {
78+ for tweet in mentions. tweets {
79+ if let Err ( err) = self . handle_mention ( tweet) . await {
80+ log:: error!( target: LOG_TARGET , "handle mention error: {err:?}" ) ;
9981 }
100- Err ( err) => {
101- error ! ( target: LOG_TARGET , "fetch mentions error: {err:?}" ) ;
82+
83+ tokio:: select! {
84+ _ = cancel_token. cancelled( ) => {
85+ return Ok ( ( ) ) ;
86+ } ,
87+ _ = sleep( Duration :: from_secs( rand_number( 3 ..=10 ) ) ) => { } ,
10288 }
10389 }
10490 }
105- _ => unreachable ! ( ) ,
91+ Err ( err) => {
92+ log:: error!( target: LOG_TARGET , "fetch mentions error: {err:?}" ) ;
93+ }
94+ }
95+
96+ if rand_number ( 0 ..=9 ) == 0 {
97+ if let Err ( err) = self . post_new_tweet ( ) . await {
98+ log:: error!( target: LOG_TARGET , "post_new_tweet error: {err:?}" ) ;
99+ }
106100 }
107101
108102 // Sleep between tasks
@@ -120,6 +114,8 @@ impl TwitterDaemon {
120114 if knowledges. is_empty ( ) {
121115 return Ok ( ( ) ) ;
122116 }
117+
118+ log:: info!( target: LOG_TARGET , "post new tweet with {} knowledges" , knowledges. len( ) ) ;
123119 let ctx = self . engine . ctx_with (
124120 self . agent . as_ref ( ) ,
125121 Some ( self . agent . character . username . clone ( ) ) ,
@@ -143,6 +139,10 @@ impl TwitterDaemon {
143139 Some ( reason) => Err ( format ! ( "Failed to generate response for tweet: {reason}" ) . into ( ) ) ,
144140 None => {
145141 let _ = self . scraper . send_tweet ( & res. content , None , None ) . await ?;
142+ log:: info!( target: LOG_TARGET ,
143+ "post new tweet: {}" ,
144+ res. content. chars( ) . take( 100 ) . collect:: <String >( )
145+ ) ;
146146 Ok ( ( ) )
147147 }
148148 }
@@ -155,8 +155,11 @@ impl TwitterDaemon {
155155 Some ( self . agent . character . username . clone ( ) ) ,
156156 None ,
157157 ) ?;
158- debug ! ( target: LOG_TARGET , "process home timeline, {} tweets" , tweets. len( ) ) ;
158+ log :: info !( target: LOG_TARGET , "process home timeline, {} tweets" , tweets. len( ) ) ;
159159
160+ let mut likes = 0 ;
161+ let mut retweets = 0 ;
162+ let mut quotes = 0 ;
160163 for tweet in tweets {
161164 let tweet_user = tweet[ "core" ] [ "user_results" ] [ "result" ] [ "legacy" ] [ "screen_name" ]
162165 . as_str ( )
@@ -192,15 +195,19 @@ impl TwitterDaemon {
192195 . await ;
193196
194197 if self . handle_like ( & ctx, & tweet_content, & tweet_id) . await ? {
198+ likes += 1 ;
195199 if self . handle_quote ( & ctx, & tweet_content, & tweet_id) . await ? {
196200 // TODO: save tweet to knowledge store
201+ quotes += 1 ;
197202 } else {
198203 self . handle_retweet ( & ctx, & tweet_content, & tweet_id) . await ?;
204+ retweets += 1 ;
199205 }
200206 }
201207
202208 sleep ( Duration :: from_secs ( rand_number ( 1 ..=10 ) ) ) . await ;
203209 }
210+ log:: info!( target: LOG_TARGET , "home timeline: likes {}, retweets {}, quotes {}" , likes, retweets, quotes) ;
204211 Ok ( ( ) )
205212 }
206213
@@ -217,12 +224,13 @@ impl TwitterDaemon {
217224 }
218225 let ctx = self
219226 . engine
220- . ctx_with ( self . agent . as_ref ( ) , Some ( tweet_user) , None ) ?;
227+ . ctx_with ( self . agent . as_ref ( ) , Some ( tweet_user. clone ( ) ) , None ) ?;
221228
222229 let handle_key = format ! ( "D_{}" , tweet_id) ;
223230 if ctx. cache_contains ( & handle_key) {
224231 return Ok ( ( ) ) ;
225232 }
233+
226234 ctx. cache_set (
227235 & handle_key,
228236 (
@@ -266,15 +274,13 @@ impl TwitterDaemon {
266274 . collect ( ) ;
267275
268276 // Reply to the original tweet
269- let tweet_id : Option < & str > = tweet. id . as_deref ( ) ;
277+ let tweet : Option < & str > = tweet. id . as_deref ( ) ;
270278 for chunk in & chunks {
271- let _ = self
272- . scraper
273- . send_tweet ( chunk. as_str ( ) , tweet_id, None )
274- . await ?;
279+ let _ = self . scraper . send_tweet ( chunk. as_str ( ) , tweet, None ) . await ?;
275280 sleep ( Duration :: from_secs ( rand_number ( 1 ..=3 ) ) ) . await ;
276281 }
277282
283+ log:: info!( target: LOG_TARGET , "handle mention: {} - {}, {} chunks" , tweet_user, tweet_id, chunks. len( ) ) ;
278284 Ok ( ( ) )
279285 }
280286
0 commit comments