Added support for misskey publisher, and switching between publishers via config
This commit is contained in:
parent
677226a77f
commit
bd42f495dc
File diff suppressed because it is too large
Load Diff
|
@ -17,3 +17,5 @@ uuid = { version = "0.8.2", features = ["v4"] }
|
||||||
anyhow = "1.0.41"
|
anyhow = "1.0.41"
|
||||||
mammut = "0.13.0"
|
mammut = "0.13.0"
|
||||||
thiserror = "1.0.26"
|
thiserror = "1.0.26"
|
||||||
|
misskey = "0.2.0"
|
||||||
|
url = "2.2.2"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{error::Error, path::Path};
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{error::Error, path::Path};
|
||||||
use telegram_bot::ChatId;
|
use telegram_bot::ChatId;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -10,12 +10,12 @@ pub struct Config {
|
||||||
pub temperature: String,
|
pub temperature: String,
|
||||||
pub top_k: String,
|
pub top_k: String,
|
||||||
pub gpt_code_path: String,
|
pub gpt_code_path: String,
|
||||||
pub fediverse_base_url: String,
|
|
||||||
pub interval_seconds: MinMax,
|
pub interval_seconds: MinMax,
|
||||||
pub bot_token: String,
|
pub bot_token: String,
|
||||||
pub chat_ref: ChatId,
|
pub chat_ref: ChatId,
|
||||||
pub fediverse_token: Option<mammut::Data>,
|
pub mastodon_token: Option<mammut::Data>,
|
||||||
pub post_buffer: u32,
|
pub post_buffer: u32,
|
||||||
|
pub publisher: Publisher,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -24,6 +24,18 @@ pub struct MinMax {
|
||||||
pub max: u64,
|
pub max: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum Publisher {
|
||||||
|
Misskey(FediverseConfig<String>),
|
||||||
|
Mastodon(FediverseConfig<Option<mammut::Data>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct FediverseConfig<T> {
|
||||||
|
pub base_url: String,
|
||||||
|
pub token: T,
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Config {
|
Config {
|
||||||
|
@ -32,15 +44,18 @@ impl Default for Config {
|
||||||
temperature: String::from("1"),
|
temperature: String::from("1"),
|
||||||
top_k: String::from("40"),
|
top_k: String::from("40"),
|
||||||
gpt_code_path: String::from("./gpt/"),
|
gpt_code_path: String::from("./gpt/"),
|
||||||
fediverse_base_url: String::from("https://lain.com"),
|
|
||||||
interval_seconds: MinMax {
|
interval_seconds: MinMax {
|
||||||
min: 60 * 30,
|
min: 60 * 30,
|
||||||
max: 60 * 90,
|
max: 60 * 90,
|
||||||
},
|
},
|
||||||
post_buffer: 5,
|
post_buffer: 5,
|
||||||
fediverse_token: None,
|
mastodon_token: None,
|
||||||
bot_token: "".to_owned(),
|
bot_token: "".to_owned(),
|
||||||
chat_ref: ChatId::new(0),
|
chat_ref: ChatId::new(0),
|
||||||
|
publisher: Publisher::Misskey(FediverseConfig {
|
||||||
|
base_url: "".to_string(),
|
||||||
|
token: "".to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
79
src/main.rs
79
src/main.rs
|
@ -10,11 +10,13 @@ use rand::Rng;
|
||||||
use telegram_bot::{Api, ChatId, ChatRef, ToChatRef};
|
use telegram_bot::{Api, ChatId, ChatRef, ToChatRef};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config::{FediverseConfig, Publisher},
|
||||||
publish::MastodonPublisher,
|
publish::MastodonPublisher,
|
||||||
|
publish::MisskeyPublisher,
|
||||||
selection::{telegram::get_chat_ref, SelectorExt, TelegramSelector},
|
selection::{telegram::get_chat_ref, SelectorExt, TelegramSelector},
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures::{channel::mpsc::channel, sink::unfold, SinkExt, StreamExt, TryStreamExt};
|
use futures::{SinkExt, StreamExt, TryStreamExt, channel::mpsc::channel, future::Either, sink::unfold};
|
||||||
use model::SampleModelExt;
|
use model::SampleModelExt;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -38,34 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let app = AppBuilder {
|
let publisher = resolve_publisher(&mut cfg).await?;
|
||||||
client_name: "izzilis",
|
|
||||||
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
|
||||||
scopes: Scopes::Write,
|
|
||||||
website: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut registration = Registration::new(cfg.fediverse_base_url.clone());
|
|
||||||
registration.register(app)?;
|
|
||||||
|
|
||||||
let mastodon = if let Some(data) = &cfg.fediverse_token {
|
|
||||||
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)?;
|
|
||||||
|
|
||||||
cfg.fediverse_token = Some(fedi.data.clone());
|
|
||||||
cfg.save(CONFIG_PATH)?;
|
|
||||||
|
|
||||||
fedi
|
|
||||||
};
|
|
||||||
|
|
||||||
let publisher = MastodonPublisher::new(mastodon);
|
|
||||||
|
|
||||||
let api = Arc::new(Api::new(cfg.bot_token.clone()));
|
let api = Arc::new(Api::new(cfg.bot_token.clone()));
|
||||||
|
|
||||||
|
@ -145,7 +120,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
});
|
});
|
||||||
|
|
||||||
publisher
|
publisher
|
||||||
.sink_map_err(|e| Box::new(e) as Box<dyn Error>)
|
.sink_map_err(|e| e)
|
||||||
.send_all(
|
.send_all(
|
||||||
&mut receiver
|
&mut receiver
|
||||||
.then(|item| {
|
.then(|item| {
|
||||||
|
@ -165,3 +140,47 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn resolve_publisher(
|
||||||
|
config: &mut config::Config,
|
||||||
|
) -> Result<Either<MisskeyPublisher, MastodonPublisher>, Box<dyn Error>> {
|
||||||
|
let publisher = match &config.publisher {
|
||||||
|
config::Publisher::Misskey(cfg) => {
|
||||||
|
Either::Left(MisskeyPublisher::new(&cfg.base_url, cfg.token.clone())?)
|
||||||
|
}
|
||||||
|
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)?;
|
||||||
|
|
||||||
|
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()),
|
||||||
|
});
|
||||||
|
config.save(CONFIG_PATH)?;
|
||||||
|
|
||||||
|
fedi
|
||||||
|
};
|
||||||
|
|
||||||
|
Either::Right(MastodonPublisher::new(mastodon))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(publisher)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use std::{
|
use std::{error::Error, pin::Pin, task::{Context, Poll}};
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll},
|
|
||||||
};
|
|
||||||
|
|
||||||
use futures::Sink;
|
use futures::Sink;
|
||||||
use mammut::{status_builder::Visibility, Mastodon, StatusBuilder};
|
use mammut::{status_builder::Visibility, Mastodon, StatusBuilder};
|
||||||
|
@ -17,7 +14,7 @@ impl MastodonPublisher {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink<String> for MastodonPublisher {
|
impl Sink<String> for MastodonPublisher {
|
||||||
type Error = mammut::Error;
|
type Error = Box<dyn Error>;
|
||||||
|
|
||||||
fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
use futures::Sink;
|
||||||
|
use misskey::{ClientExt, HttpClient};
|
||||||
|
use std::{error::Error, task::Poll};
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
pub struct MisskeyPublisher {
|
||||||
|
client: HttpClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MisskeyPublisher {
|
||||||
|
pub fn new(url: &String, token: String) -> Result<Self, Box<dyn Error>> {
|
||||||
|
Ok(Self {
|
||||||
|
client: HttpClient::with_token(Url::parse(url)?, token)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sink<String> for MisskeyPublisher {
|
||||||
|
type Error = Box<dyn Error>;
|
||||||
|
|
||||||
|
fn poll_ready(
|
||||||
|
self: std::pin::Pin<&mut Self>,
|
||||||
|
_: &mut std::task::Context<'_>,
|
||||||
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_send(self: std::pin::Pin<&mut Self>, item: String) -> Result<(), Self::Error> {
|
||||||
|
let mut runtime = Runtime::new()?;
|
||||||
|
let fut = self.client.create_note(item);
|
||||||
|
runtime.block_on(fut)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(
|
||||||
|
self: std::pin::Pin<&mut Self>,
|
||||||
|
_: &mut std::task::Context<'_>,
|
||||||
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_close(
|
||||||
|
self: std::pin::Pin<&mut Self>,
|
||||||
|
_: &mut std::task::Context<'_>,
|
||||||
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,4 @@
|
||||||
mod mastodon;
|
mod mastodon;
|
||||||
|
mod misskey;
|
||||||
pub use mastodon::MastodonPublisher;
|
pub use mastodon::MastodonPublisher;
|
||||||
|
pub use crate::publish::misskey::MisskeyPublisher;
|
||||||
|
|
Loading…
Reference in New Issue