1
0
Fork 0
stickerdeploy/src/deploy_telegram.rs
ChaotiCryptidz bde32f5dd7
beep
2022-08-22 21:09:57 +01:00

294 lines
9.5 KiB
Rust

use std::io::Read;
use std::ops::Index;
use std::{collections::HashMap, error::Error};
use crate::{
creds::Creds,
sticker_config::{Sticker, StickerConfig, StickerType},
tg_api::{TelegramAPI, TelegramSticker},
};
struct TelegramStickerIDState {
// File ID to Sticker Name
data: HashMap<String, String>,
base_stickerdb_path: String,
}
impl TelegramStickerIDState {
pub fn new(base_stickerdb_path: &str) -> Self {
TelegramStickerIDState {
data: HashMap::new(),
base_stickerdb_path: base_stickerdb_path.to_owned(),
}
}
pub fn load(&mut self) -> Result<(), Box<dyn Error>> {
let path = std::path::PathBuf::from(&self.base_stickerdb_path).join("telegram_state.yml");
let file = std::fs::OpenOptions::new()
.write(true)
.read(true)
.create(true)
.open(path)?;
let data: HashMap<String, String> = serde_yaml::from_reader(file)?;
self.data.extend(data.into_iter());
Ok(())
}
pub fn save(&self) -> Result<(), Box<dyn Error>> {
let path = std::path::PathBuf::from(&self.base_stickerdb_path).join("telegram_state.yml");
let file = std::fs::OpenOptions::new()
.write(true)
.create(true)
.open(path)?;
serde_yaml::to_writer(file, &self.data)?;
Ok(())
}
pub fn get(&self, file_id: &String) -> Option<&String> {
self.data.get(file_id)
}
pub fn set(&mut self, file_id: &str, sticker_name: &str) {
self.data
.insert(file_id.to_owned(), sticker_name.to_owned());
}
}
pub async fn deploy_telegram(
deploy_id: String,
sticker_config: StickerConfig,
creds: Creds,
base_stickerdb_path: String,
) {
let mut tg_state = TelegramStickerIDState::new(&base_stickerdb_path);
tg_state.load().expect("could not load sticker state");
let deploy_where = sticker_config.deploy_where.get(&deploy_id).unwrap();
let deploy_location = deploy_where.telegram.as_ref().unwrap();
if deploy_location.r#type == StickerType::Gif {
panic!("gif stickers not supported on telegram, bodge it into video")
}
let pack_contents = sticker_config
.sticker_sets
.get(&deploy_where.pack_id)
.unwrap();
let pack_stickers: HashMap<String, Sticker> = pack_contents
.iter()
.map(|sticker_name| {
return (
sticker_name.clone(),
sticker_config.stickers.get(sticker_name).unwrap().clone(),
);
})
.collect();
let contains_invalid_stickers = pack_stickers
.iter()
.find(|sticker| sticker.1.r#type != deploy_location.r#type);
if contains_invalid_stickers.is_some() {
panic!("pack contains a invalid type of emoji for pack type")
}
let max = match deploy_location.r#type {
StickerType::Regular => 120,
StickerType::TelegramVideo => 50,
StickerType::TelegramAnimated => 50,
_ => {
unreachable!();
}
};
if pack_contents.len() >= max - 1 {
panic!("too many stickers in pack");
}
println!("{}", pack_contents.len());
let tg_bot = TelegramAPI::new(creds.telegram_bot_token);
let tg_sticker_set = tg_bot
.get_sticker_set(&deploy_location.name)
.await
.expect("could not get sticker pack");
let mut tg_stickers: Vec<(String, TelegramSticker)> = Vec::new();
// Delete stickers that arent in state
// add valid stickers to tg_stickers
{
let mut tg_sticker_set_iter = tg_sticker_set.stickers.iter();
// Skip the first sticker
tg_sticker_set_iter.next();
for sticker in tg_sticker_set_iter {
match tg_state.get(&sticker.file_unique_id) {
Some(sticker_name) => tg_stickers.push((sticker_name.clone(), sticker.clone())),
None => {
println!(
"Deleting sticker with unique_id {} as is not in state",
&sticker.file_unique_id
);
tg_bot
.delete_sticker(&sticker.file_id)
.await
.expect("could not delete sticker");
}
}
}
}
// Delete stickers that have a name but are no longer in the new pack
{
let invalid_stickers: Vec<TelegramSticker> = tg_stickers
.clone()
.into_iter()
.filter(|sticker| !pack_contents.contains(&sticker.0))
.map(|sticker| sticker.1)
.collect();
for invalid_sticker in invalid_stickers.iter() {
println!(
"Deleting sticker with name {} as is not in pack",
&invalid_sticker.file_unique_id
);
tg_bot
.delete_sticker(&invalid_sticker.file_id)
.await
.expect("could not delete sticker");
tg_stickers.retain(|sticker| {
// keep if true
sticker.1.file_unique_id != invalid_sticker.file_unique_id
})
}
}
// +1 for skipping the first sticker
let new_sticker_position_base = tg_stickers.len() + 1;
let mut new_stickers: Vec<String> = Vec::new();
// add stickers that arent in tg_stickers
{
let missing_stickers: Vec<String> = pack_contents
.clone()
.into_iter()
.filter(|sticker| {
for tg_sticker in tg_stickers.iter() {
if tg_sticker.0 == sticker.clone() {
return false;
}
}
true
})
.collect();
for sticker_name in missing_stickers.iter() {
println!("Uploading Sticker: {}", sticker_name);
let sticker_data = pack_stickers.get(sticker_name).unwrap();
let file_path = std::path::PathBuf::from(&base_stickerdb_path).join(&sticker_data.file);
let mut file = std::fs::File::open(file_path).unwrap();
let mut file_data: Vec<u8> = Vec::new();
file.read_to_end(&mut file_data)
.expect("could not read file");
let mut png_sticker: Option<Vec<u8>> = None;
let mut tgs_sticker: Option<Vec<u8>> = None;
let mut webm_sticker: Option<Vec<u8>> = None;
match deploy_location.r#type {
StickerType::Regular => {
png_sticker = Some(file_data);
}
StickerType::TelegramVideo => {
webm_sticker = Some(file_data);
}
StickerType::TelegramAnimated => {
tgs_sticker = Some(file_data);
}
_ => {}
}
tg_bot
.upload_sticker(
deploy_location.user_id,
deploy_location.name.clone(),
Some(sticker_data.emojis.concat()),
png_sticker,
tgs_sticker,
webm_sticker,
)
.await
.expect("could not upload sticker");
new_stickers.push(sticker_name.clone());
}
}
// Update tg_stickers with current sticker contents
{
let tg_new_sticker_set = tg_bot
.get_sticker_set(&deploy_location.name)
.await
.expect("could not get sticker pack");
for (i, sticker_name) in new_stickers.iter().enumerate() {
let new_sticker = tg_new_sticker_set
.stickers
.index(new_sticker_position_base + i)
.clone();
tg_state.set(&new_sticker.file_unique_id, sticker_name);
tg_stickers.push((
sticker_name.clone(),
tg_new_sticker_set
.stickers
.index(new_sticker_position_base + i)
.clone(),
));
}
}
tg_state.save().expect("could not save state");
// Reorder stickers using order of pack_contents
{
for (correct_sticker_i, sticker_name) in pack_contents.iter().enumerate() {
let pack_sticker = sticker_name.clone();
let tg_sticker = tg_stickers.index(correct_sticker_i).0.clone();
if pack_sticker != tg_sticker {
println!(
"Sticker in position {} is the wrong sticker",
correct_sticker_i
);
let mut sticker_incorrect_pos: Option<usize> = None;
for (sticker_i, sticker) in tg_stickers.iter().enumerate() {
if sticker.0 == pack_sticker {
sticker_incorrect_pos = Some(sticker_i);
}
}
if sticker_incorrect_pos.is_none() {
unreachable!()
}
println!(
"Moving sticker at position {} to {}",
sticker_incorrect_pos.unwrap(),
correct_sticker_i
);
let sticker = tg_stickers.remove(sticker_incorrect_pos.unwrap());
tg_stickers.insert(correct_sticker_i, sticker.clone());
tg_bot
.set_sticker_position(sticker.1.file_id.clone(), correct_sticker_i + 1)
.await
.expect("could not move sticker");
}
}
}
}