Skip to content

Commit

Permalink
chore: update file structure
Browse files Browse the repository at this point in the history
  • Loading branch information
BIYUEHU committed Aug 2, 2024
1 parent 9deb638 commit 4fe188c
Show file tree
Hide file tree
Showing 63 changed files with 3,771 additions and 1,815 deletions.
15 changes: 4 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
node_modules
dist
lib
.husky/_

.vscode/*
.vs/*
!.vscode/extensions.json
coverage
log
data

*.env
*.tgz
*.log
tsconfig.tsbuildinfo
test.http
kotori.dev.*

log/*
data/*

*.env
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "packages/fluoro"]
path = packages/fluoro
url = [email protected]:biyuehu/fluoro
6 changes: 6 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
preset: 'ts-jest',
coverageDirectory: 'coverage',
testEnvironment: 'node',
globals: {},
};
41 changes: 41 additions & 0 deletions kotori.dev.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[global]
port = 721
lang = "zh_CN"
command-prefix = "/"
dirs = []
noColor = false
level = 20


[adapter.cmd-test]
extends = "cmd"
master = 2333
nickname = "Kotarou"
age = 18
sex = "male"
self-id = 720

[adapter.sena]
extends = "onebot"
master = 3324656453
mode = "ws-reverse"
port = 23

[adapter.mizuki]
extends = "sandbox"
master = 899110018
port = 233

[adapter.romi]
extends = "minecraft"
command-prefix = "~"
master = 2333
template = "<§b§l%nickname%§f> §a%msg%§f"
nickname = "Romi"

[plugin.helper]
content = "请发送 /help"

[plugin.filter]
mode = 'exclude'
list = ['kotori-plugin-adapter-{onebot,minecraft,qq}']
2 changes: 1 addition & 1 deletion modules/adapter-cmd/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @Blog: https://hotaru.icu
* @Date: 2023-09-29 14:31:09
* @LastEditors: Hotaru [email protected]
* @LastEditTime: 2024-07-30 19:49:25
* @LastEditTime: 2024-08-01 17:44:48
*/
import { Adapter, type AdapterConfig, type Context, MessageScope, Tsu } from 'kotori-bot'
import CmdApi from './api'
Expand Down
File renamed without changes.
File renamed without changes.
157 changes: 78 additions & 79 deletions modules/adapter-qq/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,40 @@
* @LastEditors: Hotaru [email protected]
* @LastEditTime: 2024-02-17 16:42:08
*/
import { Adapter, AdapterConfig, Context, MessageScope, Tsu } from 'kotori-bot';
import WebSocket from 'ws';
import QQApi from './api';
import { PayloadData } from './types';
import QQElements from './elements';
import { Adapter, AdapterConfig, Context, MessageScope, Tsu } from 'kotori-bot'
import WebSocket from 'ws'
import QQApi from './api'
import { PayloadData } from './types'
import QQElements from './elements'

const WS_ADDRESS = 'wss://api.sgroup.qq.com/websocket';
const API_ADDRESS = 'https://api.sgroup.qq.com/v2';
const WS_ADDRESS = 'wss://api.sgroup.qq.com/websocket'
const API_ADDRESS = 'https://api.sgroup.qq.com/v2'

export const config = Tsu.Object({
appid: Tsu.String(),
secret: Tsu.String(),
retry: Tsu.Number().positive().default(10)
});
})

type QQConfig = Tsu.infer<typeof config> & AdapterConfig;
type QQConfig = Tsu.infer<typeof config> & AdapterConfig

export class QQAdapter extends Adapter<QQApi> {
private token = '';
private token = ''

private seq = 0;
private seq = 0

/* here need */
public msg_seq = 0;
public msg_seq = 0

private groupId = '';
private groupId = ''

public imageStack: (string | true)[] = [];
public imageStack: (string | true)[] = []

public readonly config: QQConfig;
public readonly config: QQConfig

public constructor(ctx: Context, config: QQConfig, identity: string) {
super(ctx, config, identity, QQApi, new QQElements());
this.config = config;
super(ctx, config, identity, QQApi, new QQElements())
this.config = config
}

public handle(data: PayloadData) {
Expand All @@ -50,16 +50,16 @@ export class QQAdapter extends Adapter<QQApi> {
intents: 1241513984,
shard: [0, 1]
}
});
})
} else if (data.t === 'READY') {
this.ctx.emit('connect', {
type: 'connect',
adapter: this,
normal: true,
mode: 'ws',
address: WS_ADDRESS
});
this.heartbeat();
})
this.heartbeat()
} else if (data.t === 'GROUP_AT_MESSAGE_CREATE') {
this.session('on_message', {
type: MessageScope.GROUP,
Expand All @@ -76,20 +76,20 @@ export class QQAdapter extends Adapter<QQApi> {
title: ''
},
groupId: data.d.group_openid
});
this.groupId = data.d.group_openid;
})
this.groupId = data.d.group_openid
/* here need improve */
} else if (data.op === 11) {
this.online();
this.online()
// this.offlineCheck();
}
if (data.s) this.seq = data.s;
if (data.s) this.seq = data.s
// if (!this.onlineTimerId) this.onlineTimerId = setTimeout(() => this.offline, 50 * 1000);
}

public start() {
this.generateToken();
this.connect();
this.generateToken()
this.connect()
}

public stop() {
Expand All @@ -99,134 +99,133 @@ export class QQAdapter extends Adapter<QQApi> {
normal: true,
mode: 'ws',
address: WS_ADDRESS
});
this.socket?.close();
this.offline();
})
this.socket?.close()
this.offline()
}

public send(action: string, params: object) {
if (action === 'ws') {
this.socket?.send(JSON.stringify(params));
return undefined;
this.socket?.send(JSON.stringify(params))
return undefined
}
let address = '/';
let cancel = false;
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
let req: Record<string, any> = {};
let address = '/'
let cancel = false
// biome-ignore lint:
let req: Record<string, any> = {}
if (action === 'send_group_msg' && 'groupId' in params && 'message' in params && 'id' in params) {
if (!params.message) return null;
address += `groups/${params.groupId}/messages`;
if (!params.message) return null
address += `groups/${params.groupId}/messages`
req = {
content: params.message,
msg_type: 0,
msg_id: params.id,
msg_seq: this.msg_seq
};
}
if (this.imageStack[this.msg_seq]) {
cancel = true;
let timerId: NodeJS.Timeout;
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
cancel = true
let timerId: NodeJS.Timeout
const timer = () =>
setTimeout(() => {
if (timerId) clearTimeout(timerId);
if (timerId) clearTimeout(timerId)
if (this.imageStack[this.msg_seq] === true) {
timerId = timer();
return;
timerId = timer()
return
}
req.file_info = { file_info: this.imageStack[this.msg_seq] };
req.msg_type = 7;
req.file_info = { file_info: this.imageStack[this.msg_seq] }
req.msg_type = 7
this.ctx.http.post(`${API_ADDRESS}${address}`, req, {
headers: {
Authorization: `QQBot ${this.token}`,
'X-Union-Appid': this.config.appid
},
validateStatus: () => true
});
}, 500);
})
}, 500)
}
this.msg_seq += 1;
this.msg_seq += 1
} else if (action === 'send_group_msg_media' && 'url' in params && 'file_type' in params) {
address += `groups/${this.groupId}/files`;
address += `groups/${this.groupId}/files`
req = {
file_type: params.file_type,
url: params.url,
srv_send_msg: false
};
this.msg_seq += 1;
}
this.msg_seq += 1
}
if (cancel) return undefined;
if (cancel) return undefined
return this.ctx.http.post(`${API_ADDRESS}${address}`, req, {
headers: {
Authorization: `QQBot ${this.token}`,
'X-Union-Appid': this.config.appid
},
validateStatus: () => true
});
})
}

private socket: WebSocket | null = null;
private socket: WebSocket | null = null

private async connect() {
this.socket = new WebSocket(WS_ADDRESS);
this.socket = new WebSocket(WS_ADDRESS)
this.socket.on('close', () => {
this.ctx.emit('connect', {
type: 'disconnect',
adapter: this,
normal: false,
address: WS_ADDRESS,
mode: 'ws'
});
})
setTimeout(() => {
if (!this.socket) return;
this.socket.close();
if (!this.socket) return
this.socket.close()
this.ctx.emit('connect', {
type: 'connect',
adapter: this,
normal: false,
mode: 'ws',
address: WS_ADDRESS
});
this.start();
}, this.config.retry * 1000);
});
this.socket.on('message', (data) => this.handle(JSON.parse(data.toString())));
})
this.start()
}, this.config.retry * 1000)
})
this.socket.on('message', (data) => this.handle(JSON.parse(data.toString())))
}

private async generateToken() {
const data = (await this.ctx.http.post('https://bots.qq.com/app/getAppAccessToken', {
appId: this.config.appid,
clientSecret: this.config.secret
})) as Record<string, string>;
})) as Record<string, string>
if (!data.access_token) {
this.offline();
this.ctx.logger.error('got token error!');
return;
this.offline()
this.ctx.logger.error('got token error!')
return
}
this.token = data.access_token;
this.token = data.access_token
this.generateTokenTimerId = setTimeout(
() => {
if (this.generateTokenTimerId) clearInterval(this.generateTokenTimerId);
this.generateToken();
if (this.generateTokenTimerId) clearInterval(this.generateTokenTimerId)
this.generateToken()
},
(parseInt(data.expires_in, 10) - 30) * 1000
);
)
}

private async heartbeat() {
this.heartbeatTimerId = setTimeout(() => {
this.send('ws', {
op: 1,
d: this.seq || null
});
if (this.heartbeatTimerId) clearInterval(this.heartbeatTimerId);
this.heartbeat();
}, 7 * 1000);
})
if (this.heartbeatTimerId) clearInterval(this.heartbeatTimerId)
this.heartbeat()
}, 7 * 1000)
}

/* global NodeJS */
private generateTokenTimerId?: NodeJS.Timeout;
private generateTokenTimerId?: NodeJS.Timeout

private heartbeatTimerId?: NodeJS.Timeout;
private heartbeatTimerId?: NodeJS.Timeout
}

export default QQAdapter;
export default QQAdapter
11 changes: 6 additions & 5 deletions modules/bangumi/src/http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Kotori from 'kotori-bot';
import { Http } from 'kotori-bot'

const req = new Http()

const headers = {
'user-agent': 'czy0729/Bangumi/6.4.0 (Android) (http://github.com/czy0729/Bangumi)'
};
}

export const http: typeof Kotori.http.get = async (url, params) =>
Kotori.http.get(`https://api.bgm.tv/${url}`, params, { headers });
export const http: typeof req.get = async (url, params) => req.get(`https://api.bgm.tv/${url}`, params, { headers })

export default http;
export default http
Loading

0 comments on commit 4fe188c

Please sign in to comment.