generated from Xithrius/rust-binary-project-template
-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
main.rs
134 lines (112 loc) · 3.9 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![forbid(unsafe_code)]
#![warn(clippy::nursery, clippy::pedantic)]
#![allow(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::cast_precision_loss,
clippy::module_name_repetitions,
clippy::struct_excessive_bools,
clippy::unused_self,
clippy::future_not_send,
clippy::suboptimal_flops,
clippy::too_many_lines,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::must_use_candidate,
clippy::struct_field_names,
clippy::too_many_arguments
)]
use clap::Parser;
use color_eyre::eyre::{Result, WrapErr};
use log::{info, warn};
use std::thread;
use tokio::sync::{broadcast, mpsc};
use crate::{
handlers::{app::App, args::Cli, config::CompleteConfig},
utils::emotes::emotes_enabled,
};
mod commands;
mod emotes;
mod handlers;
mod terminal;
pub mod twitch;
mod ui;
mod utils;
fn initialize_logging(config: &CompleteConfig) {
let logger = fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.target(),
record.level(),
message
));
})
.level(if config.terminal.verbose {
log::LevelFilter::Debug
} else {
log::LevelFilter::Info
});
if let Some(log_file_path) = config.terminal.log_file.clone() {
if !log_file_path.is_empty() {
logger
.chain(fern::log_file(log_file_path).unwrap())
.apply()
.unwrap();
}
} else {
logger.apply().unwrap();
}
}
#[tokio::main]
async fn main() -> Result<()> {
let startup_time = chrono::Local::now();
color_eyre::install().unwrap();
let mut config = CompleteConfig::new(Cli::parse())
.wrap_err("Configuration error.")
.unwrap();
initialize_logging(&config);
info!("Logging system initialised");
let (twitch_tx, terminal_rx) = mpsc::channel(100);
let (terminal_tx, twitch_rx) = broadcast::channel(100);
let app = App::new(config.clone(), startup_time);
info!("Started tokio communication channels.");
let decoded_rx = if emotes_enabled(&config.frontend) {
// We need to probe the terminal for it's size before starting the tui,
// as writing on stdout on a different thread can interfere.
match crossterm::terminal::window_size() {
Ok(size) => {
app.emotes.cell_size.get_or_init(|| {
(
f32::from(size.width / size.columns),
f32::from(size.height / size.rows),
)
});
let (decoder_tx, decoder_rx) = mpsc::channel(100);
emotes::DECODE_EMOTE_SENDER.get_or_init(|| decoder_tx);
let (decoded_tx, decoded_rx) = mpsc::channel(100);
// As decoding an image is a blocking task, spawn a separate thread to handle it.
// We cannot use tokio tasks here as it will create noticeable freezes.
thread::spawn(move || emotes::decoder(decoder_rx, &decoded_tx));
Some(decoded_rx)
}
Err(e) => {
config.frontend.twitch_emotes = false;
config.frontend.betterttv_emotes = false;
config.frontend.seventv_emotes = false;
config.frontend.frankerfacez_emotes = false;
warn!("Unable to query terminal for it's dimensions, disabling emotes. {e}");
None
}
}
} else {
None
};
let cloned_config = config.clone();
tokio::task::spawn(async move {
twitch::twitch_irc(config, twitch_tx, twitch_rx).await;
});
terminal::ui_driver(cloned_config, app, terminal_tx, terminal_rx, decoded_rx).await;
std::process::exit(0)
}