Skip to content

Commit 8d4a6e9

Browse files
soso
authored andcommitted
Release v0.1.5
1 parent 6f49b48 commit 8d4a6e9

8 files changed

Lines changed: 79 additions & 17 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "emby302gateway-rs"
3-
version = "0.1.4"
3+
version = "0.1.5"
44
edition = "2024"
55
license = "MIT"
66

docs/changelog.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# 版本更新日志
22

3+
## v0.1.5
4+
5+
发布时间:2026-05-28
6+
7+
### 新增
8+
9+
- 播放频率限制 Webhook 通知新增 IP 归属地信息,命中封禁时会在 IP 下方显示归属地。
10+
- 拦截日志新增“封禁变更”级别筛选,可同时查看封禁动作和解除封禁记录。
11+
12+
### 优化
13+
14+
- 日志页类型名称精简为“播放日志 / 拦截日志 / 反代请求 / 运行日志”。
15+
- 播放日志隐藏无差异的级别筛选,避免“全部级别”和“成功”显示相同内容造成误解。
16+
- 运行日志级别筛选仅保留实际会产生的 `INFO / WARNING / ERROR`
17+
- 拦截日志级别筛选将 `BLOCKED - 已拦截` 调整为中文“已拦截”。
18+
- 调整日志筛选栏宽度,缩窄日志类型和请求类型下拉框,提升一行展示稳定性。
19+
20+
### 修复
21+
22+
- 修复拦截日志中封禁动作和解除封禁无法通过级别筛选统一查看的问题。
23+
- 修复拦截日志级别筛选只在前端过滤、后端接口不识别动作级别的问题。
24+
25+
### 验证
26+
27+
- `cargo fmt`
28+
- `cargo check`
29+
- `cd frontend && npx vue-tsc -b --noEmit`
30+
331
## v0.1.4
432

533
发布时间:2026-05-27

frontend/src/App.vue

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,9 @@ const activityLogLoadStep = 80
462462
const requestDetailLoadStep = 100
463463
const logViewLabels: Record<LogViewFilter, string> = {
464464
playback: '播放日志',
465-
blocked: '拦截日志明细',
466-
proxy: '反代请求明细',
467-
general: '信息',
465+
blocked: '拦截日志',
466+
proxy: '反代请求',
467+
general: '运行日志',
468468
}
469469
470470
const realIpModeOptions: Array<{ value: RealIpMode; label: string }> = [
@@ -533,11 +533,13 @@ const canLoadMoreRequestDetails = computed(() =>
533533
&& requestDetailLimit.value < requestDetailDisplayMax,
534534
)
535535
const isRequestDetailLogView = computed(() => selectedLogView.value === 'proxy' || selectedLogView.value === 'blocked')
536+
const showLogLevelFilter = computed(() => selectedLogView.value !== 'playback')
536537
const logLevelOptions = computed(() => {
537538
if (selectedLogView.value === 'blocked') {
538539
return [
539540
{ value: 'all', label: '全部级别' },
540-
{ value: 'blocked', label: 'BLOCKED - 已拦截' },
541+
{ value: 'blocked', label: '已拦截' },
542+
{ value: 'ban_change', label: '封禁变更' },
541543
]
542544
}
543545
if (isRequestDetailLogView.value) {
@@ -554,11 +556,9 @@ const logLevelOptions = computed(() => {
554556
if (selectedLogView.value === 'general') {
555557
return [
556558
{ value: 'all', label: '全部级别' },
557-
{ value: 'debug', label: 'DEBUG - 调试' },
558559
{ value: 'info', label: 'INFO - 信息' },
559560
{ value: 'warn', label: 'WARNING - 警告' },
560561
{ value: 'error', label: 'ERROR - 错误' },
561-
{ value: 'critical', label: 'CRITICAL - 严重' },
562562
]
563563
}
564564
return [
@@ -1581,7 +1581,7 @@ function logQueryParams(limit: number) {
15811581
if (selectedLogServer.value !== 'all') params.set('server_id', selectedLogServer.value)
15821582
if (selectedLogView.value === 'playback') params.set('kind', 'playback')
15831583
if (selectedLogView.value === 'general') params.set('kind', 'general')
1584-
if (selectedLogLevel.value !== 'all') params.set('level', selectedLogLevel.value)
1584+
if (showLogLevelFilter.value && selectedLogLevel.value !== 'all') params.set('level', selectedLogLevel.value)
15851585
if (logKeywordFilter.value.trim()) params.set('keyword', logKeywordFilter.value.trim())
15861586
if (logSince.value) params.set('since_ms', String(new Date(logSince.value).getTime()))
15871587
if (logUntil.value) params.set('until_ms', String(new Date(logUntil.value).getTime()))
@@ -1592,6 +1592,7 @@ async function fetchProxyRequestDetails() {
15921592
const params = new URLSearchParams({ limit: String(requestDetailLimit.value) })
15931593
if (selectedLogServer.value !== 'all') params.set('server_id', selectedLogServer.value)
15941594
if (selectedRequestPathType.value !== 'all') params.set('path_type', selectedRequestPathType.value)
1595+
if (selectedLogView.value === 'blocked' && selectedLogLevel.value !== 'all') params.set('level', selectedLogLevel.value)
15951596
if (logKeywordFilter.value.trim()) params.set('keyword', logKeywordFilter.value.trim())
15961597
if (logSince.value) params.set('since_ms', String(new Date(logSince.value).getTime()))
15971598
if (logUntil.value) params.set('until_ms', String(new Date(logUntil.value).getTime()))
@@ -1633,6 +1634,7 @@ function handleScrollableLogListScroll(event: Event, loadMore: () => void) {
16331634
}
16341635
16351636
function requestSeverity(row: ProxyRequestDetail) {
1637+
if (row.event_type === 'block') return 'blocked'
16361638
if (row.event_type === 'unblock') return 'success'
16371639
if (row.blocked) return 'blocked'
16381640
if (row.cache_hit) return 'cache'
@@ -2916,7 +2918,7 @@ onBeforeUnmount(stopDashboardPolling)
29162918
<div>
29172919
<h2>日志</h2>
29182920
<p class="muted">
2919-
单列表查看播放日志、拦截日志明细、反代请求明细和运行信息,页面打开时每 3 秒自动刷新。
2921+
单列表查看播放日志、拦截日志、反代请求和运行日志,页面打开时每 3 秒自动刷新。
29202922
</p>
29212923
</div>
29222924
<div class="panel-actions">
@@ -2933,12 +2935,12 @@ onBeforeUnmount(stopDashboardPolling)
29332935
<span>日志类型</span>
29342936
<select v-model="selectedLogView" @change="handleLogViewChange">
29352937
<option value="playback">播放日志</option>
2936-
<option value="blocked">拦截日志明细</option>
2937-
<option value="proxy">反代请求明细</option>
2938-
<option value="general">信息</option>
2938+
<option value="blocked">拦截日志</option>
2939+
<option value="proxy">反代请求</option>
2940+
<option value="general">运行日志</option>
29392941
</select>
29402942
</label>
2941-
<label>
2943+
<label v-if="showLogLevelFilter">
29422944
<span>级别</span>
29432945
<select v-model="selectedLogLevel" @change="refreshLogsWithReset">
29442946
<option v-for="option in logLevelOptions" :key="option.value" :value="option.value">

frontend/src/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ label span {
986986
}
987987

988988
.log-toolbar.compact {
989-
grid-template-columns: 132px 132px 142px 100px 188px 188px 188px;
989+
grid-template-columns: 108px 132px 142px 100px 188px 188px 188px;
990990
gap: 10px;
991991
align-items: end;
992992
justify-content: start;
@@ -997,7 +997,7 @@ label span {
997997
}
998998

999999
.log-toolbar.compact.proxy {
1000-
grid-template-columns: 132px 132px 142px 150px 100px 176px 176px 176px;
1000+
grid-template-columns: 108px 132px 142px 132px 100px 176px 176px 176px;
10011001
}
10021002

10031003
.log-search-field {

src/block_log.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub struct BlockLogInsert<'a> {
7171
pub struct BlockLogFilter<'a> {
7272
pub server_id: Option<&'a str>,
7373
pub path_type: Option<&'a str>,
74+
pub level: Option<&'a str>,
7475
pub keyword: Option<&'a str>,
7576
pub since_ms: Option<u128>,
7677
pub until_ms: Option<u128>,
@@ -368,6 +369,12 @@ fn matches_filter(
368369
{
369370
return false;
370371
}
372+
if filter
373+
.level
374+
.is_some_and(|level| !matches_level(entry, level))
375+
{
376+
return false;
377+
}
371378
if filter
372379
.since_ms
373380
.is_some_and(|since| entry.timestamp_ms < since)
@@ -401,6 +408,19 @@ fn matches_filter(
401408
true
402409
}
403410

411+
fn matches_level(entry: &BlockLogEntry, level: &str) -> bool {
412+
match level {
413+
"blocked" => entry.event_type == "request" && entry.blocked,
414+
"ban_change" => matches!(entry.event_type.as_str(), "block" | "unblock"),
415+
"success" => entry.event_type == "request" && entry.status_code < 300,
416+
"redirect" => entry.event_type == "request" && (300..400).contains(&entry.status_code),
417+
"cache" => entry.event_type == "request" && entry.cache_hit,
418+
"warn" => entry.event_type == "request" && (400..500).contains(&entry.status_code),
419+
"error" => entry.event_type == "request" && entry.status_code >= 500,
420+
_ => true,
421+
}
422+
}
423+
404424
fn default_event_type() -> String {
405425
"request".to_string()
406426
}

src/client_control.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct RateLimitNotification<'a> {
4545
action: &'a str,
4646
playback_user: &'a str,
4747
playback_ip: &'a str,
48+
ip_location_text: &'a str,
4849
window: u64,
4950
max_requests: u64,
5051
block_seconds: u64,
@@ -830,16 +831,23 @@ fn rate_limit_webhook_payload(
830831
action: &str,
831832
playback_user: &str,
832833
playback_ip: &str,
834+
ip_location_text: &str,
833835
window: u64,
834836
max_requests: u64,
835837
block_seconds: u64,
836838
) -> (String, String) {
837839
let action_label = rate_limit_action_label(action);
838840
let title = format!("播放频率限制 - {action_label}");
841+
let ip_location_line = if ip_location_text.trim().is_empty() {
842+
String::new()
843+
} else {
844+
format!("\n归属地:{}", ip_location_text.trim())
845+
};
839846
let text = format!(
840-
"服务器:{server_name}\n用户:{}\nIP:{}\n策略:{action_label}\n窗口:{window}s\n阈值:{max_requests} 次\n处理时长:{block_seconds}s",
847+
"服务器:{server_name}\n用户:{}\nIP:{}{}\n策略:{action_label}\n窗口:{window}s\n阈值:{max_requests} 次\n处理时长:{block_seconds}s",
841848
normalize_value(playback_user),
842849
normalize_value(playback_ip),
850+
ip_location_line,
843851
);
844852
(title, text)
845853
}
@@ -854,6 +862,7 @@ async fn notify_rate_limit_block(
854862
notification.action,
855863
notification.playback_user,
856864
notification.playback_ip,
865+
notification.ip_location_text,
857866
notification.window,
858867
notification.max_requests,
859868
notification.block_seconds,
@@ -1386,6 +1395,7 @@ pub async fn enforce_playback_rate_limit(
13861395
action: &action,
13871396
playback_user,
13881397
playback_ip,
1398+
ip_location_text: &ip_location_text,
13891399
window,
13901400
max_requests,
13911401
block_seconds,

src/monitoring.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub struct RequestDetailQuery {
6363
pub struct BlockLogQuery {
6464
server_id: Option<String>,
6565
path_type: Option<String>,
66+
level: Option<String>,
6667
keyword: Option<String>,
6768
since_ms: Option<u128>,
6869
until_ms: Option<u128>,
@@ -300,6 +301,7 @@ pub async fn block_logs(
300301
let mut rows = state.block_log.list(crate::block_log::BlockLogFilter {
301302
server_id: query.server_id.as_deref().filter(|value| *value != "all"),
302303
path_type: query.path_type.as_deref().filter(|value| *value != "all"),
304+
level: query.level.as_deref().filter(|value| *value != "all"),
303305
keyword: query.keyword.as_deref(),
304306
since_ms: query.since_ms,
305307
until_ms: query.until_ms,

0 commit comments

Comments
 (0)