feat(wip): 新的客户端协议库
This commit is contained in:
114
client-protocol/LingChairClient.ts
Normal file
114
client-protocol/LingChairClient.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
// deno-lint-ignore-file no-explicit-any
|
||||
import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'
|
||||
import crypto from 'node:crypto'
|
||||
import { CallMethod, ClientEvent } from './ApiDeclare.ts'
|
||||
import ApiCallbackMessage from './ApiCallbackMessage.ts'
|
||||
import User from "./User.ts"
|
||||
import UserMySelf from "./UserMySelf.ts"
|
||||
|
||||
export {
|
||||
User,
|
||||
UserMySelf,
|
||||
}
|
||||
|
||||
export default class LingChairClient {
|
||||
declare client: Socket
|
||||
declare access_token: string
|
||||
declare refresh_token?: string
|
||||
constructor(args: {
|
||||
server_url: string
|
||||
device_id: string,
|
||||
io?: Partial<ManagerOptions & SocketOptions>
|
||||
}) {
|
||||
this.client = io(args.server_url, {
|
||||
transports: ["polling", "websocket", "webtransport"],
|
||||
...args.io,
|
||||
auth: {
|
||||
...args.io?.auth,
|
||||
device_id: args.device_id,
|
||||
session_id: crypto.randomUUID(),
|
||||
},
|
||||
})
|
||||
this.client.on("The_White_Silk", (name: string, data: unknown, _callback: (ret: unknown) => void) => {
|
||||
try {
|
||||
if (name == null || data == null) return
|
||||
this.events[name]?.forEach((v) => v(data))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
connect() {
|
||||
this.client.connect()
|
||||
}
|
||||
disconnect() {
|
||||
this.client.disconnect()
|
||||
}
|
||||
reconnect() {
|
||||
this.disconnect()
|
||||
this.connect()
|
||||
}
|
||||
invoke(method: CallMethod, args: object = {}, timeout: number = 10000): Promise<ApiCallbackMessage> {
|
||||
return new Promise((resolve) => {
|
||||
this.client!.timeout(timeout).emit("The_White_Silk", method, args, (err: Error, res: ApiCallbackMessage) => {
|
||||
// 错误处理
|
||||
if (err) return resolve({
|
||||
code: -1,
|
||||
msg: err.message,
|
||||
})
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
}
|
||||
events: { [key: string]: ((data: any) => void)[] } = {}
|
||||
on(eventName: ClientEvent, func: (data: any) => void) {
|
||||
if (this.events[eventName] == null)
|
||||
this.events[eventName] = []
|
||||
if (this.events[eventName].indexOf(func) == -1)
|
||||
this.events[eventName].push(func)
|
||||
}
|
||||
off(eventName: ClientEvent, func: (data: any) => void) {
|
||||
if (this.events[eventName] == null)
|
||||
this.events[eventName] = []
|
||||
const index = this.events[eventName].indexOf(func)
|
||||
if (index != -1)
|
||||
this.events[eventName].splice(index, 1)
|
||||
}
|
||||
async auth(args: {
|
||||
refresh_token?: string,
|
||||
access_token?: string,
|
||||
account?: string,
|
||||
password?: string,
|
||||
}) {
|
||||
if ((!args.access_token && !args.refresh_token) && (!args.account && !args.password))
|
||||
throw new Error('Access/Refresh token or account & password required')
|
||||
|
||||
this.refresh_token = args.refresh_token
|
||||
|
||||
let access_token = args.access_token
|
||||
if (!access_token && args.refresh_token) {
|
||||
const re = await this.invoke('User.refreshAccessToken', {
|
||||
refresh_token: args.refresh_token,
|
||||
})
|
||||
if (re.code == 200) {
|
||||
access_token = re.data!.access_token as string | undefined
|
||||
} else return re
|
||||
}
|
||||
|
||||
if (!access_token && (args.account && args.password)) {
|
||||
const re = await this.invoke('User.login', {
|
||||
account: args.account,
|
||||
password: crypto.createHash('sha256').update(args.password).digest('hex'),
|
||||
})
|
||||
if (re.code == 200) {
|
||||
access_token = re.data!.access_token as string | undefined
|
||||
} else return re
|
||||
}
|
||||
|
||||
const re = await this.invoke('User.auth', {
|
||||
access_token: access_token
|
||||
})
|
||||
if (re.code == 200) this.access_token = access_token as string
|
||||
return re
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user