You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.9 KiB
131 lines
3.9 KiB
#[macro_use]
|
|
extern crate log;
|
|
#[macro_use]
|
|
extern crate failure;
|
|
#[macro_use]
|
|
extern crate smart_default;
|
|
#[macro_use]
|
|
extern crate serde;
|
|
|
|
use websocket::{OwnedMessage};
|
|
use std::thread;
|
|
|
|
mod bootstrap;
|
|
mod store;
|
|
mod ele;
|
|
|
|
use crate::bootstrap::handle_cli_args_and_load_config;
|
|
|
|
use crate::store::Store;
|
|
use crate::ele::{EleSession, EleStreamSocket, parse_stream_socket_msg, ParsedSocketMsg};
|
|
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)]
|
|
#[serde(default)]
|
|
pub struct Config {
|
|
/// Logging level to use (can be increased using -v flags)
|
|
#[default="info"]
|
|
pub logging: String,
|
|
/// Instance domain name, e.g. example.com
|
|
pub instance: String,
|
|
/// File to use for session storage
|
|
#[default="manabu_store.json"]
|
|
pub store: String,
|
|
}
|
|
|
|
fn main() {
|
|
let config : Config = handle_cli_args_and_load_config().expect("error init");
|
|
|
|
debug!("Loaded config: {:#?}", config);
|
|
|
|
let mut store = Store::from_file(&config.store);
|
|
store.set_autosave(true);
|
|
store.set_pretty_print(true);
|
|
|
|
let registered = ele::register(&mut store, &config);
|
|
|
|
let session = ele::open_session(&mut store, registered);
|
|
|
|
debug!("Listening to events");
|
|
|
|
let m_session = session.clone();
|
|
let handle = thread::spawn(move || job_listen_to_stream(m_session, "user"));
|
|
|
|
let _ = handle.join();
|
|
}
|
|
|
|
/// Listen to a streaming API channel, reconnecting on failure.
|
|
fn job_listen_to_stream(session : EleSession, kind : &str) -> ! {
|
|
loop {
|
|
debug!("Trying to open websocket");
|
|
|
|
match ele::open_stream_websocket(&session, kind) {
|
|
Ok(socket) => process_incoming_events(&session, socket),
|
|
Err(e) => error!("Error opening socket: {}", e)
|
|
}
|
|
|
|
debug!("Delay before reconnecting...");
|
|
thread::sleep(Duration::from_secs(5));
|
|
}
|
|
}
|
|
|
|
/// Process events received from a streaming API websocket
|
|
fn process_incoming_events(session : &EleSession, mut socket : EleStreamSocket) {
|
|
'listen: loop {
|
|
let recv_result = socket.recv_message();
|
|
|
|
if let Ok(Some(msg)) = parse_stream_socket_msg(recv_result) {
|
|
match msg {
|
|
ParsedSocketMsg::WsClose => {
|
|
debug!("Close");
|
|
break 'listen;
|
|
},
|
|
ParsedSocketMsg::WsPing(data) => {
|
|
debug!("Sending Pong");
|
|
let _ = socket.send_message(&OwnedMessage::Pong(data));
|
|
},
|
|
ParsedSocketMsg::Event(event) => {
|
|
handle_received_event(session, event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 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.");
|
|
}
|
|
_ => {
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|