use async_trait::async_trait;
use night_fury_core::BrowserSession;
use night_fury_daemon_core::protocol::Response;
use serde_json::{json, Value};
use tail_fin_twitter::{TimelineType, TwitterApi, TwitterClient};
use crate::handlers::params::required_str;
use crate::handlers::response::{err_str, ok_value};
use crate::handlers::SiteHandler;
pub struct TwitterHandler {
session: BrowserSession,
}
impl TwitterHandler {
pub fn new(session: BrowserSession) -> Self {
Self { session }
}
}
#[async_trait]
impl SiteHandler for TwitterHandler {
async fn handle(&self, id: &str, cmd: &str, params: &Value) -> Response {
let client = TwitterClient::new(self.session.clone());
match cmd {
"twitter.timeline" => {
let kind = parse_timeline_type(params);
let count = count_param(params, 20);
let cursor = params
.get("cursor")
.and_then(|v| v.as_str())
.map(String::from);
match client.timeline(kind, count, cursor.as_deref()).await {
Ok(resp) => ok_value(
id,
json!({"tweets": resp.tweets, "next_cursor": resp.next_cursor}),
),
Err(e) => err_str(id, e.to_string()),
}
}
"twitter.search" => match required_str(params, "query") {
Ok(q) => {
let count = count_param(params, 20);
let cursor = params
.get("cursor")
.and_then(|v| v.as_str())
.map(String::from);
match client.search(&q, count, cursor.as_deref()).await {
Ok(resp) => ok_value(
id,
json!({
"tweets": resp.tweets,
"next_cursor": resp.next_cursor,
"count": resp.tweets.len()
}),
),
Err(e) => err_str(id, e.to_string()),
}
}
Err(e) => err_str(id, e),
},
other => err_str(id, format!("unknown twitter cmd: {other}")),
}
}
}
fn parse_timeline_type(params: &Value) -> TimelineType {
match params
.get("type")
.and_then(|v| v.as_str())
.unwrap_or("following")
{
"for-you" => TimelineType::ForYou,
_ => TimelineType::Following,
}
}
fn count_param(params: &Value, default: usize) -> usize {
params
.get("count")
.and_then(|v| v.as_u64())
.map(|c| c as usize)
.unwrap_or(default)
}