saved notified channel

This commit is contained in:
WanderingPenwing 2024-07-13 23:03:51 +02:00
parent f39954d5bc
commit d004661dab
4 changed files with 134 additions and 24 deletions

View file

@ -9,6 +9,9 @@ edition = "2021"
eframe = "0.26.2" eframe = "0.26.2"
futures = "0.3.30" futures = "0.3.30"
image = "0.24.9" image = "0.24.9"
serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111"
chrono = "0.4" chrono = "0.4"
serenity = { version = "0.9.0-rc.2", default-features = false, features = ["client", "gateway", "model", "builder", "rustls_backend", "cache", "http"] } serenity = { version = "0.9.0-rc.2", default-features = false, features = ["client", "gateway", "model", "builder", "rustls_backend", "cache", "http"] }
tokio = {features = ["macros"], version = "0.2"} tokio = {features = ["macros"], version = "0.2"}
homedir = "0.2.1"

View file

@ -1 +1 @@
{"categories":[{"name":"to do","content":[{"name":"ability to change token","description":"use a config file to store token so that \n\n1- it is away from github\n\n2- it is configurable if need be","id":1},{"name":"better ui error display","description":"handle the error packet for better display","id":1},{"name":"clean up bot code","description":"try to remove unnecessary code\n\nunindent\n\ngive sender to function ?","id":2},{"name":"proper links","description":"when there is a link, ability to click it","id":3},{"name":"trayable ?","description":"// Hello there","id":5},{"name":"handle unknown channel better","description":"when receiving a message from a not yet scanned guild, create the channel and put the message\n\nallow scanning if guild selected\n\ndo not add duplicate channel","id":1},{"name":"guild unread ?","description":"// Hello there","id":2}]},{"name":"in progress","content":[{"name":"notifications !!!","description":"// Hello there","id":4}]},{"name":"done","content":[{"name":"run discord bot","description":"make it so the bot is running","id":1},{"name":"fixed token in github","description":"// Hello there","id":1},{"name":"fetch previous messages","description":"// Hello there","id":4},{"name":"ability to write messages","description":"// Hello there","id":5},{"name":"get incoming messages","description":"read","id":2},{"name":"unread system","description":"add a * when a channel just received a message","id":1}]},{"name":"bugs","content":[]},{"name":"+","content":[]}]} {"categories":[{"name":"to do","content":[{"name":"ability to change token","description":"use a config file to store token so that \n\n1- it is away from github\n\n2- it is configurable if need be","id":1},{"name":"better ui error display","description":"handle the error packet for better display","id":1},{"name":"clean up bot code","description":"try to remove unnecessary code\n\nunindent\n\ngive sender to function ?","id":2},{"name":"proper links","description":"when there is a link, ability to click it","id":3},{"name":"trayable ?","description":"// Hello there","id":5},{"name":"handle unknown channel better","description":"when receiving a message from a not yet scanned guild, create the channel and put the message\n\nallow scanning if guild selected\n\ndo not add duplicate channel","id":1},{"name":"guild unread ?","description":"// Hello there","id":2},{"name":"timestamps","description":"// Hello there","id":1},{"name":"new message marker","description":"perma if too complicated to detect read","id":2},{"name":"remember channel id for dm","description":"and put in config file\n\nmaybe load message ? dm first ?","id":3}]},{"name":"in progress","content":[{"name":"notifications !!!","description":"// Hello there","id":4}]},{"name":"done","content":[{"name":"run discord bot","description":"make it so the bot is running","id":1},{"name":"fixed token in github","description":"// Hello there","id":1},{"name":"fetch previous messages","description":"// Hello there","id":4},{"name":"ability to write messages","description":"// Hello there","id":5},{"name":"get incoming messages","description":"read","id":2},{"name":"unread system","description":"add a * when a channel just received a message","id":1}]},{"name":"bugs","content":[]},{"name":"+","content":[]}]}

View file

@ -1,12 +1,15 @@
use eframe::egui; use eframe::egui;
use image::GenericImageView; use std::{sync::Arc, sync::mpsc, thread, time};
use std::{error::Error, sync::Arc, sync::mpsc, thread, time};
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use std::sync::Mutex; use std::sync::Mutex;
use std::path::PathBuf;
use std::collections::HashMap;
use homedir::get_my_home;
mod bot; mod bot;
mod postman; mod postman;
mod discord_structure; mod discord_structure;
mod state;
const MAX_FPS: f32 = 30.0; const MAX_FPS: f32 = 30.0;
const RUNNING_REQUEST_REFRESH_DELAY: f32 = 0.2; const RUNNING_REQUEST_REFRESH_DELAY: f32 = 0.2;
@ -27,7 +30,7 @@ fn main() {
} }
fn gui(sender: mpsc::Sender<postman::Packet>, receiver: mpsc::Receiver<postman::Packet>) { fn gui(sender: mpsc::Sender<postman::Packet>, receiver: mpsc::Receiver<postman::Packet>) {
let icon_data = load_icon().unwrap_or_default(); let icon_data = state::load_icon().unwrap_or_default();
let options = eframe::NativeOptions { let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default() viewport: egui::ViewportBuilder::default()
@ -43,6 +46,7 @@ struct Jiji {
next_frame: time::Instant, next_frame: time::Instant,
sender: mpsc::Sender<postman::Packet>, sender: mpsc::Sender<postman::Packet>,
receiver: mpsc::Receiver<postman::Packet>, receiver: mpsc::Receiver<postman::Packet>,
bot_token: String,
guilds: Vec<discord_structure::Guild>, guilds: Vec<discord_structure::Guild>,
selected_guild: Option<usize>, selected_guild: Option<usize>,
selected_channel: Option<usize>, selected_channel: Option<usize>,
@ -54,17 +58,20 @@ struct Jiji {
impl Jiji { impl Jiji {
fn new(sender: mpsc::Sender<postman::Packet>, receiver: mpsc::Receiver<postman::Packet>) -> Self { fn new(sender: mpsc::Sender<postman::Packet>, receiver: mpsc::Receiver<postman::Packet>) -> Self {
let app_state = state::load_state(&save_path());
Self { Self {
next_frame: time::Instant::now(), next_frame: time::Instant::now(),
sender, sender,
receiver, receiver,
bot_token: app_state.bot_token.clone(),
guilds: vec![], guilds: vec![],
selected_guild: None, selected_guild: None,
selected_channel: None, selected_channel: None,
time_watch: 0.0, time_watch: 0.0,
pending_bot_requests: 0, pending_bot_requests: 0,
current_message: "".into(), current_message: "".into(),
channels_to_notify: vec![], channels_to_notify: app_state.channels_to_notify.clone(),
} }
} }
} }
@ -88,7 +95,17 @@ impl eframe::App for Jiji {
if self.guilds[i].id != channel.guild_id { if self.guilds[i].id != channel.guild_id {
continue continue
} }
self.guilds[i].add_channel(channel.clone());
let mut discord_channel = channel.clone(); // finish if with variable clone of channel to update with notify
if let Some(index) = self.channels_to_notify.iter().position(|x| x == &channel.id) {
discord_channel.notify = true;
self.channels_to_notify.remove(index);
}
self.guilds[i].add_channel(discord_channel.clone());
} }
} }
postman::Packet::Message(message) => { postman::Packet::Message(message) => {
@ -176,7 +193,7 @@ impl eframe::App for Jiji {
} }
fn on_exit(&mut self, _gl: std::option::Option<&eframe::glow::Context>) { fn on_exit(&mut self, _gl: std::option::Option<&eframe::glow::Context>) {
//self.runtime.shutdown_background(); self.save_state();
} }
} }
@ -337,24 +354,39 @@ impl Jiji {
}); });
}); });
} }
}
pub fn load_icon() -> Result<egui::IconData, Box<dyn Error>> { pub fn save_state(&self) {
let (icon_rgba, icon_width, icon_height) = { let mut channels_to_notify = self.channels_to_notify.clone();
let icon = include_bytes!("../assets/icon.png");
let image = image::load_from_memory(icon)?;
let rgba = image.clone().into_rgba8().to_vec();
let (width, height) = image.dimensions();
(rgba, width, height)
};
Ok(egui::IconData { for g in 0..self.guilds.len() {
rgba: icon_rgba, for c in 0..self.guilds[g].channels.len() {
width: icon_width, if !self.guilds[g].channels[c].notify {
height: icon_height, continue
}) }
channels_to_notify.push(self.guilds[g].channels[c].id.clone());
}
}
let app_state = state::AppState {
bot_token: self.bot_token.clone(),
channels_to_notify: channels_to_notify,
dm_channels: HashMap::new(),
};
let _ = state::save_state(&app_state, save_path().as_path());
}
} }
pub fn hex_str_to_color(hex_str: &str) -> egui::Color32 { pub fn hex_str_to_color(hex_str: &str) -> egui::Color32 {
egui::Color32::from_hex(hex_str).unwrap_or_else(|_| egui::Color32::WHITE) egui::Color32::from_hex(hex_str).unwrap_or_else(|_| egui::Color32::WHITE)
} }
pub fn save_path() -> PathBuf {
get_my_home()
.unwrap()
.unwrap()
.as_path()
.join(".jiji")
.join("save.json")
.to_path_buf()
}

75
src/state.rs Normal file
View file

@ -0,0 +1,75 @@
use eframe::egui;
use image::GenericImageView;
use std::{
error::Error,
fs,
fs::{read_to_string, OpenOptions},
io::Write,
path::Path,
};
use serde::Serialize;
use serde::Deserialize;
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct AppState {
pub bot_token: String,
pub channels_to_notify: Vec<String>,
pub dm_channels: HashMap<String, String>,
}
impl Default for AppState {
fn default() -> Self {
Self {
bot_token: "".to_string(),
channels_to_notify: vec![],
dm_channels: HashMap::new()
}
}
}
pub fn save_state(state: &AppState, file_path: &Path) -> Result<(), std::io::Error> {
let serialized_state = serde_json::to_string(state)?;
if let Some(parent_dir) = file_path.parent() {
fs::create_dir_all(parent_dir)?;
}
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file_path)?;
file.write_all(serialized_state.as_bytes())?;
println!("state : Saved state at {}", file_path.display());
Ok(())
}
pub fn load_state(file_path: &Path) -> AppState {
if let Ok(serialized_state) = read_to_string(file_path) {
if let Ok(app_state) = serde_json::from_str(&serialized_state) {
return app_state
}
}
println!("state : failed to load state");
AppState::default()
}
pub fn load_icon() -> Result<egui::IconData, Box<dyn Error>> {
let (icon_rgba, icon_width, icon_height) = {
let icon = include_bytes!("../assets/icon.png");
let image = image::load_from_memory(icon)?;
let rgba = image.clone().into_rgba8().to_vec();
let (width, height) = image.dimensions();
(rgba, width, height)
};
Ok(egui::IconData {
rgba: icon_rgba,
width: icon_width,
height: icon_height,
})
}