添加关闭付费响应的开关,删除分号

This commit is contained in:
xys20071111 2022-11-10 12:53:53 +08:00
parent aa6e39ffe4
commit e70174f4a4
No known key found for this signature in database
GPG Key ID: 29CB7FFE349CFD03
7 changed files with 137 additions and 127 deletions

View File

@ -1,15 +1,15 @@
import { EventEmitter, WebSocketClient, WebSocketServer } from "./Deps.ts";
import { EventEmitter, WebSocketClient, WebSocketServer } from "./Deps.ts"
import { sendDanmaku } from './SendDanmaku.ts'
import config from "./Config.ts";
import config from "./Config.ts"
interface Message {
cmd: string;
cmd: string
// deno-lint-ignore no-explicit-any
data: any;
data: any
}
const server: WebSocketServer = new WebSocketServer(config.api.port);
const authedClientSet: Set<WebSocketClient> = new Set();
const server: WebSocketServer = new WebSocketServer(config.api.port)
const authedClientSet: Set<WebSocketClient> = new Set()
class APIMsgHandler extends EventEmitter {
emit(
@ -19,41 +19,41 @@ class APIMsgHandler extends EventEmitter {
): boolean {
if (eventName === "AUTH") {
if (args[0] === config.api.token) {
authedClientSet.add(socket);
socket.send(JSON.stringify({ cmd: "AUTH", data: "AUTHED" }));
return true;
authedClientSet.add(socket)
socket.send(JSON.stringify({ cmd: "AUTH", data: "AUTHED" }))
return true
} else {
socket.send(JSON.stringify({ cmd: "AUTH", data: "FAILED" }));
return true;
socket.send(JSON.stringify({ cmd: "AUTH", data: "FAILED" }))
return true
}
}
if (authedClientSet.has(socket)) {
return super.emit.apply(this, [eventName, socket, args]);
return super.emit.apply(this, [eventName, socket, args])
}
return false;
return false
}
}
const serverEventEmitter = new APIMsgHandler();
const serverEventEmitter = new APIMsgHandler()
serverEventEmitter.on("SEND", (_socket: WebSocketClient, data: string) => {
sendDanmaku({
msg: data,
});
});
})
})
serverEventEmitter.on("ROOMID", (socket: WebSocket) => {
socket.send(JSON.stringify({
cmd: "ROOMID",
data: config.room_id,
}));
});
}))
})
server.on("connection", (client: WebSocketClient) => {
client.on("message", (data: string) => {
const msg: Message = JSON.parse(data);
serverEventEmitter.emit(msg.cmd, client, msg.data);
});
});
const msg: Message = JSON.parse(data)
serverEventEmitter.emit(msg.cmd, client, msg.data)
})
})
export { server };
export { server }

View File

@ -28,9 +28,12 @@ interface ConfigStruct {
advertiseing_cold_down: number
api: api_config
free_gift_action: boolean
disable_gift_action: boolean
disable_super_chat_action: boolean
disable_graud_action: boolean
}
const decoder = new TextDecoder('utf-8')
const config: ConfigStruct = JSON.parse(decoder.decode(Deno.readFileSync(`config/${Deno.args[0]}`)));
const config: ConfigStruct = JSON.parse(decoder.decode(Deno.readFileSync(`config/${Deno.args[0]}`)))
export default config;
export default config

View File

@ -1,6 +1,6 @@
import { brotli, EventEmitter, WebSocketClient } from "./Deps.ts";
import config from "./Config.ts";
import { printLog } from "./utils/mod.ts";
import { brotli, EventEmitter, WebSocketClient } from "./Deps.ts"
import config from "./Config.ts"
import { printLog } from "./utils/mod.ts"
import { server as apiServer } from './APIServer.ts'
enum DANMAKU_PROTOCOL {
@ -19,16 +19,16 @@ enum DANMAKU_TYPE {
}
const cookie =
`buvid3=${config.verify.buvid3};SESSDATA=${config.verify.sessdata};bili_jct=${config.verify.csrf}`;
const encoder = new TextEncoder();
const decoder = new TextDecoder("utf-8");
`buvid3=${config.verify.buvid3}SESSDATA=${config.verify.sessdata}bili_jct=${config.verify.csrf}`
const encoder = new TextEncoder()
const decoder = new TextDecoder("utf-8")
export class DanmakuReceiver extends EventEmitter {
private roomId: number;
private ws: WebSocket | null = null;
private roomId: number
private ws: WebSocket | null = null
constructor(roomId: number) {
super();
this.roomId = roomId;
super()
this.roomId = roomId
}
public async connect() {
const roomConfig = await (await fetch(
@ -41,12 +41,12 @@ export class DanmakuReceiver extends EventEmitter {
host: "api.live.bilibili.com",
},
},
)).json();
)).json()
this.ws = new WebSocket(
`wss://${roomConfig.data.host_server_list[0].host}:${
roomConfig.data.host_server_list[0].wss_port
}/sub`,
);
)
this.ws.onopen = () => {
const payload = JSON.stringify({
roomid: this.roomId,
@ -54,87 +54,87 @@ export class DanmakuReceiver extends EventEmitter {
platform: "web",
uid: config.verify.uid,
key: roomConfig.data.token,
});
})
this.ws!.send(this.generatePacket(
1,
7,
payload,
));
this.ws!.onmessage = this.danmakuProcesser.bind(this);
};
))
this.ws!.onmessage = this.danmakuProcesser.bind(this)
}
this.ws.onclose = () => {
this.emit("closed");
};
this.emit("closed")
}
}
private generatePacket(
protocol: number,
type: number,
payload: string,
): ArrayBuffer {
const payloadEncoded = encoder.encode(payload);
const packetLength = 16 + payloadEncoded.length;
const packet = new ArrayBuffer(packetLength);
const packetArray = new Uint8Array(packet);
const packetView = new DataView(packet);
packetView.setInt32(0, packetLength); // 总长度
packetView.setInt16(4, 16); // 头长度
packetView.setUint16(6, protocol); // 协议类型
packetView.setUint32(8, type); // 包类型
packetView.setUint32(12, 1); // 一个常数
packetArray.set(payloadEncoded, 16); //写入负载
return packet;
const payloadEncoded = encoder.encode(payload)
const packetLength = 16 + payloadEncoded.length
const packet = new ArrayBuffer(packetLength)
const packetArray = new Uint8Array(packet)
const packetView = new DataView(packet)
packetView.setInt32(0, packetLength) // 总长度
packetView.setInt16(4, 16) // 头长度
packetView.setUint16(6, protocol) // 协议类型
packetView.setUint32(8, type) // 包类型
packetView.setUint32(12, 1) // 一个常数
packetArray.set(payloadEncoded, 16) //写入负载
return packet
}
private async danmakuProcesser(ev: MessageEvent<Blob>) {
// 弹幕事件处理
const msgPacket = await ev.data.arrayBuffer()
const msgArray = new Uint8Array(msgPacket);
const msg = new DataView(msgPacket);
const packetProtocol = msg.getInt16(6);
const packetType = msg.getInt32(8);
const packetPayload: Uint8Array = msgArray.slice(16);
let jsonData;
const msgArray = new Uint8Array(msgPacket)
const msg = new DataView(msgPacket)
const packetProtocol = msg.getInt16(6)
const packetType = msg.getInt32(8)
const packetPayload: Uint8Array = msgArray.slice(16)
let jsonData
switch (packetType) {
case DANMAKU_TYPE.HEARTBEAT_REPLY:
// 心跳包,不做处理
break;
break
case DANMAKU_TYPE.AUTH_REPLY:
printLog('弹幕接收器' ,"通过认证");
printLog('弹幕接收器' ,"通过认证")
// 认证通过每30秒发一次心跳包
setInterval(() => {
const heartbeatPayload = "陈睿你妈死了";
const heartbeatPayload = "陈睿你妈死了"
if (this.ws) {
this.ws.send(this.generatePacket(1, 2, heartbeatPayload));
this.ws.send(this.generatePacket(1, 2, heartbeatPayload))
}
}, 30000);
this.emit("connected");
break;
}, 30000)
this.emit("connected")
break
case DANMAKU_TYPE.DATA:
switch (packetProtocol) {
case DANMAKU_PROTOCOL.JSON:
// 这些数据大都没用,但还是留着吧
jsonData = JSON.parse(decoder.decode(packetPayload));
this.emit(jsonData.cmd, jsonData.data);
break;
jsonData = JSON.parse(decoder.decode(packetPayload))
this.emit(jsonData.cmd, jsonData.data)
break
case DANMAKU_PROTOCOL.BROTLI: {
const resultRaw = brotli.decompress(packetPayload);
const result = new DataView(resultRaw.buffer);
let offset = 0;
const resultRaw = brotli.decompress(packetPayload)
const result = new DataView(resultRaw.buffer)
let offset = 0
while (offset < resultRaw.length) {
const length = result.getUint32(offset);
const packetData = resultRaw.slice(offset + 16, offset + length);
const data = JSON.parse(decoder.decode(packetData));
const cmd = data.cmd.split(":")[0];
this.emit(cmd, data.info || data.data);
const length = result.getUint32(offset)
const packetData = resultRaw.slice(offset + 16, offset + length)
const data = JSON.parse(decoder.decode(packetData))
const cmd = data.cmd.split(":")[0]
this.emit(cmd, data.info || data.data)
apiServer.clients.forEach((client: WebSocketClient) => {
client.send(JSON.stringify({ cmd, data: data.info || data.data }))
})
offset += length;
offset += length
}
}
}
break;
break
default:
printLog('弹幕接收器', `未知的弹幕数据包种类 ${packetType}`);
printLog('弹幕接收器', `未知的弹幕数据包种类 ${packetType}`)
}
}
}

View File

@ -3,4 +3,4 @@ import * as events from 'https://deno.land/x/events@v1.0.0/mod.ts'
const EventEmitter = events.default
export { EventEmitter }
export * as brotli from 'https://deno.land/x/brotli@v0.1.4/mod.ts'
export { WebSocketServer, type WebSocketClient } from 'https://deno.land/x/websocket@v0.1.4/mod.ts';
export { WebSocketServer, type WebSocketClient } from 'https://deno.land/x/websocket@v0.1.4/mod.ts'

View File

@ -1,7 +1,7 @@
import config from './Config.ts';
import { DanmakuReceiver } from './DanmakuReceiver.ts';
import { onGraud, onLiveEnd, onLiveStart, onSuperChat, onTotalGift, receiveDanmaku, receiveGift } from './DanmakuCallbacks.ts';
import { printLog } from './utils/mod.ts';
import config from './Config.ts'
import { DanmakuReceiver } from './DanmakuReceiver.ts'
import { onGraud, onLiveEnd, onLiveStart, onSuperChat, onTotalGift, receiveDanmaku, receiveGift } from './DanmakuCallbacks.ts'
import { printLog } from './utils/mod.ts'
async function launchAllPlugins() {
const pluginsList = await Deno.readDir('./plugins')
@ -15,19 +15,26 @@ async function launchAllPlugins() {
}
}
const danmakuReceiver = new DanmakuReceiver(config.room_id);
const danmakuReceiver = new DanmakuReceiver(config.room_id)
danmakuReceiver.on('connected', () => {
printLog('主程序', '连接成功');
});
printLog('主程序', '连接成功')
})
danmakuReceiver.on('closed', () => danmakuReceiver.connect());
danmakuReceiver.on('SEND_GIFT', receiveGift);
danmakuReceiver.on('LIVE', onLiveStart);
danmakuReceiver.on('PREPARING', onLiveEnd);
danmakuReceiver.on('DANMU_MSG', receiveDanmaku);
danmakuReceiver.on('COMBO_SEND', onTotalGift);
danmakuReceiver.on('GUARD_BUY', onGraud);
danmakuReceiver.on('SUPER_CHAT_MESSAGE', onSuperChat);
if (!config.disable_gift_action) {
danmakuReceiver.on('COMBO_SEND', onTotalGift)
danmakuReceiver.on('SEND_GIFT', receiveGift)
}
if (!config.disable_super_chat_action) {
danmakuReceiver.on('GUARD_BUY', onGraud)
}
if (!config.disable_super_chat_action) {
danmakuReceiver.on('SUPER_CHAT_MESSAGE', onSuperChat)
}
danmakuReceiver.on('closed', () => danmakuReceiver.connect())
danmakuReceiver.on('LIVE', onLiveStart)
danmakuReceiver.on('PREPARING', onLiveEnd)
danmakuReceiver.on('DANMU_MSG', receiveDanmaku)
launchAllPlugins()
danmakuReceiver.connect();
danmakuReceiver.connect()

View File

@ -1,50 +1,50 @@
import config from "./Config.ts";
import config from "./Config.ts"
const cookie =
`buvid3=${config.verify.buvid3}; SESSDATA=${config.verify.sessdata}; bili_jct=${config.verify.csrf};`;
`buvid3=${config.verify.buvid3} SESSDATA=${config.verify.sessdata} bili_jct=${config.verify.csrf}`
export interface DanmakuStruct {
color?: number;
bubble?: number;
msg: string;
mode?: number;
fontsize?: number;
rnd?: number;
roomid?: number;
csrf?: string;
csrf_token?: string;
color?: number
bubble?: number
msg: string
mode?: number
fontsize?: number
rnd?: number
roomid?: number
csrf?: string
csrf_token?: string
}
export function sendDanmaku(danmaku: DanmakuStruct) {
if (danmaku.msg.length > 19) {
sendDanmaku({
msg: danmaku.msg.slice(0, 15),
});
})
setTimeout(() => {
sendDanmaku({
msg: danmaku.msg.slice(15, danmaku.msg.length),
});
}, 2000);
return;
})
}, 2000)
return
}
danmaku.rnd = new Date().getTime();
danmaku.rnd = new Date().getTime()
if (!danmaku.color) {
danmaku.color = 5816798;
danmaku.color = 5816798
}
if (!danmaku.bubble) {
danmaku.bubble = 0;
danmaku.bubble = 0
}
if (!danmaku.mode) {
danmaku.mode = 1;
danmaku.mode = 1
}
if (!danmaku.fontsize) {
danmaku.fontsize = 24;
danmaku.fontsize = 24
}
danmaku.roomid = config.room_id as number;
danmaku.csrf = danmaku.csrf_token = config.verify.csrf;
const data = new FormData();
danmaku.roomid = config.room_id as number
danmaku.csrf = danmaku.csrf_token = config.verify.csrf
const data = new FormData()
for (const k in danmaku) {
data.append(k, danmaku[k as keyof DanmakuStruct]!.toString());
data.append(k, danmaku[k as keyof DanmakuStruct]!.toString())
}
fetch("https://api.live.bilibili.com/msg/send", {
method: 'POST',
@ -52,9 +52,9 @@ export function sendDanmaku(danmaku: DanmakuStruct) {
headers: {
cookie: cookie,
"user-agent":
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36",
"Mozilla/5.0 (X11 Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36",
host: "api.live.bilibili.com",
"Referer": "https://live.bilibili.com",
}
});
})
}

View File

@ -1,8 +1,8 @@
// deno-lint-ignore no-explicit-any
export function FormatString(str: string, args: any): string {
let result: string = str;
let result: string = str
for(const arg in args) {
result = result.replace(new RegExp(`{${arg}}`, 'g'), args[arg])
}
return result;
return result
}