add pretty printing to json store, move notif handling to a thread

master
Ondřej Hruška 5 years ago
parent dc88755e7b
commit 176bde9d01
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 11
      src/bootstrap.rs
  2. 19
      src/ele.rs
  3. 54
      src/main.rs
  4. 18
      src/store.rs

@ -1,15 +1,9 @@
//! Application start-up code handling CLI args, logging, config file load etc
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use failure::Fallible; use failure::Fallible;
use serde::Deserialize;
use serde::Serialize;
use crate::store::Store;
use crate::Config; use crate::Config;
use elefren::{Registration, Mastodon};
use elefren::http_send::HttpSender;
use elefren::helpers::cli;
use elefren::scopes::Scopes;
use std::str::FromStr;
const CONFIG_FILE: &str = "manabu.toml"; const CONFIG_FILE: &str = "manabu.toml";
@ -39,6 +33,7 @@ pub fn load_config(file: &str) -> Fallible<Config> {
Ok(config) Ok(config)
} }
/// Boot up the application. Initializes common stuff and returns the loaded config.
pub fn handle_cli_args_and_load_config() -> Fallible<Config> { pub fn handle_cli_args_and_load_config() -> Fallible<Config> {
let version = format!("{}, built from {}", env!("CARGO_PKG_VERSION"), env!("GIT_REV")); let version = format!("{}, built from {}", env!("CARGO_PKG_VERSION"), env!("GIT_REV"));
let argv = let argv =

@ -1,6 +1,5 @@
use std::fs::File; //! Mastodon API types and functions building on elefren
use std::io::Read;
use failure::Fallible;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use crate::store::Store; use crate::store::Store;
@ -10,13 +9,14 @@ use elefren::http_send::HttpSender;
use elefren::helpers::cli; use elefren::helpers::cli;
use elefren::scopes::Scopes; use elefren::scopes::Scopes;
use std::str::FromStr; use std::str::FromStr;
use failure::Fallible;
const KEY_OAUTH_REGISTRATION: &str = "oauth.registration"; const KEY_OAUTH_REGISTRATION: &str = "oauth.registration";
const KEY_OAUTH_SESSION: &str = "oauth.session"; const KEY_OAUTH_SESSION: &str = "oauth.session";
pub type EleRegistratered = elefren::registration::Registered<HttpSender>; pub type EleRegistratered = elefren::registration::Registered<HttpSender>;
pub type EleSession = elefren::Mastodon<HttpSender>; pub type EleSession = elefren::Mastodon<HttpSender>;
pub type EleWebsocket = websocket::sync::Client<native_tls::TlsStream<std::net::TcpStream>>; pub type EleStreamSocket = websocket::sync::Client<native_tls::TlsStream<std::net::TcpStream>>;
/// Wrapper for the long tuple with Registration state /// Wrapper for the long tuple with Registration state
#[derive(Serialize,Deserialize,Debug)] #[derive(Serialize,Deserialize,Debug)]
@ -49,6 +49,7 @@ pub fn register(store : &mut Store, config : &Config) -> EleRegistratered {
} }
} }
/// Open mastodon API session (get access token)
pub fn open_session(store : &mut Store, registered: EleRegistratered) -> EleSession { pub fn open_session(store : &mut Store, registered: EleRegistratered) -> EleSession {
match store.get::<elefren::Data>(KEY_OAUTH_SESSION) { match store.get::<elefren::Data>(KEY_OAUTH_SESSION) {
Some(data) => { Some(data) => {
@ -68,8 +69,9 @@ pub fn open_session(store : &mut Store, registered: EleRegistratered) -> EleSess
} }
} }
pub fn open_stream_websocket(session : &EleSession, stream_name : &str) -> EleWebsocket { /// Open streaming api websocket
let connector = native_tls::TlsConnector::new().unwrap(); pub fn open_stream_websocket(session : &EleSession, stream_name : &str) -> Fallible<EleStreamSocket> {
let connector = native_tls::TlsConnector::new()?;
let hostname = &session.data.base[session.data.base.find("://").unwrap()+3..]; let hostname = &session.data.base[session.data.base.find("://").unwrap()+3..];
@ -80,8 +82,7 @@ pub fn open_stream_websocket(session : &EleSession, stream_name : &str) -> EleWe
debug!("WS url = {}", &url); debug!("WS url = {}", &url);
websocket::ClientBuilder::new(&url) Ok(websocket::ClientBuilder::new(&url)
.expect("Error create ClientBuilder") .expect("Error create ClientBuilder")
.connect_secure(Some(connector)) .connect_secure(Some(connector))?)
.expect("Error connect to wss")
} }

@ -6,19 +6,9 @@ extern crate failure;
extern crate smart_default; extern crate smart_default;
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
#[macro_use]
use elefren::{ use websocket::{OwnedMessage};
helpers::cli, use std::thread;
prelude::*,
entities::prelude::*,
http_send::HttpSender,
};
use failure::Fallible;
use native_tls::TlsConnector;
use std::io::{Read, Write};
use std::net::TcpStream;
use websocket::{OwnedMessage, ClientBuilder};
mod bootstrap; mod bootstrap;
mod store; mod store;
@ -27,13 +17,18 @@ 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 std::time::Duration;
#[derive(SmartDefault,Serialize,Deserialize,Debug)] #[derive(SmartDefault,Serialize,Deserialize,Debug)]
#[serde(default)] #[serde(default)]
pub struct Config { pub struct Config {
/// Logging level to use (can be increased using -v flags)
#[default="info"] #[default="info"]
pub logging: String, pub logging: String,
/// Instance domain name, e.g. example.com
pub instance: String, pub instance: String,
/// File to use for session storage
#[default="manabu_store.json"] #[default="manabu_store.json"]
pub store: String, pub store: String,
} }
@ -45,6 +40,7 @@ fn main() {
let mut store = Store::from_file(&config.store); let mut store = Store::from_file(&config.store);
store.set_autosave(true); store.set_autosave(true);
store.set_pretty_print(true);
let registered = ele::register(&mut store, &config); let registered = ele::register(&mut store, &config);
@ -52,25 +48,43 @@ fn main() {
debug!("Listening to events"); debug!("Listening to events");
let mut socket = ele::open_stream_websocket(&session, "user"); let m_session = session.clone();
let handle = thread::spawn(move || handle_stream(m_session));
let _ = handle.join();
}
fn handle_stream(session : EleSession) -> ! {
loop {
debug!("Trying to open websocket");
match ele::open_stream_websocket(&session, "user") {
Ok(socket) => process_incoming_events(socket),
Err(e) => error!("Error opening socket: {}", e)
}
debug!("Delay before reconnecting...");
thread::sleep(Duration::from_secs(10));
}
}
for m in socket.incoming_messages() { fn process_incoming_events(mut socket : EleStreamSocket) {
'listen: for m in socket.incoming_messages() {
match m { match m {
Ok(OwnedMessage::Text(text)) => { Ok(OwnedMessage::Text(text)) => {
debug!("Got msg: {}", text); debug!("Got msg: {}", text);
}, },
Ok(OwnedMessage::Close(text)) => { Ok(OwnedMessage::Close(_text)) => {
debug!("Close"); debug!("Close");
break; break 'listen;
}, },
Ok(any) => { Ok(any) => {
debug!("Unhandled msg: {:?}", any); debug!("Unhandled msg: {:?}", any);
} }
Err(e) => { Err(e) => {
error!("{}", e); error!("Error reading from socket: {}", e);
break; break 'listen;
}, },
} }
} }
info!("Exit.");
} }

@ -1,3 +1,7 @@
#![allow(unused)]
//! JSON store
use std::borrow::Cow; use std::borrow::Cow;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
@ -18,6 +22,7 @@ use std::fmt::{self, Display, Formatter};
pub struct Store { pub struct Store {
path: Option<PathBuf>, path: Option<PathBuf>,
autosave: bool, autosave: bool,
prettysave: bool,
items: Map<String, serde_json::Value>, items: Map<String, serde_json::Value>,
} }
@ -26,6 +31,7 @@ impl Default for Store {
Self { Self {
path: None, path: None,
autosave: false, autosave: false,
prettysave: false,
items: Map::new() items: Map::new()
} }
} }
@ -82,6 +88,7 @@ impl Store {
let mut store = Store { let mut store = Store {
path: Some(path.as_ref().into()), path: Some(path.as_ref().into()),
autosave: false, autosave: false,
prettysave: false,
items: Map::new(), items: Map::new(),
}; };
@ -92,6 +99,11 @@ impl Store {
store store
} }
/// Set pretty print option to use when saved
pub fn set_pretty_print(&mut self, pretty : bool) {
self.prettysave = pretty;
}
/// Set auto-save option - save on each mutation. /// Set auto-save option - save on each mutation.
pub fn set_autosave(&mut self, autosave: bool) { pub fn set_autosave(&mut self, autosave: bool) {
self.autosave = autosave; self.autosave = autosave;
@ -142,7 +154,11 @@ impl Store {
/// Save the map to a custom file path. /// Save the map to a custom file path.
pub fn save_to<P: AsRef<Path>>(&self, path: P) -> Result<()> { pub fn save_to<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let as_str = serde_json::to_string(&self.items).unwrap(); let as_str = (if self.prettysave {
serde_json::to_string_pretty(&self.items)
} else {
serde_json::to_string(&self.items)
}).unwrap();
let mut file = File::create(path)?; let mut file = File::create(path)?;
file.write(as_str.as_bytes())?; file.write(as_str.as_bytes())?;

Loading…
Cancel
Save