Compare commits
26 Commits
5c7d4c5a60
...
main
Author | SHA1 | Date | |
---|---|---|---|
998777d46a
|
|||
61d7df6922
|
|||
eb8f1b17c8
|
|||
fc5e942f0c
|
|||
d2a394cec2
|
|||
27d5dac208
|
|||
ddd6f37118
|
|||
14ca1bcdee
|
|||
84efc31248
|
|||
3904c576f0
|
|||
08436c0a56
|
|||
d5603fda52
|
|||
4633901ca0
|
|||
a8fd189a63
|
|||
b540d0c007
|
|||
bf31cf2a8f
|
|||
840320d0d2
|
|||
5d60645c0f
|
|||
e7c06cf9d1
|
|||
025b24b8f0
|
|||
7bbc3370d7
|
|||
d6777a0c6a
|
|||
87a333d744
|
|||
2f0bfe08b0
|
|||
97856f3765
|
|||
7b03adda1f
|
Submodule .config/ai/scpt updated: 6d1f88588c...7a4d642e41
18
.gitea/workflows/release.yaml
Normal file
18
.gitea/workflows/release.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
name: Gitea Actions Demo
|
||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||
on: [push]
|
||||
jobs:
|
||||
Explore-Gitea-Actions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
|
||||
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
ls ${{ gitea.workspace }}
|
||||
- run: echo "🍏 This job's status is ${{ gitea.status }}."
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,6 +1,6 @@
|
||||
Cargo.lock
|
||||
target
|
||||
*.json
|
||||
#*.json
|
||||
*.DS_Store
|
||||
**.DS_Store
|
||||
scpt/json/
|
||||
@ -12,3 +12,8 @@ scpt/json/
|
||||
.ssh/*.pub
|
||||
.ssh/*config
|
||||
.env
|
||||
|
||||
pnpm-lock.yaml
|
||||
**Cargo.lock
|
||||
*/target/
|
||||
*/**/*.rs.bk
|
||||
|
@ -1,7 +1,9 @@
|
||||
[package]
|
||||
name = "ai"
|
||||
version = "0.0.1"
|
||||
authors = ["syui"]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "latest@2024-08-18"
|
||||
|
||||
[dependencies]
|
||||
seahorse = "*"
|
||||
|
@ -1,5 +1,4 @@
|
||||
FROM syui/aios
|
||||
ADD .ssh /root/.ssh
|
||||
|
||||
WORKDIR /root
|
||||
ADD ./test/entrypoint.sh .
|
||||
|
64
README.md
64
README.md
@ -10,7 +10,11 @@
|
||||
$ ai
|
||||
```
|
||||
|
||||
### logo
|
||||
```sh
|
||||
$ docker run -it syui/aios ai
|
||||
```
|
||||
|
||||
### build
|
||||
|
||||
```sh
|
||||
$ cargo build
|
||||
@ -59,15 +63,19 @@ $ ai bot
|
||||
|
||||
|command|sub|type|link|auth|
|
||||
|---|---|---|---|---|
|
||||
|@yui.syui.ai did||mention, reply| [plc.directory](https://plc.directory)/$did/log |user|
|
||||
|@yui.syui.ai card|r, s, b|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|@yui.syui.ai ten|start, d, p, coin|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|@yui.syui.ai fav|{cid}|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|@yui.syui.ai egg|{password}|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|@yui.syui.ai 占い||mention, reply| [yui.syui.ai](https://yui.syui.ai) |user|
|
||||
|@yui.syui.ai nyan|🍰|mention, reply| [yui.syui.ai](https://yui.syui.ai) |user|
|
||||
|@yui.syui.ai diffusers|{keyword}|mention, reply| [huggingface.co/diffusers](https://huggingface.co/docs/diffusers/index) |user|
|
||||
|@yui.syui.ai sh|{command}|mention, reply| [archlinux.org](https://wiki.archlinux.org/title/Systemd-nspawn) |admin|
|
||||
|/did||mention, reply| [plc.directory](https://plc.directory)/$did/log |user|
|
||||
|/card|r, s, b|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|/ten|start, close, d, p|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|/fav|{cid}|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|/egg|{password}|mention, reply| [card.syui.ai](https://card.syui.ai) |user|
|
||||
|/nyan|🍬|mention, reply| [yui.syui.ai](https://yui.syui.ai) |user|
|
||||
|/diffusers|{keyword}|mention, reply| [huggingface.co/diffusers](https://huggingface.co/docs/diffusers/index) |user|
|
||||
|/sh|{command}|mention, reply| [archlinux.org](https://wiki.archlinux.org/title/Systemd-nspawn) |admin|
|
||||
|/占い||mention, reply| [yui.syui.ai](https://yui.syui.ai) |user|
|
||||
|
||||
```sh
|
||||
@yui.syui.ai /did
|
||||
```
|
||||
|
||||
### test
|
||||
|
||||
@ -84,7 +92,6 @@ $ cargo install --force cargo-make
|
||||
$ cargo make build
|
||||
```
|
||||
|
||||
|
||||
### docker
|
||||
|
||||
> .env
|
||||
@ -100,3 +107,38 @@ ADMIN=syui.syu.is
|
||||
$ docker compose build
|
||||
$ docker compose up -d
|
||||
```
|
||||
|
||||
## pds:card
|
||||
|
||||
- https://atproto.com/ja/guides/lexicon
|
||||
- https://at.syu.is/at/did:plc:uqzpqmrjnptsxezjx4xuh2mn/ai.syui.card/3lagpwihqxi2v
|
||||
|
||||
```sh
|
||||
# oauth(button)
|
||||
[yui]ai.syui.card.verify -> [user]ai.syui.card
|
||||
|
||||
[yui]
|
||||
$ ./target/debug/ai card-verify -i 0 -p 0 -r 0 -h syui.ai -d did:plc:uqzpqmrjnptsxezjx4xuh2mn
|
||||
{"uri":"at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.card.verify/3lagpvhppmd2q"}
|
||||
|
||||
[user]
|
||||
$ ./target/debug/ai card -i 0 -p 0 -r 0 -v at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.card.verify/3lagpvhppmd2q
|
||||
```
|
||||
|
||||
## pds:game
|
||||
|
||||
- https://atproto.com/ja/specs/record-key
|
||||
- https://at.syu.is/at/did:plc:uqzpqmrjnptsxezjx4xuh2mn/ai.syui.game/self
|
||||
|
||||
```sh
|
||||
# oauth(play)
|
||||
[yui]ai.syui.game.user -> [user]ai.syui.game
|
||||
|
||||
[account]
|
||||
# https://at.syu.is/at/did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.game.user/syui
|
||||
## [rkey]
|
||||
1. echo $handle|cut -d . -f 1
|
||||
2. $handle
|
||||
3. tid
|
||||
```
|
||||
|
||||
|
10
at/feed-generator/env
Normal file
10
at/feed-generator/env
Normal file
@ -0,0 +1,10 @@
|
||||
FEEDGEN_PORT=3000
|
||||
FEEDGEN_LISTENHOST="0.0.0.0"
|
||||
FEEDGEN_SQLITE_LOCATION="/data/db.sqlite"
|
||||
FEEDGEN_SUBSCRIPTION_ENDPOINT="wss://bgs.syu.is"
|
||||
FEEDGEN_PUBLISHER_DID="did:web:feed.syu.is"
|
||||
FEEDGEN_HOSTNAME="feed.syu.is"
|
||||
|
||||
FEEDGEN_SUBSCRIPTION_RECONNECT_DELAY=3000
|
||||
FEEDGEN_PUBLISHER_DID=did:plc:4hqjfn7m6n5hno3doamuhgef
|
||||
FEEDGEN_SUBSCRIPTION_ENDPOINT="wss://bsky.network"
|
26
at/feed-generator/readme.md
Normal file
26
at/feed-generator/readme.md
Normal file
@ -0,0 +1,26 @@
|
||||
# custom feed
|
||||
|
||||
- at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd
|
||||
- [bsky.app](https://bsky.app/profile/did:plc:4hqjfn7m6n5hno3doamuhgef/feed/cmd)
|
||||
- [app.bsky.feed.getFeedSkeleton](https://feed.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd)
|
||||
|
||||
```sh
|
||||
did=did:plc:4hqjfn7m6n5hno3doamuhgef
|
||||
col=app.bsky.feed.generator
|
||||
cid=cmd
|
||||
uri=at://$did/$col/$cid
|
||||
|
||||
echo $uri
|
||||
```
|
||||
|
||||
## bsky-feed
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/bluesky-social/feed-generator
|
||||
```
|
||||
|
||||
```sh
|
||||
docker compose build feed-generator
|
||||
docker build -t publish_feed -f Dockerfile.feed .
|
||||
docker run publish_feed
|
||||
```
|
43
at/feed-generator/src/algos/cmd.ts
Normal file
43
at/feed-generator/src/algos/cmd.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { InvalidRequestError } from '@atproto/xrpc-server'
|
||||
import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton'
|
||||
import { AppContext } from '../config'
|
||||
|
||||
// max 15 chars
|
||||
export const shortname = 'cmd'
|
||||
|
||||
export const handler = async (ctx: AppContext, params: QueryParams) => {
|
||||
let builder = ctx.db
|
||||
.selectFrom('post')
|
||||
.selectAll()
|
||||
.orderBy('indexedAt', 'desc')
|
||||
.orderBy('cid', 'desc')
|
||||
.limit(params.limit)
|
||||
|
||||
if (params.cursor) {
|
||||
const [indexedAt, cid] = params.cursor.split('::')
|
||||
if (!indexedAt || !cid) {
|
||||
throw new InvalidRequestError('malformed cursor')
|
||||
}
|
||||
const timeStr = new Date(parseInt(indexedAt, 10)).toISOString()
|
||||
builder = builder
|
||||
.where('post.indexedAt', '<', timeStr)
|
||||
.orWhere((qb) => qb.where('post.indexedAt', '=', timeStr))
|
||||
.where('post.cid', '<', cid)
|
||||
}
|
||||
const res = await builder.execute()
|
||||
|
||||
const feed = res.map((row) => ({
|
||||
post: row.uri,
|
||||
}))
|
||||
|
||||
let cursor: string | undefined
|
||||
const last = res.at(-1)
|
||||
if (last) {
|
||||
cursor = `${new Date(last.indexedAt).getTime()}::${last.cid}`
|
||||
}
|
||||
|
||||
return {
|
||||
cursor,
|
||||
feed,
|
||||
}
|
||||
}
|
14
at/feed-generator/src/algos/index.ts
Normal file
14
at/feed-generator/src/algos/index.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { AppContext } from '../config'
|
||||
import {
|
||||
QueryParams,
|
||||
OutputSchema as AlgoOutput,
|
||||
} from '../lexicon/types/app/bsky/feed/getFeedSkeleton'
|
||||
import * as cmd from './cmd'
|
||||
|
||||
type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise<AlgoOutput>
|
||||
|
||||
const algos: Record<string, AlgoHandler> = {
|
||||
[cmd.shortname]: cmd.handler,
|
||||
}
|
||||
|
||||
export default algos
|
50
at/feed-generator/src/subscription.ts
Normal file
50
at/feed-generator/src/subscription.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {
|
||||
OutputSchema as RepoEvent,
|
||||
isCommit,
|
||||
} from './lexicon/types/com/atproto/sync/subscribeRepos'
|
||||
import { FirehoseSubscriptionBase, getOpsByType } from './util/subscription'
|
||||
|
||||
export class FirehoseSubscription extends FirehoseSubscriptionBase {
|
||||
async handleEvent(evt: RepoEvent) {
|
||||
if (!isCommit(evt)) return
|
||||
const ops = await getOpsByType(evt)
|
||||
|
||||
// This logs the text of every post off the firehose.
|
||||
// Just for fun :)
|
||||
// Delete before actually using
|
||||
for (const post of ops.posts.creates) {
|
||||
console.log(post.record.text)
|
||||
}
|
||||
|
||||
const postsToDelete = ops.posts.deletes.map((del) => del.uri)
|
||||
const postsToCreate = ops.posts.creates
|
||||
.filter((create) => {
|
||||
return create.record.text.match('^/[a-z]') || create.record.text.match('^@ai ') || create.record.text.match('/ai ');
|
||||
//return create.record.text.toLowerCase().includes('alf')
|
||||
})
|
||||
.map((create) => {
|
||||
// map alf-related posts to a db row
|
||||
return {
|
||||
uri: create.uri,
|
||||
cid: create.cid,
|
||||
replyParent: create.record?.reply?.parent.uri ?? null,
|
||||
replyRoot: create.record?.reply?.root.uri ?? null,
|
||||
indexedAt: new Date().toISOString(),
|
||||
}
|
||||
})
|
||||
|
||||
if (postsToDelete.length > 0) {
|
||||
await this.db
|
||||
.deleteFrom('post')
|
||||
.where('uri', 'in', postsToDelete)
|
||||
.execute()
|
||||
}
|
||||
if (postsToCreate.length > 0) {
|
||||
await this.db
|
||||
.insertInto('post')
|
||||
.values(postsToCreate)
|
||||
.onConflict((oc) => oc.doNothing())
|
||||
.execute()
|
||||
}
|
||||
}
|
||||
}
|
38
docs/atproto.md
Normal file
38
docs/atproto.md
Normal file
@ -0,0 +1,38 @@
|
||||
## curl
|
||||
|
||||
no-authorization
|
||||
|
||||
https://docs.bsky.app/docs/api/com-atproto-repo-describe-repo
|
||||
|
||||
```sh
|
||||
handle=yui.syui.ai
|
||||
host=bsky.social
|
||||
api=$host/xrpc
|
||||
plc=plc.directory
|
||||
url=$api/com.atproto.repo.describeRepo
|
||||
|
||||
curl -sL ${host}/xrpc/_health
|
||||
|
||||
d=`curl -sL "${url}?repo=$handle"`
|
||||
echo $d
|
||||
did=`echo $d|jq -r .did`
|
||||
echo $did
|
||||
|
||||
collection=app.bsky.feed.post
|
||||
url=$api/com.atproto.repo.listRecords
|
||||
timed=`curl -sL "${url}?repo=$handle&collection=$collection&reverse=true&limit=1"|jq -r ".[]|.[0]?|.value.createdAt"`
|
||||
cid=`curl -sL "${url}?repo=$handle&collection=$collection&reverse=true&limit=1"|jq -r ".[]|.[0]?|.cid"`
|
||||
uri=`curl -sL "${url}?repo=$handle&collection=$collection&reverse=true&limit=1"|jq -r ".[]|.[0]?|.uri"`
|
||||
|
||||
rkey=`echo $uri|cut -d / -f 5`
|
||||
url=$api/com.atproto.repo.getRecord
|
||||
curl -sL "$url?repo=$did&collection=$collection&rkey=$rkey"|jq .
|
||||
|
||||
uri=at://did:plc:vjug55kidv6sye7ykr5faxxn/app.bsky.feed.post/3jzn6g7ixgq2y
|
||||
cid=bafyreiey2tt4dhvuvr7tofatdverqrxmscnnus2uyfcmkacn2fov3vb4wa
|
||||
did=did:plc:vjug55kidv6sye7ykr5faxxn
|
||||
rkey=3jzn6g7ixgq2y
|
||||
url=$api/com.atproto.repo.getRecord
|
||||
curl -sL "$url?repo=$did&collection=$collection&rkey=$rkey&cid="|jq .
|
||||
```
|
||||
|
184
docs/wiki.md
184
docs/wiki.md
@ -1,4 +1,11 @@
|
||||
### docker
|
||||
## test-notify
|
||||
|
||||
```sh
|
||||
./target/debug/ai n|jq -r ".notifications|.[].cid" >> ~/.config/ai/txt/notify_cid*
|
||||
./target/debug/ai bot
|
||||
```
|
||||
|
||||
## docker
|
||||
|
||||
```sh
|
||||
$ docker run -it syui/aios ai
|
||||
@ -11,7 +18,7 @@ $ cp -rf ~/.config/ai ./.config/
|
||||
$ docker compose up
|
||||
```
|
||||
|
||||
### cron
|
||||
## cron
|
||||
|
||||
```sh
|
||||
$ sudo pacman -S fcron
|
||||
@ -19,7 +26,7 @@ $ fcrontab -e
|
||||
* * * * * $HOME/bot/test/ai.zsh c
|
||||
```
|
||||
|
||||
### ssh
|
||||
## ssh
|
||||
|
||||
```sh
|
||||
$ ssh-keygen -f /.ssh/diffusers.key -t ed25519
|
||||
@ -50,3 +57,174 @@ services:
|
||||
- ./.config:/root/.config
|
||||
command: ai bot -a syui.syu.is
|
||||
```
|
||||
|
||||
## openapi
|
||||
|
||||
```sh
|
||||
# https://github.com/rdmurphy/atproto-openapi-types
|
||||
$ curl -sLO https://raw.githubusercontent.com/rdmurphy/atproto-openapi-types/main/spec/api.json
|
||||
```
|
||||
|
||||
## plc
|
||||
|
||||
```sh
|
||||
# 何度か実行するとplcをlatestまでexportされる
|
||||
$ .config/ai/scpt/test/pds.zsh e
|
||||
```
|
||||
|
||||
## cmt
|
||||
|
||||
blogなどにblueskyアカウントのpostを表示します。
|
||||
|
||||
以下でbotがblogのコメントシステムを開きます。
|
||||
|
||||
```sh
|
||||
@yui.syui.ai /comment https://syui.ai/blog/post/2024/04/25/bluesky/
|
||||
```
|
||||
|
||||
開いたbotのpostに返信することで、特定のblog path上でpostを表示します。
|
||||
|
||||
<blockquote class="bluesky-embed" data-bluesky-uri="at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.post/3kqxbtmwlje2h" data-bluesky-cid="bafyreiasxp5g3nkkd6g7lxh55qaxcc7ylefaljmbcp627nu2geks62c57m"><p lang="">please reply with your comments here ↓
|
||||
</p>— ai (<a href="https://bsky.app/profile/did:plc:4hqjfn7m6n5hno3doamuhgef?ref_src=embed">@yui.syui.ai</a>) <a href="https://bsky.app/profile/did:plc:4hqjfn7m6n5hno3doamuhgef/post/3kqxbtmwlje2h?ref_src=embed">Apr 25, 2024 at 20:18</a></blockquote><script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script>
|
||||
|
||||
```ts
|
||||
<link href="https://syui.ai/js/comment/app.js" rel="preload" as="script">
|
||||
<link href="https://syui.ai/js/comment/chunk-vendors.js" rel="preload" as="script">
|
||||
<div id="comment"></div>
|
||||
<script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script>
|
||||
<script src="https://syui.ai/js/comment/chunk-vendors.js"></script>
|
||||
<script src="https://syui.ai/js/comment/app.js"></script>
|
||||
```
|
||||
|
||||
## example json
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"uri": "at://did:plc:wkzuqomvkxx5eiv5nl2lvm23/app.bsky.feed.post/3kp4ze5dcek2j",
|
||||
"cid": "bafyreic4g7mthhw654zgv4skt5tqbs2xqg6n7bli4gayl2nquljngnotiy",
|
||||
"author": {
|
||||
"did": "did:plc:wkzuqomvkxx5eiv5nl2lvm23",
|
||||
"handle": "syui.syu.is",
|
||||
"displayName": "syui",
|
||||
"avatar": "https://api.syu.is/img/avatar/plain/did:plc:wkzuqomvkxx5eiv5nl2lvm23/bafkreifvabvstfgawt6csagh44xdevb6c2uiwpgfho3xnpdrr6o7nbkxry@jpeg",
|
||||
"indexedAt": "2024-01-14T10:20:13.367Z",
|
||||
"viewer": {
|
||||
"muted": false,
|
||||
"blockedBy": false,
|
||||
"following": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.graph.follow/3kiztjatnms25",
|
||||
"followedBy": "at://did:plc:wkzuqomvkxx5eiv5nl2lvm23/app.bsky.graph.follow/3kirwsboeos26"
|
||||
},
|
||||
"labels": []
|
||||
},
|
||||
"reason": "reply",
|
||||
"reasonSubject": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j",
|
||||
"record": {
|
||||
"text": "1",
|
||||
"$type": "app.bsky.feed.post",
|
||||
"langs": [
|
||||
"ja"
|
||||
],
|
||||
"reply": {
|
||||
"root": {
|
||||
"cid": "bafyreiceckunxajycacn7dbuojrwb2wmurhfkleermvewwik44cn6vqo3a",
|
||||
"uri": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j"
|
||||
},
|
||||
"parent": {
|
||||
"cid": "bafyreiceckunxajycacn7dbuojrwb2wmurhfkleermvewwik44cn6vqo3a",
|
||||
"uri": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j"
|
||||
}
|
||||
},
|
||||
"createdAt": "2024-04-02T07:12:28.799Z"
|
||||
},
|
||||
"isRead": true,
|
||||
"indexedAt": "2024-04-02T07:12:28.799Z",
|
||||
"labels": []
|
||||
},
|
||||
{
|
||||
"uri": "at://did:plc:wkzuqomvkxx5eiv5nl2lvm23/app.bsky.feed.post/3kp54af2zes2j",
|
||||
"cid": "bafyreig4kvfpu557qehttt2y5eh7rcyodbxqwtnl73f3fhjsstiap3abzu",
|
||||
"author": {
|
||||
"did": "did:plc:wkzuqomvkxx5eiv5nl2lvm23",
|
||||
"handle": "syui.syu.is",
|
||||
"displayName": "syui",
|
||||
"avatar": "https://api.syu.is/img/avatar/plain/did:plc:wkzuqomvkxx5eiv5nl2lvm23/bafkreifvabvstfgawt6csagh44xdevb6c2uiwpgfho3xnpdrr6o7nbkxry@jpeg",
|
||||
"indexedAt": "2024-01-14T10:20:13.367Z",
|
||||
"viewer": {
|
||||
"muted": false,
|
||||
"blockedBy": false,
|
||||
"following": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.graph.follow/3kiztjatnms25",
|
||||
"followedBy": "at://did:plc:wkzuqomvkxx5eiv5nl2lvm23/app.bsky.graph.follow/3kirwsboeos26"
|
||||
},
|
||||
"labels": []
|
||||
},
|
||||
"reason": "reply",
|
||||
"reasonSubject": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j",
|
||||
"record": {
|
||||
"text": "2",
|
||||
"$type": "app.bsky.feed.post",
|
||||
"langs": [
|
||||
"ja"
|
||||
],
|
||||
"reply": {
|
||||
"root": {
|
||||
"cid": "bafyreiceckunxajycacn7dbuojrwb2wmurhfkleermvewwik44cn6vqo3a",
|
||||
"uri": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j"
|
||||
},
|
||||
"parent": {
|
||||
"cid": "bafyreiceckunxajycacn7dbuojrwb2wmurhfkleermvewwik44cn6vqo3a",
|
||||
"uri": "at://did:plc:dconvttcori3mrh2wrmehvwt/app.bsky.feed.post/3kp4zdnlo5s2j"
|
||||
}
|
||||
},
|
||||
"createdAt": "2024-04-02T08:04:03.938Z"
|
||||
},
|
||||
"isRead": true,
|
||||
"indexedAt": "2024-04-02T08:04:03.938Z",
|
||||
"labels": []
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"uri": "at://did:plc:uqzpqmrjnptsxezjx4xuh2mn/app.bsky.feed.post/3kp5qniyzm42h",
|
||||
"cid": "bafyreihmutmtf2clpgmx5l3qpu6xea6z25xrop74mltsycs5lfacm27u6e",
|
||||
"author": {
|
||||
"did": "did:plc:uqzpqmrjnptsxezjx4xuh2mn",
|
||||
"handle": "syui.ai",
|
||||
"displayName": "syui",
|
||||
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:uqzpqmrjnptsxezjx4xuh2mn/bafkreid6kcc5pnn4b3ar7mj6vi3eiawhxgkcrw3edgbqeacyrlnlcoetea@jpeg",
|
||||
"viewer": {
|
||||
"muted": false,
|
||||
"blockedBy": false,
|
||||
"followedBy": "at://did:plc:uqzpqmrjnptsxezjx4xuh2mn/app.bsky.graph.follow/3kkvst5iq6r2a"
|
||||
},
|
||||
"labels": [],
|
||||
"description": "https://syui.ai",
|
||||
"indexedAt": "2024-01-25T23:54:12.979Z"
|
||||
},
|
||||
"reason": "reply",
|
||||
"reasonSubject": "at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.post/3kp5qn72s232q",
|
||||
"record": {
|
||||
"$type": "app.bsky.feed.post",
|
||||
"createdAt": "2024-04-02T14:09:18.926Z",
|
||||
"langs": [
|
||||
"ja"
|
||||
],
|
||||
"reply": {
|
||||
"parent": {
|
||||
"cid": "bafyreiewdfyh6rywpkdzpmf5markqa6tavc5smc32q7cw2wpwbqik5hnfm",
|
||||
"uri": "at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.post/3kp5qn72s232q"
|
||||
},
|
||||
"root": {
|
||||
"cid": "bafyreiewdfyh6rywpkdzpmf5markqa6tavc5smc32q7cw2wpwbqik5hnfm",
|
||||
"uri": "at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.post/3kp5qn72s232q"
|
||||
}
|
||||
},
|
||||
"text": "first"
|
||||
},
|
||||
"isRead": true,
|
||||
"indexedAt": "2024-04-02T14:09:18.926Z",
|
||||
"labels": []
|
||||
}
|
||||
```
|
||||
|
812
src/bot.rs
812
src/bot.rs
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@ pub fn log_file(s: &str) -> String {
|
||||
match &*s {
|
||||
"n1" => f + &"notify_cid.txt",
|
||||
"n2" => f + &"notify_cid_run.txt",
|
||||
"c1" => f + &"comment_cid.txt",
|
||||
_ => f + &s,
|
||||
}
|
||||
}
|
||||
@ -106,6 +107,7 @@ pub struct BaseUrl {
|
||||
pub record_list: String,
|
||||
pub record_create: String,
|
||||
pub record_delete: String,
|
||||
pub record_put: String,
|
||||
pub session_create: String,
|
||||
pub session_refresh: String,
|
||||
pub session_get: String,
|
||||
@ -123,6 +125,7 @@ pub struct BaseUrl {
|
||||
pub follow: String,
|
||||
pub follows: String,
|
||||
pub followers: String,
|
||||
pub feed_get: String,
|
||||
}
|
||||
|
||||
pub fn url(s: &str) -> String {
|
||||
@ -140,6 +143,7 @@ pub fn url(s: &str) -> String {
|
||||
let baseurl = BaseUrl {
|
||||
profile_get: "com.atproto.identity.resolveHandle".to_string(),
|
||||
thread_get: "app.bsky.feed.getPostThread".to_string(),
|
||||
record_put: "com.atproto.repo.putRecord".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(),
|
||||
@ -148,6 +152,7 @@ pub fn url(s: &str) -> 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(),
|
||||
feed_get: "app.bsky.feed.getFeed".to_string(),
|
||||
timeline_author: "app.bsky.feed.getAuthorFeed".to_string(),
|
||||
like: "app.bsky.feed.like".to_string(),
|
||||
repost: "app.bsky.feed.repost".to_string(),
|
||||
@ -170,6 +175,7 @@ pub fn url(s: &str) -> String {
|
||||
"record_list" => t.to_string() + &baseurl.record_list,
|
||||
"record_create" => t.to_string() + &baseurl.record_create,
|
||||
"record_delete" => t.to_string() + &baseurl.record_delete,
|
||||
"record_put" => t.to_string() + &baseurl.record_put,
|
||||
"session_create" => t.to_string() + &baseurl.session_create,
|
||||
"session_refresh" => t.to_string() + &baseurl.session_refresh,
|
||||
"session_get" => t.to_string() + &baseurl.session_get,
|
||||
@ -187,6 +193,7 @@ pub fn url(s: &str) -> String {
|
||||
"follow" => t.to_string() + &baseurl.follow,
|
||||
"follows" => t.to_string() + &baseurl.follows,
|
||||
"followers" => t.to_string() + &baseurl.followers,
|
||||
"feed_get" => t.to_string() + &baseurl.feed_get,
|
||||
_ => s,
|
||||
}
|
||||
}
|
||||
|
33
src/delete_record.rs
Normal file
33
src/delete_record.rs
Normal file
@ -0,0 +1,33 @@
|
||||
extern crate reqwest;
|
||||
use crate::data_toml;
|
||||
use crate::data_refresh;
|
||||
use crate::url;
|
||||
use serde_json::json;
|
||||
|
||||
pub async fn post_request(rkey: String, col: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
//let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
|
||||
let url = url(&"record_delete");
|
||||
|
||||
let post = Some(json!({
|
||||
"repo": handle.to_string(),
|
||||
"rkey": rkey.to_string(),
|
||||
"collection": col.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;
|
||||
}
|
33
src/feed_get.rs
Normal file
33
src/feed_get.rs
Normal file
@ -0,0 +1,33 @@
|
||||
extern crate reqwest;
|
||||
use crate::data_refresh;
|
||||
use crate::url;
|
||||
|
||||
pub async fn get_request(feed: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let url = url(&"feed_get");
|
||||
let feed = feed.to_string();
|
||||
//let col = "app.bsky.feed.generator".to_string();
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let res = client
|
||||
.get(url)
|
||||
.query(&[("feed", feed)])
|
||||
//.query(&[("feed", feed), ("collection", col)])
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
77
src/feed_watch.rs
Normal file
77
src/feed_watch.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use seahorse::Context;
|
||||
|
||||
//use crate::openai;
|
||||
use crate::feed_get;
|
||||
|
||||
use crate::data::data_toml;
|
||||
use crate::data::Timeline;
|
||||
use crate::data::log_file;
|
||||
use crate::data::w_cid;
|
||||
|
||||
pub fn c_feed_watch(c: &Context) {
|
||||
let mut feed = "at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd".to_string();
|
||||
if c.string_flag("url").is_ok() {
|
||||
feed = c.string_flag("url").unwrap();
|
||||
}
|
||||
let mut tag = "syai".to_string();
|
||||
if c.string_flag("tag").is_ok() {
|
||||
tag = c.string_flag("tag").unwrap();
|
||||
}
|
||||
|
||||
let h = async {
|
||||
let notify = feed_get::get_request(feed).await;
|
||||
if notify == "err" {
|
||||
return;
|
||||
//refresh(c);
|
||||
//notify = feed_get::get_request("at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd".to_string()).await;
|
||||
}
|
||||
let timeline: Timeline = serde_json::from_str(¬ify).unwrap();
|
||||
let n = timeline.feed;
|
||||
let host = data_toml(&"host");
|
||||
let length = &n.len();
|
||||
let su = 0..*length;
|
||||
for i in su {
|
||||
let cid = &n[i].post.cid;
|
||||
let check_cid = w_cid(cid.to_string(), log_file(&"n1"), false);
|
||||
let handle = &n[i].post.author.handle;
|
||||
let did = &n[i].post.author.did;
|
||||
let uri = &n[i].post.uri;
|
||||
let _time = &n[i].post.indexedAt;
|
||||
let cid_root = cid;
|
||||
let uri_root = uri;
|
||||
let mut text = "";
|
||||
if !n[i].post.record.text.is_none() {
|
||||
text = &n[i].post.record.text.as_ref().unwrap();
|
||||
}
|
||||
|
||||
let vec: Vec<&str> = text.split_whitespace().collect();
|
||||
let com = vec[0].trim().to_string();
|
||||
let mut prompt = "".to_string();
|
||||
let mut prompt_sub = "".to_string();
|
||||
|
||||
if com == "@ai" || com == "/ai" || com == tag {
|
||||
prompt_sub = vec[1..].join(" ");
|
||||
} else {
|
||||
prompt = vec[1..].join(" ");
|
||||
if vec.len() > 1 {
|
||||
prompt_sub = vec[2..].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
if check_cid == false && { prompt.is_empty() == false || com.is_empty() == false } {
|
||||
println!("{}", handle);
|
||||
if c.bool_flag("debug") == true {
|
||||
println!(
|
||||
"cid:{}\nuri:{}\ncid_root:{}\nuri_root:{}\nhost:{}\ndid:{}\ncheck_cid:{}",
|
||||
cid, uri, cid_root, uri_root, host, did, check_cid
|
||||
);
|
||||
}
|
||||
println!("{}", prompt_sub);
|
||||
println!("---");
|
||||
w_cid(cid.to_string(), log_file(&"n1"), true);
|
||||
}
|
||||
}
|
||||
};
|
||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||
return res;
|
||||
}
|
5
src/game.rs
Normal file
5
src/game.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod post_card;
|
||||
pub mod post_card_verify;
|
||||
pub mod post_game;
|
||||
pub mod post_game_user;
|
||||
pub mod post_game_login;
|
44
src/game/post_card.rs
Normal file
44
src/game/post_card.rs
Normal file
@ -0,0 +1,44 @@
|
||||
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(verify: String, id: i32, cp: i32, rank: i32, rare: String, col: String, author: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
let url = url(&"record_create");
|
||||
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": {
|
||||
"id": id,
|
||||
"cp": cp,
|
||||
"rank": rank,
|
||||
"rare": rare.to_string(),
|
||||
"author": author.to_string(),
|
||||
"verify": verify.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;
|
||||
}
|
58
src/game/post_card_verify.rs
Normal file
58
src/game/post_card_verify.rs
Normal file
@ -0,0 +1,58 @@
|
||||
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(col: String, img: String, id: i32, cp: i32, rank: i32, rare: String, user_handle: String, user_did: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
let url = url(&"record_create");
|
||||
let d = Timestamp::now_utc();
|
||||
let d = d.to_string();
|
||||
let link = "https://bsky.app/profile/yui.syui.ai".to_string();
|
||||
let post = Some(json!({
|
||||
"repo": handle.to_string(),
|
||||
"did": did.to_string(),
|
||||
"collection": col.to_string(),
|
||||
"record": {
|
||||
"id": id,
|
||||
"cp": cp,
|
||||
"rank": rank,
|
||||
"rare": rare.to_string(),
|
||||
"handle": user_handle.to_string(),
|
||||
"did": user_did.to_string(),
|
||||
"embed": {
|
||||
"$type": "app.bsky.embed.external",
|
||||
"external": {
|
||||
"uri": link,
|
||||
"thumb": {
|
||||
"$type": "blob",
|
||||
"ref": {
|
||||
"$link": img.to_string()
|
||||
},
|
||||
"mimeType": "image/jpeg",
|
||||
"size": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"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;
|
||||
}
|
39
src/game/post_game.rs
Normal file
39
src/game/post_game.rs
Normal file
@ -0,0 +1,39 @@
|
||||
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(col: String, account: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
let url = url(&"record_put");
|
||||
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": "self".to_string(),
|
||||
"record": {
|
||||
"account": account.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;
|
||||
}
|
42
src/game/post_game_login.rs
Normal file
42
src/game/post_game_login.rs
Normal file
@ -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(col: String, username: String, login: bool, account: String) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
let url = url(&"record_put");
|
||||
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": "self".to_string(),
|
||||
"record": {
|
||||
"login": login,
|
||||
"username": username.to_string(),
|
||||
"account": account.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;
|
||||
}
|
55
src/game/post_game_user.rs
Normal file
55
src/game/post_game_user.rs
Normal file
@ -0,0 +1,55 @@
|
||||
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(col: String, user_name: String, user_did: String, user_handle: String, aiten: i32, limit: i32, chara: String, lv: i32, exp: i32, hp: i32, rank: i32, mode: i32, attach: i32, critical: i32, critical_d: i32) -> String {
|
||||
let token = data_refresh(&"access");
|
||||
let did = data_toml(&"did");
|
||||
let handle = data_toml(&"handle");
|
||||
let url = url(&"record_put");
|
||||
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": user_name.to_string(),
|
||||
"record": {
|
||||
"did": user_did.to_string(),
|
||||
"handle": user_handle.to_string(),
|
||||
"aiten": aiten,
|
||||
"limit": limit,
|
||||
"character": {
|
||||
chara.to_string(): {
|
||||
"lv": lv,
|
||||
"exp": exp,
|
||||
"hp": hp,
|
||||
"rank": rank,
|
||||
"mode": mode,
|
||||
"attach": attach,
|
||||
"critical": critical,
|
||||
"critical_d": critical_d,
|
||||
}
|
||||
},
|
||||
"createdAt": d.to_string(),
|
||||
"updatedAt": 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;
|
||||
}
|
389
src/main.rs
389
src/main.rs
@ -3,6 +3,7 @@ use std::env;
|
||||
|
||||
use crate::ascii::c_ascii;
|
||||
use crate::bot::c_bot;
|
||||
use crate::bot::c_bot_feed;
|
||||
use crate::data::c_follow_all;
|
||||
use crate::data::c_openai_key;
|
||||
use crate::data::data_toml;
|
||||
@ -10,6 +11,12 @@ use crate::data::data_refresh;
|
||||
use crate::data::url;
|
||||
use crate::data::w_cfg;
|
||||
use crate::data::w_refresh;
|
||||
use crate::feed_watch::c_feed_watch;
|
||||
use crate::game::post_card;
|
||||
use crate::game::post_card_verify;
|
||||
use crate::game::post_game;
|
||||
use crate::game::post_game_user;
|
||||
use crate::game::post_game_login;
|
||||
|
||||
use data::ProfileIdentityResolve;
|
||||
|
||||
@ -28,6 +35,7 @@ pub mod notify_read;
|
||||
pub mod openai;
|
||||
pub mod post;
|
||||
pub mod post_link;
|
||||
pub mod game;
|
||||
pub mod profile;
|
||||
pub mod refresh;
|
||||
pub mod reply;
|
||||
@ -37,10 +45,16 @@ pub mod repost;
|
||||
pub mod session;
|
||||
pub mod timeline_author;
|
||||
pub mod token;
|
||||
pub mod feed_get;
|
||||
pub mod feed_watch;
|
||||
pub mod delete_record;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let app = App::new(env!("CARGO_PKG_NAME"))
|
||||
.author(env!("CARGO_PKG_AUTHORS"))
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.description(env!("CARGO_PKG_DESCRIPTION"))
|
||||
.command(
|
||||
Command::new("ai")
|
||||
.alias("a")
|
||||
@ -59,6 +73,26 @@ fn main() {
|
||||
Flag::new("admin", FlagType::String)
|
||||
.alias("a"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("feed", FlagType::String)
|
||||
.alias("f"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("feed_watch")
|
||||
.action(feed_watch)
|
||||
.flag(
|
||||
Flag::new("url", FlagType::String)
|
||||
.alias("u"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("tag", FlagType::String)
|
||||
.alias("t"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("debug", FlagType::Bool)
|
||||
.alias("d"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("follow_all")
|
||||
@ -95,6 +129,12 @@ fn main() {
|
||||
.alias("t")
|
||||
.action(timeline),
|
||||
)
|
||||
.command(
|
||||
Command::new("feed")
|
||||
.description("feed <feed-uri>")
|
||||
.alias("f")
|
||||
.action(feed)
|
||||
)
|
||||
.command(
|
||||
Command::new("did")
|
||||
.description("did <handle>")
|
||||
@ -110,6 +150,170 @@ fn main() {
|
||||
.alias("l"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("delete")
|
||||
.description("d <rkey> -c <collection>")
|
||||
.alias("d")
|
||||
.action(delete)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("card")
|
||||
.description("-v <at://verify> -i <int:id> -p <int:cp> -r <int:rank> -c <collection> -a <author> -img <link> -rare <normal>")
|
||||
.action(card)
|
||||
.flag(
|
||||
Flag::new("id", FlagType::Int)
|
||||
.alias("i"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("cp", FlagType::Int)
|
||||
.alias("p"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("rank", FlagType::Int)
|
||||
.alias("r"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("rare", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("author", FlagType::String)
|
||||
.alias("a"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("verify", FlagType::String)
|
||||
.alias("v"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("img", FlagType::String)
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("card-verify")
|
||||
.description("<at://verify> -c <collection> -i <id> -p <cp> -r <rank> -rare <normal> -H <syui.ai> -d <did>")
|
||||
.action(card_verify)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("id", FlagType::Int)
|
||||
.alias("i"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("cp", FlagType::Int)
|
||||
.alias("p"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("rank", FlagType::Int)
|
||||
.alias("r"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("rare", FlagType::String)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("handle", FlagType::String)
|
||||
.alias("H"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("did", FlagType::String)
|
||||
.alias("did"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("game")
|
||||
.description("a <at://yui.syui.ai/ai.syui.game.user/username>")
|
||||
.action(game)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("account", FlagType::String)
|
||||
.alias("a"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("game-login")
|
||||
.description("l <bool> -u <username> -c <collection>")
|
||||
.action(game_login)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("login", FlagType::Bool)
|
||||
.alias("l"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("username", FlagType::String)
|
||||
.alias("u"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("game-user")
|
||||
.description("-chara ai -l 20240101 -ten 0 --lv 0 --exp 0 --hp 0 --rank 0 --mode 0 --attach 0 --critical 0 --critical_d 0")
|
||||
.action(game_user)
|
||||
.flag(
|
||||
Flag::new("username", FlagType::String)
|
||||
.alias("u"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("did", FlagType::String)
|
||||
.alias("d"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("handle", FlagType::String)
|
||||
.alias("H"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("character", FlagType::String)
|
||||
.alias("chara"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("aiten", FlagType::Int)
|
||||
.alias("ten"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("limit", FlagType::Int)
|
||||
.alias("l"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("lv", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("hp", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("attach", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("exp", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("critical", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("critical_d", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("rank", FlagType::Int)
|
||||
)
|
||||
.flag(
|
||||
Flag::new("mode", FlagType::Int)
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("like")
|
||||
.description("like <cid> -u <uri>")
|
||||
@ -190,6 +394,10 @@ fn main() {
|
||||
Flag::new("post", FlagType::String)
|
||||
.alias("p"),
|
||||
)
|
||||
.flag(
|
||||
Flag::new("col", FlagType::String)
|
||||
.alias("c"),
|
||||
)
|
||||
)
|
||||
.command(
|
||||
Command::new("follow")
|
||||
@ -271,6 +479,14 @@ fn bot(c: &Context) {
|
||||
refresh(c);
|
||||
loop {
|
||||
c_bot(c);
|
||||
c_bot_feed(c);
|
||||
}
|
||||
}
|
||||
|
||||
fn feed_watch(c: &Context) {
|
||||
refresh(c);
|
||||
loop {
|
||||
c_feed_watch(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,15 +522,12 @@ fn refresh(_c: &Context) {
|
||||
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);
|
||||
}
|
||||
@ -334,6 +547,22 @@ fn notify(c: &Context) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fn feed(c: &Context) {
|
||||
refresh(c);
|
||||
let feed_d = "at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd".to_string();
|
||||
let h = async {
|
||||
if c.args.len() == 0 {
|
||||
let j = feed_get::get_request(feed_d).await;
|
||||
println!("{}", j);
|
||||
} else {
|
||||
let j = feed_get::get_request(c.args[0].to_string()).await;
|
||||
println!("{}", j);
|
||||
}
|
||||
};
|
||||
let res = tokio::runtime::Runtime::new().unwrap().block_on(h);
|
||||
return res;
|
||||
}
|
||||
|
||||
fn did(c: &Context) {
|
||||
refresh(c);
|
||||
let h = async {
|
||||
@ -383,6 +612,19 @@ fn post(c: &Context) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fn delete(c: &Context) {
|
||||
refresh(c);
|
||||
let m = c.args[0].to_string();
|
||||
let h = async {
|
||||
if let Ok(col) = c.string_flag("col") {
|
||||
let str = delete_record::post_request(m.to_string(), col);
|
||||
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();
|
||||
@ -396,6 +638,145 @@ fn like(c: &Context) {
|
||||
return res;
|
||||
}
|
||||
|
||||
async fn c_card(c: &Context) -> Result<(), Box<dyn std::error::Error>> {
|
||||
//let m = c.args[0].to_string();
|
||||
let author = c.string_flag("author").unwrap_or_else(|_| "syui".to_string());
|
||||
let verify = c.string_flag("verify").unwrap_or_else(|_| "at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.card.verify/3lagpvhppmd2q".to_string());
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "ai.syui.card".to_string());
|
||||
//let img = c.string_flag("img").unwrap_or_else(|_| "bafkreigvcjc46qtelpc4wsg7fwf6qktbi6a23ouqiupth2r37zhrn7wbza".to_string());
|
||||
let id = c.int_flag("id")?.try_into()?;
|
||||
let cp = c.int_flag("cp")?.try_into()?;
|
||||
let rank = c.int_flag("rank")?.try_into()?;
|
||||
let rare = c.string_flag("rare").unwrap_or_else(|_| "normal".to_string());
|
||||
let str = post_card::post_request(verify, id, cp, rank, rare, col, author);
|
||||
println!("{}", str.await);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn card(c: &Context) {
|
||||
refresh(c);
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
if let Err(e) = c_card(c).await {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn c_card_verify(c: &Context) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "ai.syui.card.verify".to_string());
|
||||
let img = c.string_flag("img").unwrap_or_else(|_| "bafkreigvcjc46qtelpc4wsg7fwf6qktbi6a23ouqiupth2r37zhrn7wbza".to_string());
|
||||
let id = c.int_flag("id")?.try_into()?;
|
||||
let cp = c.int_flag("cp")?.try_into()?;
|
||||
let rank = c.int_flag("rank")?.try_into()?;
|
||||
let rare = c.string_flag("rare").unwrap_or_else(|_| "normal".to_string());
|
||||
let user_handle = c.string_flag("handle").unwrap_or_else(|_| "syui.ai".to_string());
|
||||
let user_did = c.string_flag("did").unwrap_or_else(|_| "did:plc:uqzpqmrjnptsxezjx4xuh2mn".to_string());
|
||||
|
||||
//match id === 1 let img = "xxx";
|
||||
let str = post_card_verify::post_request(col, img, id, cp, rank, rare, user_handle, user_did);
|
||||
println!("{}", str.await);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn card_verify(c: &Context) {
|
||||
refresh(c);
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
if let Err(e) = c_card_verify(c).await {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn c_game(c: &Context) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let account = c.string_flag("account").unwrap_or_else(|_| "at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.game.user/syui".to_string());
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "ai.syui.game".to_string());
|
||||
let handle = data_toml(&"handle");
|
||||
if handle == "syui.ai" {
|
||||
let str = post_game::post_request(col, account);
|
||||
println!("{}", str.await);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "Not authorized")))
|
||||
}
|
||||
}
|
||||
|
||||
fn game(c: &Context) {
|
||||
refresh(c);
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
if let Err(e) = c_game(c).await {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn c_game_user(c: &Context) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "ai.syui.game.user".to_string());
|
||||
let user_name = c.string_flag("username").unwrap_or_else(|_| "syui".to_string());
|
||||
let user_handle = c.string_flag("handle").unwrap_or_else(|_| "syui.ai".to_string());
|
||||
let user_did = c.string_flag("did").unwrap_or_else(|_| "did:plc:uqzpqmrjnptsxezjx4xuh2mn".to_string());
|
||||
let chara = c.string_flag("character").unwrap_or_else(|_| "ai".to_string());
|
||||
let limit = c.int_flag("limit")?.try_into()?;
|
||||
let aiten = c.int_flag("aiten")?.try_into()?;
|
||||
let lv = c.int_flag("lv")?.try_into()?;
|
||||
let exp = c.int_flag("exp")?.try_into()?;
|
||||
let hp = c.int_flag("hp")?.try_into()?;
|
||||
let rank = c.int_flag("rank")?.try_into()?;
|
||||
let mode = c.int_flag("mode")?.try_into()?;
|
||||
let attach = c.int_flag("attach")?.try_into()?;
|
||||
let critical = c.int_flag("critical")?.try_into()?;
|
||||
let critical_d = c.int_flag("critical_d")?.try_into()?;
|
||||
|
||||
if data_toml(&"handle") == "yui.syui.ai" {
|
||||
let str = post_game_user::post_request(col, user_name, user_did, user_handle, aiten, limit, chara, lv, exp, hp, rank, mode, attach, critical, critical_d);
|
||||
println!("{}", str.await);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "Not authorized")))
|
||||
}
|
||||
}
|
||||
|
||||
fn game_user(c: &Context) {
|
||||
refresh(c);
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
if let Err(e) = c_game_user(c).await {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn c_game_login(c: &Context) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "ai.syui.game.login".to_string());
|
||||
let user_name = c.string_flag("username").unwrap_or_else(|_| "syui".to_string());
|
||||
let account = "at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.game.user/".to_string() + &user_name;
|
||||
let login = c.bool_flag("login");
|
||||
if data_toml(&"handle") == "yui.syui.ai" {
|
||||
let str = post_game_login::post_request(col, user_name, login, account);
|
||||
println!("{}", str.await);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "Not authorized")))
|
||||
}
|
||||
}
|
||||
|
||||
fn game_login(c: &Context) {
|
||||
refresh(c);
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
if let Err(e) = c_game_login(c).await {
|
||||
eprintln!("Error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn repost(c: &Context) {
|
||||
refresh(c);
|
||||
let m = c.args[0].to_string();
|
||||
@ -450,6 +831,7 @@ fn mention(c: &Context) {
|
||||
let h = async {
|
||||
let str = profile::get_request(m.to_string()).await;
|
||||
let profile: ProfileIdentityResolve = serde_json::from_str(&str).unwrap();
|
||||
let col = c.string_flag("col").unwrap_or_else(|_| "app.bsky.feed.post".to_string());
|
||||
let udid = profile.did;
|
||||
let handle = m.to_string();
|
||||
let at = "@".to_owned() + &handle;
|
||||
@ -457,6 +839,7 @@ fn mention(c: &Context) {
|
||||
let s = 0;
|
||||
if let Ok(post) = c.string_flag("post") {
|
||||
let str = mention::post_request(
|
||||
col,
|
||||
post.to_string(),
|
||||
at.to_string(),
|
||||
udid.to_string(),
|
||||
|
@ -5,13 +5,13 @@ 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 {
|
||||
pub async fn post_request(col: String, 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 col = "app.bsky.feed.post".to_string();
|
||||
|
||||
let d = Timestamp::now_utc();
|
||||
let d = d.to_string();
|
||||
@ -22,7 +22,7 @@ pub async fn post_request(text: String, at: String, udid: String, s: i32, e: i32
|
||||
"collection": col.to_string(),
|
||||
"record": {
|
||||
"text": at.to_string() + &" ".to_string() + &text.to_string(),
|
||||
"$type": "app.bsky.feed.post",
|
||||
"$type": col.to_string(),
|
||||
"createdAt": d.to_string(),
|
||||
"facets": [
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ pub async fn post_request(prompt: String) -> String {
|
||||
";
|
||||
|
||||
let post = Some(json!({
|
||||
"model": "gpt-3.5-turbo",
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": [
|
||||
{"role": "system", "content": &setting.to_string()},
|
||||
{"role": "user", "content": &prompt.to_string()},
|
||||
|
@ -9,13 +9,14 @@ case $OSTYPE in
|
||||
esac
|
||||
d=${0:a:h}
|
||||
|
||||
source $d/env
|
||||
source $d/env.zsh
|
||||
source $d/refresh.zsh
|
||||
source $d/token.zsh
|
||||
source $d/reply.zsh
|
||||
source $d/notify.zsh
|
||||
source $d/notify_cid.zsh
|
||||
source $d/cron.zsh
|
||||
source $d/feed.zsh
|
||||
|
||||
case $1 in
|
||||
refresh|r)
|
||||
@ -36,4 +37,7 @@ case $1 in
|
||||
cid)
|
||||
cid
|
||||
;;
|
||||
feed)
|
||||
feed
|
||||
;;
|
||||
esac
|
||||
|
@ -1,7 +1,7 @@
|
||||
function cron() {
|
||||
t=`docker ps |grep aios|grep Up`
|
||||
t=`docker ps |grep aios|grep R`
|
||||
if [ -z "$t" ];then
|
||||
docker compose up -d
|
||||
exit
|
||||
fi
|
||||
exit
|
||||
docker compose up -d
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#!/bin/zsh
|
||||
|
||||
ai l $HANDLE -p $PASSWORD -s $HOST && ai bot -a $ADMIN
|
||||
#ai l $HANDLE -p $PASSWORD -s $HOST
|
||||
ai bot -a $ADMIN
|
||||
|
5
test/feed.zsh
Normal file
5
test/feed.zsh
Normal file
@ -0,0 +1,5 @@
|
||||
function feed(){
|
||||
token=`cat ~/.config/ai/token.json|jq -r .accessJwt`
|
||||
url=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd
|
||||
curl -sL "https://public.api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=$url" -H "Authorization: Bearer $token"
|
||||
}
|
Reference in New Issue
Block a user