-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
63 changed files
with
3,771 additions
and
1,815 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export default { | ||
preset: 'ts-jest', | ||
coverageDirectory: 'coverage', | ||
testEnvironment: 'node', | ||
globals: {}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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' | ||
|
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
|
@@ -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, | ||
|
@@ -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() { | ||
|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.