base64

Next, write the code to convert the characters specified in the command options to base64 and mention.

This completes the program.

First, add the base64 package.

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 = "*"
iso8601-timestamp = "0.2.10"
base64 = "*"

Then, in src/main.rs, in the mention, write the code to convert the did to base64.

These are set to suboptions.

Here is a summary of the main points.

example

.command(
        Command::new("mention")
        .alias("m")
        .action(c_mention)
        .flag(
            Flag::new("base", FlagType::String)
            .description("base flag\n\t\t\t$ ai m syui.bsky.social -p text -b 123")
            .alias("b"),
            )
        .flag(
            Flag::new("egg", FlagType::Bool)
            .description("egg flag\n\t\t\t$ ai m syui.bsky.social -e")
            .alias("e"),
            )

let did = token_toml(&"did");
let body = "/egg ".to_owned() + &encode(did.as_bytes());

Allow -b to specify the string to be converted. Be sure to enclose the string in double quotation marks, for example -b "foo bar". Use -e to get the did and convert it automatically for mention.

``sh

convert the specified string to base64 for mention

$ ai m yui.syui.ai -b "did:plc:4hqjfn7m6n5hno3doamuhgef" @yui.syui.ai /egg ZGlkOnBsYzo0aHFqZm43bTZuNWhubzNkb2FtdWhnZWY=

MENTION your did as base64

$ ai m yui.syui.ai -e @yui.syui.ai /egg ZGlkOnBsYzo0aHFqZm43bTZuNWhubzNkb2FtdWhnZWY=


Now, let's write the whole code.


!FILENAME src/main.rs
```rust
pub mod data;
pub mod mention;
pub mod profile;
//pub mod ascii;

use seahorse::{App, Command, Context, Flag, FlagType};
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;
use crate::data::Profile;
use crate::data::token_toml;
//use crate::ascii::c_ascii;

extern crate base64;
use base64::encode;

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),
            )
        .command(
            Command::new("profile")
            .alias("p")
            .action(c_profile),
            )
        .command(
            Command::new("mention")
            .alias("m")
            .action(c_mention)
            .flag(
                Flag::new("post", FlagType::String)
                .description("post flag\n\t\t\t$ ai m syui.bsky.social -p text")
                .alias("p"),
                )
            .flag(
                Flag::new("base", FlagType::String)
                .description("base flag\n\t\t\t$ ai m syui.bsky.social -p text -b 123")
                .alias("b"),
                )
            .flag(
                Flag::new("egg", FlagType::Bool)
                .description("egg flag\n\t\t\t$ ai m syui.bsky.social -e")
                .alias("e"),
                )
            )

        ;
    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();
}

fn profile(c: &Context) {
    let m = c.args[0].to_string();
    let h = async {
        let str = profile::get_request(m.to_string()).await;
        println!("{}",str);
    };
    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
    return res
}

fn c_profile(c: &Context) {
    access_token().unwrap();
    profile(c);
}

fn mention(c: &Context) {
    let m = c.args[0].to_string();
    let h = async {
        let str = profile::get_request(m.to_string()).await;
        let profile: Profile = serde_json::from_str(&str).unwrap();
        let udid = profile.did;
        let handle = profile.handle;
        let at = "@".to_owned() + &handle;
        let e = at.chars().count();
        let s = 0;
        if let Ok(base) = c.string_flag("base") {
            let body = "/egg ".to_owned() + &encode(base.as_bytes());
            let str = mention::post_request(body.to_string(), at.to_string(), udid.to_string(), s, e.try_into().unwrap()).await;
            println!("{}",str);
        }
        if let Ok(post) = c.string_flag("post") {

            let str = mention::post_request(post.to_string(), at.to_string(), udid.to_string(), s, e.try_into().unwrap()).await;
            println!("{}",str);
        }
        if c.bool_flag("egg") {
            let did = token_toml(&"did");
            let body = "/egg ".to_owned() + &encode(did.as_bytes());
            println!("{}", body);
            let str = mention::post_request(body.to_string(), at.to_string(), udid.to_string(), s, e.try_into().unwrap()).await;
            println!("{}",str);
        }
    };
    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
    return res
}

fn c_mention(c: &Context) {
    access_token().unwrap();
    mention(c);
}

//fn c_ascii_art(_c: &Context) {
//    c_ascii();
//}
cargo build

Done.

Now, if you specify yui.syui.ai as the mention and use the -e option, it will automatically convert your did to base64 and send it to you.

./target/debug/ai m yui.syui.ai -e

However, this makes it difficult to execute the command.

In order to be able to run this command from anywhere, we will put binary, i.e., .ai, which we can do when we cargo build. /target/debug/aiin$PATH`.

linux

$ echo $PATH|tr : '\n'
/usr/bin
/usr/local/bin

$ sudo cp -rf ./target/debug/ai /usr/local/bin/
$ ai -h

Name:
        ai
Flags:
        -h, --help : Show help
Commands:
        b, bluesky :
        l, login   :
        p, profile :
        m, mention :

windows

$ENV:Path.Split(";")
C:\Users\syui\scoop\apps\rust\current\bin

cp ~/scoop/rust/current/bin/
ai -h

Let's play around with making your own commands with rust like this.

results matching ""

    No results matching ""