feat: handle saving config better

This commit is contained in:
Anna 2021-09-01 13:39:16 -04:00
parent ba8f175e8f
commit ff0fd083c8
3 changed files with 43 additions and 14 deletions

View File

@ -9,6 +9,7 @@ pub mod web;
use anyhow::Result;
use cached::{TimedCache, Cached};
use chrono::Duration;
use futures::{StreamExt, SinkExt};
use irc::client::prelude::Client as IrcClient;
use rhai::Engine;
@ -40,13 +41,13 @@ use crate::app::{
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
path::Path,
sync::{
Arc,
atomic::AtomicBool,
atomic::{AtomicBool, Ordering},
},
time::Instant,
};
use std::sync::atomic::Ordering;
pub struct State {
pub user_config: UserConfig,
@ -77,15 +78,15 @@ impl State {
pub async fn new(runtime: Handle, user_config: UserConfig, mut config: Config) -> Result<Arc<Self>> {
let http_client = reqwest::Client::new();
println!("Verifying bot token");
println!("verifying bot token");
verify_token(&mut config.bot_token, &user_config, &http_client, vec![
// IRC
Scope::ChatRead,
Scope::ChatEdit,
]).await?;
println!("Bot token ready");
println!("bot token ready");
println!("Verifying user token");
println!("verifying user token");
verify_token(&mut config.user_token, &user_config, &http_client, vec![
// Channel points redemptions
Scope::ChannelReadRedemptions,
@ -96,7 +97,7 @@ impl State {
Scope::ModerationRead,
Scope::ModeratorManageAutoMod,
]).await?;
println!("User token ready");
println!("user token ready");
let config = Arc::new(RwLock::new(config));
@ -104,13 +105,29 @@ impl State {
let twitch_config = Arc::clone(&config);
let twitch = Arc::new(Twitch::new(twitch_client, twitch_config));
println!("getting channel name");
let user_id = UserId::new(user_config.twitch.channel_id.to_string());
let channel_name = twitch.client.helix.get_user_from_id(user_id, &twitch.bot_token().await?)
.await?
.ok_or_else(|| anyhow::anyhow!("no channel for id {}", user_config.twitch.channel_id))?
.login
.to_string();
println!("configured to run for channel: {}", channel_name);
println!("starting periodic config save task");
let task_config = Arc::clone(&config);
tokio::task::spawn(async move {
loop {
println!("saving config");
if let Err(e) = crate::save_config(Path::new("data.json"), &*task_config.read().await).await {
eprintln!("could not save config: {:?}", e);
}
tokio::time::sleep(Duration::minutes(5).to_std().unwrap()).await;
}
});
println!("connecting to irc");
let mut irc = self::twitch_irc::connect(&twitch).await?;
let mut irc_stream = irc.stream()?;
@ -182,6 +199,7 @@ impl State {
)?;
let task_state = Arc::clone(&state);
tokio::task::spawn(async move {
println!("starting pubsub listener");
let res: Result<()> = try {
let (ws, _) = tokio_tungstenite::connect_async("wss://pubsub-edge.twitch.tv").await?;
let (mut write, mut read) = ws.split();
@ -213,6 +231,7 @@ impl State {
// start irc task
let task_state = Arc::clone(&state);
tokio::task::spawn(async move {
println!("listening for irc events");
loop {
while let Some(event) = irc_stream.next().await.transpose().unwrap_or_default() {
let task_state = Arc::clone(&task_state);
@ -259,6 +278,8 @@ impl State {
let task_state = Arc::clone(&state);
self::task::stream_status::start_task(task_state).await;
println!("initialised");
Ok(state)
}

View File

@ -14,6 +14,7 @@ use std::{
};
pub async fn start_web(state: Arc<State>) {
println!("starting web server");
let cookie_state = Arc::clone(&state);
let authed = warp::cookie("access_token")
.or(warp::header("x-api-key"))

View File

@ -13,10 +13,7 @@ use crate::app::{
config::Config,
user_config::UserConfig,
};
use std::{
path::Path,
sync::Arc,
};
use std::path::Path;
fn main() -> anyhow::Result<()> {
let runtime = Builder::new_multi_thread()
@ -28,10 +25,12 @@ fn main() -> anyhow::Result<()> {
}
async fn inner(runtime: Handle) -> anyhow::Result<()> {
println!("reading config");
let mut uc_toml = String::new();
tokio::fs::File::open("config.toml").await?.read_to_string(&mut uc_toml).await?;
let user_config: UserConfig = toml::from_str(&uc_toml)?;
println!("reading data");
let c_path = Path::new("data.json");
let config: Config = if c_path.exists() {
let mut c_json = String::new();
@ -41,23 +40,31 @@ async fn inner(runtime: Handle) -> anyhow::Result<()> {
Config::default()
};
println!("starting bot");
let state = State::new(runtime, user_config, config).await?;
save_config(c_path, Arc::clone(&state)).await?;
save_config(c_path, &*state.config.read().await).await?;
tokio::signal::ctrl_c()
.then(|_| save_config(c_path, Arc::clone(&state)))
.then(|_| async {
println!("received ctrl-c");
println!("saving config");
save_config(c_path, &*state.config.read().await).await?;
Result::<(), anyhow::Error>::Ok(())
})
.await?;
println!("exiting");
Ok(())
}
async fn save_config(path: &Path, state: Arc<State>) -> anyhow::Result<()> {
pub async fn save_config(path: &Path, config: &Config) -> anyhow::Result<()> {
let mut config_file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(path)
.await?;
config_file.write_all(&serde_json::to_vec(&*state.config.read().await)?).await?;
config_file.write_all(&serde_json::to_vec(config)?).await?;
Ok(())
}