|
|
@ -17,8 +17,12 @@ mod ele; |
|
|
|
use crate::bootstrap::handle_cli_args_and_load_config; |
|
|
|
use crate::bootstrap::handle_cli_args_and_load_config; |
|
|
|
|
|
|
|
|
|
|
|
use crate::store::Store; |
|
|
|
use crate::store::Store; |
|
|
|
use crate::ele::{EleSession, EleStreamSocket}; |
|
|
|
use crate::ele::{EleSession, EleStreamSocket, parse_stream_socket_msg, ParsedSocketMsg}; |
|
|
|
use std::time::Duration; |
|
|
|
use std::time::Duration; |
|
|
|
|
|
|
|
use elefren::entities::prelude::*; |
|
|
|
|
|
|
|
use elefren::entities::notification::NotificationType; |
|
|
|
|
|
|
|
use elefren::{MastodonClient, StatusBuilder}; |
|
|
|
|
|
|
|
use elefren::status_builder::Visibility; |
|
|
|
|
|
|
|
|
|
|
|
#[derive(SmartDefault,Serialize,Deserialize,Debug)] |
|
|
|
#[derive(SmartDefault,Serialize,Deserialize,Debug)] |
|
|
|
#[serde(default)] |
|
|
|
#[serde(default)] |
|
|
@ -49,42 +53,79 @@ fn main() { |
|
|
|
debug!("Listening to events"); |
|
|
|
debug!("Listening to events"); |
|
|
|
|
|
|
|
|
|
|
|
let m_session = session.clone(); |
|
|
|
let m_session = session.clone(); |
|
|
|
let handle = thread::spawn(move || handle_stream(m_session)); |
|
|
|
let handle = thread::spawn(move || job_listen_to_stream(m_session, "user")); |
|
|
|
|
|
|
|
|
|
|
|
let _ = handle.join(); |
|
|
|
let _ = handle.join(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn handle_stream(session : EleSession) -> ! { |
|
|
|
/// Listen to a streaming API channel, reconnecting on failure.
|
|
|
|
|
|
|
|
fn job_listen_to_stream(session : EleSession, kind : &str) -> ! { |
|
|
|
loop { |
|
|
|
loop { |
|
|
|
debug!("Trying to open websocket"); |
|
|
|
debug!("Trying to open websocket"); |
|
|
|
|
|
|
|
|
|
|
|
match ele::open_stream_websocket(&session, "user") { |
|
|
|
match ele::open_stream_websocket(&session, kind) { |
|
|
|
Ok(socket) => process_incoming_events(socket), |
|
|
|
Ok(socket) => process_incoming_events(&session, socket), |
|
|
|
Err(e) => error!("Error opening socket: {}", e) |
|
|
|
Err(e) => error!("Error opening socket: {}", e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
debug!("Delay before reconnecting..."); |
|
|
|
debug!("Delay before reconnecting..."); |
|
|
|
thread::sleep(Duration::from_secs(10)); |
|
|
|
thread::sleep(Duration::from_secs(5)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn process_incoming_events(mut socket : EleStreamSocket) { |
|
|
|
/// Process events received from a streaming API websocket
|
|
|
|
'listen: for m in socket.incoming_messages() { |
|
|
|
fn process_incoming_events(session : &EleSession, mut socket : EleStreamSocket) { |
|
|
|
match m { |
|
|
|
'listen: loop { |
|
|
|
Ok(OwnedMessage::Text(text)) => { |
|
|
|
let recv_result = socket.recv_message(); |
|
|
|
debug!("Got msg: {}", text); |
|
|
|
|
|
|
|
}, |
|
|
|
if let Ok(Some(msg)) = parse_stream_socket_msg(recv_result) { |
|
|
|
Ok(OwnedMessage::Close(_text)) => { |
|
|
|
match msg { |
|
|
|
debug!("Close"); |
|
|
|
ParsedSocketMsg::WsClose => { |
|
|
|
break 'listen; |
|
|
|
debug!("Close"); |
|
|
|
}, |
|
|
|
break 'listen; |
|
|
|
Ok(any) => { |
|
|
|
}, |
|
|
|
debug!("Unhandled msg: {:?}", any); |
|
|
|
ParsedSocketMsg::WsPing(data) => { |
|
|
|
|
|
|
|
debug!("Sending Pong"); |
|
|
|
|
|
|
|
let _ = socket.send_message(&OwnedMessage::Pong(data)); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
ParsedSocketMsg::Event(event) => { |
|
|
|
|
|
|
|
handle_received_event(session, event); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Err(e) => { |
|
|
|
} |
|
|
|
error!("Error reading from socket: {}", e); |
|
|
|
} |
|
|
|
break 'listen; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/// Build the special syntax for a @ mention
|
|
|
|
|
|
|
|
fn make_mention(user : &Account) -> String { |
|
|
|
|
|
|
|
format!(r#"<span class="h-card"><a class="u-url mention" href="{url}">@<span>{handle}</span></a></span>"#, |
|
|
|
|
|
|
|
url=user.url, handle=user.acct |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Do something with an event we received from the API
|
|
|
|
|
|
|
|
fn handle_received_event(session : &EleSession, event: Event) { |
|
|
|
|
|
|
|
debug!("*** Event received:\n{:?}", event); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match event { |
|
|
|
|
|
|
|
Event::Notification(Notification { |
|
|
|
|
|
|
|
notification_type: NotificationType::Mention, |
|
|
|
|
|
|
|
account, status: Some(status), |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
}) => { |
|
|
|
|
|
|
|
debug!("Sending a reply."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let poste = StatusBuilder::new() |
|
|
|
|
|
|
|
.status(format!("Hello {} :blobpats:", &make_mention(&account))) |
|
|
|
|
|
|
|
.content_type("text/html") |
|
|
|
|
|
|
|
.in_reply_to(status.id) |
|
|
|
|
|
|
|
.visibility(Visibility::Unlisted) |
|
|
|
|
|
|
|
.build().expect("error build status"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
session.new_status(poste).expect("error send."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
_ => { |
|
|
|
|
|
|
|
//
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|