Skip to content

Commit

Permalink
feat: live chack
Browse files Browse the repository at this point in the history
  • Loading branch information
Innei committed Jul 23, 2023
1 parent 1b80f09 commit 4dcad35
Show file tree
Hide file tree
Showing 9 changed files with 453 additions and 0 deletions.
87 changes: 87 additions & 0 deletions src/modules/bilibili/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { appConfig } from 'app.config'
import axios from 'axios'
import { CronJob } from 'cron'
import type { PluginFunction } from '~/lib/plugin'
import type { BLRoom } from './types/room'
import type { BLUser } from './types/user'

import { userAgent } from '~/constants'

const headers = {
referer: `https://link.bilibili.com/p/center/index?visit_id=22ast2mb9zhc`,
'User-Agent': userAgent,
}
export const register: PluginFunction = (ctx) => {
let playStatus = false
const config = appConfig.bilibili

const liveId = config.live.id
const work = async () => {
const res = await axios
.get(
`https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id=${liveId}&protocol=0,1&format=0,1,2&codec=0,1&qn=0&platform=web&ptype=8&dolby=5`,
{
headers,
},
)
.catch(() => null)

if (!res?.data) {
return
}

if (res?.data?.data.playurl_info) {
if (playStatus) {
return
}

const userInfo = await axios
.get(
`https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room?roomid=${liveId}`,
{
headers,
},
)
.catch(() => null)

if (!userInfo?.data) {
return
}

const coverUrl = await axios
.get(
` https://api.live.bilibili.com/xlive/web-room/v1/index/getRoomBaseInfo?room_ids=${liveId}&req_biz=link-center`,
{
headers,
},
)
.then((res) => {
return (res.data as BLRoom).data.by_room_ids[liveId].cover
})
const info = (userInfo.data as BLUser).data.info

const { tgBot } = ctx
await Promise.all(
config.watchGroupIds.map(async (groupId) => {
tgBot.telegram.sendMediaGroup(groupId, [
{
type: 'photo',
media: coverUrl,
caption: `
📺${info.uname}(${info.uid}) 开播了
前往直播间: https://live.bilibili.com/${liveId}
`.trim(),
},
])
}),
)

playStatus = true
} else {
playStatus = false
}
}
const job = new CronJob('*/1 * * * *', work)
job.start()
work()
}
67 changes: 67 additions & 0 deletions src/modules/bilibili/types/live.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
export interface BLLive {
code: number
message: string
ttl: number
data: Data
}
interface Data {
room_id: number
short_id: number
uid: number
is_hidden: boolean
is_locked: boolean
is_portrait: boolean
live_status: number
hidden_till: number
lock_till: number
encrypted: boolean
pwd_verified: boolean
live_time: number
room_shield: number
all_special_types: any[]
playurl_info: Playurl_info
}
export interface Playurl_info {
conf_json: string
playurl: Playurl
}
interface Playurl {
cid: number
g_qn_desc: GQnDescItem[]
stream: StreamItem[]
p2p_data: P2p_data
dolby_qn: null
}
interface GQnDescItem {
qn: number
desc: string
hdr_desc: string
}
interface StreamItem {
protocol_name: string
format: FormatItem[]
}
interface FormatItem {
format_name: string
codec: CodecItem[]
}
interface CodecItem {
codec_name: string
current_qn: number
accept_qn: number[]
base_url: string
url_info: UrlInfoItem[]
hdr_qn: null
dolby_type: number
}
interface UrlInfoItem {
host: string
extra: string
stream_ttl: number
}
interface P2p_data {
p2p: boolean
p2p_type: number
m_p2p: boolean
m_servers: null
}
36 changes: 36 additions & 0 deletions src/modules/bilibili/types/room.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export interface BLRoom {
code: number
message: string
ttl: number
data: Data
}
interface Data {
by_uids: {}
by_room_ids: By_room_ids
}

interface By_room_ids {
[key: number]: RoomInfo
}
export interface RoomInfo {
room_id: number
uid: number
area_id: number
live_status: number
live_url: string
parent_area_id: number
title: string
parent_area_name: string
area_name: string
live_time: string
description: string
tags: string
attention: number
online: number
short_id: number
uname: string
cover: string
background: string
join_slide: number
live_id: number
}
53 changes: 53 additions & 0 deletions src/modules/bilibili/types/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export interface BLUser {
code: number
msg: string
message: string
data: Data
}
interface Data {
info: UserInfo
level: Level
san: number
}
export interface UserInfo {
uid: number
uname: string
face: string
rank: string
platform_user_level: number
mobile_verify: number
identification: number
official_verify: Official_verify
vip_type: number
gender: number
}
interface Official_verify {
type: number
desc: string
role: number
}
interface Level {
uid: number
cost: number
rcost: number
user_score: string
vip: number
vip_time: string
svip: number
svip_time: string
update_time: string
master_level: Master_level
user_level: number
color: number
anchor_score: number
}
interface Master_level {
level: number
color: number
current: number[]
next: number[]
anchor_score: number
upgrade_score: number
master_level_color: number
sort: string
}
60 changes: 60 additions & 0 deletions src/modules/mx-space/event-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { appConfig } from 'app.config'
import type { ModuleContext } from '~/types/context'
import type {
MxSocketEventTypes,
MxSystemEventBusEvents,
} from './types/mx-socket-types'

import { createNamespaceLogger } from '~/lib/logger'

import { getMxSpaceAggregateData } from './data'

const logger = createNamespaceLogger('mx-event')

interface TextMessage {
type: 'text' | 'Markdown' | 'HTML' | 'MarkdownV2'
content: string
}

interface MediaMessage {
type: 'media'
}

type IMessage = TextMessage | MediaMessage
type Sendable = string | IMessage[]

export const handleEvent =
(ctx: ModuleContext) =>
async (
type: MxSocketEventTypes | MxSystemEventBusEvents,
payload: any,
code?: number,
) => {
logger.debug(type, payload)

const aggregateData = await getMxSpaceAggregateData()
const sendToGroup = async (message: Sendable) => {
const { watchGroupIds } = appConfig.mxSpace

return await Promise.all(
watchGroupIds.map((id) => {
if (message instanceof Array) {
for (const msg of message) {
switch (msg.type) {
case 'text':
ctx.tgBot.telegram.sendMessage(id, msg.content)
continue
case 'HTML':
case 'Markdown':
case 'MarkdownV2':
ctx.tgBot.telegram.sendMessage(id, msg.content, {
parse_mode: msg.type,
})
continue
}
}
} else return ctx.tgBot.telegram.sendMessage(id, message)
}),
)
}
}
4 changes: 4 additions & 0 deletions src/modules/mx-space/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ import { relativeTimeFromNow } from '~/lib/time'
import { apiClient } from './api-client'
import { fetchHitokoto } from './api/hitokoto'
import { getMxSpaceAggregateData } from './data'
import { createMxSocket } from './socket'
import { urlBuilder } from './utils'

export const register: PluginFunction = async (ctx) => {
const { tgBot } = ctx

const socket = createMxSocket(ctx)
socket.connect()
await Promise.all([
bindEvents(tgBot),
bindCommands(tgBot),
Expand Down
71 changes: 71 additions & 0 deletions src/modules/mx-space/socket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { appConfig } from 'app.config'
import { io } from 'socket.io-client'
import type { MxSocketEventTypes } from '~/modules/mx-space/types/mx-socket-types'
import type { ModuleContext } from '~/types/context'
import type { Socket } from 'socket.io-client'

import { simpleCamelcaseKeys } from '@mx-space/api-client'

import { createNamespaceLogger } from '~/lib/logger'

import { handleEvent } from './event-handler'

const logger = createNamespaceLogger('mx-socket')

export function createMxSocket(ctx: ModuleContext): Socket<any, any> {
const mxSocket = io(appConfig.mxSpace?.gateway, {
transports: ['websocket'],
timeout: 10000,
forceNew: true,
query: {
token: appConfig.mxSpace.token,
},

autoConnect: false,
})

mxSocket.io.on('error', () => {
logger.error('Socket 连接异常')
})
mxSocket.io.on('reconnect', () => {
logger.info('Socket 重连成功')
})
mxSocket.io.on('reconnect_attempt', () => {
logger.info('Socket 重连中')
})
mxSocket.io.on('reconnect_failed', () => {
logger.info('Socket 重连失败')
})

mxSocket.on('disconnect', () => {
const tryReconnect = () => {
if (mxSocket.connected === false) {
mxSocket.io.connect()
} else {
timer = clearInterval(timer)
}
}
let timer: any = setInterval(tryReconnect, 2000)
})

mxSocket.on(
'message',
(payload: string | Record<'type' | 'data' | 'code', any>) => {
if (typeof payload !== 'string') {
return handleEvent(ctx)(
payload.type,
simpleCamelcaseKeys(payload.data),
payload.code,
)
}
const { data, type, code } = JSON.parse(payload) as {
data: any
type: MxSocketEventTypes
code?: number
}
handleEvent(ctx)(type, simpleCamelcaseKeys(data), code)
},
)

return mxSocket
}
Loading

0 comments on commit 4dcad35

Please sign in to comment.