2021-07-06 03:13:51 +01:00
|
|
|
use std::{convert::Infallible, error::Error, sync::Arc, time::Duration};
|
2021-06-25 20:48:06 +01:00
|
|
|
|
2021-07-06 03:13:51 +01:00
|
|
|
use async_std::io::stdin;
|
|
|
|
use futures_timer::Delay;
|
|
|
|
use mammut::{
|
|
|
|
apps::{AppBuilder, Scopes},
|
2021-07-06 03:41:24 +01:00
|
|
|
Mastodon, Registration,
|
2021-07-06 03:13:51 +01:00
|
|
|
};
|
|
|
|
use rand::Rng;
|
2021-07-06 04:09:18 +01:00
|
|
|
use telegram_bot::{Api, ChatId, ChatRef, ToChatRef};
|
2021-06-25 18:59:46 +01:00
|
|
|
|
2021-07-06 03:13:51 +01:00
|
|
|
use crate::{
|
2021-09-01 18:30:20 +01:00
|
|
|
config::{FediverseConfig, Publisher},
|
2021-07-06 03:13:51 +01:00
|
|
|
publish::MastodonPublisher,
|
2021-09-01 18:30:20 +01:00
|
|
|
publish::MisskeyPublisher,
|
2021-07-06 03:13:51 +01:00
|
|
|
selection::{telegram::get_chat_ref, SelectorExt, TelegramSelector},
|
|
|
|
};
|
2021-06-28 19:57:06 +01:00
|
|
|
|
2021-09-01 18:30:20 +01:00
|
|
|
use futures::{SinkExt, StreamExt, TryStreamExt, channel::mpsc::channel, future::Either, sink::unfold};
|
2021-07-06 03:13:51 +01:00
|
|
|
use model::SampleModelExt;
|
2021-07-04 01:21:54 +01:00
|
|
|
|
2021-06-25 18:59:46 +01:00
|
|
|
mod config;
|
|
|
|
mod model;
|
2021-07-06 03:13:51 +01:00
|
|
|
mod publish;
|
2021-06-28 19:57:06 +01:00
|
|
|
mod selection;
|
2021-06-25 18:59:46 +01:00
|
|
|
|
|
|
|
const CONFIG_PATH: &str = "bot_config.json";
|
|
|
|
|
2021-07-06 02:39:09 +01:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
let mut cfg = match config::Config::from(CONFIG_PATH) {
|
|
|
|
Ok(cfg) => Ok(cfg),
|
|
|
|
Err(_) => {
|
|
|
|
println!(
|
|
|
|
"Failed reading config at [{}], writing default",
|
|
|
|
CONFIG_PATH
|
|
|
|
);
|
|
|
|
config::Config::default().save(CONFIG_PATH)?;
|
|
|
|
Err(anyhow::anyhow!("Invalid configuration"))
|
|
|
|
}
|
|
|
|
}?;
|
2021-06-25 18:59:46 +01:00
|
|
|
|
2021-09-01 18:30:20 +01:00
|
|
|
let publisher = resolve_publisher(&mut cfg).await?;
|
2021-06-25 18:59:46 +01:00
|
|
|
|
2021-07-06 03:14:37 +01:00
|
|
|
let api = Arc::new(Api::new(cfg.bot_token.clone()));
|
2021-07-06 02:39:09 +01:00
|
|
|
|
2021-07-06 04:09:18 +01:00
|
|
|
let chat = get_chat_ref(
|
|
|
|
api.clone(),
|
|
|
|
if ChatId::new(0) == cfg.chat_ref {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(cfg.chat_ref.clone().to_chat_ref())
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.expect("could not get chat ref");
|
2021-07-06 02:39:09 +01:00
|
|
|
|
|
|
|
let chat_ref = chat.lock().await.clone();
|
|
|
|
|
|
|
|
if let ChatRef::Id(id) = chat_ref {
|
|
|
|
cfg.chat_ref = id;
|
|
|
|
cfg.save(CONFIG_PATH)?;
|
|
|
|
}
|
|
|
|
|
2021-07-06 03:13:51 +01:00
|
|
|
let (sender, receiver) = channel(cfg.post_buffer as usize);
|
|
|
|
|
2021-07-06 02:39:09 +01:00
|
|
|
let cfg_clone = cfg.clone();
|
2021-07-06 03:13:51 +01:00
|
|
|
|
|
|
|
let mut model = TelegramSelector::new(
|
2021-07-06 02:39:09 +01:00
|
|
|
api,
|
|
|
|
chat,
|
|
|
|
Box::pin(unfold((), move |_, chat_ref| {
|
|
|
|
let mut cfg_clone = cfg_clone.clone();
|
|
|
|
async move {
|
|
|
|
if let ChatRef::Id(id) = &chat_ref {
|
|
|
|
cfg_clone.chat_ref = id.clone();
|
|
|
|
let _ = cfg_clone.save(CONFIG_PATH);
|
|
|
|
}
|
|
|
|
Ok::<_, Infallible>(())
|
|
|
|
}
|
|
|
|
})),
|
|
|
|
)
|
2021-07-06 03:13:51 +01:00
|
|
|
.filter(
|
|
|
|
model::GPTSampleModel::new(
|
|
|
|
cfg.python_path.clone(),
|
|
|
|
cfg.gpt_code_path.clone(),
|
|
|
|
vec![
|
|
|
|
"generate_unconditional_samples.py".to_string(),
|
|
|
|
"--model_name".to_string(),
|
|
|
|
cfg.model_name.clone(),
|
|
|
|
"--temperature".to_string(),
|
|
|
|
cfg.temperature.clone(),
|
|
|
|
"--top_k".to_string(),
|
|
|
|
cfg.top_k.clone(),
|
|
|
|
"--nsamples".to_string(),
|
|
|
|
"1".to_string(),
|
|
|
|
],
|
|
|
|
)
|
2021-07-06 03:53:24 +01:00
|
|
|
.into_stream()
|
|
|
|
.try_filter(|message| {
|
2021-09-23 20:47:37 +01:00
|
|
|
let criteria = !message.is_empty() && message.chars().count() <= 4096;
|
|
|
|
async move { criteria }
|
2021-07-06 03:53:24 +01:00
|
|
|
}),
|
2021-07-06 03:13:51 +01:00
|
|
|
)
|
|
|
|
.map_err(|e| Box::new(e) as Box<dyn Error>);
|
2021-07-05 01:13:20 +01:00
|
|
|
|
2021-07-06 03:13:51 +01:00
|
|
|
tokio::spawn(async move {
|
2021-07-11 00:32:44 +01:00
|
|
|
loop {
|
|
|
|
if let Err(err) = sender
|
|
|
|
.clone() // Does this even make sense??? Can you clone a sender?? am i fucked now??
|
|
|
|
// shouldnt it be re-init'd?
|
|
|
|
.sink_map_err(|e| Box::new(e) as Box<dyn Error>)
|
|
|
|
.send_all(&mut model)
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
// Idk what to do here, remake stream? what? idk, im not rustie
|
|
|
|
println!("got error on sender stream: {}", err);
|
|
|
|
}
|
|
|
|
}
|
2021-07-06 03:13:51 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
publisher
|
2021-09-01 18:30:20 +01:00
|
|
|
.sink_map_err(|e| e)
|
2021-07-06 03:13:51 +01:00
|
|
|
.send_all(
|
|
|
|
&mut receiver
|
|
|
|
.then(|item| {
|
|
|
|
let interval_seconds = cfg.interval_seconds.clone();
|
|
|
|
Box::pin(async move {
|
2021-07-06 03:42:16 +01:00
|
|
|
Delay::new(Duration::from_secs(
|
2021-07-06 03:13:51 +01:00
|
|
|
rand::thread_rng()
|
2021-07-06 04:01:51 +01:00
|
|
|
.gen_range(interval_seconds.min..=interval_seconds.max),
|
2021-07-06 03:13:51 +01:00
|
|
|
))
|
|
|
|
.await;
|
|
|
|
item
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(Ok),
|
|
|
|
)
|
|
|
|
.await?;
|
2021-07-05 01:13:20 +01:00
|
|
|
|
2021-07-06 02:39:09 +01:00
|
|
|
return Ok(());
|
2021-06-25 18:59:46 +01:00
|
|
|
}
|
2021-09-01 18:30:20 +01:00
|
|
|
|
|
|
|
async fn resolve_publisher(
|
|
|
|
config: &mut config::Config,
|
|
|
|
) -> Result<Either<MisskeyPublisher, MastodonPublisher>, Box<dyn Error>> {
|
|
|
|
let publisher = match &config.publisher {
|
|
|
|
config::Publisher::Misskey(cfg) => {
|
2021-09-30 17:53:33 +01:00
|
|
|
Either::Left(MisskeyPublisher::new(&cfg.base_url, cfg.token.clone(), cfg.visibility)?)
|
2021-09-01 18:30:20 +01:00
|
|
|
}
|
|
|
|
config::Publisher::Mastodon(cfg) => {
|
|
|
|
let app = AppBuilder {
|
|
|
|
client_name: "izzilis",
|
|
|
|
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
|
|
|
scopes: Scopes::Write,
|
|
|
|
website: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut registration = Registration::new(cfg.base_url.clone());
|
|
|
|
registration.register(app)?;
|
2021-09-30 17:53:33 +01:00
|
|
|
let vis = cfg.visibility;
|
2021-09-01 18:30:20 +01:00
|
|
|
|
|
|
|
let mastodon = if let Some(data) = cfg.token.clone() {
|
|
|
|
Mastodon::from_data(data.clone())
|
|
|
|
} else {
|
|
|
|
let url = registration.authorise()?;
|
|
|
|
println!("{}", url);
|
|
|
|
|
|
|
|
let mut buffer = String::new();
|
|
|
|
stdin().read_line(&mut buffer).await?;
|
|
|
|
|
|
|
|
let fedi = registration.create_access_token(buffer)?;
|
|
|
|
|
|
|
|
config.publisher = Publisher::Mastodon(FediverseConfig {
|
|
|
|
base_url: cfg.base_url.clone(),
|
|
|
|
token: Some(fedi.data.clone()),
|
2021-09-30 17:53:33 +01:00
|
|
|
visibility: vis.clone(),
|
2021-09-01 18:30:20 +01:00
|
|
|
});
|
|
|
|
config.save(CONFIG_PATH)?;
|
|
|
|
|
|
|
|
fedi
|
|
|
|
};
|
|
|
|
|
2021-09-30 17:53:33 +01:00
|
|
|
Either::Right(MastodonPublisher::new(mastodon, vis))
|
2021-09-01 18:30:20 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok(publisher)
|
|
|
|
}
|