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"
 | 
			
		||||
mammut = "0.13.0"
 | 
			
		||||
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 std::{error::Error, path::Path};
 | 
			
		||||
use telegram_bot::ChatId;
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
| 
						 | 
				
			
			@ -10,12 +10,12 @@ pub struct Config {
 | 
			
		|||
    pub temperature: String,
 | 
			
		||||
    pub top_k: String,
 | 
			
		||||
    pub gpt_code_path: String,
 | 
			
		||||
    pub fediverse_base_url: String,
 | 
			
		||||
    pub interval_seconds: MinMax,
 | 
			
		||||
    pub bot_token: String,
 | 
			
		||||
    pub chat_ref: ChatId,
 | 
			
		||||
    pub fediverse_token: Option<mammut::Data>,
 | 
			
		||||
    pub mastodon_token: Option<mammut::Data>,
 | 
			
		||||
    pub post_buffer: u32,
 | 
			
		||||
    pub publisher: Publisher,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +24,18 @@ pub struct MinMax {
 | 
			
		|||
    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 {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Config {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,15 +44,18 @@ impl Default for Config {
 | 
			
		|||
            temperature: String::from("1"),
 | 
			
		||||
            top_k: String::from("40"),
 | 
			
		||||
            gpt_code_path: String::from("./gpt/"),
 | 
			
		||||
            fediverse_base_url: String::from("https://lain.com"),
 | 
			
		||||
            interval_seconds: MinMax {
 | 
			
		||||
                min: 60 * 30,
 | 
			
		||||
                max: 60 * 90,
 | 
			
		||||
            },
 | 
			
		||||
            post_buffer: 5,
 | 
			
		||||
            fediverse_token: None,
 | 
			
		||||
            mastodon_token: None,
 | 
			
		||||
            bot_token: "".to_owned(),
 | 
			
		||||
            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 crate::{
 | 
			
		||||
    config::{FediverseConfig, Publisher},
 | 
			
		||||
    publish::MastodonPublisher,
 | 
			
		||||
    publish::MisskeyPublisher,
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
mod config;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,34 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
 | 
			
		|||
        }
 | 
			
		||||
    }?;
 | 
			
		||||
 | 
			
		||||
    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.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 publisher = resolve_publisher(&mut cfg).await?;
 | 
			
		||||
 | 
			
		||||
    let api = Arc::new(Api::new(cfg.bot_token.clone()));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +120,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
 | 
			
		|||
    });
 | 
			
		||||
 | 
			
		||||
    publisher
 | 
			
		||||
        .sink_map_err(|e| Box::new(e) as Box<dyn Error>)
 | 
			
		||||
        .sink_map_err(|e| e)
 | 
			
		||||
        .send_all(
 | 
			
		||||
            &mut receiver
 | 
			
		||||
                .then(|item| {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,3 +140,47 @@ async fn main() -> Result<(), Box<dyn Error>> {
 | 
			
		|||
 | 
			
		||||
    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::{
 | 
			
		||||
    pin::Pin,
 | 
			
		||||
    task::{Context, Poll},
 | 
			
		||||
};
 | 
			
		||||
use std::{error::Error, pin::Pin, task::{Context, Poll}};
 | 
			
		||||
 | 
			
		||||
use futures::Sink;
 | 
			
		||||
use mammut::{status_builder::Visibility, Mastodon, StatusBuilder};
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +14,7 @@ impl 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>> {
 | 
			
		||||
        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 misskey;
 | 
			
		||||
pub use mastodon::MastodonPublisher;
 | 
			
		||||
pub use crate::publish::misskey::MisskeyPublisher;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue