This commit is contained in:
@ -15,7 +15,8 @@
|
||||
"Bash(mkdir:*)",
|
||||
"Bash(chmod:*)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(git add:*)"
|
||||
"Bash(git add:*)",
|
||||
"Bash(rg:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
|
86
src/data.rs
86
src/data.rs
@ -8,6 +8,9 @@ use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
|
||||
/// 設定ディレクトリのベースパス
|
||||
const CONFIG_BASE_DIR: &str = "~/.config/syui/ai/bot";
|
||||
|
||||
/// ホームディレクトリパスを展開するユーティリティ関数
|
||||
/// "~"で始まるパスをユーザーのホームディレクトリに展開します
|
||||
fn expand_home_path(path: &str) -> PathBuf {
|
||||
@ -22,7 +25,7 @@ fn expand_home_path(path: &str) -> PathBuf {
|
||||
|
||||
/// 設定ディレクトリのベースパスを取得し、必要に応じて作成する
|
||||
fn get_config_base_path() -> PathBuf {
|
||||
let path = expand_home_path("~/.config/syui/ai/bot");
|
||||
let path = expand_home_path(CONFIG_BASE_DIR);
|
||||
if !path.is_dir() {
|
||||
let _ = fs::create_dir_all(&path);
|
||||
}
|
||||
@ -158,15 +161,14 @@ pub struct BaseUrl {
|
||||
}
|
||||
|
||||
pub fn url(s: &str) -> String {
|
||||
let s = String::from(s);
|
||||
let data = Data::new().unwrap();
|
||||
let data = Data {
|
||||
host: data.host,
|
||||
password: data.password,
|
||||
handle: data.handle,
|
||||
did: data.did,
|
||||
access: data.access,
|
||||
refresh: data.refresh,
|
||||
let data = match Data::new() {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
eprintln!("Error: Configuration file not found at {}/token.toml",
|
||||
get_config_base_path().display());
|
||||
eprintln!("Please run 'aibot login <handle> -p <password>' first to authenticate.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let t = "https://".to_string() + &data.host.to_string() + &"/xrpc/".to_string();
|
||||
let baseurl = BaseUrl {
|
||||
@ -223,29 +225,29 @@ pub fn url(s: &str) -> String {
|
||||
"follows" => t.to_string() + &baseurl.follows,
|
||||
"followers" => t.to_string() + &baseurl.followers,
|
||||
"feed_get" => t.to_string() + &baseurl.feed_get,
|
||||
_ => s,
|
||||
_ => s.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_toml(s: &str) -> String {
|
||||
let s = String::from(s);
|
||||
let data = Data::new().unwrap();
|
||||
let data = Data {
|
||||
host: data.host,
|
||||
password: data.password,
|
||||
handle: data.handle,
|
||||
did: data.did,
|
||||
access: data.access,
|
||||
refresh: data.refresh,
|
||||
let data = match Data::new() {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
eprintln!("Error: Configuration file not found at {}/token.toml",
|
||||
get_config_base_path().display());
|
||||
eprintln!("Please run 'aibot login <handle> -p <password>' first to authenticate.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
match &*s {
|
||||
|
||||
match s {
|
||||
"host" => data.host,
|
||||
"password" => data.password,
|
||||
"handle" => data.handle,
|
||||
"did" => data.did,
|
||||
"access" => data.access,
|
||||
"refresh" => data.refresh,
|
||||
_ => s,
|
||||
_ => s.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,37 +263,39 @@ pub fn c_refresh(access: &str, refresh: &str) {
|
||||
}
|
||||
|
||||
pub fn data_refresh(s: &str) -> String {
|
||||
let s = String::from(s);
|
||||
|
||||
let data = Data::new().unwrap();
|
||||
let data = Data {
|
||||
host: data.host,
|
||||
password: data.password,
|
||||
handle: data.handle,
|
||||
did: data.did,
|
||||
access: data.access,
|
||||
refresh: data.refresh,
|
||||
let data = match Data::new() {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
eprintln!("Error: Configuration file not found at {}/token.toml",
|
||||
get_config_base_path().display());
|
||||
eprintln!("Please run 'aibot login <handle> -p <password>' first to authenticate.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let mut _file = match Refresh::new()
|
||||
{
|
||||
let mut _file = match Refresh::new() {
|
||||
Err(_why) => c_refresh(&data.access, &data.refresh),
|
||||
Ok(_) => println!(""),
|
||||
};
|
||||
let refresh = Refresh::new().unwrap();
|
||||
let refresh = Refresh {
|
||||
access: refresh.access,
|
||||
refresh: refresh.refresh,
|
||||
|
||||
let refresh = match Refresh::new() {
|
||||
Ok(refresh) => refresh,
|
||||
Err(_) => {
|
||||
eprintln!("Error: Refresh token file not found.");
|
||||
eprintln!("Please run 'aibot login <handle> -p <password>' to re-authenticate.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
match &*s {
|
||||
|
||||
match s {
|
||||
"access" => refresh.access,
|
||||
"refresh" => refresh.refresh,
|
||||
_ => s,
|
||||
_ => s.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_scpt(s: &str) -> String {
|
||||
let mut path = expand_home_path("~/.config/syui/ai/bot/scpt");
|
||||
let mut path = get_config_path("scpt");
|
||||
path.push(format!("{}.zsh", s));
|
||||
path.to_string_lossy().to_string()
|
||||
}
|
||||
|
59
src/main.rs
59
src/main.rs
@ -508,6 +508,11 @@ fn openai_key(c: &Context) {
|
||||
}
|
||||
|
||||
fn token(c: &Context) {
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Handle is required.");
|
||||
eprintln!("Usage: aibot login <handle> -p <password>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(p) = c.string_flag("password") {
|
||||
@ -600,6 +605,11 @@ fn timeline(c: &Context) {
|
||||
|
||||
fn post(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Post text is required.");
|
||||
eprintln!("Usage: aibot post <text>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(link) = c.string_flag("link") {
|
||||
@ -619,6 +629,11 @@ fn post(c: &Context) {
|
||||
|
||||
fn delete(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Record key is required.");
|
||||
eprintln!("Usage: aibot delete <rkey> --col <collection>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(col) = c.string_flag("col") {
|
||||
@ -632,6 +647,11 @@ fn delete(c: &Context) {
|
||||
|
||||
fn like(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: CID is required.");
|
||||
eprintln!("Usage: aibot like <cid> --uri <uri>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(uri) = c.string_flag("uri") {
|
||||
@ -784,6 +804,11 @@ fn game_login(c: &Context) {
|
||||
|
||||
fn repost(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: CID is required.");
|
||||
eprintln!("Usage: aibot repost <cid> --uri <uri>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(uri) = c.string_flag("uri") {
|
||||
@ -797,6 +822,11 @@ fn repost(c: &Context) {
|
||||
|
||||
fn follow(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Handle is required.");
|
||||
eprintln!("Usage: aibot follow <handle>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
let handle = data_toml(&"handle");
|
||||
@ -820,10 +850,10 @@ fn profile(c: &Context) {
|
||||
let h = async {
|
||||
if c.args.len() == 0 {
|
||||
let j = profile::get_request(data_toml(&"handle")).await;
|
||||
println!("{}", j);
|
||||
print!("{}", j);
|
||||
} else {
|
||||
let j = profile::get_request(c.args[0].to_string()).await;
|
||||
println!("{}", j);
|
||||
print!("{}", j);
|
||||
}
|
||||
};
|
||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||
@ -832,6 +862,11 @@ fn profile(c: &Context) {
|
||||
|
||||
fn mention(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Handle is required.");
|
||||
eprintln!("Usage: aibot mention <handle>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
let str = profile::get_request(m.to_string()).await;
|
||||
@ -861,6 +896,11 @@ fn mention(c: &Context) {
|
||||
|
||||
fn reply(c: &Context) {
|
||||
refresh(c);
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Reply text is required.");
|
||||
eprintln!("Usage: aibot reply <text> --cid <cid> --uri <uri>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(cid) = c.string_flag("cid") {
|
||||
@ -900,6 +940,11 @@ fn reply(c: &Context) {
|
||||
|
||||
#[tokio::main]
|
||||
async fn c_img_upload(c: &Context) -> reqwest::Result<()> {
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Image file path is required.");
|
||||
eprintln!("Usage: aibot img_upload <image_file>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let token = data_refresh(&"access");
|
||||
let atoken = "Authorization: Bearer ".to_owned() + &token;
|
||||
let con = "Content-Type: image/png";
|
||||
@ -931,6 +976,11 @@ fn img_upload(c: &Context) {
|
||||
}
|
||||
|
||||
fn img_post(c: &Context) {
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Text is required.");
|
||||
eprintln!("Usage: aibot img_post <text> --link <link> --cid <cid> --uri <uri>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let link = c.string_flag("link").unwrap();
|
||||
let cid = c.string_flag("cid").unwrap();
|
||||
@ -977,6 +1027,11 @@ fn reply_og(c: &Context) {
|
||||
}
|
||||
|
||||
fn openai(c: &Context) {
|
||||
if c.args.is_empty() {
|
||||
eprintln!("Error: Message is required.");
|
||||
eprintln!("Usage: aibot openai <message>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
let str = openai::post_request(m.to_string()).await;
|
||||
|
Reference in New Issue
Block a user