v0.1
This commit is contained in:
parent
430b5977d8
commit
be51869f4b
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Cargo.lock
|
||||||
|
target
|
||||||
|
*.json
|
||||||
|
*.DS_Store
|
||||||
|
**.DS_Store
|
||||||
|
scpt/json/
|
18
Cargo.toml
Normal file
18
Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "ai"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
seahorse = "*"
|
||||||
|
reqwest = { version = "*", features = ["blocking", "json"] }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
shellexpand = "*"
|
||||||
|
config = "*"
|
||||||
|
serde = "*"
|
||||||
|
serde_json = "*"
|
||||||
|
serde_derive = "*"
|
||||||
|
url = { version = "2.0", features = ["serde"] }
|
||||||
|
rustc-serialize = "*"
|
||||||
|
toml = "*"
|
||||||
|
iso8601-timestamp = "*"
|
58
README.md
58
README.md
@ -1,6 +1,62 @@
|
|||||||
## ai `bot`
|
## ai `bot`
|
||||||
|
|
||||||
|
<img src="./icon/avatar.png" width="100">
|
||||||
|
|
||||||
|
- name : ai bot
|
||||||
|
- base : [rust](https://www.rust-lang.org)
|
||||||
|
- host : [yui.syui.ai](https://bsky.app/profile/yui.syui.ai), [ai.syu.is](https://web.syu.is/profile/ai.syu.is)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ai
|
||||||
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cargo build
|
$ cargo build
|
||||||
$ ./target/debug/ai
|
$ ./target/debug/ai ai -t
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### login
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# ai token $handle -p $password
|
||||||
|
$ ai t yui.syui.ai -p password
|
||||||
|
|
||||||
|
$ cat ~/.config/ai/token.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# ai token $handle -p $password -s $server
|
||||||
|
$ ai t ai.syu.is -p password -s syu.is
|
||||||
|
```
|
||||||
|
|
||||||
|
### refresh
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ai r
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
# server: syu.is
|
||||||
|
$ ai r -s syu.is
|
||||||
|
```
|
||||||
|
|
||||||
|
### notify
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ai n
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ai n | jq .
|
||||||
|
```
|
||||||
|
|
||||||
|
### bot
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ai bot
|
||||||
|
```
|
||||||
|
|
||||||
|
|command|type|body|
|
||||||
|
|---|---|---|
|
||||||
|
|@yui.syui.ai did|mention, reply| plc.directory/$did/log |
|
||||||
|
|
||||||
|
27
ai.zsh
Executable file
27
ai.zsh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
case $OSTYPE in
|
||||||
|
darwin*)
|
||||||
|
alias date="/opt/homebrew/bin/gdate"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
d=${0:a:h}/scpt
|
||||||
|
source $d/env
|
||||||
|
source $d/refresh.zsh
|
||||||
|
source $d/token.zsh
|
||||||
|
source $d/reply.zsh
|
||||||
|
source $d/notify.zsh
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
refresh|r)
|
||||||
|
refresh
|
||||||
|
;;
|
||||||
|
token|t)
|
||||||
|
token
|
||||||
|
;;
|
||||||
|
reply|rep)
|
||||||
|
reply
|
||||||
|
;;
|
||||||
|
notify|n)
|
||||||
|
notify
|
||||||
|
;;
|
||||||
|
esac
|
BIN
icon/ai.png
Normal file
BIN
icon/ai.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
BIN
icon/avatar.png
Normal file
BIN
icon/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 557 KiB |
19
scpt/env
Normal file
19
scpt/env
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
cfg=~/.config/ai/test.json
|
||||||
|
host=`cat $cfg|jq -r .host`
|
||||||
|
handle=`cat $cfg|jq -r .handle`
|
||||||
|
pass=`cat $cfg|jq -r .password`
|
||||||
|
date=`date --iso-8601=seconds`
|
||||||
|
|
||||||
|
if [ ! -f $cfg.t ];then
|
||||||
|
$d/token.zsh
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f $cfg.t ];then
|
||||||
|
token=`cat $cfg.t|jq -r .accessJwt`
|
||||||
|
refresh=`cat $cfg.t|jq -r .refreshJwt`
|
||||||
|
did=`cat $cfg.t|jq -r .did`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d $d/json ];then
|
||||||
|
mkdir -p $d/json
|
||||||
|
fi
|
37
scpt/notify.zsh
Normal file
37
scpt/notify.zsh
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
function notify() {
|
||||||
|
url=https://$host/xrpc/app.bsky.notification.listNotifications
|
||||||
|
f=$d/json/notify.json
|
||||||
|
if [ ! -f $f ];then
|
||||||
|
curl -sL "Content-Type: application/json" -H "Authorization: Bearer $token" "$url?limit=100" >! $f
|
||||||
|
fi
|
||||||
|
|
||||||
|
for ((i=0;i<=99;i++))
|
||||||
|
do
|
||||||
|
echo "[$i]---"
|
||||||
|
cid=`cat $f|jq -r ".|.[].[$i]?|.cid?"`
|
||||||
|
uri=`cat $f|jq -r ".|.[].[$i]?|.uri?"`
|
||||||
|
echo cid: $cid
|
||||||
|
echo uri: $uri
|
||||||
|
cid_r=`cat $f|jq -r ".[]|.[$i]?|.record.reply.root.cid?"`
|
||||||
|
|
||||||
|
if [ "$cid_r" = "null" ];then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
uri_r=`cat $f|jq -r ".[]|.[$i]?|.record.reply.root.uri?"`
|
||||||
|
cid_p=`cat $f|jq -r ".[]|.[$i]?|.record.reply.parent.cid?"`
|
||||||
|
uri_p=`cat $f|jq -r ".[]|.[$i]?|.record.reply.parent.uri?"`
|
||||||
|
did_p=`echo $uri_p|cut -d / -f 3`
|
||||||
|
if [ "$did_p" != "did:plc:uqzpqmrjnptsxezjx4xuh2mn" ];then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo cid_root: $cid_r
|
||||||
|
echo uri_root: $uri_r
|
||||||
|
echo cid_parent: $cid_p
|
||||||
|
echo uri_parent: $uri_p
|
||||||
|
echo ---
|
||||||
|
echo uri: $uri|sed "s#at://#https://bsky.app/profile/#g"|sed 's/app.bsky.feed.post/post/g'
|
||||||
|
echo uri_root: $uri_r|sed "s#at://#https://bsky.app/profile/#g"|sed 's/app.bsky.feed.post/post/g'
|
||||||
|
echo uri_parent: $uri_p|sed "s#at://#https://bsky.app/profile/#g"|sed 's/app.bsky.feed.post/post/g'
|
||||||
|
echo ---
|
||||||
|
done
|
||||||
|
}
|
11
scpt/refresh.zsh
Executable file
11
scpt/refresh.zsh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
function refresh(){
|
||||||
|
token=`cat $cfg.t|jq -r .accessJwt`
|
||||||
|
refresh=`cat $cfg.t|jq -r .refreshJwt`
|
||||||
|
if [ ! -f $cfg ];then
|
||||||
|
token
|
||||||
|
fi
|
||||||
|
url=https://$host/xrpc/com.atproto.server.refreshSession
|
||||||
|
j=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $refresh" $url`
|
||||||
|
echo $j
|
||||||
|
echo $j >! $cfg.t
|
||||||
|
}
|
40
scpt/reply.zsh
Executable file
40
scpt/reply.zsh
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
function reply() {
|
||||||
|
|
||||||
|
#uri: https://bsky.app/profile/did:plc:4hqjfn7m6n5hno3doamuhgef/post/3kkumyv72w22o
|
||||||
|
#uri_root: https://bsky.app/profile/did:plc:uqzpqmrjnptsxezjx4xuh2mn/post/3kkumysfipk2p
|
||||||
|
#uri_parent: https://bsky.app/profile/did:plc:uqzpqmrjnptsxezjx4xuh2mn/post/3kkumysfipk2p
|
||||||
|
|
||||||
|
cid=bafyreiaxz6hbqgylsxglqita73c5gzxzoatupgitd35rwjpd6dzpa4ctwi
|
||||||
|
uri=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.post/3kkumyv72w22o
|
||||||
|
cid_root=bafyreiacxuk4ypaxbg7qxnmrvpnaej5o7azewqioelfgbuikp77jevy6hq
|
||||||
|
uri_root=at://did:plc:uqzpqmrjnptsxezjx4xuh2mn/app.bsky.feed.post/3kkumysfipk2p
|
||||||
|
cid_parent=bafyreiacxuk4ypaxbg7qxnmrvpnaej5o7azewqioelfgbuikp77jevy6hq
|
||||||
|
uri_parent=at://did:plc:uqzpqmrjnptsxezjx4xuh2mn/app.bsky.feed.post/3kkumysfipk2p
|
||||||
|
|
||||||
|
url="https://$host/xrpc/com.atproto.repo.createRecord"
|
||||||
|
col="app.bsky.feed.post"
|
||||||
|
|
||||||
|
json="{
|
||||||
|
\"repo\": \"$handle\",
|
||||||
|
\"did\": \"$did\",
|
||||||
|
\"collection\": \"$col\",
|
||||||
|
\"record\": {
|
||||||
|
\"text\": \"$text\",
|
||||||
|
\"createdAt\": \"$date\",
|
||||||
|
\"reply\": {
|
||||||
|
\"root\": {
|
||||||
|
\"cid\": \"$cid_root\",
|
||||||
|
\"uri\": \"$uri_root\"
|
||||||
|
},
|
||||||
|
\"parent\": {
|
||||||
|
\"cid\": \"$cid\",
|
||||||
|
\"uri\": \"$uri\"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
echo $json|jq .
|
||||||
|
url=https://$host/xrpc/com.atproto.repo.createRecord
|
||||||
|
curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$json" $url
|
||||||
|
}
|
6
scpt/token.zsh
Executable file
6
scpt/token.zsh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
function token() {
|
||||||
|
url=https://$host/xrpc/com.atproto.server.createSession
|
||||||
|
j=`curl -sL -X POST -H "Content-Type: application/json" -d "{\"identifier\":\"$handle\",\"password\":\"$pass\"}" $url`
|
||||||
|
echo $j
|
||||||
|
echo $j >! $cfg.t
|
||||||
|
}
|
80
src/ascii.rs
Normal file
80
src/ascii.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
pub fn c_ascii(x: bool) {
|
||||||
|
let logo = "
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠉⠀⠀⠀⠀⠀⠈⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣤⣤⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀
|
||||||
|
⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀
|
||||||
|
⠀⠀⠘⠛⠛⠛⠛⠉⠉⠉⠉⠁⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠉⠉⠉⠉⠙⠛⠛⠛⠛⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
";
|
||||||
|
|
||||||
|
let avatar = "
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣁⣀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⠖⠋⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠒⢦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⢿⣷⣦⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣴⣿⠷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣶⠿⠟⠛⠛⠋⠉⠋⠉⠉⠉⠉⠙⠛⠙⠛⠛⠻⠿⢷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠚⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⡀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢠⣷⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⣿⡇⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢁⣾⣿⡆⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢰⣿⣿⣧⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⣾⣿⣿⡇⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⣾⣿⣿⣿⡄⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⣿⣿⣿⡇⣿⡿⢣⠈⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⢹⠀⣿⣿⣿⣿⣧⢹⣿⡏⢹⣿⣿⣿⠏⣼⣿⡿⠿⢿⢣⡿⣡⣿⠀⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⢃⠸⠀⣵⡶⠶⢶⣿⡆⢿⢁⠸⣿⣿⢋⣼⣯⡴⠒⠒⠒⣼⡑⢟⣿⢠⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⢿⣿⣿⣿⣿⡟⠈⣄⠈⠡⡐⢿⣦⠹⣿⡌⢸⡆⠿⣡⣾⣿⡟⢐⠇⠙⣡⡀⣿⡎⢿⠈⢐⡲⣆⢻⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢳⡘⣿⣿⣿⣿⡇⣸⣿⡄⣶⡄⠀⣿⠀⣿⣿⣜⣷⣼⣿⣿⣿⡇⢸⡇⠀⣿⠃⣿⣿⣸⠀⡌⢇⣿⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠘⣿⣿⣿⡇⣿⣿⣧⡘⢷⣾⠟⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣌⣿⣿⣃⣼⣿⣿⡟⠀⣿⣾⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡇⢸⣿⣿⣿⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠡⠾⢛⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⡘⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢃⣶⡾⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡅⢀⡹⣿⣿⣿⣿⣿⣿⣯⣛⡛⣛⣛⣭⣿⣿⣿⣿⣿⠿⢋⣤⠟⢉⠠⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠃⣸⣿⣦⡍⠛⠻⠿⣿⣿⣿⣿⣿⣿⣿⠿⠿⢛⡉⢠⡶⠋⡄⢺⣿⡀⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⣿⣿⢿⠇⣼⢹⡀⣶⣦⣭⣭⣭⣴⣶⣿⠂⡟⠀⢋⣴⡇⡇⣾⣿⡇⢻⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⣿⡿⢸⢀⠇⣸⡀⣿⣿⣿⣿⣿⣿⣿⣿⠀⣠⠀⣿⣿⡇⠀⣿⢹⣷⠸⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⠀⣿⡇⡟⠘⢠⡿⠃⣿⣿⣿⣿⣿⣿⣿⣿⡀⣤⠀⣿⣿⠃⢰⣿⠸⣿⡀⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢜⣽⠀⣿⠁⡇⡰⣢⣼⣰⣿⣿⣿⣿⣿⣿⣿⣿⣷⣌⠀⣿⣿⠀⣼⣿⡄⣿⣧⠸⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⣠⠞⣋⠀⣿⢸⠃⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣿⣿⢠⣬⣍⣁⣙⠛⠦⠹⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⢋⠜⣡⣿⣿⢠⡿⠘⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢠⣿⡇⣸⣿⣿⣿⣿⣿⣷⣦⣍⠻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⡰⢫⣾⣿⡟⣵⢸⡇⠀⢸⡿⠿⢛⣋⣉⣿⣿⣿⣿⣿⣿⣫⣭⡍⢸⣿⠇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡌⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⢃⡞⣰⣿⣿⣿⣦⡛⢸⡇⠀⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⣿⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡈⢷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡞⢡⡏⣼⣿⣿⣿⣿⣿⣿⢸⡇⠀⣭⣭⣭⣤⣶⣦⢠⣭⣙⠻⣿⣿⣿⣿⡇⣾⡇⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⡄⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡟⢰⣿⢰⣿⣿⣿⣿⣿⣿⣿⠸⣇⠀⣿⣿⣿⣿⣿⡇⢸⣿⣿⣿⡜⣿⣿⣿⡇⣿⠀⢸⣿⡿⠿⠿⠛⠿⠿⠟⣛⣛⣉⣥⣿⡈⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
match x {
|
||||||
|
true => println!("{}", avatar),
|
||||||
|
false => println!("{}", logo),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
499
src/data.rs
Normal file
499
src/data.rs
Normal file
@ -0,0 +1,499 @@
|
|||||||
|
use config::{Config, ConfigError, File};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn data_file(s: &str) -> String {
|
||||||
|
let file = "/.config/ai/token";
|
||||||
|
let mut f = shellexpand::tilde("~").to_string();
|
||||||
|
f.push_str(&file);
|
||||||
|
match &*s {
|
||||||
|
"toml" => f + &".toml",
|
||||||
|
"json" => f + &".json",
|
||||||
|
_ => f + &"." + &s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_file(s: &str) -> String {
|
||||||
|
let file = "/.config/ai/txt/";
|
||||||
|
let mut f = shellexpand::tilde("~").to_string();
|
||||||
|
f.push_str(&file);
|
||||||
|
let path = Path::new(&f);
|
||||||
|
if path.is_dir() == false {
|
||||||
|
let _ = fs::create_dir_all(f.clone());
|
||||||
|
}
|
||||||
|
match &*s {
|
||||||
|
"n1" => f + &"notify_cid.txt",
|
||||||
|
"n2" => f + &"notify_cid_run.txt",
|
||||||
|
_ => f + &s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn new() -> Result<Self, ConfigError> {
|
||||||
|
let d = data_file("json");
|
||||||
|
let s = Config::builder()
|
||||||
|
.add_source(File::with_name(&d))
|
||||||
|
.add_source(config::Environment::with_prefix("APP"))
|
||||||
|
.build()?;
|
||||||
|
s.try_deserialize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
pub fn new() -> Result<Self, ConfigError> {
|
||||||
|
let d = data_file("toml");
|
||||||
|
let s = Config::builder()
|
||||||
|
.add_source(File::with_name(&d))
|
||||||
|
.add_source(config::Environment::with_prefix("APP"))
|
||||||
|
.build()?;
|
||||||
|
s.try_deserialize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Token {
|
||||||
|
pub did: String,
|
||||||
|
pub handle: String,
|
||||||
|
pub accessJwt: String,
|
||||||
|
pub refreshJwt: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Data {
|
||||||
|
pub host: String,
|
||||||
|
pub did: String,
|
||||||
|
pub handle: String,
|
||||||
|
pub access: String,
|
||||||
|
pub refresh: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BaseUrl {
|
||||||
|
pub profile_get: String,
|
||||||
|
pub thread_get: String,
|
||||||
|
pub describe: String,
|
||||||
|
pub record_list: String,
|
||||||
|
pub record_create: String,
|
||||||
|
pub record_delete: String,
|
||||||
|
pub session_create: String,
|
||||||
|
pub session_refresh: String,
|
||||||
|
pub session_get: String,
|
||||||
|
pub timeline_get: String,
|
||||||
|
pub timeline_author: String,
|
||||||
|
pub upload_blob: String,
|
||||||
|
pub update_handle: String,
|
||||||
|
pub account_create: String,
|
||||||
|
pub notify_count: String,
|
||||||
|
pub notify_list: String,
|
||||||
|
pub notify_update: String,
|
||||||
|
pub repo_update: String,
|
||||||
|
pub like: String,
|
||||||
|
pub repost: String,
|
||||||
|
pub follow: String,
|
||||||
|
pub follows: String,
|
||||||
|
pub followers: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn url(s: &str) -> String {
|
||||||
|
let s = String::from(s);
|
||||||
|
let data = Data::new().unwrap();
|
||||||
|
let data = Data {
|
||||||
|
host: data.host,
|
||||||
|
handle: data.handle,
|
||||||
|
did: data.did,
|
||||||
|
access: data.access,
|
||||||
|
refresh: data.refresh,
|
||||||
|
};
|
||||||
|
let t = "https://".to_string() + &data.host.to_string() + &"/xrpc/".to_string();
|
||||||
|
let baseurl = BaseUrl {
|
||||||
|
profile_get: "com.atproto.identity.resolveHandle".to_string(),
|
||||||
|
thread_get: "app.bsky.feed.getPostThread".to_string(),
|
||||||
|
record_create: "com.atproto.repo.createRecord".to_string(),
|
||||||
|
record_delete: "com.atproto.repo.deleteRecord".to_string(),
|
||||||
|
describe: "com.atproto.repo.describeRepo".to_string(),
|
||||||
|
record_list: "com.atproto.repo.listRecords".to_string(),
|
||||||
|
session_create: "com.atproto.server.createSession".to_string(),
|
||||||
|
session_refresh: "com.atproto.server.refreshSession".to_string(),
|
||||||
|
session_get: "com.atproto.server.getSession".to_string(),
|
||||||
|
timeline_get: "app.bsky.feed.getTimeline".to_string(),
|
||||||
|
timeline_author: "app.bsky.feed.getAuthorFeed".to_string(),
|
||||||
|
like: "app.bsky.feed.like".to_string(),
|
||||||
|
repost: "app.bsky.feed.repost".to_string(),
|
||||||
|
follow: "app.bsky.graph.follow".to_string(),
|
||||||
|
follows: "app.bsky.graph.getFollows".to_string(),
|
||||||
|
followers: "app.bsky.graph.getFollowers".to_string(),
|
||||||
|
upload_blob: "com.atproto.repo.uploadBlob".to_string(),
|
||||||
|
account_create: "com.atproto.server.createAccount".to_string(),
|
||||||
|
update_handle: "com.atproto.identity.updateHandle".to_string(),
|
||||||
|
notify_count: "app.bsky.notification.getUnreadCount".to_string(),
|
||||||
|
notify_list: "app.bsky.notification.listNotifications".to_string(),
|
||||||
|
notify_update: "app.bsky.notification.updateSeen".to_string(),
|
||||||
|
repo_update: "com.atproto.sync.updateRepo".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match &*s {
|
||||||
|
"profile_get" => t.to_string() + &baseurl.profile_get,
|
||||||
|
"thread_get" => t.to_string() + &baseurl.thread_get,
|
||||||
|
"describe" => t.to_string() + &baseurl.describe,
|
||||||
|
"record_list" => t.to_string() + &baseurl.record_list,
|
||||||
|
"record_create" => t.to_string() + &baseurl.record_create,
|
||||||
|
"record_delete" => t.to_string() + &baseurl.record_delete,
|
||||||
|
"session_create" => t.to_string() + &baseurl.session_create,
|
||||||
|
"session_refresh" => t.to_string() + &baseurl.session_refresh,
|
||||||
|
"session_get" => t.to_string() + &baseurl.session_get,
|
||||||
|
"timeline_get" => t.to_string() + &baseurl.timeline_get,
|
||||||
|
"timeline_author" => t.to_string() + &baseurl.timeline_get,
|
||||||
|
"upload_blob" => t.to_string() + &baseurl.upload_blob,
|
||||||
|
"account_create" => t.to_string() + &baseurl.account_create,
|
||||||
|
"update_handle" => t.to_string() + &baseurl.update_handle,
|
||||||
|
"notify_list" => t.to_string() + &baseurl.notify_list,
|
||||||
|
"notify_count" => t.to_string() + &baseurl.notify_count,
|
||||||
|
"notify_update" => t.to_string() + &baseurl.notify_update,
|
||||||
|
"repo_update" => t.to_string() + &baseurl.repo_update,
|
||||||
|
"like" => t.to_string() + &baseurl.like,
|
||||||
|
"repost" => t.to_string() + &baseurl.repost,
|
||||||
|
"follow" => t.to_string() + &baseurl.follow,
|
||||||
|
"follows" => t.to_string() + &baseurl.follows,
|
||||||
|
"followers" => t.to_string() + &baseurl.followers,
|
||||||
|
_ => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_toml(s: &str) -> String {
|
||||||
|
let s = String::from(s);
|
||||||
|
let data = Data::new().unwrap();
|
||||||
|
let data = Data {
|
||||||
|
host: data.host,
|
||||||
|
handle: data.handle,
|
||||||
|
did: data.did,
|
||||||
|
access: data.access,
|
||||||
|
refresh: data.refresh,
|
||||||
|
};
|
||||||
|
match &*s {
|
||||||
|
"host" => data.handle,
|
||||||
|
"handle" => data.handle,
|
||||||
|
"did" => data.did,
|
||||||
|
"access" => data.access,
|
||||||
|
"refresh" => data.refresh,
|
||||||
|
_ => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Notify {
|
||||||
|
pub notifications: Vec<Notifications>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Status {
|
||||||
|
pub handle: String,
|
||||||
|
pub did: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct DidDocs {
|
||||||
|
pub verificationMethod: Vec<VerificationMethod>,
|
||||||
|
pub service: Vec<Service>,
|
||||||
|
pub id: String,
|
||||||
|
pub alsoKnownAs: Vec<AlsoKnownAs>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct VerificationMethod {
|
||||||
|
pub id: String,
|
||||||
|
pub r#type: String,
|
||||||
|
pub controller: String,
|
||||||
|
pub publicKeyMultibase: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Service {
|
||||||
|
pub id: String,
|
||||||
|
pub r#type: String,
|
||||||
|
pub serviceEndpoint: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct AlsoKnownAs {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Timeline {
|
||||||
|
pub feed: Vec<Feed>
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Session {
|
||||||
|
pub did: String,
|
||||||
|
pub email: String,
|
||||||
|
pub handle: String,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Follow {
|
||||||
|
pub follows: Vec<Author>,
|
||||||
|
pub cursor: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Notifications {
|
||||||
|
pub uri: String,
|
||||||
|
pub cid: String,
|
||||||
|
pub author: Author,
|
||||||
|
pub reason: String,
|
||||||
|
//pub reasonSubject: String,
|
||||||
|
pub record: Record,
|
||||||
|
pub isRead: bool,
|
||||||
|
pub indexedAt: String,
|
||||||
|
//pub labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Thread {
|
||||||
|
pub r#type: String,
|
||||||
|
pub post: String,
|
||||||
|
pub root: String,
|
||||||
|
pub author: Author,
|
||||||
|
pub reason: String,
|
||||||
|
//pub reasonSubject: String,
|
||||||
|
pub record: Record,
|
||||||
|
pub isRead: bool,
|
||||||
|
pub indexedAt: String,
|
||||||
|
//pub labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Author {
|
||||||
|
pub did: String,
|
||||||
|
//pub declaration: Declaration,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub displayName: Option<String>,
|
||||||
|
pub handle: String,
|
||||||
|
pub avatar: Option<String>,
|
||||||
|
pub viewer: Viewer,
|
||||||
|
//pub labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Labels {
|
||||||
|
pub src: Option<String>,
|
||||||
|
pub uri: Option<String>,
|
||||||
|
pub cid: Option<String>,
|
||||||
|
pub val: Option<String>,
|
||||||
|
pub cts: Option<String>,
|
||||||
|
pub neg: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Declaration {
|
||||||
|
pub actorType: String,
|
||||||
|
pub cid: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Viewer {
|
||||||
|
pub muted: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Record {
|
||||||
|
pub text: Option<String>,
|
||||||
|
pub createdAt: String,
|
||||||
|
pub reply: Option<Reply>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Reply {
|
||||||
|
pub parent: ReplyParent,
|
||||||
|
pub root: ReplyRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ReplyRoot {
|
||||||
|
pub cid: String,
|
||||||
|
pub uri: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ReplyParent {
|
||||||
|
pub cid: String,
|
||||||
|
pub uri: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Langs {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Feed {
|
||||||
|
pub post: Post,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Post {
|
||||||
|
pub did: Option<String>,
|
||||||
|
pub uri: String,
|
||||||
|
pub cid: String,
|
||||||
|
pub collection: Option<String>,
|
||||||
|
pub record: Record,
|
||||||
|
pub author: Author,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub indexedAt: String,
|
||||||
|
pub replyCount: i32,
|
||||||
|
pub postCount: Option<i32>,
|
||||||
|
pub repostCount: i32,
|
||||||
|
pub likeCount: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Cid {
|
||||||
|
pub cid: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Img {
|
||||||
|
pub blob: Blob
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Blob {
|
||||||
|
pub r#ref: Ref,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Ref {
|
||||||
|
pub link: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Handle {
|
||||||
|
pub handle: String
|
||||||
|
}
|
||||||
|
|
||||||
|
//#[derive(Serialize, Deserialize)]
|
||||||
|
//pub struct Did {
|
||||||
|
// pub did: String
|
||||||
|
//}
|
||||||
|
|
||||||
|
//#[derive(Serialize, Deserialize)]
|
||||||
|
//pub struct Labels {
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//#[derive(Serialize, Deserialize)]
|
||||||
|
//pub struct Viewer {
|
||||||
|
// pub muted: bool,
|
||||||
|
// pub blockedBy: bool,
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct ProfileIdentityResolve {
|
||||||
|
pub did: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Profile {
|
||||||
|
pub did: String,
|
||||||
|
pub handle: String,
|
||||||
|
pub followsCount: Option<i32>,
|
||||||
|
pub followersCount: Option<i32>,
|
||||||
|
pub postsCount: i32,
|
||||||
|
pub indexedAt: Option<String>,
|
||||||
|
pub avatar: Option<String>,
|
||||||
|
pub banner: Option<String>,
|
||||||
|
pub displayName: Option<String>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub viewer: Viewer,
|
||||||
|
pub labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c_char(i: String) -> String {
|
||||||
|
let l = 250;
|
||||||
|
let mut s = String::new();
|
||||||
|
for ii in i.chars().enumerate() {
|
||||||
|
match ii.0 {
|
||||||
|
n if n > l.try_into().unwrap() => {break}
|
||||||
|
_ => {s.push(ii.1)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn w_cfg(h: &str, res: &str) {
|
||||||
|
let f = data_file(&"json");
|
||||||
|
let ff = data_file(&"toml");
|
||||||
|
let mut f = fs::File::create(f.clone()).unwrap();
|
||||||
|
let mut ff = fs::File::create(ff.clone()).unwrap();
|
||||||
|
f.write_all(&res.as_bytes()).unwrap();
|
||||||
|
let json: Token = serde_json::from_str(&res).unwrap();
|
||||||
|
let datas = Data {
|
||||||
|
host: h.to_string(),
|
||||||
|
did: json.did.to_string(),
|
||||||
|
handle: json.handle.to_string(),
|
||||||
|
access: json.accessJwt.to_string(),
|
||||||
|
refresh: json.refreshJwt.to_string(),
|
||||||
|
};
|
||||||
|
let toml = toml::to_string(&datas).unwrap();
|
||||||
|
ff.write_all(&toml.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn w_cid(cid :String, file: String, t: bool) -> bool {
|
||||||
|
let f = file;
|
||||||
|
let mut file = match OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.read(true)
|
||||||
|
.append(true)
|
||||||
|
.open(f.clone())
|
||||||
|
{
|
||||||
|
Err(why) => panic!("Couldn't open {}: {}", f, why),
|
||||||
|
Ok(file) => file,
|
||||||
|
};
|
||||||
|
let mut contents = String::new();
|
||||||
|
|
||||||
|
match file.read_to_string(&mut contents) {
|
||||||
|
Err(why) => panic!("Couldn't read {}: {}", f, why),
|
||||||
|
Ok(_) => (),
|
||||||
|
}
|
||||||
|
if contents.contains(&cid) == false {
|
||||||
|
if t {
|
||||||
|
let cid = cid + "\n";
|
||||||
|
match file.write_all(cid.as_bytes()) {
|
||||||
|
Err(why) => panic!("Couldn't write \"{}\" to {}: {}", contents, f, why),
|
||||||
|
Ok(_) => println!("finished"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let check = false;
|
||||||
|
return check
|
||||||
|
} else {
|
||||||
|
let check = true;
|
||||||
|
return check
|
||||||
|
}
|
||||||
|
}
|
221
src/main.rs
Normal file
221
src/main.rs
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
|
||||||
|
use seahorse::{App, Command, Context, Flag, FlagType};
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use crate::ascii::c_ascii;
|
||||||
|
use crate::data::data_toml;
|
||||||
|
use crate::data::log_file;
|
||||||
|
use crate::data::url;
|
||||||
|
use crate::data::w_cfg;
|
||||||
|
use crate::data::w_cid;
|
||||||
|
use crate::data::c_char;
|
||||||
|
use data::Notify as Notify;
|
||||||
|
|
||||||
|
pub mod data;
|
||||||
|
pub mod refresh;
|
||||||
|
pub mod token;
|
||||||
|
pub mod notify;
|
||||||
|
pub mod notify_read;
|
||||||
|
pub mod reply;
|
||||||
|
pub mod reply_link;
|
||||||
|
pub mod ascii;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let app = App::new(env!("CARGO_PKG_NAME"))
|
||||||
|
.command(
|
||||||
|
Command::new("ai")
|
||||||
|
.alias("a")
|
||||||
|
.action(c_ascii_art)
|
||||||
|
.flag(
|
||||||
|
Flag::new("type", FlagType::Bool)
|
||||||
|
.description("type flag")
|
||||||
|
.alias("t"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.command(
|
||||||
|
Command::new("token")
|
||||||
|
.alias("t")
|
||||||
|
.description("handle\n\t\t\t$ ai t yui.syui.ai -p password\n\t\t\t$ ai t yui.syui.ai -p password -s bsky.social")
|
||||||
|
.action(c_token)
|
||||||
|
.flag(
|
||||||
|
Flag::new("password", FlagType::String)
|
||||||
|
.description("password flag")
|
||||||
|
.alias("p"),
|
||||||
|
)
|
||||||
|
.flag(
|
||||||
|
Flag::new("server", FlagType::String)
|
||||||
|
.description("server flag")
|
||||||
|
.alias("s"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.command(
|
||||||
|
Command::new("refresh")
|
||||||
|
.alias("r")
|
||||||
|
.description("refresh\n\t\t\t$ ai r\n\t\t\t$ ai r -s bsky.social")
|
||||||
|
.action(c_refresh)
|
||||||
|
.flag(
|
||||||
|
Flag::new("server", FlagType::String)
|
||||||
|
.description("server flag")
|
||||||
|
.alias("s"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.command(
|
||||||
|
Command::new("notify")
|
||||||
|
.alias("n")
|
||||||
|
.description("notify\n\t\t\t$ ai n")
|
||||||
|
.action(c_notify),
|
||||||
|
)
|
||||||
|
.command(
|
||||||
|
Command::new("bot")
|
||||||
|
.alias("b")
|
||||||
|
.description("bot\n\t\t\t$ ai b\n\t\t\t$ ai b -s bsky.social")
|
||||||
|
.action(c_bot)
|
||||||
|
.flag(
|
||||||
|
Flag::new("server", FlagType::String)
|
||||||
|
.description("server flag")
|
||||||
|
.alias("s"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
app.run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_ascii_art(c: &Context) {
|
||||||
|
c_ascii(c.bool_flag("type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn token(c: &Context) {
|
||||||
|
let m = c.args[0].to_string();
|
||||||
|
let h = async {
|
||||||
|
if let Ok(p) = c.string_flag("password") {
|
||||||
|
if let Ok(s) = c.string_flag("server") {
|
||||||
|
let res = token::post_request(m.to_string(), p.to_string(), s.to_string()).await;
|
||||||
|
w_cfg(&s, &res)
|
||||||
|
} else {
|
||||||
|
let res = token::post_request(m.to_string(), p.to_string(), "bsky.social".to_string()).await;
|
||||||
|
w_cfg(&"bsky.social", &res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_token(c: &Context) {
|
||||||
|
token(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn refresh(c: &Context) {
|
||||||
|
let h = async {
|
||||||
|
let res = refresh::post_request().await;
|
||||||
|
if let Ok(s) = c.string_flag("server") {
|
||||||
|
w_cfg(&s, &res)
|
||||||
|
} else {
|
||||||
|
w_cfg("bsky.social", &res)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_refresh(c: &Context) {
|
||||||
|
refresh(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify() {
|
||||||
|
let h = async {
|
||||||
|
let j = notify::get_request(100).await;
|
||||||
|
println!("{}", j);
|
||||||
|
};
|
||||||
|
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_notify(_c: &Context) {
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bot(c: &Context) {
|
||||||
|
|
||||||
|
let h = async {
|
||||||
|
let server = "bsky.social";
|
||||||
|
let mut notify = notify::get_request(100).await;
|
||||||
|
if notify == "err" {
|
||||||
|
if let Ok(s) = c.string_flag("server") {
|
||||||
|
let res = refresh::post_request().await;
|
||||||
|
w_cfg(&s, &res);
|
||||||
|
} else {
|
||||||
|
let res = refresh::post_request().await;
|
||||||
|
w_cfg(&server, &res);
|
||||||
|
}
|
||||||
|
notify = notify::get_request(100).await;
|
||||||
|
}
|
||||||
|
let notify: Notify = serde_json::from_str(¬ify).unwrap();
|
||||||
|
|
||||||
|
let n = notify.notifications;
|
||||||
|
let length = &n.len();
|
||||||
|
let reason = &n[0].reason;
|
||||||
|
let handle = &n[0].author.handle;
|
||||||
|
let did = &n[0].author.did;
|
||||||
|
let read = n[0].isRead;
|
||||||
|
let cid = &n[0].cid;
|
||||||
|
let uri = &n[0].uri;
|
||||||
|
let time = &n[0].indexedAt;
|
||||||
|
let mut cid_root = cid;
|
||||||
|
let mut uri_root = uri;
|
||||||
|
let check_cid = w_cid(cid.to_string(), log_file(&"n1"), false);
|
||||||
|
let check_cid_run = w_cid(cid.to_string(), log_file(&"n2"), false);
|
||||||
|
// thread
|
||||||
|
if ! n[0].record.reply.is_none() {
|
||||||
|
cid_root = &n[0].record.reply.as_ref().unwrap().root.cid;
|
||||||
|
uri_root = &n[0].record.reply.as_ref().unwrap().root.uri;
|
||||||
|
}
|
||||||
|
println!("{}", length);
|
||||||
|
println!("{}", reason);
|
||||||
|
println!("{}", handle);
|
||||||
|
println!("{}", did);
|
||||||
|
println!("{}", read);
|
||||||
|
println!("{} {}", cid, uri);
|
||||||
|
let mut text = "";
|
||||||
|
if ! n[0].record.text.is_none() {
|
||||||
|
text = &n[0].record.text.as_ref().unwrap();
|
||||||
|
}
|
||||||
|
let vec: Vec<&str> = text.split_whitespace().collect();
|
||||||
|
let rep_com = &vec[0..].join(" ");
|
||||||
|
|
||||||
|
if check_cid == false && { reason == "mention" || reason == "reply" } || check_cid_run == false && { reason == "mention" || reason == "reply" } {
|
||||||
|
w_cid(cid.to_string(), log_file(&"n2"), true);
|
||||||
|
if rep_com.contains("did") == true || rep_com.contains("/did") == true {
|
||||||
|
let link = "https://plc.directory/".to_owned() + &did + &"/log";
|
||||||
|
let s = 0;
|
||||||
|
let e = link.chars().count();
|
||||||
|
println!("{}", link);
|
||||||
|
println!("{}", e);
|
||||||
|
|
||||||
|
let d = "\n".to_owned() + &did.to_string();
|
||||||
|
println!("{}", d);
|
||||||
|
let text_limit = c_char(d);
|
||||||
|
println!("{}", text_limit);
|
||||||
|
|
||||||
|
if text_limit.len() > 3 {
|
||||||
|
let str_rep = reply_link::post_request(text_limit.to_string(), link.to_string(), s, e.try_into().unwrap(), cid.to_string(), uri.to_string(), cid_root.to_string(), uri_root.to_string()).await;
|
||||||
|
println!("{}", str_rep);
|
||||||
|
let str_notify = notify_read::post_request(time.to_string()).await;
|
||||||
|
println!("{}", str_notify);
|
||||||
|
|
||||||
|
w_cid(cid.to_string(), log_file(&"n1"), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||||
|
return res
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bot(c: &Context) {
|
||||||
|
loop {
|
||||||
|
bot(c);
|
||||||
|
}
|
||||||
|
}
|
31
src/notify.rs
Normal file
31
src/notify.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use crate::data_toml;
|
||||||
|
use crate::url;
|
||||||
|
//use serde_json::json;
|
||||||
|
|
||||||
|
pub async fn get_request(limit: i32, ) -> String {
|
||||||
|
|
||||||
|
let token = data_toml(&"access");
|
||||||
|
let url = url(&"notify_list");
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.get(url)
|
||||||
|
.query(&[("limit", limit)])
|
||||||
|
.header("Authorization", "Bearer ".to_owned() + &token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let status_ref = res.error_for_status_ref();
|
||||||
|
|
||||||
|
match status_ref {
|
||||||
|
Ok(_) => {
|
||||||
|
return res.text().await.unwrap();
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
let e = "err".to_string();
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/notify_read.rs
Normal file
28
src/notify_read.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use crate::data_toml;
|
||||||
|
use crate::url;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
pub async fn post_request(time: String) -> String {
|
||||||
|
|
||||||
|
let token = data_toml(&"access");
|
||||||
|
let url = url(&"notify_update");
|
||||||
|
|
||||||
|
let post = Some(json!({
|
||||||
|
"seenAt": time.to_string(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.post(url)
|
||||||
|
.json(&post)
|
||||||
|
.header("Authorization", "Bearer ".to_owned() + &token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
21
src/refresh.rs
Normal file
21
src/refresh.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use crate::data_toml;
|
||||||
|
use crate::url;
|
||||||
|
|
||||||
|
pub async fn post_request() -> String {
|
||||||
|
let refresh = data_toml(&"refresh");
|
||||||
|
let url = url(&"session_refresh");
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.post(url)
|
||||||
|
.header("Authorization", "Bearer ".to_owned() + &refresh)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
53
src/reply.rs
Normal file
53
src/reply.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use crate::data_toml;
|
||||||
|
use crate::url;
|
||||||
|
use serde_json::json;
|
||||||
|
use iso8601_timestamp::Timestamp;
|
||||||
|
|
||||||
|
pub async fn post_request(text: String, cid: String, uri: String, cid_root: String, uri_root: String) -> String {
|
||||||
|
|
||||||
|
let token = data_toml(&"access");
|
||||||
|
let did = data_toml(&"did");
|
||||||
|
let handle = data_toml(&"handle");
|
||||||
|
|
||||||
|
let url = url(&"record_create");
|
||||||
|
//let url = "https://bsky.social/xrpc/com.atproto.repo.createRecord";
|
||||||
|
let col = "app.bsky.feed.post".to_string();
|
||||||
|
|
||||||
|
let d = Timestamp::now_utc();
|
||||||
|
let d = d.to_string();
|
||||||
|
|
||||||
|
let post = Some(json!({
|
||||||
|
"repo": handle.to_string(),
|
||||||
|
"did": did.to_string(),
|
||||||
|
"collection": col.to_string(),
|
||||||
|
"record": {
|
||||||
|
"text": text.to_string(),
|
||||||
|
"createdAt": d.to_string(),
|
||||||
|
"reply": {
|
||||||
|
"root": {
|
||||||
|
"cid": cid_root.to_string(),
|
||||||
|
"uri": uri_root.to_string()
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"cid": cid.to_string(),
|
||||||
|
"uri": uri.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.post(url)
|
||||||
|
.json(&post)
|
||||||
|
.header("Authorization", "Bearer ".to_owned() + &token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
66
src/reply_link.rs
Normal file
66
src/reply_link.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use crate::data_toml;
|
||||||
|
use crate::url;
|
||||||
|
use serde_json::json;
|
||||||
|
use iso8601_timestamp::Timestamp;
|
||||||
|
|
||||||
|
pub async fn post_request(text: String, link: String, s: i32, e: i32, cid: String, uri: String, cid_root: String, uri_root: String) -> String {
|
||||||
|
|
||||||
|
let token = data_toml(&"access");
|
||||||
|
let did = data_toml(&"did");
|
||||||
|
let handle = data_toml(&"handle");
|
||||||
|
|
||||||
|
let url = url(&"record_create");
|
||||||
|
let col = "app.bsky.feed.post".to_string();
|
||||||
|
|
||||||
|
let d = Timestamp::now_utc();
|
||||||
|
let d = d.to_string();
|
||||||
|
|
||||||
|
let post = Some(json!({
|
||||||
|
"repo": handle.to_string(),
|
||||||
|
"did": did.to_string(),
|
||||||
|
"collection": col.to_string(),
|
||||||
|
"record": {
|
||||||
|
"text": link.to_string() + &" ".to_string() + &text.to_string(),
|
||||||
|
"createdAt": d.to_string(),
|
||||||
|
"reply": {
|
||||||
|
"root": {
|
||||||
|
"cid": cid_root.to_string(),
|
||||||
|
"uri": uri_root.to_string()
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"cid": cid.to_string(),
|
||||||
|
"uri": uri.to_string()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"facets": [
|
||||||
|
{
|
||||||
|
"index": {
|
||||||
|
"byteStart": s,
|
||||||
|
"byteEnd": e
|
||||||
|
},
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"$type": "app.bsky.richtext.facet#link",
|
||||||
|
"uri": link.to_string()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.post(url)
|
||||||
|
.json(&post)
|
||||||
|
.header("Authorization", "Bearer ".to_owned() + &token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
24
src/token.rs
Normal file
24
src/token.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
extern crate reqwest;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub async fn post_request(handle: String, pass: String, host: String) -> String {
|
||||||
|
|
||||||
|
let url = "https://".to_owned() + &host.to_string() + &"/xrpc/com.atproto.server.createSession".to_string();
|
||||||
|
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert("identifier", &handle);
|
||||||
|
map.insert("password", &pass);
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client
|
||||||
|
.post(url)
|
||||||
|
.json(&map)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user