Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ NetworkDebug/
data.json
cookies.json
datasource.json
src/main/resources/application-dev.yml
config/*.sqlite3
config/*.sqlite3-*
data/live-report-recovery-*.pb
src/main/resources/application-dev.yml
release/
release-template/
127 changes: 123 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<groupId>com.starlwr</groupId>
<artifactId>starbot-bilibili</artifactId>
<version>1.0.0-beta</version>
<version>1.0.0</version>
<name>StarBotBilibili</name>
<description>StarBot For Bilibili</description>
<url>https://bot.starlwr.com</url>
Expand All @@ -34,7 +34,16 @@
</licenses>

<properties>
<!-- Standalone boot entry points must not be component-scanned when this artifact is loaded as a Core plugin. -->
<standalone.application.exclude>com/starlwr/bot/bilibili/StarBotBilibiliApplication*</standalone.application.exclude>
<standalone.hints.exclude>com/starlwr/bot/bilibili/StarBotNativeRuntimeHints*</standalone.hints.exclude>
<!-- Keep builds reproducible on Windows installations whose regional code page is not UTF-8. -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<kotlin.version>2.2.21</kotlin.version>
<kotlin.compiler.jvmTarget>17</kotlin.compiler.jvmTarget>
<lombok.version>1.18.42</lombok.version>
</properties>

<repositories>
Expand All @@ -52,6 +61,16 @@
</pluginRepositories>

<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.starlwr</groupId>
<artifactId>starbot-core</artifactId>
Expand All @@ -73,15 +92,30 @@
<artifactId>dec</artifactId>
<version>0.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.28.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.huaban</groupId>
<artifactId>jieba-analysis</artifactId>
<version>1.0.2</version>
<groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.51.1.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>4.33.2</version>
</dependency>
<dependency>
<groupId>com.huaban</groupId><artifactId>jieba-analysis</artifactId><version>1.0.2</version>
</dependency>

<dependency>
Expand All @@ -94,6 +128,87 @@
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<excludes>
<exclude>${standalone.application.exclude}</exclude>
<exclude>${standalone.hints.exclude}</exclude>
</excludes>
</configuration>
</plugin>
<!-- Kotlin 2.x uses the K2 compiler. Compile Kotlin before Java so both
languages can live in this plugin during the v2 migration. -->
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<extensions>true</extensions>
<configuration>
<jvmTarget>${kotlin.compiler.jvmTarget}</jvmTarget>
<javaParameters>true</javaParameters>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<executions>
<execution>
<id>kotlin-compile</id>
<phase>process-sources</phase>
<goals><goal>compile</goal></goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>kotlin-test-compile</id>
<phase>process-test-sources</phase>
<goals><goal>test-compile</goal></goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>${java.version}</release>
<parameters>true</parameters>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Required by JDK 25 when the project and Maven repository are on different Windows drives. -->
<argLine>-Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
<plugin>
<groupId>com.starlwr</groupId>
<artifactId>starbot-plugin-processor</artifactId>
Expand Down Expand Up @@ -121,6 +236,10 @@
<resources>
<resource>
<directory>${project.build.directory}</directory>
<includes>
<include>plugin.json</include>
<include>dependency.json</include>
</includes>
</resource>
</resources>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* StarBotBilibili 配置类
*/
Expand Down Expand Up @@ -99,6 +103,45 @@ public static class Network {
* 接口请求重试间隔,单位:毫秒
*/
private int apiRetryInterval = 3000;

/** Log Bilibili HTTP request and response exchanges at DEBUG. */
private boolean httpLogEnabled = false;

/** Log decoded WebSocket messages at DEBUG. */
private boolean websocketLogEnabled = false;

/** Include WebSocket heartbeat request and response messages. */
private boolean websocketHeartbeatLogEnabled = false;

/** Include request and response headers in HTTP diagnostics. */
private boolean logHeaders = true;

/** Preserve reusable credentials and tokens in DEBUG diagnostics. */
private boolean includeSensitiveData = false;

/** Maximum logged body characters; zero disables truncation. */
private int logMaxBodyLength = 16384;

/** DEBUG collection categories emitted to the console; use all to disable category filtering. */
private Set<String> consoleCategories = new LinkedHashSet<>(List.of("all"));

/** Suppress repeated DEBUG payloads while retaining change visibility. */
private boolean consoleDeduplicate = true;

/** Duplicate suppression window in seconds. */
private long consoleDeduplicateSeconds = 300;

/** Raw debug file categories. Supports all, dynamic, live, and category:type selectors. */
private Set<String> fileCategories = new LinkedHashSet<>(List.of("all"));

/** Suppress repeated raw payloads in DynamicDebug and LiveDebug independently from the console. */
private boolean fileDeduplicate = true;

/** Raw debug file duplicate suppression window in seconds. */
private long fileDeduplicateSeconds = 900;

/** Emit the URL-encoded WBI query used by current Bilibili Web clients. */
private boolean wbiEncodedQuery = true;
}

/**
Expand Down Expand Up @@ -127,6 +170,21 @@ public static class Live {
*/
private int liveRoomReconnectInterval = 1000;

/** Whether concentrated live-room disconnects are summarized as one incident. */
private boolean disconnectSummaryEnabled = true;

/** Distinct rooms required to open a disconnect incident. */
private int disconnectSummaryRoomThreshold = 3;

/** Sliding window used to correlate disconnects, in seconds. */
private int disconnectSummaryWindowSeconds = 15;

/** Quiet time before the final incident summary, in seconds. */
private int disconnectSummaryQuietSeconds = 30;

/** Maximum room identifiers retained as incident samples. */
private int disconnectSummarySampleLimit = 10;

/**
* 礼物数据缓存时间,单位:秒
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
package com.starlwr.bot.bilibili.config;

import com.starlwr.bot.core.plugin.StarBotComponent;
import com.starlwr.bot.bilibili.telemetry.LiveTelemetryProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadPoolExecutor;

/**
* StarBotBilibili 线程池配置类
*/
@Slf4j
@StarBotComponent
@EnableConfigurationProperties(LiveTelemetryProperties.class)
public class StarBotBilibiliThreadPoolConfig {
private final StarBotBilibiliProperties properties;
private final LiveTelemetryProperties telemetryProperties;

@Autowired
public StarBotBilibiliThreadPoolConfig(StarBotBilibiliProperties properties) {
public StarBotBilibiliThreadPoolConfig(StarBotBilibiliProperties properties,
LiveTelemetryProperties telemetryProperties) {
this.properties = properties;
this.telemetryProperties = telemetryProperties;
}

@Bean
Expand All @@ -35,6 +44,46 @@ public ThreadPoolTaskExecutor bilibiliThreadPool() {
return executor;
}

/** Isolates optional report API baselines from the live-room websocket executor. */
@Bean
public ThreadPoolTaskExecutor bilibiliLiveReportThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(4);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("bilibili-report-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
return executor;
}

@Bean
public ThreadPoolTaskExecutor bilibiliTelemetryThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Math.max(1, telemetryProperties.getExecutorCorePoolSize()));
executor.setMaxPoolSize(Math.max(executor.getCorePoolSize(), telemetryProperties.getExecutorMaxPoolSize()));
executor.setQueueCapacity(Math.max(1, telemetryProperties.getExecutorQueueCapacity()));
executor.setKeepAliveSeconds(Math.max(1, telemetryProperties.getExecutorKeepAliveSeconds()));
executor.setThreadNamePrefix("bilibili-telemetry-");
executor.setWaitForTasksToCompleteOnShutdown(false);
executor.setRejectedExecutionHandler(new BoundedWaitPolicy(
Math.max(0, telemetryProperties.getExecutorSubmitTimeoutMillis())));
executor.initialize();
return executor;
}

@Bean
public ThreadPoolTaskScheduler bilibiliTelemetryScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(Math.max(1, telemetryProperties.getExecutorSchedulerPoolSize()));
scheduler.setThreadNamePrefix("bilibili-telemetry-scheduler-");
scheduler.setRemoveOnCancelPolicy(true);
scheduler.setWaitForTasksToCompleteOnShutdown(false);
scheduler.initialize();
return scheduler;
}

private static class BilibiliWithLogCallerRunsPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
Expand All @@ -45,4 +94,28 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
}
}

private static class BoundedWaitPolicy implements RejectedExecutionHandler {
private final long timeoutMillis;

private BoundedWaitPolicy(long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}

@Override
public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) {
if (executor.isShutdown()) {
throw new RejectedExecutionException("Bilibili telemetry executor is shutting down");
}
try {
if (executor.getQueue().offer(task, timeoutMillis, TimeUnit.MILLISECONDS)) {
return;
}
} catch (InterruptedException error) {
Thread.currentThread().interrupt();
throw new RejectedExecutionException("Interrupted while waiting for Bilibili telemetry capacity", error);
}
throw new RejectedExecutionException("Bilibili telemetry queue remained full for " + timeoutMillis + " ms");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.starlwr.bot.bilibili.event.live;

/** Origin metadata for consumers that need to distinguish realtime and fallback observations. */
public enum BilibiliLiveEventOrigin {
REALTIME,
BACKUP_PUSH
}
Loading