diff --git a/.config/keep b/.config/keep
new file mode 100644
index 0000000..e69de29
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..784ebc7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+Cargo.lock
+target
+*.json
+*.DS_Store
+**.DS_Store
+scpt/json/
+.config/ai/*.toml
+.config/ai/*.json
+.config/ai/txt
+.config/ai/png
+.ssh
+.env
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..1e7a59e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule ".config/ai/scpt"]
+	path = .config/ai/scpt
+	url = git@git.syui.ai:ai/bot_scpt.git
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..f2a14be
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,19 @@
+[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 = "*"
+sysinfo = "*"
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..df71fd2
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,8 @@
+FROM syui/aios
+ADD .ssh /root/.ssh
+
+WORKDIR /root
+ADD ./test/entrypoint.sh .
+RUN chmod +x /root/entrypoint.sh
+
+ENTRYPOINT ["/root/entrypoint.sh"]
diff --git a/Makefile.toml b/Makefile.toml
new file mode 100644
index 0000000..83c5c1f
--- /dev/null
+++ b/Makefile.toml
@@ -0,0 +1,25 @@
+[tasks.format]
+install_crate = "rustfmt"
+command = "cargo"
+args = ["fmt", "--", "--emit=files"]
+
+[tasks.clean]
+command = "cargo"
+args = ["clean"]
+
+[tasks.build]
+command = "cargo"
+args = ["build"]
+dependencies = ["clean"]
+
+[tasks.test]
+command = "cargo"
+args = ["test"]
+dependencies = ["clean"]
+
+[tasks.my-flow]
+dependencies = [
+    "format",
+    "build",
+    "test"
+]
diff --git a/README.md b/README.md
index c7b3451..23bd1aa 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,86 @@
 ## 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
+```
+
+### logo
+
 ```sh
 $ cargo build
-$ ./target/debug/ai
+$ ./target/debug/ai ai
 ```
+
+```sh
+$ ai ai -t avatar
+```
+
+### login
+
+```sh
+# ai login $handle -p $password
+$ ai l yui.syui.ai -p password
+
+$ cat ~/.config/ai/token.toml
+```
+
+```sh
+# ai l $handle -p $password -s $server
+$ ai l ai.syu.is -p password -s syu.is
+```
+
+### refresh
+
+```
+$ ai r
+```
+
+### notify
+
+```
+$ ai n
+```
+
+```
+$ ai n | jq .
+```
+
+### bot
+
+```
+$ ai bot
+```
+
+|command|sub|type|body|
+|---|---|---|---|
+|@yui.syui.ai did||mention, reply| [plc.directory](https://plc.directory)/$did/log |
+|@yui.syui.ai card|r, s, b|mention, reply| https://card.syui.ai |
+|@yui.syui.ai ten|start, d, p|mention, reply| https://card.syui.ai |
+|@yui.syui.ai fav|{cid}|mention, reply| https://card.syui.ai |
+|@yui.syui.ai egg|{password}|mention, reply| https://card.syui.ai |
+|@yui.syui.ai 占い||mention, reply| https://yui.syui.ai |
+|@yui.syui.ai nyan|🍰|mention, reply| https://yui.syui.ai |
+|@yui.syui.ai diffusers|{keyword}|mention, reply| [diffusers](https://huggingface.co/docs/diffusers/index) |
+|@yui.syui.ai sh(admin)|{command}|mention, reply| [archlinux](https://wiki.archlinux.org/title/Systemd-nspawn) |
+
+### test
+
+`zsh`
+
+```sh
+$ ./test/ai.zsh t
+```
+
+### make
+
+```sh
+$ cargo install --force cargo-make
+$ cargo make build
+```
+
diff --git a/compose.yml b/compose.yml
new file mode 100644
index 0000000..2d6c159
--- /dev/null
+++ b/compose.yml
@@ -0,0 +1,11 @@
+services:
+  aios:
+    #image: syui/aios
+    #command: ai bot -a syui.syu.is
+    build:
+      context: .
+    restart: always
+    env_file:
+      - .env
+    volumes:
+      - ./.config:/root/.config
diff --git a/docs/wiki.md b/docs/wiki.md
new file mode 100644
index 0000000..cd2152b
--- /dev/null
+++ b/docs/wiki.md
@@ -0,0 +1,52 @@
+### docker
+
+```sh
+$ docker run -it syui/aios ai
+$ docker run -it -d syui/aios zsh -c "ai login <handle> -p <password> && ai bot"
+```
+
+```sh
+$ cp -rf ~/.config/ai ./.config/
+
+$ docker compose up
+```
+
+### cron
+
+```sh
+$ sudo pacman -S fcron
+$ fcrontab -e
+* * * * * $HOME/bot/test/ai.zsh c
+```
+
+### ssh
+
+```sh
+$ ssh-keygen -f /.ssh/diffusers.key -t ed25519
+```
+
+```sh
+FROM syui/aios
+ADD .ssh /root/.ssh
+```
+
+```sh
+Host diffusers
+	HostName localhost
+	User root
+	IdentityFile ~/.ssh/diffusers.key
+	StrictHostKeyChecking no
+	UserKnownHostsFile /dev/null
+```
+
+```sh
+services:
+  aios:
+    #image: syui/aios
+    build:
+      context: .
+    restart: always
+    volumes:
+      - ./.config:/root/.config
+    command: ai bot -a syui.syu.is
+```
diff --git a/icon/ai.png b/icon/ai.png
new file mode 100644
index 0000000..d21dabe
Binary files /dev/null and b/icon/ai.png differ
diff --git a/icon/avatar.png b/icon/avatar.png
new file mode 100644
index 0000000..f091ef1
Binary files /dev/null and b/icon/avatar.png differ
diff --git a/k8s/aios-deployment.yaml b/k8s/aios-deployment.yaml
new file mode 100644
index 0000000..e2cdf38
--- /dev/null
+++ b/k8s/aios-deployment.yaml
@@ -0,0 +1,57 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations:
+    kompose.cmd: kompose convert -f ../compose.yml --volumes hostPath
+    kompose.version: 1.32.0 (HEAD)
+  labels:
+    io.kompose.service: aios
+  name: aios
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      io.kompose.service: aios
+  strategy:
+    type: Recreate
+  template:
+    metadata:
+      annotations:
+        kompose.cmd: kompose convert -f ../compose.yml --volumes hostPath
+        kompose.version: 1.32.0 (HEAD)
+      labels:
+        io.kompose.network/bot-default: "true"
+        io.kompose.service: aios
+    spec:
+      containers:
+        - env:
+            - name: ADMIN
+              valueFrom:
+                configMapKeyRef:
+                  key: ADMIN
+                  name: env
+            - name: HANDLE
+              valueFrom:
+                configMapKeyRef:
+                  key: HANDLE
+                  name: env
+            - name: HOST
+              valueFrom:
+                configMapKeyRef:
+                  key: HOST
+                  name: env
+            - name: PASSWORD
+              valueFrom:
+                configMapKeyRef:
+                  key: PASSWORD
+                  name: env
+          image: aios
+          name: aios
+          volumeMounts:
+            - mountPath: /root/.config
+              name: aios-hostpath0
+      restartPolicy: Always
+      volumes:
+        - hostPath:
+            path: /Users/syui/ai/bot/.config
+          name: aios-hostpath0
diff --git a/k8s/env-configmap.yaml b/k8s/env-configmap.yaml
new file mode 100644
index 0000000..521649b
--- /dev/null
+++ b/k8s/env-configmap.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+data:
+  ADMIN: $ADMIN
+  HANDLE: $HANDLE
+  HOST: $HOST
+  PASSWORD: $PASSWORD
+kind: ConfigMap
+metadata:
+  labels:
+    io.kompose.service: aios-env
+  name: env
diff --git a/src/ascii.rs b/src/ascii.rs
new file mode 100644
index 0000000..7d7fd46
--- /dev/null
+++ b/src/ascii.rs
@@ -0,0 +1,205 @@
+use sysinfo::System;
+
+pub fn c_ascii(x: &str) {
+    let logo = "
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠉⠀⠀⠀⠀⠀⠈⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣤⣤⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀
+⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀
+⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀
+⠀⠀⠘⠛⠛⠛⠛⠉⠉⠉⠉⠁⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠉⠉⠉⠉⠙⠛⠛⠛⠛⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+";
+
+    let avatar = "
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣁⣀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⠖⠋⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠒⢦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⢿⣷⣦⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣴⣿⠷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣶⠿⠟⠛⠛⠋⠉⠋⠉⠉⠉⠉⠙⠛⠙⠛⠛⠻⠿⢷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠚⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⡀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢠⣷⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⣿⡇⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢁⣾⣿⡆⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢰⣿⣿⣧⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⣾⣿⣿⡇⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⣾⣿⣿⣿⡄⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⣿⣿⣿⡇⣿⡿⢣⠈⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⢹⠀⣿⣿⣿⣿⣧⢹⣿⡏⢹⣿⣿⣿⠏⣼⣿⡿⠿⢿⢣⡿⣡⣿⠀⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⢃⠸⠀⣵⡶⠶⢶⣿⡆⢿⢁⠸⣿⣿⢋⣼⣯⡴⠒⠒⠒⣼⡑⢟⣿⢠⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⢿⣿⣿⣿⣿⡟⠈⣄⠈⠡⡐⢿⣦⠹⣿⡌⢸⡆⠿⣡⣾⣿⡟⢐⠇⠙⣡⡀⣿⡎⢿⠈⢐⡲⣆⢻⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢳⡘⣿⣿⣿⣿⡇⣸⣿⡄⣶⡄⠀⣿⠀⣿⣿⣜⣷⣼⣿⣿⣿⡇⢸⡇⠀⣿⠃⣿⣿⣸⠀⡌⢇⣿⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠘⣿⣿⣿⡇⣿⣿⣧⡘⢷⣾⠟⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣌⣿⣿⣃⣼⣿⣿⡟⠀⣿⣾⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡇⢸⣿⣿⣿⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠡⠾⢛⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⡘⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢃⣶⡾⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡅⢀⡹⣿⣿⣿⣿⣿⣿⣯⣛⡛⣛⣛⣭⣿⣿⣿⣿⣿⠿⢋⣤⠟⢉⠠⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠃⣸⣿⣦⡍⠛⠻⠿⣿⣿⣿⣿⣿⣿⣿⠿⠿⢛⡉⢠⡶⠋⡄⢺⣿⡀⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⣿⣿⢿⠇⣼⢹⡀⣶⣦⣭⣭⣭⣴⣶⣿⠂⡟⠀⢋⣴⡇⡇⣾⣿⡇⢻⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⣿⡿⢸⢀⠇⣸⡀⣿⣿⣿⣿⣿⣿⣿⣿⠀⣠⠀⣿⣿⡇⠀⣿⢹⣷⠸⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⠀⣿⡇⡟⠘⢠⡿⠃⣿⣿⣿⣿⣿⣿⣿⣿⡀⣤⠀⣿⣿⠃⢰⣿⠸⣿⡀⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢜⣽⠀⣿⠁⡇⡰⣢⣼⣰⣿⣿⣿⣿⣿⣿⣿⣿⣷⣌⠀⣿⣿⠀⣼⣿⡄⣿⣧⠸⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⣠⠞⣋⠀⣿⢸⠃⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣿⣿⢠⣬⣍⣁⣙⠛⠦⠹⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⢋⠜⣡⣿⣿⢠⡿⠘⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢠⣿⡇⣸⣿⣿⣿⣿⣿⣷⣦⣍⠻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⡰⢫⣾⣿⡟⣵⢸⡇⠀⢸⡿⠿⢛⣋⣉⣿⣿⣿⣿⣿⣿⣫⣭⡍⢸⣿⠇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡌⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⢃⡞⣰⣿⣿⣿⣦⡛⢸⡇⠀⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⣿⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡈⢷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡞⢡⡏⣼⣿⣿⣿⣿⣿⣿⢸⡇⠀⣭⣭⣭⣤⣶⣦⢠⣭⣙⠻⣿⣿⣿⣿⡇⣾⡇⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⡄⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡟⢰⣿⢰⣿⣿⣿⣿⣿⣿⣿⠸⣇⠀⣿⣿⣿⣿⣿⡇⢸⣿⣿⣿⡜⣿⣿⣿⡇⣿⠀⢸⣿⡿⠿⠿⠛⠿⠿⠟⣛⣛⣉⣥⣿⡈⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+
+";
+
+    let color = "
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣾⣿⣿⣿⣿⣿⣿⣧⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⡿⠟⠛⠉⠉⠉⠙⠛⠿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣤⣄⣀⣀⣠⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠛⠛⠛⠛⠉⠉⠉⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠉⠉⠉⠙⠛⠛⠛⠛⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠻⠿⠿⠿⠿⠟⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+    ";
+
+    let avatar_color = "
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡤⠖⠊⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠁⠒⠦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠿⣷⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣴⡿⠷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⡶⠾⠟⠛⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠛⠛⠿⠷⣶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠊⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⣴⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⢀⣧⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⣸⣿⡆⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⣾⣿⡀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⢠⣿⣿⣧⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⣼⣿⣿⡇⣿⣿⡿⠛⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⠃⣼⣿⣿⣿⡀⣿⣿⣿⣿⣿⣿⣿⣿⠃⣰⣿⣿⣿⠇⣿⡿⢡⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡏⢸⠀⣿⡿⢿⣿⣇⠸⣿⠏⢹⣿⣿⣿⠃⣰⣿⠿⠿⠿⢀⡟⢡⣿⠀⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⠃⠘⠀⣤⠶⠶⢦⣿⡆⢻⠀⠘⣿⣿⠃⣴⣯⡴⠒⠒⠂⠜⡀⠛⣿⠀⣿⠿⢿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⢻⣿⣿⣿⣿⡏⠈⡀⠀⠡⠀⠶⣆⠹⣿⡌⢸⡄⠿⢡⣾⣿⡏⠐⠂⠘⣁⠀⣿⡄⢿⠀⠐⠒⡆⢹⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⠈⣿⣿⣿⣿⡇⢰⣿⡀⢰⠀⠀⣹⠀⣿⣷⣌⣷⣴⣿⣿⣿⡇⢸⡀⠀⣸⠀⣿⣷⣸⠀⡌⠃⡿⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠈⢿⣿⣿⡇⢹⣿⣧⠘⢷⢶⠋⣰⣿⣿⣿⣿⣿⣿⣿⣿⣷⣌⡛⠚⢁⣼⣿⣿⡏⠀⣿⣾⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣿⡇⢸⣿⣿⣿⣾⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠠⠞⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢷⡈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡁⢀⠙⢿⣿⣿⣿⣿⣿⣍⣛⠛⢛⣋⣩⣿⣿⣿⣿⣿⠿⠋⠀⠀⢀⠀⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⣸⣷⣤⡉⠛⠻⠿⣿⣿⣿⣿⣿⣿⡿⠿⠟⠛⠉⠀⠀⠀⡀⢰⣿⠀⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⣿⣿⢻⠃⠈⠀⠀⣶⣤⣤⣭⣭⣴⣶⣾⠀⠌⠀⢀⣴⡆⠃⣸⢿⡆⢸⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⣿⡏⢸⠀⠃⠐⠀⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⣿⣿⠁⠀⡇⢸⣇⠘⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⣿⠇⡄⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⠀⣄⠀⣿⣿⠀⢀⣧⠈⣿⠀⢿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣹⠀⣿⠀⡇⠠⢀⣴⣠⣿⣿⣿⣿⣿⣿⣿⣿⣷⣌⠀⣿⣿⠀⣸⣿⠀⢿⣇⠘⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠄⡠⠞⣋⠀⡿⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣿⡟⢠⣤⣈⣁⡈⠛⠂⠹⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⢂⠔⣡⣾⡯⠀⡇⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣿⡇⢸⣿⣿⣿⣿⣿⣶⣦⣈⠛⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠎⡠⢃⣼⣿⠟⣰⠀⡇⠀⢸⡿⠿⠛⣋⣉⣻⣿⣿⣿⣿⡿⢋⣤⡍⢰⣿⠃⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⡌⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⢁⠜⣰⣿⣿⣿⣤⡙⠘⡇⠀⣼⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⡿⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠈⢧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡜⢠⠎⣰⣿⣿⣿⣿⣿⣿⠀⡇⠀⣉⣩⣥⣤⣤⡄⢠⣍⣙⠻⢿⣿⣿⣿⡇⢸⠇⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⡄⢳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡞⢠⣿⢠⣿⣿⣿⣿⣿⣿⣿⠀⡇⠀⣿⣿⣿⣿⣿⡇⢸⣿⣿⣿⡘⣿⣿⣿⠃⡿⠀⢸⣿⡿⠿⠛⠛⠛⠿⠛⢛⣋⣉⣀⣿⠀⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+    ";
+
+    let mut sys = System::new_all();
+    sys.refresh_all();
+
+    let s = x.to_string();
+    match &*s {
+        "logo" => println!("{}", logo),
+        "color" => println!("{}", color),
+        "avatar" => println!("{}", avatar),
+        "avatar_color" => println!("{}", avatar_color),
+        "os" => println!("{}\n\t", color),
+        _ => println!("not matched"),
+    }
+
+    println!("total memory: {} bytes", sys.total_memory());
+    println!("System name:             {:?}", System::name().unwrap());
+    println!(
+        "System kernel version:   {:?}",
+        System::kernel_version().unwrap()
+    );
+    //println!("System OS version:       {:?}", System::os_version().unwrap());
+    println!(
+        "System host name:        {:?}",
+        System::host_name().unwrap()
+    );
+    println!("NB CPUs: {}", sys.cpus().len());
+
+    //let disks = Disks::new_with_refreshed_list();
+    //for disk in &disks {
+    //    println!("{disk:?}");
+    //}
+
+    //let networks = Networks::new_with_refreshed_list();
+    //println!("=> networks:");
+    //for (interface_name, data) in &networks {
+    //    println!("{interface_name}: {}/{} B", data.received(), data.transmitted());
+    //}
+
+    //let components = Components::new_with_refreshed_list();
+    //println!("=> components:");
+    //for component in &components {
+    //    println!("{component:?}");
+    //}
+}
diff --git a/src/bot.rs b/src/bot.rs
new file mode 100644
index 0000000..540327e
--- /dev/null
+++ b/src/bot.rs
@@ -0,0 +1,364 @@
+use seahorse::Context;
+use std::process::Command;
+
+use crate::notify;
+use crate::notify_read;
+use crate::openai;
+use crate::refresh;
+use crate::reply;
+use crate::reply_link;
+
+use crate::data::c_char;
+use crate::data::data_scpt;
+use crate::data::log_file;
+use crate::data::w_cid;
+use crate::data::Notify;
+
+pub fn c_bot(c: &Context) {
+    let h = async {
+        let mut notify = notify::get_request(100).await;
+        if notify == "err" {
+            refresh(c);
+            notify = notify::get_request(100).await;
+        }
+        let notify: Notify = serde_json::from_str(&notify).unwrap();
+
+        let n = notify.notifications;
+        let length = &n.len();
+        let su = 0..*length;
+        for i in su {
+            let reason = &n[i].reason;
+            let handle = &n[i].author.handle;
+            let did = &n[i].author.did;
+            let read = n[i].isRead;
+            let cid = &n[i].cid;
+            let uri = &n[i].uri;
+            let time = &n[i].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[i].record.reply.is_none() {
+                cid_root = &n[i].record.reply.as_ref().unwrap().root.cid;
+                uri_root = &n[i].record.reply.as_ref().unwrap().root.uri;
+            }
+
+            let mut text = "";
+            if !n[i].record.text.is_none() {
+                text = &n[i].record.text.as_ref().unwrap();
+            }
+            let vec: Vec<&str> = text.split_whitespace().collect();
+            let handlev: Vec<&str> = handle.split('.').collect();
+            let mut handlev = handlev[0].trim().to_string();
+
+            let mut link = "https://card.syui.ai/".to_owned() + &handlev;
+            let s = 0;
+            let mut e = link.chars().count();
+
+            let mut com = "".to_string();
+            let mut prompt = "".to_string();
+            let mut prompt_sub = "".to_string();
+            let mut prompt_chat = "".to_string();
+            if reason == "mention" {
+                com = vec[1].trim().to_string();
+                prompt = vec[2..].join(" ");
+                prompt_chat = vec[1..].join(" ");
+                if vec.len() > 2 {
+                    prompt_sub = vec[3..].join(" ");
+                }
+            } else if reason == "reply" {
+                com = vec[0].trim().to_string();
+                prompt = vec[1..].join(" ");
+                prompt_chat = vec[0..].join(" ");
+                if vec.len() > 1 {
+                    prompt_sub = vec[2..].join(" ");
+                }
+            }
+
+            if prompt.is_empty() == false || com.is_empty() == false {
+                println!("{}", read);
+                println!("{}", handle);
+                println!(
+                    "cid:{}\nuri:{}\ncid_root:{}\nuri_root:{}",
+                    cid, uri, cid_root, uri_root
+                );
+                println!("reason:{}\ncom:{}\nprompt:{}", reason, com, prompt);
+                println!("prompt_sub:{}", prompt_sub);
+            }
+
+            let mut admin = "".to_string();
+            if c.string_flag("admin").is_ok() {
+                admin = c.string_flag("admin").unwrap();
+            }
+
+            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 com == "/did" || com == "did" {
+                    let link = "https://plc.directory/".to_owned() + &did + &"/log";
+                    let s = 0;
+                    let e = link.chars().count();
+                    let d = "\n".to_owned() + &did.to_string();
+                    let text_limit = c_char(d);
+                    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;
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                        println!("{}", str_rep);
+                    }
+                } else if com == "/diffusers" || com == "diffusers" {
+                    let _output = Command::new(data_scpt(&"diffusers"))
+                        .arg(&did)
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let _output = Command::new(data_scpt(&"diffusers_img"))
+                        .arg(&cid)
+                        .arg(&uri)
+                        .output()
+                        .expect("zsh");
+                    w_cid(cid.to_string(), log_file(&"n1"), true);
+                } else if com.contains("占") == true
+                    || com.contains("うらない") == true
+                    || com.contains("うらなって") == true
+                {
+                    let output = Command::new(data_scpt(&"card_fortune"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&cid)
+                        .arg(&uri)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let d = d.to_string();
+                    let text_limit = c_char(d);
+                    if text_limit.len() > 3 {
+                        println!("{}", text_limit);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if com == "/card" || com == "card" {
+                    let output = Command::new(data_scpt(&"api_card"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let dd = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(dd);
+                    if text_limit.len() > 3 {
+                        if d.contains("handle") == false {
+                            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);
+                        } else {
+                            handlev = handle.replace(".", "-").to_string();
+                            link = "https://card.syui.ai/".to_owned() + &handlev;
+                            e = link.chars().count();
+                            let str_rep = reply_link::post_request(
+                                d.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);
+                        }
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if com == "/fav" || com == "fav" {
+                    let output = Command::new(data_scpt(&"api_fav"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let dd = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(dd);
+                    if text_limit.len() > 3 {
+                        let str_rep = reply_link::post_request(
+                            d.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);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if com == "/egg" || com == "egg" {
+                    let output = Command::new(data_scpt(&"api_egg"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let dd = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(dd);
+                    if text_limit.len() > 3 {
+                        let str_rep = reply_link::post_request(
+                            d.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);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if com == "/nyan" || com == "nyan" {
+                    let output = Command::new(data_scpt(&"nyancat"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&cid)
+                        .arg(&uri)
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let dd = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(dd);
+                    println!("{}", text_limit);
+                    if text_limit.len() > 3 {
+                        let str_rep = reply::post_request(
+                            text_limit.to_string(),
+                            cid.to_string(),
+                            uri.to_string(),
+                            cid_root.to_string(),
+                            uri_root.to_string(),
+                        )
+                        .await;
+                        println!("{}", str_rep);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if com == "/ten" || com == "ten" {
+                    let output = Command::new(data_scpt(&"api_ten"))
+                        .arg(&handle)
+                        .arg(&did)
+                        .arg(&cid)
+                        .arg(&uri)
+                        .arg(&prompt)
+                        .arg(&prompt_sub)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let d = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(d);
+                    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);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else if { com == "sh" || com == "/sh" } && handle == &admin {
+                    println!("admin:{}", admin);
+                    let output = Command::new(data_scpt(&"arch"))
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let d = d.to_string();
+                    let text_limit = c_char(d);
+                    let str_rep = reply::post_request(
+                        text_limit.to_string(),
+                        cid.to_string(),
+                        uri.to_string(),
+                        cid_root.to_string(),
+                        uri_root.to_string(),
+                    )
+                    .await;
+                    println!("{}", str_rep);
+                    w_cid(cid.to_string(), log_file(&"n1"), true);
+                } else if { com == "mitractl" || com == "/mitractl" } && handle == &admin {
+                    println!("admin:{}", admin);
+                    let output = Command::new(data_scpt(&"mitractl"))
+                        .arg(&prompt)
+                        .output()
+                        .expect("zsh");
+                    let d = String::from_utf8_lossy(&output.stdout);
+                    let d = "\n".to_owned() + &d.to_string();
+                    let text_limit = c_char(d);
+                    link = "https://m.syu.is".to_string();
+                    e = link.chars().count();
+                    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);
+                        w_cid(cid.to_string(), log_file(&"n1"), true);
+                    }
+                } else {
+                    // openai
+                    let str_openai = openai::post_request(prompt_chat.to_string()).await;
+                    let text_limit = c_char(str_openai);
+                    let str_rep = reply::post_request(
+                        text_limit.to_string(),
+                        cid.to_string(),
+                        uri.to_string(),
+                        cid_root.to_string(),
+                        uri_root.to_string(),
+                    )
+                    .await;
+                    println!("{}", str_rep);
+                    w_cid(cid.to_string(), log_file(&"n1"), true);
+                }
+                let str_notify = notify_read::post_request(time.to_string()).await;
+                println!("{}", str_notify);
+                println!("---");
+            }
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
diff --git a/src/data.rs b/src/data.rs
new file mode 100644
index 0000000..3f569e6
--- /dev/null
+++ b/src/data.rs
@@ -0,0 +1,647 @@
+use config::{Config, ConfigError, File};
+use seahorse::Context;
+use serde_derive::{Deserialize, Serialize};
+use std::fs;
+use std::fs::OpenOptions;
+use std::io::Read;
+use std::io::Write;
+use std::path::Path;
+
+pub fn data_file(s: &str) -> String {
+    let file = "/.config/ai/";
+    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 {
+        "toml" => f + &"token.toml",
+        "json" => f + &"token.json",
+        "refresh" => f + &"refresh.toml",
+        _ => 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()
+    }
+}
+
+impl Refresh {
+    pub fn new() -> Result<Self, ConfigError> {
+        let d = data_file("refresh");
+        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 password: String,
+    pub did: String,
+    pub handle: String,
+    pub access: String,
+    pub refresh: String,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[allow(non_snake_case)]
+pub struct Refresh {
+    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,
+        password: data.password,
+        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,
+        password: data.password,
+        handle: data.handle,
+        did: data.did,
+        access: data.access,
+        refresh: data.refresh,
+    };
+    match &*s {
+        "host" => data.host,
+        "password" => data.password,
+        "handle" => data.handle,
+        "did" => data.did,
+        "access" => data.access,
+        "refresh" => data.refresh,
+        _ => s,
+    }
+}
+
+pub fn c_refresh(access: &str, refresh: &str) {
+    let ff = data_file(&"refresh");
+    let mut ff = fs::File::create(ff.clone()).unwrap();
+    let refreshs = Refresh {
+        access: access.to_string(),
+        refresh: refresh.to_string(),
+    };
+    let toml = toml::to_string(&refreshs).unwrap();
+    ff.write_all(&toml.as_bytes()).unwrap();
+}
+
+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 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,
+    };
+    match &*s {
+        "access" => refresh.access,
+        "refresh" => refresh.refresh,
+        _ => s,
+    }
+}
+
+pub fn data_scpt(s: &str) -> String {
+    let s = String::from(s);
+    let file = "/.config/ai/scpt/".to_owned() + &s + &".zsh";
+    let mut f = shellexpand::tilde("~").to_string();
+    f.push_str(&file);
+    return f;
+}
+
+#[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, password: &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(),
+        password: password.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();
+
+    let ff = data_file(&"refresh");
+    let mut ff = fs::File::create(ff.clone()).unwrap();
+    let refreshs = Refresh {
+        access: json.accessJwt.to_string(),
+        refresh: json.refreshJwt.to_string(),
+    };
+    let toml = toml::to_string(&refreshs).unwrap();
+    ff.write_all(&toml.as_bytes()).unwrap();
+}
+
+pub fn w_refresh(res: &str) {
+    let ff = data_file(&"refresh");
+    let mut ff = fs::File::create(ff.clone()).unwrap();
+    let json: Token = serde_json::from_str(&res).unwrap();
+    let refreshs = Refresh {
+        access: json.accessJwt.to_string(),
+        refresh: json.refreshJwt.to_string(),
+    };
+    let toml = toml::to_string(&refreshs).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;
+    }
+}
+
+pub fn c_follow_all() {
+    let file = "/.config/ai/scpt/follow_all.zsh";
+    let mut f = shellexpand::tilde("~").to_string();
+    f.push_str(&file);
+    use std::process::Command;
+    let output = Command::new(&f).output().expect("zsh");
+    let d = String::from_utf8_lossy(&output.stdout);
+    let d = "\n".to_owned() + &d.to_string();
+    println!("{}", d);
+}
+
+pub fn c_openai_key(c: &Context) {
+    let api = c.args[0].to_string();
+    let o = "api='".to_owned() + &api.to_string() + &"'".to_owned();
+    let o = o.to_string();
+    let l = shellexpand::tilde("~") + "/.config/ai/openai.toml";
+    let l = l.to_string();
+    let mut l = fs::File::create(l).unwrap();
+    if o != "" {
+        l.write_all(&o.as_bytes()).unwrap();
+    }
+    println!("{:#?}", l);
+}
+
+impl Open {
+    pub fn new() -> Result<Self, ConfigError> {
+        let d = shellexpand::tilde("~") + "/.config/ai/openai.toml";
+        let s = Config::builder()
+            .add_source(File::with_name(&d))
+            .add_source(config::Environment::with_prefix("APP"))
+            .build()?;
+        s.try_deserialize()
+    }
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Open {
+    pub api: String,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct OpenData {
+    choices: Vec<Choices>,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Choices {
+    text: String,
+}
+
diff --git a/src/describe.rs b/src/describe.rs
new file mode 100644
index 0000000..75e5ae5
--- /dev/null
+++ b/src/describe.rs
@@ -0,0 +1,22 @@
+extern crate reqwest;
+//use crate::data_toml;
+use crate::url;
+
+pub async fn get_request(user: String) -> String {
+    //let token = data_refresh(&"access");
+    let url = url(&"describe");
+
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .query(&[("repo", &user)])
+        //.header("Authorization", "Bearer ".to_owned() + &token)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+
+    return res;
+}
diff --git a/src/follow.rs b/src/follow.rs
new file mode 100644
index 0000000..d1317f6
--- /dev/null
+++ b/src/follow.rs
@@ -0,0 +1,81 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+//use crate::data::Follow;
+
+pub async fn post_request(u: String) -> String {
+    let token = data_refresh(&"access");
+    let did = data_toml(&"did");
+    let handle = data_toml(&"handle");
+
+    let url = url(&"record_create");
+    let col = "app.bsky.graph.follow".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": {
+            "subject": u.to_string(),
+            "createdAt": d.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;
+}
+
+pub async fn delete_request(u: String, rkey: String) -> String {
+    let token = data_refresh(&"access");
+    let did = data_toml(&"did");
+    let handle = data_toml(&"handle");
+
+    let url = url(&"record_delete");
+    let col = "app.bsky.graph.follow".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(),
+        "rkey": rkey.to_string(),
+        "record": {
+            "subject": u.to_string(),
+            "createdAt": d.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;
+}
diff --git a/src/followers.rs b/src/followers.rs
new file mode 100644
index 0000000..0927289
--- /dev/null
+++ b/src/followers.rs
@@ -0,0 +1,24 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+//use serde_json::json;
+
+pub async fn get_request(actor: String, cursor: Option<String>) -> String {
+    let token = data_refresh(&"access");
+    let url = url(&"followers");
+    let cursor = cursor.unwrap();
+
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .query(&[("actor", actor), ("cursor", cursor)])
+        .header("Authorization", "Bearer ".to_owned() + &token)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+
+    return res;
+}
diff --git a/src/follows.rs b/src/follows.rs
new file mode 100644
index 0000000..bb517e0
--- /dev/null
+++ b/src/follows.rs
@@ -0,0 +1,26 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+//use serde_json::json;
+
+pub async fn get_request(actor: String, cursor: Option<String>) -> String {
+    let token = data_refresh(&"access");
+    let url = url(&"follows");
+    let cursor = cursor.unwrap();
+    //let cursor = "1682386039125::bafyreihwgwozmvqxcxrhbr65agcaa4v357p27ccrhzkjf3mz5xiozjvzfa".to_string();
+    //let cursor = "1682385956974::bafyreihivhux5m3sxbg33yruhw5ozhahwspnuqdsysbo57smzgptdcluem".to_string();
+
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .query(&[("actor", actor), ("cursor", cursor)])
+        //cursor.unwrap()
+        .header("Authorization", "Bearer ".to_owned() + &token)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+    return res;
+}
diff --git a/src/img.rs b/src/img.rs
new file mode 100644
index 0000000..013917b
--- /dev/null
+++ b/src/img.rs
@@ -0,0 +1,59 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use serde_json::json;
+use iso8601_timestamp::Timestamp;
+
+pub async fn post_request(text: String, link: String) -> String {
+
+    let token = data_refresh(&"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": {
+            "createdAt": d.to_string(),
+            "text": text.to_string(),
+            "embed": {
+                "$type": "app.bsky.embed.images",
+                "images": [
+                    {
+                        "alt": "",
+                        "image": {
+                            "$type":"blob",
+                            "ref": {
+                                "$link" : link.to_string()
+                            },
+                            "mimeType": "image/png",
+                                "size": 0
+                        }
+                    }
+                ]
+            }
+        }
+    }));
+
+    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
+}
diff --git a/src/img_reply.rs b/src/img_reply.rs
new file mode 100644
index 0000000..f7b3a9a
--- /dev/null
+++ b/src/img_reply.rs
@@ -0,0 +1,74 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(
+    text: String,
+    link: String,
+    cid: String,
+    uri: String,
+    itype: String,
+) -> String {
+    let token = data_refresh(&"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": {
+            "createdAt": d.to_string(),
+            "text": text.to_string(),
+            "embed": {
+                "$type": "app.bsky.embed.images",
+                "images": [
+                    {
+                        "alt": "",
+                        "image": {
+                            "$type":"blob",
+                            "ref": {
+                                "$link" : link.to_string()
+                            },
+                            "mimeType": itype.to_string(),
+                                "size": 0
+                        }
+                    }
+                ]
+            },
+            "reply": {
+                "root": {
+                    "cid": cid.to_string(),
+                    "uri": uri.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;
+}
diff --git a/src/img_upload.rs b/src/img_upload.rs
new file mode 100644
index 0000000..013917b
--- /dev/null
+++ b/src/img_upload.rs
@@ -0,0 +1,59 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use serde_json::json;
+use iso8601_timestamp::Timestamp;
+
+pub async fn post_request(text: String, link: String) -> String {
+
+    let token = data_refresh(&"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": {
+            "createdAt": d.to_string(),
+            "text": text.to_string(),
+            "embed": {
+                "$type": "app.bsky.embed.images",
+                "images": [
+                    {
+                        "alt": "",
+                        "image": {
+                            "$type":"blob",
+                            "ref": {
+                                "$link" : link.to_string()
+                            },
+                            "mimeType": "image/png",
+                                "size": 0
+                        }
+                    }
+                ]
+            }
+        }
+    }));
+
+    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
+}
diff --git a/src/like.rs b/src/like.rs
new file mode 100644
index 0000000..ffc4821
--- /dev/null
+++ b/src/like.rs
@@ -0,0 +1,45 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(cid: String, uri: String) -> String {
+    let token = data_refresh(&"access");
+    let did = data_toml(&"did");
+    let handle = data_toml(&"handle");
+
+    let url = url(&"record_create");
+    let col = "app.bsky.feed.like".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": {
+            "subject": {
+                "uri": uri.to_string(),
+                "cid": cid.to_string()
+            },
+            "createdAt": d.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;
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..57eeea7
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,591 @@
+use seahorse::{App, Command, Context, Flag, FlagType};
+use std::env;
+
+use crate::ascii::c_ascii;
+use crate::bot::c_bot;
+use crate::data::c_follow_all;
+use crate::data::c_openai_key;
+use crate::data::data_toml;
+use crate::data::data_refresh;
+use crate::data::url;
+use crate::data::w_cfg;
+use crate::data::w_refresh;
+
+use data::ProfileIdentityResolve;
+
+pub mod ascii;
+pub mod bot;
+pub mod data;
+pub mod describe;
+pub mod follow;
+pub mod followers;
+pub mod follows;
+pub mod img_reply;
+pub mod like;
+pub mod mention;
+pub mod notify;
+pub mod notify_read;
+pub mod openai;
+pub mod post;
+pub mod post_link;
+pub mod profile;
+pub mod refresh;
+pub mod reply;
+pub mod reply_link;
+pub mod reply_og;
+pub mod repost;
+pub mod session;
+pub mod timeline_author;
+pub mod token;
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    let app = App::new(env!("CARGO_PKG_NAME"))
+        .command(
+            Command::new("ai")
+            .alias("a")
+            .action(ascii_art)
+            .flag(
+                Flag::new("type", FlagType::String)
+                .description("type flag")
+                .alias("t"),
+            )
+        )
+        .command(
+            Command::new("bot")
+            .alias("b")
+            .action(bot)
+            .flag(
+                Flag::new("admin", FlagType::String)
+                .alias("a"),
+            )
+        )
+        .command(
+            Command::new("follow_all")
+            .action(follow_all),
+        )
+        .command(
+            Command::new("login")
+            .alias("l")
+            .description("l <handle> -p <password>\n\t\t\tl <handle> -p <password> -s <server>")
+            .action(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")
+            .action(refresh),
+        )
+        .command(
+            Command::new("notify")
+            .alias("n")
+            .action(notify),
+            )
+        .command(
+            Command::new("timeline")
+            .alias("t")
+            .action(timeline),
+        )
+        .command(
+            Command::new("did")
+            .description("did <handle>")
+            .action(did)
+            )
+        .command(
+            Command::new("post")
+            .description("p <text>")
+            .alias("p")
+            .action(post)
+            .flag(
+                Flag::new("link", FlagType::String)
+                .alias("l"),
+            )
+        )
+        .command(
+            Command::new("like")
+            .description("like <cid> -u <uri>")
+            .action(like)
+            .flag(
+                Flag::new("uri", FlagType::String)
+                .alias("u"),
+                )
+            )
+        .command(
+            Command::new("repost")
+            .description("repost <cid> -u <uri>")
+            .action(repost)
+            .flag(
+                Flag::new("uri", FlagType::String)
+                .alias("u"),
+            )
+        )
+        .command(
+            Command::new("reply-og")
+            .description("reply-og <text> -c <cid> -u <uri> -i <img> -t <title> -d <description> -l <link>")
+            .action(reply_og)
+            .flag(
+                Flag::new("uri", FlagType::String)
+                .alias("u"),
+            )
+            .flag(
+                Flag::new("cid", FlagType::String)
+                .alias("c"),
+            )
+            .flag(
+                Flag::new("link", FlagType::String)
+                .alias("l"),
+            )
+            .flag(
+                Flag::new("title", FlagType::String)
+                .alias("t"),
+            )
+            .flag(
+                Flag::new("description", FlagType::String)
+                .alias("d"),
+            )
+            .flag(
+                Flag::new("img", FlagType::String)
+                .alias("i"),
+            )
+        )
+        .command(
+            Command::new("reply")
+            .description("r <text> -u <uri> -c <cid>")
+            .action(reply)
+            .flag(
+                Flag::new("uri", FlagType::String)
+                .alias("u"),
+            )
+            .flag(
+                Flag::new("cid", FlagType::String)
+                .alias("c"),
+            )
+            .flag(
+                Flag::new("link", FlagType::String)
+                .description("-l <link>")
+                .alias("l"),
+            )
+        )
+        .command(
+            Command::new("mention")
+            .description("@ <handle> -p <text>")
+            .alias("@")
+            .action(mention)
+            .flag(
+                Flag::new("post", FlagType::String)
+                .alias("p"),
+            )
+        )
+        .command(
+            Command::new("follow")
+            .description("follow <did>")
+            .action(follow)
+            .flag(
+                Flag::new("follows", FlagType::Bool)
+                .alias("s"),
+            )
+            .flag(
+                Flag::new("delete", FlagType::String)
+                .alias("d"),
+            )
+            .flag(
+                Flag::new("followers", FlagType::Bool)
+                .alias("w"),
+            )
+            .flag(
+                Flag::new("all", FlagType::Bool)
+                .alias("a"),
+            )
+            .flag(
+                Flag::new("cursor", FlagType::String)
+                .alias("c"),
+            )
+        )
+        .command(
+            Command::new("profile")
+            .description("pro <handle>")
+            .alias("pro")
+            .action(profile)
+        )
+        .command(
+            Command::new("img-upload")
+            .description("img-upload <img>")
+            .action(img_upload)
+        )
+        .command(
+            Command::new("img-post")
+            .description("img-post <text> -l <link> -u <uri> -c <cid>")
+            .action(img_post)
+            .flag(
+                Flag::new("link", FlagType::String)
+                .alias("l"),
+            )
+            .flag(
+                Flag::new("uri", FlagType::String)
+                .alias("u"),
+            )
+            .flag(
+                Flag::new("cid", FlagType::String)
+                .alias("c"),
+            )
+        )
+        .command(
+            Command::new("openai")
+            .description("openai <text>")
+            .alias("chat")
+            .action(openai)
+        )
+        .command(
+            Command::new("openai-key")
+            .description("openai-key <API_KEY>")
+            .action(openai_key),
+        )
+        ;
+    app.run(args);
+}
+
+fn ascii_art(c: &Context) {
+    if let Ok(t) = c.string_flag("type") {
+        c_ascii(&t);
+    } else {
+        c_ascii("color");
+    }
+}
+
+fn bot(c: &Context) {
+    refresh(c);
+    loop {
+        c_bot(c);
+    }
+}
+
+fn follow_all(_c: &Context) {
+    c_follow_all();
+}
+
+fn openai_key(c: &Context) {
+    c_openai_key(c);
+}
+
+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, &p);
+            } else {
+                let res =
+                    token::post_request(m.to_string(), p.to_string(), "bsky.social".to_string())
+                        .await;
+                w_cfg(&"bsky.social", &res, &p);
+            }
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn refresh(_c: &Context) {
+    let h = async {
+        let session = session::get_request().await;
+        if session == "err" {
+            let res = refresh::post_request().await;
+            println!("{}", res);
+            if res == "err" {
+                let m = data_toml(&"handle");
+                let p = data_toml(&"password");
+                let s = data_toml(&"host");
+                println!("handle:{}, pass:{}, host:{}", m, p, s);
+                let res = token::post_request(m.to_string(), p.to_string(), s.to_string()).await;
+                w_cfg(&s, &res, &p);
+                println!("res:{}", res);
+            } else {
+                w_refresh(&res);
+            }
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn notify(c: &Context) {
+    refresh(c);
+    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 did(c: &Context) {
+    refresh(c);
+    let h = async {
+        if c.args.len() == 0 {
+            let j = describe::get_request(data_toml(&"handle")).await;
+            println!("{}", j);
+        } else {
+            let j = describe::get_request(c.args[0].to_string()).await;
+            println!("{}", j);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn timeline(c: &Context) {
+    refresh(c);
+    let h = async {
+        if c.args.len() == 0 {
+            let str = timeline_author::get_request(data_toml(&"handle").to_string());
+            println!("{}", str.await);
+        } else {
+            let str = timeline_author::get_request(c.args[0].to_string());
+            println!("{}", str.await);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn post(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        if let Ok(link) = c.string_flag("link") {
+            let e = link.chars().count();
+            let s = 0;
+            let str =
+                post_link::post_request(m.to_string(), link.to_string(), s, e.try_into().unwrap());
+            println!("{}", str.await);
+        } else {
+            let str = post::post_request(m.to_string());
+            println!("{}", str.await);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn like(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        if let Ok(uri) = c.string_flag("uri") {
+            let str = like::post_request(m.to_string(), uri);
+            println!("{}", str.await);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn repost(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        if let Ok(uri) = c.string_flag("uri") {
+            let str = repost::post_request(m.to_string(), uri);
+            println!("{}", str.await);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn follow(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        let handle = data_toml(&"handle");
+        if let Ok(cursor) = c.string_flag("cursor") {
+            let str = follow::post_request(m.to_string());
+            println!("{}", str.await);
+            //let str = follow::delete_request(m.to_string(), delete.to_string());
+            //let str = followers::get_request(handle,Some("".to_string()));
+            //let str = followers::get_request(handle,Some(cursor.to_string()));
+            //let str = follows::get_request(handle,Some("".to_string()));
+            let str = follows::get_request(handle, Some(cursor.to_string()));
+            println!("{}", str.await);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn profile(c: &Context) {
+    refresh(c);
+    let h = async {
+        if c.args.len() == 0 {
+            let j = profile::get_request(data_toml(&"handle")).await;
+            println!("{}", j);
+        } else {
+            let j = profile::get_request(c.args[0].to_string()).await;
+            println!("{}", j);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn mention(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        let str = profile::get_request(m.to_string()).await;
+        let profile: ProfileIdentityResolve = serde_json::from_str(&str).unwrap();
+        let udid = profile.did;
+        let handle = m.to_string();
+        let at = "@".to_owned() + &handle;
+        let e = at.chars().count();
+        let s = 0;
+        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);
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn reply(c: &Context) {
+    refresh(c);
+    let m = c.args[0].to_string();
+    let h = async {
+        if let Ok(cid) = c.string_flag("cid") {
+            if let Ok(uri) = c.string_flag("uri") {
+                if let Ok(link) = c.string_flag("link") {
+                    let s = 0;
+                    let e = link.chars().count();
+                    let str = reply_link::post_request(
+                        m.to_string(),
+                        link.to_string(),
+                        s,
+                        e.try_into().unwrap(),
+                        cid.to_string(),
+                        uri.to_string(),
+                        cid.to_string(),
+                        uri.to_string(),
+                    )
+                    .await;
+                    println!("{}", str);
+                } else {
+                    let str = reply::post_request(
+                        m.to_string(),
+                        cid.to_string(),
+                        uri.to_string(),
+                        cid.to_string(),
+                        uri.to_string(),
+                    )
+                    .await;
+                    println!("{}", str);
+                }
+            }
+        }
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+#[tokio::main]
+async fn c_img_upload(c: &Context) -> reqwest::Result<()> {
+    let token = data_refresh(&"access");
+    let atoken = "Authorization: Bearer ".to_owned() + &token;
+    let con = "Content-Type: image/png";
+    let url = url(&"upload_blob");
+    let f = "@".to_owned() + &c.args[0].to_string();
+    use std::process::Command;
+    let output = Command::new("curl")
+        .arg("-X")
+        .arg("POST")
+        .arg("-sL")
+        .arg("-H")
+        .arg(&con)
+        .arg("-H")
+        .arg(&atoken)
+        .arg("--data-binary")
+        .arg(&f)
+        .arg(&url)
+        .output()
+        .expect("curl");
+    let d = String::from_utf8_lossy(&output.stdout);
+    let d = d.to_string();
+    println!("{}", d);
+    Ok(())
+}
+
+fn img_upload(c: &Context) {
+    refresh(c);
+    c_img_upload(c).unwrap();
+}
+
+fn img_post(c: &Context) {
+    let m = c.args[0].to_string();
+    let link = c.string_flag("link").unwrap();
+    let cid = c.string_flag("cid").unwrap();
+    let uri = c.string_flag("uri").unwrap();
+    let h = async {
+        let itype = "image/png";
+        let str = img_reply::post_request(
+            m.to_string(),
+            link.to_string(),
+            cid.to_string(),
+            uri.to_string(),
+            itype.to_string(),
+        )
+        .await;
+        println!("{}", str);
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn reply_og(c: &Context) {
+    refresh(c);
+
+    //let mut admin = "".to_string();
+    //if c.string_flag("admin").is_ok() {
+    //    admin = c.string_flag("admin").unwrap();
+    //}
+
+    let m = c.args[0].to_string();
+    let link = c.string_flag("link").unwrap();
+    let cid = c.string_flag("cid").unwrap();
+    let uri = c.string_flag("uri").unwrap();
+    let title = c.string_flag("title").unwrap();
+    let desc = c.string_flag("description").unwrap();
+    let img = c.string_flag("img").unwrap();
+    let h = async {
+        let str = reply_og::post_request(m, link, cid, uri, img, title, desc);
+        println!("{}", str.await);
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
+
+fn openai(c: &Context) {
+    let m = c.args[0].to_string();
+    let h = async {
+        let str = openai::post_request(m.to_string()).await;
+        println!("{}", str);
+    };
+    let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
+    return res;
+}
diff --git a/src/mention.rs b/src/mention.rs
new file mode 100644
index 0000000..84cf978
--- /dev/null
+++ b/src/mention.rs
@@ -0,0 +1,57 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(text: String, at: String, udid: String, s: i32, e: i32) -> String {
+    let token = data_refresh(&"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!({
+        "did": did.to_string(),
+        "repo": handle.to_string(),
+        "collection": col.to_string(),
+        "record": {
+            "text": at.to_string() + &" ".to_string() + &text.to_string(),
+            "$type": "app.bsky.feed.post",
+            "createdAt": d.to_string(),
+            "facets": [
+            {
+                "$type": "app.bsky.richtext.facet",
+                "index": {
+                    "byteEnd": e,
+                    "byteStart": s
+                },"features": [
+                {
+                    "did": udid.to_string(),
+                    "$type": "app.bsky.richtext.facet#mention"
+                }
+                ]
+            }
+            ]
+        },
+    }));
+
+    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;
+}
diff --git a/src/notify.rs b/src/notify.rs
new file mode 100644
index 0000000..cd74660
--- /dev/null
+++ b/src/notify.rs
@@ -0,0 +1,30 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+//use serde_json::json;
+
+pub async fn get_request(limit: i32) -> String {
+    let token = data_refresh(&"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;
+        }
+    }
+}
diff --git a/src/notify_read.rs b/src/notify_read.rs
new file mode 100644
index 0000000..e8941ec
--- /dev/null
+++ b/src/notify_read.rs
@@ -0,0 +1,27 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+use serde_json::json;
+
+pub async fn post_request(time: String) -> String {
+    let token = data_refresh(&"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;
+}
diff --git a/src/openai.rs b/src/openai.rs
new file mode 100644
index 0000000..e7e2b07
--- /dev/null
+++ b/src/openai.rs
@@ -0,0 +1,58 @@
+extern crate reqwest;
+use crate::data::Open;
+use serde::{Deserialize, Serialize};
+use serde_json::json;
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(tag = "type")]
+struct OpenChar {
+    choices: Vec<ChoicesChar>,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+struct ChoicesChar {
+    message: OpenContent,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+struct OpenContent {
+    content: String,
+}
+
+pub async fn post_request(prompt: String) -> String {
+    let data = Open::new().unwrap();
+    let data = Open { api: data.api };
+
+    let setting = "あなたはyuiという作品のアイと呼ばれるキャラクターです。第一人称は「アイ」です。
+    第二人称はできる限り省略してください。
+    自由気ままな優しさを兼ね備えます。
+    口調例:アイね、ここでお昼寝するの。
+    幼い子供の口調で話してください。
+    誕生日は1月23日。
+    自分を信じて。
+        ";
+
+    let post = Some(json!({
+    "model": "gpt-3.5-turbo",
+    "messages": [
+    {"role": "system", "content": &setting.to_string()},
+    {"role": "user", "content": &prompt.to_string()},
+    ]
+    }));
+
+    let client = reqwest::Client::new();
+    let res = client
+        .post("https://api.openai.com/v1/chat/completions")
+        .header("Authorization", "Bearer ".to_owned() + &data.api)
+        .json(&post)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+    let p: OpenChar = serde_json::from_str(&res).unwrap();
+    let o = &p.choices[0].message.content;
+
+    return o.to_string();
+}
diff --git a/src/post.rs b/src/post.rs
new file mode 100644
index 0000000..c90992b
--- /dev/null
+++ b/src/post.rs
@@ -0,0 +1,42 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(text: String) -> String {
+    let token = data_refresh(&"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": text.to_string(),
+            "createdAt": d.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;
+}
diff --git a/src/post_link.rs b/src/post_link.rs
new file mode 100644
index 0000000..ba50aea
--- /dev/null
+++ b/src/post_link.rs
@@ -0,0 +1,56 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(text: String, link: String, s: i32, e: i32) -> String {
+    let token = data_refresh(&"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(),
+            "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;
+}
diff --git a/src/profile.rs b/src/profile.rs
new file mode 100644
index 0000000..6c49ebf
--- /dev/null
+++ b/src/profile.rs
@@ -0,0 +1,21 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+
+pub async fn get_request(user: String) -> String {
+    let token = data_refresh(&"access");
+    let url = url(&"profile_get") + &"?handle=" + &user;
+
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .header("Authorization", "Bearer ".to_owned() + &token)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+
+    return res;
+}
diff --git a/src/refresh.rs b/src/refresh.rs
new file mode 100644
index 0000000..06fe322
--- /dev/null
+++ b/src/refresh.rs
@@ -0,0 +1,28 @@
+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();
+
+    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;
+        }
+    }
+}
diff --git a/src/reply.rs b/src/reply.rs
new file mode 100644
index 0000000..812229f
--- /dev/null
+++ b/src/reply.rs
@@ -0,0 +1,59 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(
+    text: String,
+    cid: String,
+    uri: String,
+    cid_root: String,
+    uri_root: String,
+) -> String {
+    let token = data_refresh(&"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;
+}
diff --git a/src/reply_link.rs b/src/reply_link.rs
new file mode 100644
index 0000000..d34b9eb
--- /dev/null
+++ b/src/reply_link.rs
@@ -0,0 +1,75 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+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_refresh(&"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;
+}
diff --git a/src/reply_og.rs b/src/reply_og.rs
new file mode 100644
index 0000000..af27c9d
--- /dev/null
+++ b/src/reply_og.rs
@@ -0,0 +1,76 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(
+    m: String,
+    link: String,
+    cid: String,
+    uri: String,
+    img: String,
+    title: String,
+    description: String,
+) -> String {
+    let token = data_refresh(&"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": {
+            "createdAt": d.to_string(),
+            "text": m.to_string(),
+            "embed": {
+                "$type": "app.bsky.embed.external",
+                "external": {
+                    "uri": link.to_string(),
+                    "thumb": {
+                      "$type": "blob",
+                      "ref": {
+                        "$link": img.to_string()
+                      },
+                      "mimeType": "image/jpeg",
+                      "size": 0
+                    },
+                    "title": title.to_string(),
+                    "description": description.to_string()
+                }
+            },
+            "reply": {
+                "root": {
+                    "cid": cid.to_string(),
+                    "uri": uri.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;
+}
diff --git a/src/repost.rs b/src/repost.rs
new file mode 100644
index 0000000..44f202a
--- /dev/null
+++ b/src/repost.rs
@@ -0,0 +1,45 @@
+extern crate reqwest;
+use crate::data_toml;
+use crate::data_refresh;
+use crate::url;
+use iso8601_timestamp::Timestamp;
+use serde_json::json;
+
+pub async fn post_request(cid: String, uri: String) -> String {
+    let token = data_refresh(&"access");
+    let did = data_toml(&"did");
+    let handle = data_toml(&"handle");
+
+    let url = url(&"record_create");
+    let col = "app.bsky.feed.repost".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": {
+            "subject": {
+                "uri": uri.to_string(),
+                "cid": cid.to_string()
+            },
+            "createdAt": d.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;
+}
diff --git a/src/session.rs b/src/session.rs
new file mode 100644
index 0000000..ad49cb1
--- /dev/null
+++ b/src/session.rs
@@ -0,0 +1,28 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+
+pub async fn get_request() -> String {
+    let token = data_refresh(&"access");
+    let url = url(&"session_get");
+
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .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;
+        }
+    }
+}
diff --git a/src/timeline_author.rs b/src/timeline_author.rs
new file mode 100644
index 0000000..bbb447e
--- /dev/null
+++ b/src/timeline_author.rs
@@ -0,0 +1,27 @@
+extern crate reqwest;
+use crate::data_refresh;
+use crate::url;
+
+pub async fn get_request(actor: String) -> String {
+    let token = data_refresh(&"access");
+    let url = url(&"record_list");
+
+    let actor = actor.to_string();
+    //let cursor = cursor.unwrap();
+
+    let col = "app.bsky.feed.post".to_string();
+    let client = reqwest::Client::new();
+    let res = client
+        .get(url)
+        .query(&[("repo", actor), ("collection", col)])
+        //.query(&[("actor", actor),("cursor", cursor)])
+        .header("Authorization", "Bearer ".to_owned() + &token)
+        .send()
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap();
+
+    return res;
+}
diff --git a/src/token.rs b/src/token.rs
new file mode 100644
index 0000000..29ed701
--- /dev/null
+++ b/src/token.rs
@@ -0,0 +1,25 @@
+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;
+}
diff --git a/test/ai.zsh b/test/ai.zsh
new file mode 100755
index 0000000..d53abc1
--- /dev/null
+++ b/test/ai.zsh
@@ -0,0 +1,35 @@
+#!/bin/zsh
+
+# https://www.docs.bsky.app/docs/get-started
+
+case $OSTYPE in
+	darwin*)
+		alias date="/opt/homebrew/bin/gdate"
+		;;
+esac
+d=${0:a:h}
+
+source $d/env
+source $d/refresh.zsh
+source $d/token.zsh
+source $d/reply.zsh
+source $d/notify.zsh
+source $d/cron.zsh
+
+case $1 in
+	refresh|r)
+		refresh
+		;;
+	token|t)
+		token
+		;;
+	reply|rep)
+		reply
+		;;
+	notify|n)
+		notify
+		;;
+	cron|c)
+		cron
+		;;
+esac
diff --git a/test/cron.zsh b/test/cron.zsh
new file mode 100644
index 0000000..e9f389a
--- /dev/null
+++ b/test/cron.zsh
@@ -0,0 +1,7 @@
+function cron() {
+	t=`docker ps |grep aios|grep Up`
+	if [ -z "$t" ];then
+		docker compose up -d
+	fi
+	exit
+}
diff --git a/test/entrypoint.sh b/test/entrypoint.sh
new file mode 100644
index 0000000..dfdd5dc
--- /dev/null
+++ b/test/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/zsh
+
+ai l $HANDLE -p $PASSWORD -s $HOST && ai bot -a syui.$HOST
diff --git a/test/env b/test/env
new file mode 100644
index 0000000..863b1c5
--- /dev/null
+++ b/test/env
@@ -0,0 +1,18 @@
+cfg=~/.config/ai/test.json
+
+if [ -f $cfg ];then
+	host=`cat $cfg|jq -r .host`
+	handle=`cat $cfg|jq -r .handle`
+	pass=`cat $cfg|jq -r .password`
+	date=`date --iso-8601=seconds`
+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
diff --git a/test/notify.zsh b/test/notify.zsh
new file mode 100644
index 0000000..8f5879f
--- /dev/null
+++ b/test/notify.zsh
@@ -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
+}
diff --git a/test/refresh.zsh b/test/refresh.zsh
new file mode 100755
index 0000000..81998ce
--- /dev/null
+++ b/test/refresh.zsh
@@ -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
+}
diff --git a/test/reply.zsh b/test/reply.zsh
new file mode 100755
index 0000000..c0ebed4
--- /dev/null
+++ b/test/reply.zsh
@@ -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
+}
diff --git a/test/token.zsh b/test/token.zsh
new file mode 100755
index 0000000..c9a5d24
--- /dev/null
+++ b/test/token.zsh
@@ -0,0 +1,18 @@
+function token() {
+		mkdir -p ~/.config/ai
+		echo server:
+		read host
+
+		echo password:
+		read pass
+
+		echo handle:
+		read handle
+
+		echo "{ \"host\":\"$host\", \"password\":\"$pass\", \"handle\":\"$handle\" }" >> $cfg
+
+	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
+}