config

blueskyの認証系のコードを追加します。

具体的には~/.config/ai/config.tomlに情報を書いておくと、~/.config/ai/token.tomlに認証情報を置くコマンドオプションを作成します。

~/.config/ai/config.toml

handle = "yui.syui.ai"
pass = "xxx"
host = "bsky.social"

Cargo.toml

[package]
name = "ai"
version = "0.1.0"
edition = "2021"

[dependencies]
seahorse = "*"
reqwest = { version = "*", features = ["blocking", "json"] }
tokio = { version = "1", features = ["full"] }
serde_derive = "1.0"
serde_json = "1.0"
serde = "*"
config = { git = "https://github.com/mehcode/config-rs", branch = "master" }
shellexpand = "*"
toml = "*"

src/data.rs

use config::{Config, ConfigError, File};
use serde_derive::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
#[allow(unused)]
pub struct Data {
    pub host: String,
    pub pass: String,
    pub handle: String,
}

#[derive(Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Token {
    pub did: String,
    pub accessJwt: String,
    pub refreshJwt: String,
    pub handle: String,
}

#[derive(Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Tokens {
    pub did: String,
    pub access: String,
    pub refresh: String,
    pub handle: String,
}

impl Data {
    pub fn new() -> Result<Self, ConfigError> {
        let d = shellexpand::tilde("~") + "/.config/ai/config.toml";
        let s = Config::builder()
            .add_source(File::with_name(&d))
            .add_source(config::Environment::with_prefix("APP"))
            .build()?;
        s.try_deserialize()
    }
}

src/main.rs

pub mod data;
use seahorse::{App, Context, Command};
use std::env;
use std::fs;
use std::io::Write;
use std::collections::HashMap;

use data::Data as Datas;
use crate::data::Token;
use crate::data::Tokens;

fn main() {
    let args: Vec<String> = env::args().collect();
    let app = App::new(env!("CARGO_PKG_NAME"))
        //.action(c_ascii_art)
        .command(
                Command::new("bluesky")
                .alias("b")
                .action(c_list_records),
                )
        .command(
                Command::new("login")
                .alias("l")
                .action(c_access_token),
                )

        ;
        app.run(args);
}

#[tokio::main]
async fn list_records() -> reqwest::Result<()> {
    let client = reqwest::Client::new();
    let handle= "support.bsky.team";
    let col = "app.bsky.feed.post";
    let body = client.get("https://bsky.social/xrpc/com.atproto.repo.listRecords")
        .query(&[("repo", &handle),("collection", &col),("limit", &"1"),("revert", &"true")])
        .send()
        .await?
        .text()
        .await?;
    println!("{}", body);
    Ok(())
}

fn c_list_records(_c: &Context) {
    list_records().unwrap();
}

#[tokio::main]
async fn access_token() -> reqwest::Result<()> {
    let file = "/.config/ai/token.toml";
    let mut f = shellexpand::tilde("~").to_string();
    f.push_str(&file);

    let data = Datas::new().unwrap();
    let data = Datas {
        host: data.host,
        handle: data.handle,
        pass: data.pass,
    };
    let url = "https://".to_owned() + &data.host + &"/xrpc/com.atproto.server.createSession";

    let mut map = HashMap::new();
    map.insert("identifier", &data.handle);
    map.insert("password", &data.pass);

    let client = reqwest::Client::new();
    let res = client
        .post(url)
        .json(&map)
        .send()
        .await?
        .text()
        .await?;

    let json: Token = serde_json::from_str(&res).unwrap();
    let tokens = Tokens {
        did: json.did.to_string(),
        access: json.accessJwt.to_string(),
        refresh: json.refreshJwt.to_string(),
        handle: json.handle.to_string(),
    };

    let toml = toml::to_string(&tokens).unwrap();
    let mut f = fs::File::create(f.clone()).unwrap();
    f.write_all(&toml.as_bytes()).unwrap();

    Ok(())
}

fn c_access_token(_c: &Context) {
    access_token().unwrap();
}

results matching ""

    No results matching ""