From 2effa207eb96e9f1a345aca234927119b200bd09 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Mon, 9 Nov 2026 11:48:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=90=8C=E6=AD=A5=20fork=20?= =?UTF-8?q?=E9=80=9A=E7=94=A8=E5=8A=9F=E8=83=BD=E6=94=B9=E5=8A=A8=E8=87=B3?= =?UTF-8?q?=E4=B8=8A=E6=B8=B8=EF=BC=88=E8=87=AA=E5=8A=A8=E6=8E=92=E9=99=A4?= =?UTF-8?q?=20fork=20=E7=A7=81=E6=9C=89=E4=BB=A3=E7=A0=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 5 +- public/app.js | 285 ++++++++++++++++++-- public/index.html | 20 ++ public/style.css | 1 + src/defaultConfig.ts | 1 + src/modules/dislike/manage.ts | 10 +- src/modules/dislike/snapshotDataManage.ts | 73 +++++- src/modules/list/manage.ts | 5 +- src/modules/list/snapshotDataManage.ts | 54 +++- src/server/integrations/subsonic.ts | 302 +++++++++++++++++++++- src/server/openlist/openlistBackupDb.ts | 3 + src/server/ratingSnapshot.ts | 192 ++++++++++++++ src/server/server.ts | 167 ++++++++---- src/types/config.d.ts | 9 + test/openlist-busy-timeout.test.ts | 30 +++ test/openlist.test.cjs | 6 +- test/rating-snapshot.test.ts | 141 ++++++++++ test/snapshot-imported.test.ts | 134 ++++++++++ test/snapshot-rating-wiring.test.ts | 185 +++++++++++++ test/subsonic-rating-playlists.test.ts | 150 +++++++++++ 20 files changed, 1687 insertions(+), 86 deletions(-) create mode 100644 src/server/ratingSnapshot.ts create mode 100644 test/openlist-busy-timeout.test.ts create mode 100644 test/rating-snapshot.test.ts create mode 100644 test/snapshot-imported.test.ts create mode 100644 test/snapshot-rating-wiring.test.ts create mode 100644 test/subsonic-rating-playlists.test.ts diff --git a/docker-compose.yml b/docker-compose.yml index 31d988e1..ceba9e40 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,13 +20,14 @@ services: # Subsonic 独立服务 # - SUBSONIC_STANDALONE=true # - SUBSONIC_PORT=4050 - # WebDAV 备份目标 + # WebDAV 备份目标(仅填地址与凭据不会启动同步,需显式开启 WEBDAV_ENABLE) + # - WEBDAV_ENABLE=true # - WEBDAV_URL= # - WEBDAV_USERNAME= # - WEBDAV_PASSWORD= # 网页播放器鉴权 # - ENABLE_WEBPLAYER_AUTH=true - # - WEBPLAYER_PASSWORD=123456 + # - WEBPLAYER_PASSWORD=<请设置强密码,勿使用默认值> # 其他常用项 # - SYNC_INTERVAL=60 # - CONFIG_PATH=/server/data/config.js diff --git a/public/app.js b/public/app.js index f7821344..ea7b7889 100644 --- a/public/app.js +++ b/public/app.js @@ -3361,6 +3361,9 @@ class App { if (form.elements['subsonic.dislikeRequireSinger']) { form.elements['subsonic.dislikeRequireSinger'].checked = config['subsonic.dislikeRequireSinger'] !== false; } + if (form.elements['subsonic.ratingPlaylists']) { + form.elements['subsonic.ratingPlaylists'].checked = config['subsonic.ratingPlaylists'] !== false; + } if (form.elements['subsonic.linkRatingToDislike']) { form.elements['subsonic.linkRatingToDislike'].checked = config['subsonic.linkRatingToDislike'] === true; } @@ -3392,6 +3395,9 @@ class App { this.initCustomSelects(); this.syncCustomSelects(); + this.bindLinkSyncToggles(); + this.updateLinkSyncUI(); + void this.loadLinkSyncUsers(); } catch (e) { console.error('Failed to load subsonic config:', e); } @@ -3430,6 +3436,7 @@ class App { 'subsonic.dislikeDuetMode': formData.get('subsonic.dislikeDuetMode') || 'any', 'subsonic.dislikeNormalizeName': formData.get('subsonic.dislikeNormalizeName') === 'on', 'subsonic.dislikeRequireSinger': formData.get('subsonic.dislikeRequireSinger') === 'on', + 'subsonic.ratingPlaylists': formData.get('subsonic.ratingPlaylists') === 'on', 'subsonic.linkRatingToDislike': formData.get('subsonic.linkRatingToDislike') === 'on', 'subsonic.linkDislikeToRating': formData.get('subsonic.linkDislikeToRating') === 'on', 'subsonic.quality.enabled': formData.get('subsonic.quality.enabled') === 'on', @@ -3494,6 +3501,137 @@ class App { } } + // ---- Subsonic 联动数据手动同步(与导入 / 回滚链路解耦) ---- + + bindLinkSyncToggles() { + if (this._linkSyncBound) return; + const form = document.getElementById('subsonic-form'); + if (!form) return; + ['subsonic.linkRatingToDislike', 'subsonic.linkDislikeToRating'].forEach(key => { + const el = form.elements[key]; + if (el) el.addEventListener('change', () => this.updateLinkSyncUI()); + }); + this._linkSyncBound = true; + } + + updateLinkSyncUI() { + const form = document.getElementById('subsonic-form'); + [ + ['subsonic.linkRatingToDislike', 'sync-rating-to-dislike-btn'], + ['subsonic.linkDislikeToRating', 'sync-dislike-to-rating-btn'], + ].forEach(([key, btnId]) => { + const btn = document.getElementById(btnId); + if (btn) btn.classList.toggle('hidden', !form?.elements[key]?.checked); + }); + } + + async loadLinkSyncUsers() { + const select = document.getElementById('subsonic-sync-user'); + if (!select) return; + try { + const users = await this.request('/api/users'); + const names = (Array.isArray(users) ? users : []).map(u => u.name).filter(Boolean); + const wanted = this.pendingLinkSyncUser || select.value; + select.innerHTML = ''; + names.forEach(n => { + const opt = document.createElement('option'); + opt.value = n; + opt.textContent = n; + select.appendChild(opt); + }); + if (names.includes(wanted)) select.value = wanted; + else if (names.length) select.value = names[0]; + this.pendingLinkSyncUser = null; + // 动态填充后同步自定义下拉显示(菜单在展开时会重新渲染) + this.initCustomSelects(); + this.syncCustomSelects(); + } catch (e) { + console.warn('[LinkSync] 加载用户列表失败:', e); + } + } + + async syncLink(direction) { + if (this._linkSyncBusy) return; + const isRatingToDislike = direction === 'ratingToDislike'; + const key = isRatingToDislike ? 'subsonic.linkRatingToDislike' : 'subsonic.linkDislikeToRating'; + const label = isRatingToDislike ? '评星 → 不喜欢' : '不喜欢 → 评星'; + const btn = document.getElementById(isRatingToDislike ? 'sync-rating-to-dislike-btn' : 'sync-dislike-to-rating-btn'); + const form = document.getElementById('subsonic-form'); + // 开关以服务端已保存的配置为准,避免「表单勾了但没保存」时后端拒绝 + const checked = !!form?.elements[key]?.checked; + const saved = (this.loadedSubsonicConfig || {})[key] === true; + if (!checked || !saved) { + showError(`请先开启「${label} 自动联动」并保存配置,再执行同步。`); + return; + } + const user = document.getElementById('subsonic-sync-user')?.value || ''; + if (!user) { + showError('请先选择联动同步目标用户'); + return; + } + const confirmed = await showSelect('手动联动同步', + `将对用户 ${this.escapeHtml(user)} 执行「${label}」补数据:只补目标侧缺失的数据,不覆盖已有数据,也不会改动导入 / 回滚逻辑。\n\n确定继续吗?`, + { confirmText: '开始同步', cancelText: '取消' }); + if (!confirmed) return; + + this._linkSyncBusy = true; + const oldText = btn?.textContent; + if (btn) { btn.disabled = true; btn.textContent = '同步中…'; } + try { + const res = await this.request('/api/subsonic/sync-link', { + method: 'POST', + body: JSON.stringify({ user, direction }) + }); + const text = `同步完成(${label} · 用户 ${user}):扫描 ${res.scanned} 条,新增 ${res.added} 条,已存在 ${res.skipped} 条` + + (res.failed ? `,失败 ${res.failed} 条` : '') + + (res.batches > 1 ? `,分 ${res.batches} 批处理(全量)` : '') + '。'; + const box = document.getElementById('link-sync-result'); + if (box) { + box.textContent = text; + box.classList.remove('hidden'); + } + showSuccess(text); + } catch (err) { + showError('同步失败: ' + err.message); + } finally { + this._linkSyncBusy = false; + if (btn) { btn.disabled = false; btn.textContent = oldText || '同步'; } + } + } + + async maybeOfferLinkSync(user, kindLabel) { + try { + // 用服务端已保存的配置校验开关,只提供手动操作入口,绝不自动执行联动 + const config = await this.request('/api/config'); + const ratingToDislike = config['subsonic.linkRatingToDislike'] === true; + const dislikeToRating = config['subsonic.linkDislikeToRating'] === true; + const threshold = Number(config['subsonic.dislikeRating'] ?? 1); + if ((!ratingToDislike && !dislikeToRating) || !(threshold > 0)) return; + const dirs = [ratingToDislike ? '评星 → 不喜欢' : '', dislikeToRating ? '不喜欢 → 评星' : ''] + .filter(Boolean).join(' / '); + const go = await showSelect('回滚完成,联动数据未自动同步', + `已回滚用户 ${this.escapeHtml(user)} 的「${this.escapeHtml(kindLabel)}」数据。\n\n` + + `检测到联动开关已开启(${dirs})。导入 / 回滚不会自动补另一侧数据,如需对齐请前往 Subsonic 配置页手动点击「同步」。`, + { confirmText: '前往配置', cancelText: '稍后处理' }); + if (go) await this.jumpToLinkSync(user); + } catch (e) { + console.warn('[LinkSync] 联动提示检查失败:', e); + } + } + + async jumpToLinkSync(user) { + this.pendingLinkSyncUser = user; + await this.switchView('subsonic'); + setTimeout(() => { + const target = document.getElementById('link-sync-field'); + if (!target) return; + target.scrollIntoView({ behavior: 'smooth', block: 'center' }); + target.style.outline = '2px solid var(--accent-primary)'; + target.style.outlineOffset = '4px'; + setTimeout(() => { target.style.outline = 'none'; }, 2000); + }, 350); + } + async loadLogs(isAuto = false) { const logType = document.getElementById('log-type-select')?.value || 'app'; @@ -6194,9 +6332,10 @@ class App { return; } - // 确保「全部 / 歌单快照 / 不喜欢」子页签存在 + // 确保「类型 / 来源」筛选条件存在 this.ensureSnapshotKindTabs(); const kind = this._snapshotKind || 'all'; + const origin = this._snapshotOrigin || 'all'; // 添加加载状态 container.classList.add('content-loading'); @@ -6204,19 +6343,33 @@ class App { try { // 添加 user 参数 const all = await this.request(`/api/data/snapshots?user=${encodeURIComponent(username)}`); - const list = kind === 'all' ? all : all.filter(i => (i.kind || 'list') === kind); + const list = all.filter(i => + (kind === 'all' || (i.kind || 'list') === kind) && + (origin === 'all' || (i.origin || 'auto') === origin)); if (!list.length) { - const emptyText = kind === 'dislike' ? '该用户暂无「不喜欢」快照' : '暂无快照'; + const emptyText = origin === 'imported' ? '该用户暂无导入的备份快照' + : kind === 'dislike' ? '该用户暂无「不喜欢」快照' + : kind === 'rating' ? '该用户暂无「我的评分」快照' : '暂无快照'; container.innerHTML = `
${emptyText}
`; container.classList.remove('content-loading'); return; } - container.innerHTML = list.map(item => ` + container.innerHTML = list.map(item => { + const imported = item.origin === 'imported'; + const originTag = imported + ? '导入备份' + : '系统快照'; + const kindTag = item.kind === 'dislike' + ? '我不喜欢' + : item.kind === 'rating' + ? '我的评分' + : '我的歌单'; + return `
-
${new Date(item.time).toLocaleString('zh-CN', { hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })}
-
snapshot_${item.id}${item.kind === 'dislike' ? '我不喜欢' : '我的歌单'}
+
${new Date(item.time).toLocaleString('zh-CN', { hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })}
+
snapshot_${item.id}${kindTag}${originTag}
${this.formatFileSize(item.size)}
- `).join(''); + `; }).join(''); // 移除加载状态并添加淡入动画 container.classList.remove('content-loading'); @@ -6264,19 +6417,20 @@ class App { } } - // 在「歌单快照」面板顶部注入「类型」下拉查询条件,便于按 我的歌单 / 我不喜欢 过滤 + // 在「歌单快照」面板顶部注入「类型 / 来源」两个下拉查询条件 ensureSnapshotKindTabs() { - if (document.getElementById('snapshot-kind-filter')) return; const container = document.getElementById('snapshots-list'); const toolbar = document.getElementById('snapshot-toolbar-actions'); if (!container || !toolbar) return; + // loadSnapshots 会被反复调用(切用户 / 上传 / 删除后),避免重复注入多个筛选框 + if (document.getElementById('snapshot-kind-filter')) return; const sel = document.createElement('select'); sel.id = 'snapshot-kind-filter'; sel.className = 'form-input config-input olb-select'; sel.setAttribute('aria-label', '快照类型'); sel.style.width = 'auto'; const cur = this._snapshotKind || 'all'; - sel.innerHTML = ''; + sel.innerHTML = ''; sel.value = cur; sel.addEventListener('change', () => { this._snapshotKind = sel.value; @@ -6295,24 +6449,97 @@ class App { document.getElementById('snapshot-upload-input').click(); } + // 导入时由超管从用户清单显式选择目标用户,选择结果即最终目标 + async showImportTargetDialog({ filename, kindLabel, defaultUser }) { + let users = this.allUsers; + if (!Array.isArray(users) || !users.length) { + try { + users = await this.request('/api/users'); + this.allUsers = users; + } catch (err) { + showError('获取用户清单失败: ' + err.message); + return null; + } + } + if (!users.length) { + showError('用户清单为空,无法导入'); + return null; + } + const options = users.map(u => { + const label = u.name === '_open' ? '公开用户 (_open)' : u.name; + return ``; + }).join(''); + return new Promise(resolve => { + const modal = document.createElement('div'); + modal.id = 'snapshot-import-target-modal'; + modal.className = 'fixed inset-0 z-[3000] flex items-center justify-center p-6 animate-fade-in'; + modal.innerHTML = ` +
+
+
+

选择导入目标用户

+

+ 备份文件:${this.escapeHtml(filename)}
+ 备份类型:${kindLabel} +

+ + +
+
+ + +
+
`; + document.body.appendChild(modal); + const close = (result) => { modal.remove(); resolve(result); }; + modal.querySelector('#snapshot-import-target-ok').onclick = () => close(modal.querySelector('#snapshot-import-target-user').value); + modal.querySelector('#snapshot-import-target-cancel').onclick = () => close(null); + modal.querySelector('.absolute.inset-0').onclick = () => close(null); + }); + } + // [新增] 处理快照上传 async handleSnapshotUpload(event) { const file = event.target.files[0]; if (!file) return; - - const username = document.getElementById('snapshot-user-select')?.value; - if (!username) return; - // 重置 input,允许重复上传同名文件 event.target.value = ''; + const panelUser = document.getElementById('snapshot-user-select')?.value || ''; + let content; try { - const content = await file.text(); - // 使用文件最后修改时间 - const time = file.lastModified; - const filename = file.name; + content = await file.text(); + } catch (err) { + showError('读取备份文件失败: ' + err.message); + return; + } + let jsonData = null; + try { jsonData = JSON.parse(content); } catch { /* 非 JSON 也可按原生歌单快照导入 */ } + const isRatingBackup = jsonData && (jsonData.type === 'lxRating_v1' || ( + jsonData.ratings && typeof jsonData.ratings === 'object' && !Array.isArray(jsonData.ratings) && + !Array.isArray(jsonData.dislikeList) && !Array.isArray(jsonData.defaultList) && !Array.isArray(jsonData.userList) + )); + const kindLabel = isRatingBackup ? '我的评分' + : jsonData && Array.isArray(jsonData.dislikeList) && + !Array.isArray(jsonData.defaultList) && !Array.isArray(jsonData.userList) ? '我不喜欢' : '我的歌单'; + + // 目标用户由超管在清单中选择,选择结果即最终目标 + const targetUser = await this.showImportTargetDialog({ filename: file.name, kindLabel, defaultUser: panelUser }); + if (!targetUser) return; + + // 「导入后立即恢复」默认开启:回滚会覆盖目标用户的数据,操作前二次确认 + const restore = document.getElementById('snapshot-upload-restore')?.checked !== false; + if (restore) { + const safeTarget = this.escapeHtml(targetUser); + const confirmed = await showSelect('导入并恢复备份', + `导入到用户:${safeTarget}\n\n导入后将以该文件覆盖 ${safeTarget} 当前的对应数据。\n系统会自动把导入前的状态保存为一份「系统快照」,之后可随时回滚。是否继续?`, + { danger: true, confirmText: '导入并恢复' }); + if (!confirmed) return; + } - const response = await fetch(`/api/data/upload-snapshot?user=${encodeURIComponent(username)}&time=${time}&filename=${encodeURIComponent(filename)}`, { + try { + const time = file.lastModified; + const response = await fetch(`/api/data/upload-snapshot?user=${encodeURIComponent(targetUser)}&time=${time}&filename=${encodeURIComponent(file.name)}&restore=${restore ? 1 : 0}`, { method: 'POST', headers: { 'X-Frontend-Auth': this.password @@ -6325,8 +6552,16 @@ class App { throw new Error(text || 'Upload failed'); } - showSuccess('上传成功'); - this.loadSnapshots(); + const result = await response.json().catch(() => ({})); + const resultKindLabel = result.kind === 'rating' ? '我的评分' : result.kind === 'dislike' ? '我不喜欢' : '我的歌单'; + showSuccess(result.restored + ? `已导入「${resultKindLabel}」备份到用户 ${targetUser} 并恢复成功${result.safetySnapshot ? '(已自动保存导入前快照)' : ''}` + : `已导入「${resultKindLabel}」备份到用户 ${targetUser}(仅保存为快照,可稍后手动恢复)`); + // 仅提示 + 提供手动操作入口,不在此处调用联动同步 + if (result.restored) void this.maybeOfferLinkSync(targetUser, resultKindLabel); + // 目标用户与面板用户不同时切换面板,便于立刻看到导入结果(selectUser 内部会刷新列表) + if (targetUser !== panelUser) this.selectUser('snapshot', targetUser); + else this.loadSnapshots(); } catch (err) { console.error(err); showError('上传失败: ' + err.message); @@ -6373,7 +6608,11 @@ class App { const data = await this.request(`/api/data/snapshot?id=${encodeURIComponent(id)}&kind=${kind || 'list'}&user=${encodeURIComponent(username)}`); let backupData, fname; - if (kind === 'dislike') { + if (kind === 'rating') { + // 评分快照导出为 lxRating_v1(含完整 subsonic-meta 结构),导入时按 type 识别 + backupData = { ...data, type: 'lxRating_v1' }; + fname = `lx_rating_${username}_${id.substring(0, 8)}.json`; + } else if (kind === 'dislike') { // 不喜欢快照直接导出原始规则({ dislikeList: [...] }),不要套 playList_v2(否则内容会被清空成空壳) backupData = data; fname = `lx_dislike_${username}_${id.substring(0, 8)}.json`; @@ -6507,6 +6746,8 @@ class App { body: JSON.stringify({ id, kind }) }); showSuccess('回滚成功!请重启客户端或重新连接同步服务。'); + // 仅提示 + 提供手动操作入口,不在此处调用联动同步 + void this.maybeOfferLinkSync(username, kind === 'rating' ? '我的评分' : kind === 'dislike' ? '我不喜欢' : '我的歌单'); this.loadDashboard(); // 刷新数据概览 } catch (err) { showError('回滚失败: ' + err.message); diff --git a/public/index.html b/public/index.html index 234d147a..a80381b1 100644 --- a/public/index.html +++ b/public/index.html @@ -1743,6 +1743,26 @@

Subsonic 协议配置 + + +
+ +
+ + +
+
+ +
音质 / 源优选 (Subsonic)
diff --git a/public/style.css b/public/style.css index e05aeedb..40346b33 100644 --- a/public/style.css +++ b/public/style.css @@ -4847,6 +4847,7 @@ input:-webkit-autofill:active { border-radius: 6px; border: 1px solid rgba(255, 255, 255, 0.06); display: flex; + flex-wrap: wrap; /* 窄视口下让类型/来源标签换行,而不是被 overflow 裁掉 */ align-items: center; gap: 0.4rem; min-width: 0; diff --git a/src/defaultConfig.ts b/src/defaultConfig.ts index af945886..77037961 100644 --- a/src/defaultConfig.ts +++ b/src/defaultConfig.ts @@ -108,6 +108,7 @@ const config: LX.Config = { 'subsonic.sharedListMode': 'leaderboard', // 共享歌单内容模式: leaderboard | playlist | both 'subsonic.sharedListSort': 'hot', // 共享歌单排序: hot | new 'subsonic.dislikeRating': 1, // 评分联动 dislike 阈值: 0 < rating <= 该值 视为不喜欢(写回原生 dislike 规则); 设为 0 关闭联动 + 'subsonic.ratingPlaylists': true, // 是否向 Subsonic 客户端暴露 1~5 星评星歌单(虚拟只读, 不落盘); 开启时 1 星歌单承载「我不喜欢」并强制双向联动 'subsonic.linkRatingToDislike': false, // 解耦开关(正向): 评星 -> 不喜欢 是否自动联动; false=不联动(仅记录评分) 'subsonic.linkDislikeToRating': false, // 解耦开关(反向): 不喜欢 -> 评星 是否自动联动; false=不联动(仅记录不喜欢) 'subsonic.hideDisliked': true, // 是否在 Subsonic 列表中隐藏 dislike 命中的歌曲(关闭则只评分不剔除) diff --git a/src/modules/dislike/manage.ts b/src/modules/dislike/manage.ts index fb03dfbb..a166d6fb 100644 --- a/src/modules/dislike/manage.ts +++ b/src/modules/dislike/manage.ts @@ -21,7 +21,10 @@ export class DislikeManage { if (snapshotInfo.list.includes(md5)) { snapshotInfo.list.splice(snapshotInfo.list.indexOf(md5), 1) } else await this.snapshotDataManage.saveSnapshot(md5, listData) - if (snapshotInfo.latest) snapshotInfo.list.unshift(snapshotInfo.latest) + // 用户导入的备份不纳入系统快照 list/配额清理,避免被自动删除或误判为系统生成 + if (snapshotInfo.latest && !this.snapshotDataManage.isImported(snapshotInfo.latest)) { + snapshotInfo.list.unshift(snapshotInfo.latest) + } snapshotInfo.latest = md5 snapshotInfo.time = Date.now() this.snapshotDataManage.saveSnapshotInfo(snapshotInfo) @@ -60,5 +63,10 @@ export class DislikeManage { this.snapshotDataManage.clearClients() this.snapshotDataManage.setLatest(name) } + + /** 导入外部下载的 dislike 备份文件(保留原文件时间) */ + saveSnapshotWithTime = async(name: string, data: string, time: number) => { + await this.snapshotDataManage.saveSnapshotWithTime(name, data, time) + } } diff --git a/src/modules/dislike/snapshotDataManage.ts b/src/modules/dislike/snapshotDataManage.ts index 01843b15..8afcd83d 100644 --- a/src/modules/dislike/snapshotDataManage.ts +++ b/src/modules/dislike/snapshotDataManage.ts @@ -10,6 +10,8 @@ interface SnapshotInfo { latest: string | null time: number list: string[] + /** 由用户上传导入的快照 id;系统自动生成的快照不在此列 */ + imported: string[] clients: Record } export class SnapshotDataManage { @@ -21,6 +23,48 @@ export class SnapshotDataManage { clientSnapshotKeys: string[] private readonly saveSnapshotInfoThrottle: () => void + /** 兼容旧版 snapshotInfo.json(无 imported 字段) */ + private getImported = (): string[] => { + if (!Array.isArray(this.snapshotInfo.imported)) this.snapshotInfo.imported = [] + return this.snapshotInfo.imported + } + + /** + * 来源登记直接同步落盘,不走 saveSnapshotInfoThrottle: + * 该节流回调会触发 clearOldSnapshot,避免在清理路径里互相触发写入。 + */ + private persistSnapshotInfo = () => { + try { + fs.writeFileSync(this.snapshotInfoFilePath, JSON.stringify(this.snapshotInfo)) + } catch (err) { + syncLog.warn(err) + } + } + + /** 登记用户导入的备份,来源由服务端显式持久化,不靠文件名/latest 推断 */ + markImported = (name: string) => { + const imported = this.getImported() + if (imported.includes(name)) return + imported.push(name) + this.persistSnapshotInfo() + } + + /** 删除快照时移除来源登记 */ + unmarkImported = (name: string) => { + const imported = this.getImported() + const idx = imported.indexOf(name) + if (idx < 0) return + imported.splice(idx, 1) + this.persistSnapshotInfo() + } + + /** + * 判定是否为导入来源:优先读显式登记;兼容本次改动前已导入的备份—— + * 系统自动快照 id 恒为 32 位 md5,其余 id 只可能是外部导入的文件名。 + */ + isImported = (name: string): boolean => + this.getImported().includes(name) || !/^[0-9a-f]{32}$/.test(name) + isIncluedsDevice = (key: string) => { return this.clientSnapshotKeys.includes(key) } @@ -124,6 +168,26 @@ export class SnapshotDataManage { } } + /** 导入外部下载的 dislike 备份:直接写入原始 JSON 内容并保留文件时间(与歌单快照 saveSnapshotWithTime 同构) */ + saveSnapshotWithTime = async(name: string, data: string, time: number) => { + syncLog.info('saveSnapshotWithTime', this.userDataManage.userName, name, time) + const filePath = path.join(this.snapshotDir, `snapshot_${name}`) + try { + fs.writeFileSync(filePath, data) + if (time) { + const date = new Date(time) + fs.utimesSync(filePath, date, date) + } + // 导入来源是显式登记的,避免下次自动快照把它误当成系统快照 + this.markImported(name) + void (globalThis as any).lx?.scheduleOpenlistSync?.() + void (globalThis as any).lx?.backupSnapshotToLocal?.(filePath, this.userDataManage.userName, name) + } catch (err) { + syncLog.error(err) + throw err + } + } + removeSnapshot = async(name: string) => { syncLog.info('removeSnapshot', this.userDataManage.userName, name) const filePath = path.join(this.snapshotDir, `snapshot_${name}`) @@ -133,13 +197,14 @@ export class SnapshotDataManage { syncLog.error(err) throw err } + this.unmarkImported(name) // 一并清理本地备份目录中该快照的所有带时间戳历史副本(含旧版无时间戳副本),避免孤儿文件 void (globalThis as any).lx?.removeSnapshotLocalBackups?.(this.userDataManage.userName, name) } /** 列出不喜欢快照(与歌单快照 getSnapshotListWithMeta 同构,供 /api/data/snapshots 合并展示) */ - getSnapshotListWithMeta = async () => { - const list: Array<{ id: string, time: number, size: number }> = [] + getSnapshotListWithMeta = async (): Promise> => { + const list: Array<{ id: string, time: number, size: number, origin: 'imported' | 'auto' }> = [] try { const files = await fs.promises.readdir(this.snapshotDir) for (const file of files) { @@ -148,7 +213,7 @@ export class SnapshotDataManage { const filePath = path.join(this.snapshotDir, file) try { const stat = await fs.promises.stat(filePath) - list.push({ id: name, time: stat.mtimeMs, size: stat.size }) + list.push({ id: name, time: stat.mtimeMs, size: stat.size, origin: this.isImported(name) ? 'imported' : 'auto' }) } catch { /* ignore missing files */ } } } catch (err) { @@ -225,7 +290,7 @@ export class SnapshotDataManage { this.snapshotInfoFilePath = path.join(this.dislikeDir, File.dislikeSnapshotInfoJSON) this.snapshotInfo = fs.existsSync(this.snapshotInfoFilePath) ? JSON.parse(fs.readFileSync(this.snapshotInfoFilePath).toString()) - : { latest: null, time: 0, list: [], clients: {} } + : { latest: null, time: 0, list: [], imported: [], clients: {} } this.updateSnapshotDir() diff --git a/src/modules/list/manage.ts b/src/modules/list/manage.ts index 2386f8ba..66bb21e4 100644 --- a/src/modules/list/manage.ts +++ b/src/modules/list/manage.ts @@ -21,7 +21,10 @@ export class ListManage { if (snapshotInfo.list.includes(md5)) { snapshotInfo.list.splice(snapshotInfo.list.indexOf(md5), 1) } else await this.snapshotDataManage.saveSnapshot(md5, listData) - if (snapshotInfo.latest) snapshotInfo.list.unshift(snapshotInfo.latest) + // 用户导入的备份不纳入系统快照 list/配额清理,避免被自动删除或误判为系统生成 + if (snapshotInfo.latest && !this.snapshotDataManage.isImported(snapshotInfo.latest)) { + snapshotInfo.list.unshift(snapshotInfo.latest) + } snapshotInfo.latest = md5 snapshotInfo.time = Date.now() this.snapshotDataManage.saveSnapshotInfo(snapshotInfo) diff --git a/src/modules/list/snapshotDataManage.ts b/src/modules/list/snapshotDataManage.ts index dfae7b87..5f30da6a 100644 --- a/src/modules/list/snapshotDataManage.ts +++ b/src/modules/list/snapshotDataManage.ts @@ -10,6 +10,8 @@ interface SnapshotInfo { latest: string | null time: number list: string[] + /** 由用户上传导入的快照 id;系统自动生成的快照不在此列 */ + imported: string[] clients: Record } export class SnapshotDataManage { @@ -21,6 +23,48 @@ export class SnapshotDataManage { clientSnapshotKeys: string[] private readonly saveSnapshotInfoThrottle: () => void + /** 兼容旧版 snapshotInfo.json(无 imported 字段) */ + private getImported = (): string[] => { + if (!Array.isArray(this.snapshotInfo.imported)) this.snapshotInfo.imported = [] + return this.snapshotInfo.imported + } + + /** + * 来源登记直接同步落盘,不走 saveSnapshotInfoThrottle: + * 该节流回调会触发 clearOldSnapshot,避免在清理路径里互相触发写入。 + */ + private persistSnapshotInfo = () => { + try { + fs.writeFileSync(this.snapshotInfoFilePath, JSON.stringify(this.snapshotInfo)) + } catch (err) { + syncLog.warn(err) + } + } + + /** 登记用户导入的备份,来源由服务端显式持久化,不靠文件名/latest 推断 */ + markImported = (name: string) => { + const imported = this.getImported() + if (imported.includes(name)) return + imported.push(name) + this.persistSnapshotInfo() + } + + /** 删除快照时移除来源登记 */ + unmarkImported = (name: string) => { + const imported = this.getImported() + const idx = imported.indexOf(name) + if (idx < 0) return + imported.splice(idx, 1) + this.persistSnapshotInfo() + } + + /** + * 判定是否为导入来源:优先读显式登记;兼容本次改动前已导入的备份—— + * 系统自动快照 id 恒为 32 位 md5,其余 id 只可能是外部导入的文件名。 + */ + isImported = (name: string): boolean => + this.getImported().includes(name) || !/^[0-9a-f]{32}$/.test(name) + isIncluedsDevice = (key: string) => { return this.clientSnapshotKeys.includes(key) } @@ -113,6 +157,8 @@ export class SnapshotDataManage { const date = new Date(time) fs.utimesSync(filePath, date, date) } + // 导入来源是显式登记的,避免下次自动快照把它误当成系统快照 + this.markImported(name) // 歌单快照落盘后,防抖触发一次云端备份(与缓存落盘上传同一入口;按配置备份 snapshots 类型) void (globalThis as any).lx?.scheduleOpenlistSync?.() // 本地备份开关打开时,复制一份快照到备份目录("跟配置走",复用 configBackup.enable 与备份目录约定) @@ -132,12 +178,13 @@ export class SnapshotDataManage { syncLog.error(err) throw err } + this.unmarkImported(name) // 一并清理本地备份目录中该快照的所有带时间戳历史副本(含旧版无时间戳副本),避免孤儿文件 void (globalThis as any).lx?.removeSnapshotLocalBackups?.(this.userDataManage.userName, name) } - getSnapshotListWithMeta = async () => { - const list = [] + getSnapshotListWithMeta = async (): Promise> => { + const list: Array<{ id: string, time: number, size: number, origin: 'imported' | 'auto' }> = [] try { const files = await fs.promises.readdir(this.snapshotDir) for (const file of files) { @@ -150,6 +197,7 @@ export class SnapshotDataManage { id: name, time: stat.mtimeMs, size: stat.size, + origin: this.isImported(name) ? 'imported' : 'auto', }) } catch (e) { // ignore missing files @@ -259,7 +307,7 @@ export class SnapshotDataManage { this.listDir = path.join(userDataManage.userDir, File.listDir) checkAndCreateDirSync(this.listDir) - this.snapshotInfo = { latest: null, time: 0, list: [], clients: {} } + this.snapshotInfo = { latest: null, time: 0, list: [], imported: [], clients: {} } this.updateSnapshotDir() this.saveSnapshotInfoThrottle = throttle(() => { diff --git a/src/server/integrations/subsonic.ts b/src/server/integrations/subsonic.ts index 89ba68d7..d112a1c0 100644 --- a/src/server/integrations/subsonic.ts +++ b/src/server/integrations/subsonic.ts @@ -5,6 +5,7 @@ import { pipeline } from 'stream/promises' import crypto from 'crypto' import { URL } from 'url' import { getUserSpace, getUserDirname, getUserConfig } from '@/user' +import { createRatingSnapshot } from '../ratingSnapshot' import { callUserApiGetMusicUrl } from '@/server/sources/userApi' import { downloadAndCache, checkCache, serveCacheFile, getFileName } from '@/server/music/fileCache' import { resolveOpenlistCacheEntry } from '@/server/openlist/openlistBackup' @@ -124,6 +125,30 @@ function withTimeout(p: Promise, ms: number): Promise { }) } +/** 手动联动同步:每批解析的歌曲数(全量分批,不截断),避免一次发起大量在线回源 */ +const LINK_SYNC_BATCH_SIZE = 20 +const LINK_SYNC_ITEM_TIMEOUT_MS = 8000 + +export interface LinkSyncSummary { + direction: 'ratingToDislike' | 'dislikeToRating' + user: string + /** 本次扫描的候选条目数 */ + scanned: number + /** 实际新增的 dislike 规则 / 低星评分数 */ + added: number + /** 已存在、无需补写的条目数 */ + skipped: number + /** 解析失败或超时的条目数 */ + failed: number + /** 生效的 dislike 阈值 */ + threshold: number + /** 实际处理的批次数(0 表示无待处理条目) */ + batches: number +} + +const countDislikeRules = (rules: string): number => + String(rules || '').split('\n').filter(l => l.trim()).length + /** 多源结果按源轮询交错取数,避免"响应最快的源"占满全部名额 */ function interleaveBySource(groups: T[][], max: number): T[] { const out: T[] = [] @@ -754,6 +779,8 @@ export async function syncDislikeToRating(username: string, id: string, rating: } catch (e) { subsonicLog.error('[Subsonic] dislike<->rating 同步失败:', e) } + // 评分写入后生成/复用一份「我的评分」快照,使当前评分可被下载备份 + void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 评分快照生成失败:', e)) } /** @@ -2003,6 +2030,62 @@ class SubsonicHandler { : songs[0]?.id || 'logo' } + /** 评星歌单 id 前缀(虚拟只读,不落盘) */ + private static readonly RATING_PLAYLIST_PREFIX = 'rating_' + + /** + * 聚合 1~5 星评星歌单的歌曲。 + * - 数据来源:subsonic-meta.json 的 ratings(key 为 Subsonic 歌曲 id),反查回 MusicInfo; + * - rating_1 额外并入「我不喜欢」规则命中的歌曲,使只能用评星操作的 Subsonic 客户端 + * 可通过 1 星歌单查找并处理不喜欢(打 1 星 -> 写 dislike,提高/清除评分 -> 移除 dislike); + * - 不写入任何实体歌单,LX 客户端「我的歌单」不受影响。 + */ + private async getRatingPlaylistSongs(username: string): Promise> { + const groups = new Map() + for (let star = 1; star <= 5; star++) groups.set(star, []) + + const meta = await this.getUserSubsonicMeta(username) + const ratings = meta.ratings || {} + + // 所有可能被评星的歌曲:用户歌单 + 已缓存的在线歌曲(含本地音乐转换而来的对象) + const listData = await this.getSubsonicListData(username) + const all = new Map() + for (const m of [...listData.loveList, ...listData.defaultList, ...listData.userList.flatMap(l => l.list || [])]) all.set(m.id, m) + this.loadOnlineSongCache() + for (const [id, m] of this.onlineSongCache) if (!all.has(id)) all.set(id, m) + // 补充未收藏的本地歌曲:cacheOnlineSong 会跳过本地歌曲,仅靠歌单会漏掉已评分的 NAS 曲目; + // 在线缓存超出上限被淘汰的已评分歌曲暂无法覆盖(可接受)。 + for (const t of await getLocalTracks(username)) if (!all.has(t.id)) all.set(t.id, localMusic(t)) + + const assigned = new Set() + for (const [id, music] of all) { + const star = ratings[id] + // ratings 来自可手工编辑的 subsonic-meta.json;只接受 1~5 的整数, + // 否则 groups.get(1.5) 为 undefined,push 会让整个 getPlaylists 请求 500。 + if (typeof star === 'number' && Number.isInteger(star) && star >= 1 && star <= 5) { + groups.get(star)!.push(music) + assigned.add(id) + } + } + + // 1 星歌单 = 1 星歌曲 ∪ dislike 规则命中的歌曲 + if (global.lx.config['subsonic.ratingPlaylists'] !== false) { + const candidates = [...all.values()].filter(m => !assigned.has(m.id) || ratings[m.id] === 1) + const kept = await this.filterDislikedSongs(username, candidates) + const keptIds = new Set(kept.map(m => m.id)) + const oneStar = groups.get(1)! + const oneStarIds = new Set(oneStar.map(m => m.id)) + for (const m of candidates) { + if (!keptIds.has(m.id) && !oneStarIds.has(m.id)) oneStar.push(m) + } + } + return groups + } + + private isRatingPlaylistEnabled(): boolean { + return global.lx.config['subsonic.ratingPlaylists'] !== false + } + private async handleGetPlaylists(res: http.ServerResponse, username: string, format: string) { const userSpace = getUserSpace(username) const listData = await this.getSubsonicListData(username) @@ -2077,6 +2160,25 @@ class SubsonicHandler { } } + // [新增] 评星歌单:1~5 星各一个虚拟只读播放列表,1 星承载「我不喜欢」 + if (this.isRatingPlaylistEnabled()) { + try { + const groups = await this.getRatingPlaylistSongs(username) + for (let star = 1; star <= 5; star++) { + const musics = groups.get(star) || [] + // 与 default 歌单一致:不暴露 0 首的虚拟歌单,避免客户端歌单列表里出现空星级。 + // 直接打开指定 rating_N 仍返回空列表(handleGetPlaylist / getMusicDirectory 不受影响)。 + if (!musics.length) continue + const name = star === 1 + ? '★☆☆☆☆ 1星 · 我不喜欢' + : `${'★'.repeat(star)}${'☆'.repeat(5 - star)} ${star}星` + playlists.push(buildPlaylist(`${SubsonicHandler.RATING_PLAYLIST_PREFIX}${star}`, name, musics)) + } + } catch (err) { + subsonicLog.error('[Subsonic] 生成评星歌单失败:', err) + } + } + if (format === 'json') { return this.sendResponse(res, { playlists: { playlist: playlists } }, format) } @@ -2105,6 +2207,39 @@ class SubsonicHandler { return this.handleGetSharedPlaylist(res, username, id, format) } + // [新增] 评星歌单(虚拟只读):1 星承载「我不喜欢」。 + // 必须在此提前返回:下方 hideDisliked 会剔除 dislike 命中的歌曲,导致 1 星歌单被清空。 + if (id.startsWith(SubsonicHandler.RATING_PLAYLIST_PREFIX)) { + if (!this.isRatingPlaylistEnabled()) return this.sendError(res, 70, 'Rating playlists are disabled', format) + const star = parseInt(id.slice(SubsonicHandler.RATING_PLAYLIST_PREFIX.length), 10) + if (!(star >= 1 && star <= 5)) return this.sendError(res, 70, 'Rating playlist not found', format) + const groups = await this.getRatingPlaylistSongs(username) + const musics = groups.get(star) || [] + // 强制标注该星级,让客户端把这批歌识别为对应评分(1 星歌单里的 dislike 歌曲可能没有 rating 记录) + const entry = musics.map((m: LX.Music.MusicInfo) => ({ + ...this.musicToSongFlat(m, id, undefined, username), + userRating: star, + })) + const name = star === 1 + ? '★☆☆☆☆ 1星 · 我不喜欢' + : `${'★'.repeat(star)}${'☆'.repeat(5 - star)} ${star}星` + return this.sendLocalResponse(res, { + playlist: { + id, + name, + comment: star === 1 ? '该歌单关联「我不喜欢」:打 1 星即加入,提高或清除评分即移除' : '', + owner: username, + public: false, + songCount: musics.length, + duration: musics.reduce((sum: number, m: any) => sum + this.parseDuration(m.interval), 0), + created: new Date().toISOString(), + changed: new Date().toISOString(), + coverArt: this.playlistCoverId(id, musics), + entry, + }, + }, format) + } + const userSpace = getUserSpace(username) const listData = await this.getSubsonicListData(username) @@ -2160,6 +2295,7 @@ class SubsonicHandler { if (!playlistId) return this.sendError(res, 10, 'Required parameter is missing: playlistId', format) if (playlistId.startsWith('lb_')) return this.sendError(res, 0, '排行榜为只读播放列表,不支持修改', format) if (playlistId.startsWith('pl_')) return this.sendError(res, 0, '共享歌单为只读播放列表,不支持修改', format) + if (playlistId.startsWith(SubsonicHandler.RATING_PLAYLIST_PREFIX)) return this.sendError(res, 0, '评星歌单为只读播放列表,请通过给歌曲评星来修改', format) try { const userSpace = getUserSpace(username) @@ -2266,6 +2402,7 @@ class SubsonicHandler { if (!id) return this.sendError(res, 10, 'Required parameter is missing: id', format) if (id.startsWith('lb_')) return this.sendError(res, 0, '排行榜为只读播放列表,不支持删除', format) if (id.startsWith('pl_')) return this.sendError(res, 0, '共享歌单为只读播放列表,不支持删除', format) + if (id.startsWith(SubsonicHandler.RATING_PLAYLIST_PREFIX)) return this.sendError(res, 0, '评星歌单为只读播放列表,不支持删除', format) if (id === 'default' || id === 'love') { return this.sendError(res, 0, 'Built-in playlists cannot be deleted', format) } @@ -3016,8 +3153,18 @@ class SubsonicHandler { let musics: LX.Music.MusicInfo[] = [] let dirName = 'Unknown' - - if (id.startsWith('radio_tx_')) { + let ratingStar = 0 // 评星歌单星级;0 表示非评星歌单 + + // [新增] 评星歌单也可通过 getMusicDirectory 浏览(部分客户端用此端点打开歌单) + if (id.startsWith(SubsonicHandler.RATING_PLAYLIST_PREFIX)) { + if (!this.isRatingPlaylistEnabled()) return this.sendError(res, 70, 'Rating playlists are disabled', format) + const star = parseInt(id.slice(SubsonicHandler.RATING_PLAYLIST_PREFIX.length), 10) + if (!(star >= 1 && star <= 5)) return this.sendError(res, 70, 'Rating playlist not found', format) + const groups = await this.getRatingPlaylistSongs(username) + musics = groups.get(star) || [] + ratingStar = star + dirName = star === 1 ? '★☆☆☆☆ 1星 · 我不喜欢' : `${'★'.repeat(star)}${'☆'.repeat(5 - star)} ${star}星` + } else if (id.startsWith('radio_tx_')) { // [新增] 返回具体电台内的歌曲 // const radioId = id.replace('radio_tx_', '') try { @@ -3055,17 +3202,22 @@ class SubsonicHandler { } } - // [dislike] 过滤不喜欢的歌曲 - if (global.lx.config['subsonic.hideDisliked']) { + // [dislike] 过滤不喜欢的歌曲;评星歌单必须跳过,否则 1 星歌单会被全部剔除 + if (global.lx.config['subsonic.hideDisliked'] && !ratingStar) { musics = await this.filterDislikedSongs(username, musics) } + // 评星歌单强制标注星级,让客户端把 dislike 命中的歌曲也识别为对应评分 + const toSong = (m: LX.Music.MusicInfo) => { + const flat = this.musicToSongFlat(m, id, undefined, username) + return ratingStar ? { ...flat, userRating: ratingStar } : flat + } if (format === 'json') { return this.sendResponse(res, { directory: { id, name: dirName, - child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, undefined, username)), + child: musics.map((m: LX.Music.MusicInfo) => toSong(m)), }, }, format) } @@ -3073,7 +3225,7 @@ class SubsonicHandler { directory: { attrs: { id, name: dirName }, children: { - child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, undefined, username)), + child: musics.map((m: LX.Music.MusicInfo) => ({ attrs: toSong(m) })), }, }, }, format) @@ -5297,6 +5449,128 @@ class SubsonicHandler { return entries.filter(e => keptIds.has(e.music.id)) } + /** + * 手动补数据(评星 → 不喜欢):对「我的评分」里落在 dislike 区间的低星歌曲补写原生 dislike 规则。 + * 语义等价于重放一次 setRating 的正向联动,但只补不删;与快照导入/回滚完全解耦, + * 仅由管理员在 Subsonic 配置页点击「同步」时触发。 + */ + async syncRatingsToDislike(username: string): Promise { + const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) + const summary: LinkSyncSummary = { + direction: 'ratingToDislike', user: username, + scanned: 0, added: 0, skipped: 0, failed: 0, threshold, batches: 0, + } + if (threshold <= 0) return summary + + const meta = readSubsonicMeta(username) + const ratings = meta.ratings || {} + const lowRatedIds = Object.keys(ratings).filter(id => + typeof ratings[id] === 'number' && ratings[id] > 0 && ratings[id] <= threshold) + summary.scanned = lowRatedIds.length + if (lowRatedIds.length === 0) return summary + + const userSpace = getUserSpace(username) as any + // 全量分批:每批解析后批量写入,直到所有低星歌曲都处理完;绝不因条数上限截断 + try { + for (let start = 0; start < lowRatedIds.length; start += LINK_SYNC_BATCH_SIZE) { + const batch = lowRatedIds.slice(start, start + LINK_SYNC_BATCH_SIZE) + summary.batches++ + const infos: any[] = [] + const albumSingers = new Map>() + // 单条解析可能在线回源,逐条设超时;失败只记数,不中断后续批次 + for (const id of batch) { + try { + const target = await withTimeout(this.resolveDislikeTarget(username, id), LINK_SYNC_ITEM_TIMEOUT_MS) + for (const info of target.infos) infos.push(info) + if (target.album) { + const singers = albumSingers.get(target.album.albumName) ?? new Set() + for (const s of target.album.singers) singers.add(s) + albumSingers.set(target.album.albumName, singers) + } + } catch (e) { + summary.failed++ + subsonicLog.warn(`[Subsonic] 联动同步:解析评分歌曲 ${id} 失败`, e) + } + } + if (infos.length === 0 && albumSingers.size === 0) continue + + const albumInfos = Array.from(albumSingers).flatMap(([albumName, singers]) => + Array.from(singers).map(singer => ({ albumName, singer }))) + try { + // addDislikeInfo / addDislikeAlbums 自带按规则行去重,只补不删 + const before = userSpace.dislikeManage.dislikeDataManage.getDislikeRulesString() as string + await userSpace.dislikeManage.dislikeDataManage.addDislikeInfo(infos) + if (albumInfos.length > 0) await userSpace.dislikeManage.dislikeDataManage.addDislikeAlbums(albumInfos) + const after = userSpace.dislikeManage.dislikeDataManage.getDislikeRulesString() as string + const added = Math.max(0, countDislikeRules(after) - countDislikeRules(before)) + summary.added += added + summary.skipped += Math.max(0, infos.length + albumInfos.length - added) + } catch (e) { + // 单批写入失败也不能中断后续批次,否则会变成「只处理部分」 + summary.failed += infos.length + albumInfos.length + subsonicLog.warn(`[Subsonic] 联动同步:第 ${summary.batches} 批写入 dislike 失败`, e) + } + } + } finally { + // 全部分批结束后统一落盘 + 失效缓存,只生成一份快照,避免按批堆积 + if (summary.added > 0) { + await userSpace.dislikeManage.createSnapshot() + invalidateDislikeCache(username) + } + } + return summary + } + + /** + * 手动补数据(不喜欢 → 评星):对当前 dislike 规则命中的歌曲补写低星评分。 + * 语义等价于重放一次网页端「不喜欢」的反向联动(1 星),只补不覆盖已有评分。 + */ + async syncDislikesToRating(username: string): Promise { + const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) + const summary: LinkSyncSummary = { + direction: 'dislikeToRating', user: username, + scanned: 0, added: 0, skipped: 0, failed: 0, threshold, batches: 0, + } + if (threshold <= 0) return summary + + // 与评星歌单同源:用户歌单 + 已缓存的在线歌曲,纯内存规则匹配,不在线回源 + const listData = await this.getSubsonicListData(username) + const all = new Map() + for (const m of [ + ...listData.loveList, + ...listData.defaultList, + ...listData.userList.flatMap(l => (l.list || []) as LX.Music.MusicInfo[]), + ]) all.set(m.id, m) + this.loadOnlineSongCache() + for (const [id, m] of this.onlineSongCache) if (!all.has(id)) all.set(id, m) + // 同样补充未收藏的本地歌曲,避免手动同步漏掉本地曲目的 dislike 规则 + for (const t of await getLocalTracks(username)) if (!all.has(t.id)) all.set(t.id, localMusic(t)) + const candidates = Array.from(all.values()) + summary.scanned = candidates.length + if (candidates.length === 0) return summary + summary.batches = 1 + + const kept = await this.filterDislikedSongs(username, candidates) + const keptIds = new Set(kept.map(m => m.id)) + const hitIds = candidates.filter(m => !keptIds.has(m.id)).map(m => m.id) + + // 与 /api/music/dislike/add 的自动联动保持一致:不喜欢回写 1 星 + await withMetaLock(username, async () => { + const meta = readSubsonicMeta(username) + for (const id of hitIds) { + if (meta.ratings[id] > 0) { summary.skipped++; continue } + meta.ratings[id] = 1 + summary.added++ + } + if (summary.added > 0) { + writeSubsonicMeta(username, meta) + this.userRatingsCache.set(username, meta.ratings || {}) + void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 联动同步评分快照生成失败:', e)) + } + }) + return summary + } + /** * 处理 Subsonic setRating:写回评分,并按配置把低分(<=阈值)联动为「不喜欢」。 */ @@ -5320,11 +5594,16 @@ class SubsonicHandler { this.userRatingsCache.set(username, meta.ratings || {}) }) subsonicLog.debug(`[Subsonic] setRating ${id} -> ${rating} (user=${username})`) + // 评分写入后生成/复用一份「我的评分」快照,使当前评分可被下载备份 + void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 评分快照生成失败:', e)) // [dislike 联动] 0 < rating <= dislikeRating 视为「不喜欢」,写回 lx-music 原生 dislike 规则; // 提高评分或清除评分则移除此前写入的规则。需 linkRatingToDislike 开启才联动,否则仅记录评分。 const threshold = global.lx.config['subsonic.dislikeRating'] ?? 1 - if (global.lx.config['subsonic.linkRatingToDislike'] && threshold > 0) { + // 评星歌单开启时,1 星歌单承载「我不喜欢」,正向联动必须生效: + // 客户端给歌曲打 1 星 -> 写入 dislike 规则;提高评分或清除 -> 移除规则。 + const linkToDislike = global.lx.config['subsonic.linkRatingToDislike'] || this.isRatingPlaylistEnabled() + if (linkToDislike && threshold > 0) { try { const target = await this.resolveDislikeTarget(username, id) // [调试] 打印解析到的维度与身份信息,便于确认各入口能拿到什么 @@ -7775,3 +8054,12 @@ export function invalidateSubsonicPlaylistCache(): void { } export const subsonicHandler = new SubsonicHandler() + +/** 管理端「联动数据同步」按钮入口:仅手动触发,不参与快照导入/回滚链路 */ +export function syncRatingsToDislike(username: string): Promise { + return subsonicHandler.syncRatingsToDislike(username) +} + +export function syncDislikesToRating(username: string): Promise { + return subsonicHandler.syncDislikesToRating(username) +} diff --git a/src/server/openlist/openlistBackupDb.ts b/src/server/openlist/openlistBackupDb.ts index 9f29c107..097cf934 100644 --- a/src/server/openlist/openlistBackupDb.ts +++ b/src/server/openlist/openlistBackupDb.ts @@ -95,6 +95,9 @@ export function getBackupDb(): DatabaseSync { const db = new DatabaseSync(dbPath) db.exec('PRAGMA journal_mode = WAL') db.exec('PRAGMA synchronous = NORMAL') + // WAL 允许多读单写:不设置 busy_timeout 时第二个写事务会立刻抛 SQLITE_BUSY(database is locked), + // 多进程共用同一数据目录(多开 dev 实例、备份进程与页面同时写)时会频繁撞锁,这里改为等待重试。 + db.exec('PRAGMA busy_timeout = 8000') db.exec(`CREATE TABLE IF NOT EXISTS openlist_backup_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT NOT NULL, diff --git a/src/server/ratingSnapshot.ts b/src/server/ratingSnapshot.ts new file mode 100644 index 00000000..f0939dc3 --- /dev/null +++ b/src/server/ratingSnapshot.ts @@ -0,0 +1,192 @@ +import fs from 'node:fs' +import path from 'node:path' +import { createHash } from 'node:crypto' +import { getUserDirname } from '@/user' +import { getUserConfig } from '@/user/data' + +/** + * 「我的评分」快照(第三种备份类型)。 + * 评星数据独立于歌单/不喜欢,存放在 <用户目录>/subsonic-meta.json, + * 因此独立成一套快照目录 <用户目录>/rating/snapshot/,与另外两类并列展示。 + */ +export interface RatingMeta { + starredAlbums: string[] + starredArtists: string[] + starredArtistNames: string[] + ratings: Record +} + +export interface RatingSnapshotItem { + id: string + time: number + size: number + origin: 'imported' | 'auto' +} + +interface RatingSnapshotInfo { + imported: string[] +} + +const emptyMeta = (): RatingMeta => ({ starredAlbums: [], starredArtists: [], starredArtistNames: [], ratings: {} }) + +const userDir = (username: string) => path.join(global.lx.userPath, getUserDirname(username)) +const metaPath = (username: string) => path.join(userDir(username), 'subsonic-meta.json') +const ratingDir = (username: string) => path.join(userDir(username), 'rating') +const snapshotDir = (username: string) => path.join(ratingDir(username), 'snapshot') +const infoPath = (username: string) => path.join(ratingDir(username), 'snapshotInfo.json') + +/** + * 快照 id 直接来自外部输入(下载/删除/恢复接口的 id 参数、导入时的文件名), + * 这里统一拒绝路径分隔符与上跳片段,避免拼进 snapshotPath 后发生路径穿越。 + */ +export const isValidSnapshotId = (id: unknown): id is string => { + if (typeof id !== 'string') return false + if (!id || id.length > 200) return false + if (id === '.' || id === '..' || id.includes('..')) return false + return !/[\\/:*?"<>|]/.test(id) +} + +const snapshotPath = (username: string, id: string) => { + if (!isValidSnapshotId(id)) throw new Error('Invalid snapshot id') + return path.join(snapshotDir(username), `snapshot_${id}`) +} + +const normalizeMeta = (data: any): RatingMeta => ({ + starredAlbums: Array.isArray(data?.starredAlbums) ? data.starredAlbums : [], + starredArtists: Array.isArray(data?.starredArtists) ? data.starredArtists : [], + starredArtistNames: Array.isArray(data?.starredArtistNames) ? data.starredArtistNames : [], + ratings: data?.ratings && typeof data.ratings === 'object' && !Array.isArray(data.ratings) ? data.ratings : {}, +}) + +/** 供 HTTP 导入入口复用:外部备份(含 lxRating_v1 标记)统一归一化为评分元数据后再落盘 */ +export const normalizeRatingMeta = normalizeMeta + +const readMeta = (username: string): RatingMeta => { + try { + if (fs.existsSync(metaPath(username))) return normalizeMeta(JSON.parse(fs.readFileSync(metaPath(username), 'utf8'))) + } catch { /* 损坏时按空评分处理 */ } + return emptyMeta() +} + +const writeMeta = (username: string, meta: RatingMeta) => { + fs.mkdirSync(path.dirname(metaPath(username)), { recursive: true }) + fs.writeFileSync(metaPath(username), JSON.stringify(meta), 'utf8') +} + +const readInfo = (username: string): RatingSnapshotInfo => { + try { + if (fs.existsSync(infoPath(username))) { + const data = JSON.parse(fs.readFileSync(infoPath(username), 'utf8')) + if (Array.isArray(data.imported)) return { imported: data.imported } + } + } catch { /* ignore */ } + return { imported: [] } +} + +const writeInfo = (username: string, info: RatingSnapshotInfo) => { + fs.mkdirSync(ratingDir(username), { recursive: true }) + fs.writeFileSync(infoPath(username), JSON.stringify(info), 'utf8') +} + +const ensureDirs = (username: string) => fs.mkdirSync(snapshotDir(username), { recursive: true }) + +const md5 = (text: string) => createHash('md5').update(text).digest('hex') + +/** 自动评分快照保留上限:导入快照永久保留,只清理超量的系统快照(保留最新 max 份) */ +const cleanupAutoSnapshots = (username: string) => { + try { + const info = readInfo(username) + const max = Math.max(1, Number(getUserConfig(username)?.maxSnapshotNum) || Number(global.lx.config.maxSnapshotNum) || 10) + const entries = fs.readdirSync(snapshotDir(username)) + .filter(file => file.startsWith('snapshot_')) + .map(file => ({ + id: file.slice('snapshot_'.length), + mtime: fs.statSync(path.join(snapshotDir(username), file)).mtimeMs, + })) + .filter(entry => !info.imported.includes(entry.id)) + .sort((a, b) => b.mtime - a.mtime) + for (const entry of entries.slice(max)) { + try { fs.unlinkSync(snapshotPath(username, entry.id)) } catch { /* ignore */ } + } + } catch { /* ignore */ } +} + +/** 按当前评分内容生成(或复用)一份系统快照,返回快照 id */ +export const createRatingSnapshot = async (username: string): Promise => { + const meta = readMeta(username) + const id = md5(JSON.stringify(meta)) + ensureDirs(username) + const file = snapshotPath(username, id) + if (!fs.existsSync(file)) fs.writeFileSync(file, JSON.stringify(meta), 'utf8') + else { + // 复用内容相同的旧快照时刷新 mtime:清理按 mtime 只保留最新 N 份,不刷新会把刚复用的快照当成最旧的删掉 + const now = new Date() + try { fs.utimesSync(file, now, now) } catch { /* ignore */ } + } + cleanupAutoSnapshots(username) + return id +} + +/** 保存用户导入的评分备份:按原文件名落盘、保留文件时间、显式登记来源 */ +export const saveRatingImport = async (username: string, name: string, meta: RatingMeta, time: number): Promise => { + ensureDirs(username) + const file = snapshotPath(username, name) + fs.writeFileSync(file, JSON.stringify(meta), 'utf8') + if (time) { + const date = new Date(time) + fs.utimesSync(file, date, date) + } + const info = readInfo(username) + if (!info.imported.includes(name)) { + info.imported.push(name) + writeInfo(username, info) + } +} + +export const listRatingSnapshots = async (username: string): Promise => { + ensureDirs(username) + const info = readInfo(username) + const list: RatingSnapshotItem[] = [] + for (const file of fs.readdirSync(snapshotDir(username))) { + if (!file.startsWith('snapshot_')) continue + const id = file.slice('snapshot_'.length) + try { + const stat = fs.statSync(snapshotPath(username, id)) + list.push({ + id, + time: stat.mtimeMs, + size: stat.size, + origin: info.imported.includes(id) ? 'imported' : 'auto', + }) + } catch { /* 文件已消失 */ } + } + return list.sort((a, b) => b.time - a.time) +} + +export const readRatingSnapshot = async (username: string, id: string): Promise => { + try { + const file = snapshotPath(username, id) + if (!fs.existsSync(file)) return null + return normalizeMeta(JSON.parse(fs.readFileSync(file, 'utf8'))) + } catch { return null } +} + +/** 回滚:把快照内容写回 subsonic-meta.json(Subsonic 每次请求会重新预读该文件,缓存自动刷新) */ +export const restoreRatingSnapshot = async (username: string, id: string): Promise => { + const meta = await readRatingSnapshot(username, id) + if (!meta) throw new Error('Rating snapshot not found') + writeMeta(username, meta) +} + +export const deleteRatingSnapshot = async (username: string, id: string): Promise => { + const file = snapshotPath(username, id) + if (!fs.existsSync(file)) return false + fs.unlinkSync(file) + const info = readInfo(username) + const index = info.imported.indexOf(id) + if (index >= 0) { + info.imported.splice(index, 1) + writeInfo(username, info) + } + return true +} diff --git a/src/server/server.ts b/src/server/server.ts index a60f8827..83e74e84 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -23,7 +23,8 @@ import { parseDislikeRules, splitSingers } from '@/modules/dislike/match' import { encodeAlbumRule } from '@/modules/dislike/utils' import { normalizeText } from '@/server/utils/songVersion' import { invalidateDislikeCache } from '@/server/utils/dislikeCache' -import { invalidateSubsonicPlaylistCache } from '@/server/integrations/subsonic' +import { invalidateSubsonicPlaylistCache, syncRatingsToDislike, syncDislikesToRating } from '@/server/integrations/subsonic' +import { createRatingSnapshot, saveRatingImport, listRatingSnapshots, readRatingSnapshot, restoreRatingSnapshot, deleteRatingSnapshot, normalizeRatingMeta, isValidSnapshotId } from './ratingSnapshot' import { createMsg2call } from 'message2call' import { handleFileManager } from './integrations/fileManager' import formidable from 'formidable' @@ -37,6 +38,29 @@ import { prepareOpenlistIntegrity, startOpenlistIntegrity, integrityStatus, canc import { BACKUP_TYPE_INFO, getBackupTypes, normalizeBackupTypes, isCloudBackupRunning } from '@/utils/backupPolicy' import { OpenListClient } from '@/server/openlist/openlistClient' +/** 快照备份的三类目录;检测口径与 public/app.js 的导入识别保持一致 */ +type SnapshotKind = 'list' | 'dislike' | 'rating' +const isSnapshotObject = (value: unknown): value is Record => + !!value && typeof value === 'object' && !Array.isArray(value) + +const detectSnapshotKind = (parsed: unknown): SnapshotKind => { + if (!isSnapshotObject(parsed)) return 'list' + if (parsed.type === 'lxRating_v1') return 'rating' + if (Array.isArray(parsed.defaultList) || Array.isArray(parsed.userList)) return 'list' + if (Array.isArray(parsed.dislikeList)) return 'dislike' + if (isSnapshotObject(parsed.ratings)) return 'rating' + return 'list' +} + +/** 落雪音乐离线备份 playList_v2 转回服务端内部歌单快照结构 */ +const toInternalListSnapshot = (parsed: unknown): string | null => { + if (!isSnapshotObject(parsed) || parsed.type !== 'playList_v2' || !Array.isArray(parsed.data)) return null + const defaultList = parsed.data.find((l: any) => l?.id === 'default')?.list || [] + const loveList = parsed.data.find((l: any) => l?.id === 'love')?.list || [] + const userList = parsed.data.filter((l: any) => l?.id !== 'default' && l?.id !== 'love') + return JSON.stringify({ defaultList, loveList, userList }) +} + async function validateOpenListConfig(newConfig: any): Promise { const c: any = global.lx.config const enable = newConfig['openlist.enable'] !== undefined ? !!newConfig['openlist.enable'] : !!c['openlist.enable'] @@ -1991,9 +2015,11 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi try { const listSnaps = await userSpace.listManage.getSnapshotList() const dislikeSnaps = userSpace.dislikeManage ? await userSpace.dislikeManage.snapshotDataManage.getSnapshotListWithMeta() : [] + const ratingSnaps = await listRatingSnapshots(verifiedUser) const list = [ ...listSnaps.map(s => ({ ...s, kind: 'list' })), ...dislikeSnaps.map(s => ({ ...s, kind: 'dislike' })), + ...ratingSnaps.map(s => ({ ...s, kind: 'rating' })), ].sort((a, b) => (b.time || 0) - (a.time || 0)) res.writeHead(200, { 'Content-Type': 'application/json', @@ -2042,10 +2068,16 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi } try { const kind = urlObj.searchParams.get('kind') - if (kind && kind !== 'list' && kind !== 'dislike') throw new Error('Invalid snapshot kind') - let data: any = kind === 'dislike' ? null : await userSpace.listManage.getSnapshot(id) - if (!data && kind !== 'list' && userSpace.dislikeManage) { - data = await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id) + if (kind && kind !== 'list' && kind !== 'dislike' && kind !== 'rating') throw new Error('Invalid snapshot kind') + let data: any + if (kind === 'rating') { + // 评分快照严格隔离读取,避免与歌单 / 不喜欢目录中的同名 id 串数据 + data = await readRatingSnapshot(verifiedUser, id) + } else { + data = kind === 'dislike' ? null : await userSpace.listManage.getSnapshot(id) + if (!data && kind !== 'list' && userSpace.dislikeManage) { + data = await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id) + } } if (!data) { res.writeHead(404) @@ -2096,7 +2128,12 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi const { id, kind } = JSON.parse(body) if (!id) throw new Error('Missing id') - if (kind === 'dislike' && userSpace.dislikeManage) { + if (kind && kind !== 'list' && kind !== 'dislike' && kind !== 'rating') throw new Error('Invalid snapshot kind') + if (kind === 'rating') { + await restoreRatingSnapshot(verifiedUser, id) + // Subsonic 每次非轻量请求都会重新预读 subsonic-meta.json,评星缓存随之刷新 + invalidateSubsonicPlaylistCache() + } else if (kind === 'dislike' && userSpace.dislikeManage) { await userSpace.dislikeManage.restoreSnapshot(id) invalidateDislikeCache(verifiedUser) } else { @@ -2299,13 +2336,15 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi const { id, kind } = JSON.parse(body) if (!id) throw new Error('Missing id') - if (kind && kind !== 'list' && kind !== 'dislike') throw new Error('Invalid snapshot kind') - if (kind === 'dislike') { - if (!await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id)) throw new Error('快照不存在') + if (kind && kind !== 'list' && kind !== 'dislike' && kind !== 'rating') throw new Error('Invalid snapshot kind') + if (kind === 'rating') { + if (!await deleteRatingSnapshot(verifiedUser, id)) throw new Error('快照不存在') + } else if (kind === 'dislike') { + if (!userSpace.dislikeManage || !await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id)) throw new Error('快照不存在') await userSpace.dislikeManage.snapshotDataManage.removeSnapshot(id) } else if (await userSpace.listManage.getSnapshot(id)) { await userSpace.listManage.removeSnapshot(id) - } else if (!kind && await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id)) { + } else if (!kind && userSpace.dislikeManage && await userSpace.dislikeManage.snapshotDataManage.getSnapshot(id)) { await userSpace.dislikeManage.snapshotDataManage.removeSnapshot(id) } else { throw new Error('快照不存在') @@ -2326,6 +2365,7 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi const userParam = urlObj.searchParams.get('user') const time = parseInt(urlObj.searchParams.get('time') || '0') const filename = urlObj.searchParams.get('filename') + const restore = urlObj.searchParams.get('restore') === '1' if (!userParam) { res.writeHead(400) @@ -2357,48 +2397,56 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi try { const body = await readBody(req) - let finalData = body + let parsed: unknown = null + try { parsed = JSON.parse(body) } catch { /* 非 JSON 按原生歌单快照导入 */ } - // [核心兼容性修复] 检测是否为落雪音乐离线备份格式 (playList_v2) - try { - const jsonData = JSON.parse(body) - if (jsonData && jsonData.type === 'playList_v2' && Array.isArray(jsonData.data)) { - startupLog.info(`[Snapshot] Detected LX Music backup format for user ${verifiedUser}, converting back to internal format...`) - - // 寻找默认列表 - const defaultList = jsonData.data.find((l: any) => l.id === 'default')?.list || [] - // 寻找收藏列表 - const loveList = jsonData.data.find((l: any) => l.id === 'love')?.list || [] - // 其他所有列表均作为用户列表 - const userList = jsonData.data.filter((l: any) => l.id !== 'default' && l.id !== 'love') - - // 拼装为服务器内部快照格式 - const internalFormat = { - defaultList, - loveList, - userList - } - - // 压缩为单行 JSON 以节省磁盘空间并保持与原生快照一致的大小 - finalData = JSON.stringify(internalFormat) - startupLog.info(`[Snapshot] Conversion complete for user ${verifiedUser}.`) - } - } catch (parseErr) { - // 解析失败说明不是标准的 JSON 格式或已经是原始快照,保持原样即可 - } + // 三类备份分流到各自目录:歌单 / 不喜欢 / 我的评分,与前端导入识别口径一致 + const kind: SnapshotKind = detectSnapshotKind(parsed) + const ratingMeta = kind === 'rating' ? normalizeRatingMeta(parsed) : null + const convertedList = kind === 'list' ? toInternalListSnapshot(parsed) : null + const finalData = ratingMeta ? JSON.stringify(ratingMeta) : (convertedList || body) - // 处理文件名:如果以 snapshot_ 开头,则去掉(因为 saveSnapshotWithTime 会自动加) - // 如果不以 snapshot_ 开头,则保持原样(saveSnapshotWithTime 会自动加 snapshot_ 前缀) + // 文件名会直接拼进快照目录,统一拒绝路径分隔符与上跳片段 let name = filename - if (name.startsWith('snapshot_')) { - name = name.substring(9) + if (name.startsWith('snapshot_')) name = name.substring(9) + if (!isValidSnapshotId(name)) throw new Error('Invalid snapshot id') + + // 「导入并恢复」:先把导入前状态存成系统快照,再落盘并立即恢复 + let safetySnapshot = false + if (restore) { + if (kind === 'rating') await createRatingSnapshot(verifiedUser) + else if (kind === 'dislike') { + if (!userSpace.dislikeManage) throw new Error('不喜欢管理未启用') + await userSpace.dislikeManage.createSnapshot() + } else await userSpace.listManage.createSnapshot() + safetySnapshot = true + } + + if (kind === 'rating') { + await saveRatingImport(verifiedUser, name, ratingMeta!, time) + } else if (kind === 'dislike') { + if (!userSpace.dislikeManage) throw new Error('不喜欢管理未启用') + await userSpace.dislikeManage.saveSnapshotWithTime(name, finalData, time) + } else { + await userSpace.listManage.saveSnapshotWithTime(name, finalData, time) } - // 调用 ListManage 中的 saveSnapshotWithTime 方法 - await userSpace.listManage.saveSnapshotWithTime(name, finalData, time) + if (restore) { + if (kind === 'rating') { + await restoreRatingSnapshot(verifiedUser, name) + invalidateSubsonicPlaylistCache() + } else if (kind === 'dislike') { + if (!userSpace.dislikeManage) throw new Error('不喜欢管理未启用') + await userSpace.dislikeManage.restoreSnapshot(name) + invalidateDislikeCache(verifiedUser) + } else { + await userSpace.listManage.restoreSnapshot(name) + invalidateSubsonicPlaylistCache() + } + } res.writeHead(200, { 'Content-Type': 'application/json' }) - res.end(JSON.stringify({ success: true })) + res.end(JSON.stringify({ success: true, kind, restored: restore, safetySnapshot })) } catch (err: any) { res.writeHead(500) res.end(err.message) @@ -2406,6 +2454,35 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi return } + // [新增] Subsonic 评分 / 不喜欢 联动补数据(仅管理员从配置页手动触发) + if (pathname === '/api/subsonic/sync-link' && req.method === 'POST') { + if (req.headers['x-frontend-auth'] !== global.lx.config['admin.password']) { + res.writeHead(401, { 'Content-Type': 'application/json' }) + res.end(JSON.stringify({ success: false, message: 'Unauthorized' })) + return + } + try { + const { user, direction } = JSON.parse(await readBody(req)) + if (!user || typeof user !== 'string') throw new Error('Missing user') + if (direction !== 'ratingToDislike' && direction !== 'dislikeToRating') throw new Error('Invalid direction') + const enabled = direction === 'ratingToDislike' + ? global.lx.config['subsonic.linkRatingToDislike'] + : global.lx.config['subsonic.linkDislikeToRating'] + if (!enabled) throw new Error('联动开关未开启,请先在配置中开启并保存') + const known = user === '_open' || global.lx.config.users.some((u: any) => u.name === user) + if (!known) throw new Error('用户不存在') + const result = direction === 'ratingToDislike' + ? await syncRatingsToDislike(user) + : await syncDislikesToRating(user) + res.writeHead(200, { 'Content-Type': 'application/json' }) + res.end(JSON.stringify(result)) + } catch (err: any) { + res.writeHead(400, { 'Content-Type': 'application/json' }) + res.end(err.message) + } + return + } + // [新增] User Login Verification if (pathname === '/api/user/verify' && req.method === 'POST') { void readBody(req).then(body => { diff --git a/src/types/config.d.ts b/src/types/config.d.ts index f47d6279..beac82f2 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -401,6 +401,15 @@ declare namespace LX { */ 'subsonic.linkDislikeToRating'?: boolean + /** + * 是否向 Subsonic 客户端暴露 1~5 星评星歌单 (默认 true) + * 虚拟只读歌单(不落盘、不影响 LX 客户端「我的歌单」):id 为 rating_1 ~ rating_5。 + * rating_1 承载「我不喜欢」:除 1 星歌曲外并入 dislike 规则命中的歌曲,并强制显示 1 星; + * 开启时「1 星 <-> 不喜欢」双向联动强制生效(不受上面两个解耦开关影响), + * 便于只能用评星操作的 Subsonic 客户端通过 1 星查找并处理不喜欢。 + */ + 'subsonic.ratingPlaylists'?: boolean + /** * Subsonic 列表中是否隐藏 dislike 命中的歌曲 (默认 true) * 开启后,命中不喜欢规则的歌曲会直接从专辑/歌单/搜索等列表中剔除; diff --git a/test/openlist-busy-timeout.test.ts b/test/openlist-busy-timeout.test.ts new file mode 100644 index 00000000..6797c152 --- /dev/null +++ b/test/openlist-busy-timeout.test.ts @@ -0,0 +1,30 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' +import { getBackupDb } from '../src/server/openlist/openlistBackupDb' + +// getDataPath() 在 getBackupDb() 调用时才读取,因此可在静态 import 之后再设置 +const dataPath = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-busy-timeout-')) +;(globalThis as any).lx = { dataPath } + +test('S10 OpenList SQLite:busy_timeout 已生效且连接单例复用', () => { + const db = getBackupDb() + assert.equal(getBackupDb(), db, '重复调用应返回同一连接,避免多连接互相抢锁') + const row = db.prepare('PRAGMA busy_timeout').get() as Record + assert.equal(Number(Object.values(row)[0]), 8000) + assert.equal(db.prepare('PRAGMA journal_mode').get() !== undefined, true) + const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='openlist_backup_files'").all() + assert.equal(tables.length, 1) + assert.ok(fs.existsSync(path.join(dataPath, 'openlist-backup.db'))) + db.close() + fs.rmSync(dataPath, { recursive: true, force: true }) +}) + +test('S10 契约:busy_timeout 与并发注释保留在连接初始化处', () => { + const source = fs.readFileSync(path.resolve('src/server/openlist/openlistBackupDb.ts'), 'utf8') + assert.match(source, /PRAGMA busy_timeout = 8000/) + assert.match(source, /PRAGMA journal_mode = WAL/) + assert.match(source, /function getBackupDb\(\)/) +}) diff --git a/test/openlist.test.cjs b/test/openlist.test.cjs index 93ab5988..3b876f17 100644 --- a/test/openlist.test.cjs +++ b/test/openlist.test.cjs @@ -403,7 +403,11 @@ test('OpenList backup, restore and synchronization against an HTTP storage serve remote.get(history).modified = '2020-01-01T00:00:00Z' await api.runSyncNow() assert.equal([...remote.keys()].filter(p => p.startsWith('/new-mount/_system/config-history/')).length, 1) - assert.ok(Date.parse(remote.get(history).modified) > Date.parse('2020-01-01')) + // 同步会删掉过期副本并按「当前秒」重建;跨秒时文件名里的秒级时间戳会变, + // 不能复用同步前的 key(该条目已从远端移除),否则读取 undefined.modified 抛错。 + const refreshed = [...remote.keys()].find(p => p.startsWith('/new-mount/_system/config-history/')) + assert.ok(refreshed, '同步后应保留一份配置历史副本') + assert.ok(Date.parse(remote.get(refreshed).modified) > Date.parse('2020-01-01'), '过期副本应被重新上传并刷新 mtime') config['openlist.root'] = '/third-mount' await api.runSyncNow() assert.ok(remote.has('/third-mount/_data/config.js')) diff --git a/test/rating-snapshot.test.ts b/test/rating-snapshot.test.ts new file mode 100644 index 00000000..d568a8b4 --- /dev/null +++ b/test/rating-snapshot.test.ts @@ -0,0 +1,141 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' +import vm from 'node:vm' +import { createRequire } from 'node:module' +import { transformSync } from 'esbuild' + +/** 用 vm 注入受控的 global.lx 与 @/ 别名依赖,隔离文件系统的真实用户目录 */ +const nodeRequire = createRequire(import.meta.url) +type Api = Record + +const load = (userPath: string, maxSnapshotNum = 3): Api => { + const source = fs.readFileSync(path.resolve('src/server/ratingSnapshot.ts'), 'utf8') + const code = transformSync(source, { loader: 'ts', format: 'cjs', target: 'node20' }).code + const mod = { exports: {} as Api } + const require = (id: string): any => { + if (id === '@/user') return { getUserDirname: (u: string) => u } + if (id === '@/user/data') return { getUserConfig: () => ({ maxSnapshotNum }) } + return nodeRequire(id) + } + const context = vm.createContext({ + module: mod, + exports: mod.exports, + require, + global: { lx: { userPath, config: { maxSnapshotNum } } }, + console, + process, + Buffer, + __dirname: path.resolve('src/server'), + __filename: path.resolve('src/server/ratingSnapshot.ts'), + }) + vm.runInContext(code, context) + return mod.exports +} + +const withUser = async (maxSnapshotNum: number, fn: (api: Api, userDir: string) => Promise | void) => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-rating-snap-')) + try { + const userDir = path.join(root, 'alice') + fs.mkdirSync(userDir, { recursive: true }) + await fn(load(root, maxSnapshotNum), userDir) + } finally { + fs.rmSync(root, { recursive: true, force: true }) + } +} + +const metaFile = (userDir: string) => path.join(userDir, 'subsonic-meta.json') +const snapshotDir = (userDir: string) => path.join(userDir, 'rating', 'snapshot') +const infoFile = (userDir: string) => path.join(userDir, 'rating', 'snapshotInfo.json') +const writeMeta = (userDir: string, ratings: Record) => + fs.writeFileSync(metaFile(userDir), JSON.stringify({ ratings, starredAlbums: [], starredArtists: [], starredArtistNames: [] }), 'utf8') +const plain = (value: T): T => JSON.parse(JSON.stringify(value)) + +test('S4 快照 id:路径穿越与非法字符全部拒绝', async () => { + await withUser(3, (api) => { + for (const id of ['abc', '2026-11-08', 'a'.repeat(32), '用户备份']) { + assert.equal(api.isValidSnapshotId(id), true, `应接受 ${id}`) + } + for (const id of ['', '.', '..', '../evil', 'a..b', 'a/b', 'a\\b', 'a:b', 'a*b', 'a?b', 'a"b', 'ab', 'a|b', 'x'.repeat(201), null, 1, {}, []]) { + assert.equal(api.isValidSnapshotId(id), false, `应拒绝 ${String(id)}`) + } + }) +}) + +test('S9 内容去重:同一评分只生成一份快照,复用时刷新 mtime', async () => { + await withUser(3, async (api, userDir) => { + writeMeta(userDir, { a: 3 }) + const id1 = await api.createRatingSnapshot('alice') + const file = path.join(snapshotDir(userDir), `snapshot_${id1}`) + assert.ok(fs.existsSync(file)) + const old = new Date(Date.now() - 10 * 86_400_000) + fs.utimesSync(file, old, old) + const id2 = await api.createRatingSnapshot('alice') + assert.equal(id2, id1) + assert.ok(fs.statSync(file).mtimeMs > old.getTime() + 5 * 86_400_000) + writeMeta(userDir, { a: 5 }) + const id3 = await api.createRatingSnapshot('alice') + assert.notEqual(id3, id1) + }) +}) + +test('S9 配额清理:只清超量的 auto 快照,imported 永久保留', async () => { + await withUser(2, async (api, userDir) => { + writeMeta(userDir, { a: 1 }) + const first = await api.createRatingSnapshot('alice') + // 错开 mtime,避免同毫秒导致清理顺序不稳定 + fs.utimesSync(path.join(snapshotDir(userDir), `snapshot_${first}`), new Date(1), new Date(1)) + for (const star of [2, 3, 4]) { + writeMeta(userDir, { a: star }) + const id = await api.createRatingSnapshot('alice') + fs.utimesSync(path.join(snapshotDir(userDir), `snapshot_${id}`), new Date(star * 1000), new Date(star * 1000)) + } + const imported = 'my-import.json' + await api.saveRatingImport('alice', imported, { ratings: { z: 5 }, starredAlbums: [], starredArtists: [], starredArtistNames: [] }, Date.now() - 86_400_000) + const list = plain(await api.listRatingSnapshots('alice')) + assert.ok(fs.existsSync(path.join(snapshotDir(userDir), `snapshot_${imported}`))) + assert.equal(list.filter((x: any) => x.origin === 'auto').length, 2, 'auto 快照应只保留最新 2 份') + assert.equal(list.find((x: any) => x.id === imported)?.origin, 'imported') + assert.equal(JSON.parse(fs.readFileSync(infoFile(userDir), 'utf8')).imported.includes(imported), true) + }) +}) + +test('S9 索引兼容:旧版 snapshotInfo 无 imported 字段时降级为空数组', async () => { + await withUser(3, async (api, userDir) => { + writeMeta(userDir, { a: 1 }) + fs.mkdirSync(snapshotDir(userDir), { recursive: true }) + fs.writeFileSync(infoFile(userDir), '{ not json', 'utf8') + await api.createRatingSnapshot('alice') + const list = plain(await api.listRatingSnapshots('alice')) + assert.equal(list[0].origin, 'auto') + fs.writeFileSync(infoFile(userDir), JSON.stringify({ unrelated: 1 }), 'utf8') + assert.equal(plain(await api.listRatingSnapshots('alice'))[0].origin, 'auto') + }) +}) + +test('S9 meta 损坏降级为空评分;读写与删除、回滚幂等', async () => { + await withUser(3, async (api, userDir) => { + fs.writeFileSync(metaFile(userDir), '{ broken', 'utf8') + const id = await api.createRatingSnapshot('alice') + const meta = plain(await api.readRatingSnapshot('alice', id)) + assert.deepEqual(meta.ratings, {}) + assert.equal(await api.readRatingSnapshot('alice', 'missing'), null) + assert.equal(await api.readRatingSnapshot('alice', '../evil'), null) + assert.equal(await api.deleteRatingSnapshot('alice', 'missing'), false) + await assert.rejects(() => api.restoreRatingSnapshot('alice', 'missing'), /not found/) + + writeMeta(userDir, { song: 4 }) + const target = 'user-backup' + await api.saveRatingImport('alice', target, { ratings: { song: 1 }, starredAlbums: [], starredArtists: [], starredArtistNames: [] }, 0) + await api.saveRatingImport('alice', target, { ratings: { song: 1 }, starredAlbums: [], starredArtists: [], starredArtistNames: [] }, 0) + assert.equal(JSON.parse(fs.readFileSync(infoFile(userDir), 'utf8')).imported.length, 1, '重复导入不应重复登记') + + await api.restoreRatingSnapshot('alice', target) + assert.equal(JSON.parse(fs.readFileSync(metaFile(userDir), 'utf8')).ratings.song, 1) + assert.equal(await api.deleteRatingSnapshot('alice', target), true) + assert.equal(JSON.parse(fs.readFileSync(infoFile(userDir), 'utf8')).imported.length, 0) + await assert.rejects(() => api.saveRatingImport('alice', '../evil', {}, 0), /Invalid snapshot id/) + }) +}) diff --git a/test/snapshot-imported.test.ts b/test/snapshot-imported.test.ts new file mode 100644 index 00000000..403bd0c3 --- /dev/null +++ b/test/snapshot-imported.test.ts @@ -0,0 +1,134 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' +import vm from 'node:vm' +import { transformSync } from 'esbuild' + +/** + * 提取 SnapshotDataManage 中与 imported 相关的真实成员,放进最小 Harness 里执行。 + * 歌单与不喜欢两份实现分别加载,用同一组断言验证行为对称。 + */ +const MEMBERS = [ + 'private getImported =', + 'private persistSnapshotInfo =', + 'markImported =', + 'unmarkImported =', + 'isImported =', + 'getSnapshotListWithMeta =', +] + +const extractMember = (lines: string[], marker: string): string => { + const start = lines.findIndex(line => line.includes(marker)) + assert.ok(start >= 0, `找不到成员 ${marker}`) + let end = start + 1 + for (; end < lines.length; end++) { + if (/^ [A-Za-z_]\w*\s*[=(]/.test(lines[end])) break + } + return lines.slice(start, end).join('\n') +} + +const build = (rel: string, dir: string) => { + const src = fs.readFileSync(path.resolve(rel), 'utf8') + const lines = src.split('\n') + const members = MEMBERS.map(m => extractMember(lines, m)).join('\n') + const infoPath = path.join(dir, 'snapshotInfo.json') + const snapshotDir = path.join(dir, 'snapshot') + fs.mkdirSync(snapshotDir, { recursive: true }) + const harness = ` +class Harness { + snapshotInfo = { latest: null, time: 0, list: [], clients: {} } + snapshotInfoFilePath = ${JSON.stringify(infoPath)} + snapshotDir = ${JSON.stringify(snapshotDir)} +${members} +} +globalThis.Harness = Harness +` + const context = vm.createContext({ + fs, + path, + syncLog: { warn() {}, error() {} }, + console, + global: { lx: {} }, + }) + vm.runInContext(transformSync(harness, { loader: 'ts', format: 'cjs', target: 'node20' }).code, context) + return { instance: new (context as any).Harness(), infoPath, snapshotDir } +} + +const plain = (value: T): T => JSON.parse(JSON.stringify(value)) +const md5 = 'a'.repeat(32) + +for (const rel of ['src/modules/list/snapshotDataManage.ts', 'src/modules/dislike/snapshotDataManage.ts']) { + const label = rel.includes('/list/') ? '歌单' : '不喜欢' + + test(`S6 ${label}:旧索引无 imported 字段时兼容降级`, () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-imported-')) + try { + const { instance } = build(rel, dir) + assert.equal(instance.isImported(md5), false, '32 位 md5 应视为系统快照') + assert.equal(instance.isImported('user-backup'), true, '非 md5 文件名应视为用户导入') + assert.deepEqual(plain(instance.snapshotInfo.imported), []) + } finally { fs.rmSync(dir, { recursive: true, force: true }) } + }) + + test(`S6 ${label}:来源登记幂等且落盘持久化`, () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-imported-')) + try { + const { instance, infoPath } = build(rel, dir) + instance.markImported('backup-1') + instance.markImported('backup-1') + instance.markImported('backup-2') + assert.deepEqual(plain(instance.snapshotInfo.imported), ['backup-1', 'backup-2']) + assert.deepEqual(JSON.parse(fs.readFileSync(infoPath, 'utf8')).imported, ['backup-1', 'backup-2']) + instance.unmarkImported('not-there') + assert.deepEqual(plain(instance.snapshotInfo.imported), ['backup-1', 'backup-2']) + instance.unmarkImported('backup-1') + assert.deepEqual(plain(instance.snapshotInfo.imported), ['backup-2']) + instance.markImported(md5) + assert.equal(instance.isImported(md5), true, '显式登记应优先于 md5 推断') + } finally { fs.rmSync(dir, { recursive: true, force: true }) } + }) + + test(`S6 ${label}:快照列表 origin 判定与按时间倒序`, async () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-imported-')) + try { + const { instance, snapshotDir } = build(rel, dir) + const autoFile = path.join(snapshotDir, `snapshot_${md5}`) + const importFile = path.join(snapshotDir, 'snapshot_user-backup') + fs.writeFileSync(autoFile, '{}') + fs.writeFileSync(importFile, '{}') + fs.utimesSync(importFile, new Date(1000), new Date(1000)) + fs.utimesSync(autoFile, new Date(2000), new Date(2000)) + const list = plain(await instance.getSnapshotListWithMeta()) + assert.equal(list.length, 2) + assert.equal(list[0].id, md5) + assert.equal(list[0].origin, 'auto') + assert.equal(list[1].id, 'user-backup') + assert.equal(list[1].origin, 'imported') + } finally { fs.rmSync(dir, { recursive: true, force: true }) } + }) +} + +test('S7 双实现对称性:歌单与不喜欢的 imported 语义一致', () => { + const a = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-imported-a-')) + const b = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-imported-b-')) + try { + const x = build('src/modules/list/snapshotDataManage.ts', a).instance + const y = build('src/modules/dislike/snapshotDataManage.ts', b).instance + for (const inst of [x, y]) { + inst.markImported('same') + inst.markImported('same') + inst.markImported(md5) + } + assert.deepEqual(plain(x.snapshotInfo.imported), plain(y.snapshotInfo.imported)) + assert.equal(x.isImported('same'), y.isImported('same')) + assert.equal(x.isImported(md5), y.isImported(md5)) + assert.equal(x.isImported('other'), y.isImported('other')) + for (const inst of [x, y]) inst.unmarkImported('same') + assert.deepEqual(plain(x.snapshotInfo.imported), plain(y.snapshotInfo.imported)) + } finally { + fs.rmSync(a, { recursive: true, force: true }) + fs.rmSync(b, { recursive: true, force: true }) + } +}) diff --git a/test/snapshot-rating-wiring.test.ts b/test/snapshot-rating-wiring.test.ts new file mode 100644 index 00000000..e2bcfb66 --- /dev/null +++ b/test/snapshot-rating-wiring.test.ts @@ -0,0 +1,185 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import fs from 'node:fs' +import path from 'node:path' +import vm from 'node:vm' +import { transformSync } from 'esbuild' + +/** + * 从真实源码抽出两段可独立执行的逻辑: + * 1. server.ts 顶层的备份类型判定 / playList_v2 转换(上传快照分流的核心) + * 2. /api/subsonic/sync-link 路由的业务校验与分流 + * 另外用 public/app.js 的真实判定表达式做前后端口径一致性校验,防止两类目录写串。 + */ +const serverSource = fs.readFileSync(path.resolve('src/server/server.ts'), 'utf8') +const appSource = fs.readFileSync(path.resolve('public/app.js'), 'utf8') + +const slice = (from: string, to: string): string => { + const start = serverSource.indexOf(from) + const end = serverSource.indexOf(to, start + from.length) + assert.ok(start >= 0 && end > start, `无法从 server.ts 定位 ${from} ~ ${to}`) + return serverSource.slice(start, end) +} + +const runInVm = (code: string, context: Record, exportExpr: string): T => { + const sandbox = vm.createContext({ console, ...context }) + vm.runInContext(transformSync(`${code}\nglobalThis.__export = ${exportExpr}`, { + loader: 'ts', format: 'cjs', target: 'node20', + }).code, sandbox) + return (sandbox as any).__export as T +} + +const kindBlock = slice('type SnapshotKind = ', 'async function validateOpenListConfig') +const kindApi = runInVm<{ + detectSnapshotKind: (parsed: unknown) => 'list' | 'dislike' | 'rating' + toInternalListSnapshot: (parsed: unknown) => string | null +}>(kindBlock, {}, '{ detectSnapshotKind, toInternalListSnapshot }') + +/** public/app.js 中真实的 isRatingBackup / kindLabel 判定,注入同一批样本比对 */ +const frontStart = appSource.indexOf(' const isRatingBackup = ') +const frontEnd = appSource.indexOf(' // 目标用户由超管', frontStart) +assert.ok(frontStart >= 0 && frontEnd > frontStart, '无法从 public/app.js 定位导入类型判定') +const frontKind = new Function('jsonData', `${appSource.slice(frontStart, frontEnd)}\nreturn kindLabel`) as (data: unknown) => string + +const samples: Array<{ name: string, value: unknown, kind: 'list' | 'dislike' | 'rating' }> = [ + { name: '非 JSON / 空值', value: null, kind: 'list' }, + { name: '原生歌单快照', value: { defaultList: [{ id: 'a' }], loveList: [], userList: [] }, kind: 'list' }, + { name: 'playList_v2 离线备份', value: { type: 'playList_v2', data: [{ id: 'default', list: [] }, { id: 'love', list: [] }] }, kind: 'list' }, + { name: '原生不喜欢快照', value: { dislikeList: ['a@歌手@歌曲'] }, kind: 'dislike' }, + { name: 'lxRating_v1 评分快照', value: { type: 'lxRating_v1', ratings: { a: 5 }, starredAlbums: [] }, kind: 'rating' }, + { name: '旧版评分快照(无 type)', value: { ratings: { a: 3 }, starredAlbums: [], starredArtists: [], starredArtistNames: [] }, kind: 'rating' }, + { name: 'type 优先于 dislikeList', value: { type: 'lxRating_v1', ratings: {}, dislikeList: [] }, kind: 'rating' }, + { name: '歌单字段优先于 ratings', value: { ratings: { a: 1 }, defaultList: [] }, kind: 'list' }, + { name: '空对象', value: {}, kind: 'list' }, + { name: '数组', value: [], kind: 'list' }, + { name: '字符串', value: 'not an object', kind: 'list' }, +] + +test('S19 备份类型判定:歌单 / 不喜欢 / 评分三类分流', () => { + for (const s of samples) { + assert.equal(kindApi.detectSnapshotKind(s.value), s.kind, `样本「${s.name}」应判为 ${s.kind}`) + } +}) + +test('S19 前后端导入类型判定口径一致(避免上传到错误目录)', () => { + const label: Record = { list: '我的歌单', dislike: '我不喜欢', rating: '我的评分' } + for (const s of samples) { + assert.equal(frontKind(s.value), label[kindApi.detectSnapshotKind(s.value)], `样本「${s.name}」前后端判定不一致`) + } +}) + +test('S19 playList_v2 转回内部结构:default / love / 其余列表', () => { + const converted = kindApi.toInternalListSnapshot({ + type: 'playList_v2', + data: [ + { id: 'default', list: [{ id: 'd' }] }, + { id: 'love', list: [{ id: 'l' }] }, + { id: 'custom', list: [{ id: 'c' }] }, + ], + }) + assert.ok(converted) + assert.deepEqual(JSON.parse(converted), { + defaultList: [{ id: 'd' }], + loveList: [{ id: 'l' }], + userList: [{ id: 'custom', list: [{ id: 'c' }] }], + }) +}) + +test('S19 playList_v2 转换:非该格式返回 null,残缺 data 不抛异常', () => { + assert.equal(kindApi.toInternalListSnapshot(null), null) + assert.equal(kindApi.toInternalListSnapshot({ type: 'lxRating_v1', ratings: {} }), null) + assert.equal(kindApi.toInternalListSnapshot({ type: 'playList_v2', data: 'bad' }), null) + const partial = kindApi.toInternalListSnapshot({ type: 'playList_v2', data: [null, { id: 'default', list: [] }] }) + assert.ok(partial) + assert.deepEqual(JSON.parse(partial).defaultList, []) +}) + +const syncLinkBody = slice( + ' const { user, direction } = JSON.parse(await readBody(req))', + ' } catch (err: any) {', +) + +const runSyncLink = async (options: { + body: unknown + config?: Record + users?: string[] +}): Promise<{ ok: boolean, payload?: any, error?: string }> => { + const written: string[] = [] + const res = { writeHead: () => {}, end: (text: string) => written.push(text) } + const config = { + users: (options.users ?? ['alice']).map(name => ({ name })), + ...options.config, + } + const context = { + req: {}, + global: { lx: { config } }, + readBody: async () => JSON.stringify(options.body), + syncRatingsToDislike: async (user: string) => ({ direction: 'ratingToDislike', user, scanned: 1, added: 1, skipped: 0, failed: 0, threshold: 1, batches: 1 }), + syncDislikesToRating: async (user: string) => ({ direction: 'dislikeToRating', user, scanned: 2, added: 0, skipped: 2, failed: 0, threshold: 1, batches: 1 }), + res, + } + const run = runInVm<(user?: string) => Promise>( + `async function run() {\n${syncLinkBody}\n}`, + context, + 'run', + ) + try { + await run() + return { ok: true, payload: written.length ? JSON.parse(written[0]) : null } + } catch (err: any) { + return { ok: false, error: err.message } + } +} + +test('S20 /api/subsonic/sync-link:非法 direction / 缺用户被拒绝', async () => { + const badDirection = await runSyncLink({ body: { user: 'alice', direction: 'unknown' } }) + assert.equal(badDirection.ok, false) + assert.match(badDirection.error || '', /Invalid direction/) + + const noUser = await runSyncLink({ body: { direction: 'ratingToDislike' } }) + assert.equal(noUser.ok, false) + assert.match(noUser.error || '', /Missing user/) +}) + +test('S20 /api/subsonic/sync-link:开关未开启时不得执行同步', async () => { + const result = await runSyncLink({ body: { user: 'alice', direction: 'ratingToDislike' } }) + assert.equal(result.ok, false, '服务端必须独立校验开关,不能只依赖前端') + assert.match(result.error || '', /联动开关未开启/) +}) + +test('S20 /api/subsonic/sync-link:未知用户不得创建用户空间', async () => { + const result = await runSyncLink({ + body: { user: 'mallory', direction: 'ratingToDislike' }, + config: { 'subsonic.linkRatingToDislike': true }, + }) + assert.equal(result.ok, false) + assert.match(result.error || '', /用户不存在/) +}) + +test('S20 /api/subsonic/sync-link:两个方向分别调用对应同步实现', async () => { + const forward = await runSyncLink({ + body: { user: 'alice', direction: 'ratingToDislike' }, + config: { 'subsonic.linkRatingToDislike': true }, + }) + assert.equal(forward.ok, true, forward.error) + assert.equal(forward.payload.direction, 'ratingToDislike') + assert.equal(forward.payload.added, 1) + + const backward = await runSyncLink({ + body: { user: 'bob', direction: 'dislikeToRating' }, + config: { 'subsonic.linkDislikeToRating': true }, + users: ['alice', 'bob'], + }) + assert.equal(backward.ok, true, backward.error) + assert.equal(backward.payload.direction, 'dislikeToRating') + assert.equal(backward.payload.user, 'bob') +}) + +test('S20 /api/subsonic/sync-link:_open 公开用户同样允许同步', async () => { + const result = await runSyncLink({ + body: { user: '_open', direction: 'ratingToDislike' }, + config: { 'subsonic.linkRatingToDislike': true }, + }) + assert.equal(result.ok, true, result.error) + assert.equal(result.payload.user, '_open') +}) diff --git a/test/subsonic-rating-playlists.test.ts b/test/subsonic-rating-playlists.test.ts new file mode 100644 index 00000000..d864a2c4 --- /dev/null +++ b/test/subsonic-rating-playlists.test.ts @@ -0,0 +1,150 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import fs from 'node:fs' +import path from 'node:path' +import vm from 'node:vm' +import { transformSync } from 'esbuild' + +/** 从 subsonic.ts 抽出评分歌单的两个私有方法,隔离其余依赖后放进 vm 执行 */ +const source = fs.readFileSync(path.resolve('src/server/integrations/subsonic.ts'), 'utf8') +const start = source.indexOf(' private async getRatingPlaylistSongs') +const end = source.indexOf(' private async handleGetPlaylists', start) +assert.ok(start > 0 && end > start, '无法从 subsonic.ts 中定位评分歌单方法') +const methods = source.slice(start, end) + +const harness = ` +class Harness { + onlineSongCache = new Map() + meta = { ratings: {} } + listData = { loveList: [], defaultList: [], userList: [] } + disliked = new Set() + loadOnlineSongCache() {} + async getUserSubsonicMeta() { return this.meta } + async getSubsonicListData() { return this.listData } + async filterDislikedSongs(_u, arr) { return arr.filter(m => !this.disliked.has(m.id)) } +${methods} +} +globalThis.Harness = Harness +` + +const build = (ratingPlaylists: boolean | undefined = undefined) => { + const config: Record = {} + if (ratingPlaylists !== undefined) config['subsonic.ratingPlaylists'] = ratingPlaylists + const context = vm.createContext({ + global: { lx: { config } }, + getLocalTracks: async () => [], + localMusic: (x: any) => x, + console, + }) + vm.runInContext(transformSync(harness, { loader: 'ts', format: 'cjs', target: 'node20' }).code, context) + return { instance: new (context as any).Harness(), config } +} + +const song = (id: string) => ({ id, name: id }) + +test('S5 ratings 值域:非整数 / 越界 / 字符串评分不得让 getPlaylists 抛错', async () => { + const { instance } = build() + instance.meta = { ratings: { a: 1.5, b: 2.1, c: 0, d: 6, e: -1, f: '3', g: null, h: NaN, good: 3 } } + instance.listData = { + loveList: [], + defaultList: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'good'].map(song), + userList: [], + } + const groups = await instance.getRatingPlaylistSongs('alice') + assert.equal(groups.get(3).length, 1, '只有整数 3 应进入 3 星歌单') + for (const star of [1, 2, 4, 5]) assert.equal(groups.get(star).length, 0) +}) + +test('S8 开关:默认开启,显式 false 关闭', () => { + assert.equal(build().instance.isRatingPlaylistEnabled(), true) + assert.equal(build(true).instance.isRatingPlaylistEnabled(), true) + assert.equal(build(false).instance.isRatingPlaylistEnabled(), false) +}) + +test('S8 1 星歌单 = 1 星歌曲 ∪ dislike 命中;关闭开关后不再并入', async () => { + const enabled = build(true) + enabled.instance.meta = { ratings: { a: 1 } } + enabled.instance.listData = { loveList: [], defaultList: [song('a'), song('b')], userList: [] } + enabled.instance.disliked = new Set(['b']) + const on = await enabled.instance.getRatingPlaylistSongs('alice') + assert.deepEqual(Array.from(on.get(1)).map((m: any) => m.id).sort(), ['a', 'b']) + + const disabled = build(false) + disabled.instance.meta = { ratings: { a: 1 } } + disabled.instance.listData = { loveList: [], defaultList: [song('a'), song('b')], userList: [] } + disabled.instance.disliked = new Set(['b']) + const off = await disabled.instance.getRatingPlaylistSongs('alice') + assert.deepEqual(Array.from(off.get(1)).map((m: any) => m.id), ['a']) +}) + +test('S8 只读语义与配置契约:虚拟歌单不得被写入或删除', () => { + assert.match(source, /RATING_PLAYLIST_PREFIX = 'rating_'/) + assert.match(source, /if \(this\.isRatingPlaylistEnabled\(\)\)/) + assert.match(source, /评星歌单为只读播放列表,请通过给歌曲评星来修改/) + assert.match(source, /评星歌单为只读播放列表,不支持删除/) + assert.match(source, /Rating playlists are disabled/) + assert.match(source, /linkToDislike = .*\|\| this\.isRatingPlaylistEnabled\(\)/) + const defaults = fs.readFileSync(path.resolve('src/defaultConfig.ts'), 'utf8') + assert.match(defaults, /'subsonic\.ratingPlaylists': true/) +}) + +/** 从 handleGetPlaylists 抽出「生成评星歌单」的真实代码块,验证空星级是否会被跳过 */ +const blockStart = source.indexOf(' // [新增] 评星歌单:1~5 星') +const blockEnd = source.indexOf(" if (format === 'json')", blockStart) +assert.ok(blockStart > 0 && blockEnd > blockStart, '无法从 subsonic.ts 中定位评星歌单生成块') +const ratingPlaylistBlock = source.slice(blockStart, blockEnd) + +const playlistHarness = ` +class PlaylistHarness { + constructor(groups, enabled) { + this.groups = groups + this.enabled = enabled + this.playlists = [] + } + isRatingPlaylistEnabled() { return this.enabled } + async getRatingPlaylistSongs() { return this.groups } + async run() { + const playlists = this.playlists + const buildPlaylist = (id, name, musics) => ({ id, name, songCount: musics.length }) + const username = 'alice' + const subsonicLog = { error() {} } + const SubsonicHandler = { RATING_PLAYLIST_PREFIX: 'rating_' } +${ratingPlaylistBlock} + return playlists + } +} +globalThis.PlaylistHarness = PlaylistHarness +` + +const buildPlaylists = async (counts: Record, enabled = true): Promise> => { + const groups = new Map() + for (let star = 1; star <= 5; star++) { + groups.set(star, Array.from({ length: counts[star] || 0 }, (_, i) => song(`${star}-${i}`))) + } + const context = vm.createContext({ console }) + vm.runInContext(transformSync(playlistHarness, { loader: 'ts', format: 'cjs', target: 'node20' }).code, context) + const instance = new (context as any).PlaylistHarness(groups, enabled) + // vm 里的数组来自另一个 realm,deepStrictEqual 会因原型不同而误判;先转成主 realm 的普通对象。 + return JSON.parse(JSON.stringify(await instance.run())) +} + +test('S18 空星级不生成歌单:只暴露有歌曲的星级', async () => { + const list = await buildPlaylists({ 1: 1, 3: 2 }) + assert.deepEqual(list.map(p => p.id), ['rating_1', 'rating_3']) + assert.deepEqual(list.map(p => p.songCount), [1, 2]) + assert.match(list[0].name, /我不喜欢/) +}) + +test('S18 五个星级都为空时不生成任何评星歌单', async () => { + assert.deepEqual(await buildPlaylists({}), []) +}) + +test('S18 关闭开关时不生成评星歌单', async () => { + assert.deepEqual(await buildPlaylists({ 5: 1 }, false), []) +}) + +test('S18 五个星级都有歌曲时全部保留且顺序固定', async () => { + const list = await buildPlaylists({ 1: 1, 2: 1, 3: 1, 4: 1, 5: 1 }) + assert.deepEqual(list.map(p => p.id), ['rating_1', 'rating_2', 'rating_3', 'rating_4', 'rating_5']) + assert.ok(list.every(p => p.songCount === 1)) +}) From b239c077137f3ddad710cee45c6e72915136a603 Mon Sep 17 00:00:00 2001 From: XCQ0607 Date: Tue, 10 Nov 2026 18:05:46 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(rating):=20=E7=BB=9F=E4=B8=80=20Web=20?= =?UTF-8?q?=E4=B8=8E=20Subsonic=20=E8=AF=84=E5=88=86=E5=8F=8A=E4=B8=8D?= =?UTF-8?q?=E5=96=9C=E6=AC=A2=E8=81=94=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Web 评分入口、分数标签与评分合集,完善后台评分及不喜欢筛选和详情 - 将不喜欢自动补分改为用户独立偏好,区分自动补分与后台补分来源 - 统一本地关联后的在线评分身份,迁移评分来源、历史及不喜欢原因 - 使用事务日志保障评分迁移与快照恢复一致性,并支持失败任务重试 - 将评分模块集中到 server/rating,补充回归测试、双语文档与更新截图 验证:376 项全量测试、20 项真实 HTTP 测试及 TypeScript 检查通过。 --- changelog.md | 20 +- docs/en/guide/backup-recovery.md | 14 + docs/en/guide/web-player.md | 38 ++ docs/guide/backup-recovery.md | 14 + docs/guide/web-player.md | 38 ++ md/log/2.2.0-6.png | Bin 0 -> 228358 bytes md/log/2.2.0-7.png | Bin 0 -> 139932 bytes md/log/2.2.0-8.png | Bin 0 -> 332830 bytes md/log/2.2.0-9.png | Bin 0 -> 92688 bytes public/app.js | 396 +++++++++++++++++- public/index.html | 155 ++++--- public/music/app.js | 64 ++- public/music/css/rating.css | 188 +++++++++ public/music/index.html | 21 + public/music/js/library/dislike_manager.js | 38 +- .../music/js/library/leaderboard_manager.js | 5 +- public/music/js/library/rating_manager.js | 375 +++++++++++++++++ public/music/js/library/songlist_manager.js | 9 +- public/music/js/local/customDir.js | 10 +- public/music/js/local/local_music.js | 12 +- public/music/js/ui/theme_manager.js | 1 + public/style.css | 259 ++++++++++++ scripts/sdk-interface-audit.mjs | 99 ----- src/defaultConfig.ts | 3 +- src/modules/dislike/dislikeDataManage.ts | 89 ++-- src/modules/dislike/match.ts | 40 +- src/modules/dislike/utils.ts | 7 + src/server/integrations/subsonic.ts | 368 ++++++++-------- src/server/music/customMusicManager.ts | 6 +- src/server/music/fileCache.ts | 7 +- src/server/music/subsonicLocal.ts | 33 +- src/server/rating/README.md | 16 + src/server/rating/ratingIdentityLock.ts | 10 + src/server/rating/ratingMigration.ts | 92 ++++ src/server/rating/ratingPreferences.ts | 19 + src/server/rating/ratingService.ts | 262 ++++++++++++ src/server/{ => rating}/ratingSnapshot.ts | 106 ++++- src/server/rating/ratingValidation.ts | 16 + src/server/server.ts | 145 +++++-- src/server/utils/dislikeCache.ts | 10 +- src/types/config.d.ts | 11 +- src/types/dislike_list.d.ts | 6 + src/utils/backupPolicy.ts | 4 +- test/admin-dislike-view.test.cjs | 61 +++ test/backup-policy.test.ts | 6 + test/dislike-enrichment.test.ts | 50 +++ test/integration/web-rating-live.cjs | 65 +++ test/rating-dialog-select.test.cjs | 13 + test/rating-feature-coverage.test.ts | 181 ++++++++ test/rating-link-policy.test.ts | 121 ++++++ test/rating-migration.test.ts | 54 +++ test/rating-preferences.test.ts | 25 ++ test/rating-recommendation-switch.test.ts | 16 + test/rating-snapshot.test.ts | 86 +++- test/snapshot-rating-wiring.test.ts | 2 +- test/subsonic-rating-playlists.test.ts | 26 +- test/web-rating-controls.test.cjs | 34 ++ test/web-rating-service.test.ts | 172 ++++++++ 58 files changed, 3417 insertions(+), 501 deletions(-) create mode 100644 md/log/2.2.0-6.png create mode 100644 md/log/2.2.0-7.png create mode 100644 md/log/2.2.0-8.png create mode 100644 md/log/2.2.0-9.png create mode 100644 public/music/css/rating.css create mode 100644 public/music/js/library/rating_manager.js delete mode 100644 scripts/sdk-interface-audit.mjs create mode 100644 src/server/rating/README.md create mode 100644 src/server/rating/ratingIdentityLock.ts create mode 100644 src/server/rating/ratingMigration.ts create mode 100644 src/server/rating/ratingPreferences.ts create mode 100644 src/server/rating/ratingService.ts rename src/server/{ => rating}/ratingSnapshot.ts (53%) create mode 100644 src/server/rating/ratingValidation.ts create mode 100644 test/admin-dislike-view.test.cjs create mode 100644 test/dislike-enrichment.test.ts create mode 100644 test/integration/web-rating-live.cjs create mode 100644 test/rating-dialog-select.test.cjs create mode 100644 test/rating-feature-coverage.test.ts create mode 100644 test/rating-link-policy.test.ts create mode 100644 test/rating-migration.test.ts create mode 100644 test/rating-preferences.test.ts create mode 100644 test/rating-recommendation-switch.test.ts create mode 100644 test/web-rating-controls.test.cjs create mode 100644 test/web-rating-service.test.ts diff --git a/changelog.md b/changelog.md index 87d15cdd..b68e61b8 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,19 @@ # Changelog -## v2.2.0 (2026-11-7) +## v2.2.0 (2026-11-10) ### 🌟 新增功能与体验升级 +- **Subsonic 评分歌单与联动补数据 (#508 @pyss56)**:新增按 1–5 星汇总的虚拟评分歌单,1 星歌单包含命中不喜欢规则的歌曲,空星级不生成歌单;接入评分快照创建、导出与恢复,并在后台提供目标用户选择和两个方向的手动联动补数据入口。 +- **快照导入与恢复完善 (#508 @pyss56)**:歌单及不喜欢快照区分导入与系统生成来源,支持按来源筛选,避免导入记录参与系统快照自动清理;恢复前先保存当前状态。 +- **Web 播放器歌曲评分**:播放器、歌曲列表、歌单、排行榜及本地音乐支持 1–5 星评分与清除,「我的评分」集中查看、筛选及导出;与 Subsonic 共用评分数据,独立保存到评分目录,不写入歌单。本地歌曲关联在线版后,在线已有评分优先,否则迁移本地评分、来源与历史,并删除本地重复记录。 + - ![Web 播放器歌曲评分与我的评分](md/log/2.2.0-6.png) +- **后台评分与不喜欢数据查看**:按用户查看歌曲、歌手、专辑的评分与不喜欢记录,展示封面、音乐平台、添加或评分来源及详细资料;支持组合筛选、排序、分页和导出筛选结果。 + - ![后台查看用户评分数据](md/log/2.2.0-7.png) +- **Subsonic 缓存优先时优先使用 OpenList**:后台新增「缓存优先时优先使用 OpenList」设置,可在缓存优先播放流程中优先尝试该用户可用的 OpenList 播放来源。 + - ![后台缓存优先时优先使用 OpenList 设置](md/log/2.2.0-8.png) +- **Web 不喜欢自动补分设置**:在 Web 设置中为当前账号单独开启或关闭「不喜欢自动补分」,默认关闭;将歌曲加入不喜欢时,仅为未评分歌曲补 1 星,已有评分不覆盖。设置保存到服务器,同一账号跨设备生效,后台手动补分独立执行。 + - ![Web 设置中的不喜欢自动补分](md/log/2.2.0-9.png) - **聚合搜索关键词联想**:并发获取多源联想,快源先展示,合并重复词并优先展示多源共同推荐内容;增加短期缓存、超时与中文输入法处理,切换输入或正式搜索时取消旧联想,支持方向键选词和回车搜索,保留聚合音源选择。 - **歌曲搜索分批加载与聚合排序**:各音源先请求一页并按歌名相关性及原始排名交错展示,保留按设置数量的本地分页,翻到未加载页面时自动取下一批,也可点击常驻「加载更多」按钮;独立记录各源页码、结束与失败状态,避免深页翻唱因歌手名字较短挤到前列,修复跨源 ID 碰撞,并保留手动追加前的页码、结果顺序与滚动位置。 - **内置音乐 SDK 接口更新**:同步 QQ 签名搜索、推荐歌单、歌手与歌单详情及 QRC 逐字歌词,更新酷我歌词、网易歌手和咪咕封面接口,补齐酷狗分享歌单解析;保留被替换的旧实现为注释,修复歌词时间精度、分页与取消请求问题。 @@ -21,6 +31,12 @@ ### 🐛 缺陷修复与体验优化 +- **评分模块归类与迁移边界修复**:评分服务、偏好、快照、校验、身份锁及事务迁移集中到 `src/server/rating/`;修复无评分用户的关联整理、仅评分事务覆盖未保存不喜欢数据的问题,并在不喜欢数据初始化时恢复遗留事务。 + +- **评分迁移与恢复一致性修复**:本地关联在线歌曲时同步迁移不喜欢原因中的评分 ID;评分、歌曲资料与相关不喜欢快照通过事务日志提交,写入失败可回滚,中断后可恢复。旧评分快照恢复时直接整理关联身份,保留手动不喜欢原因与历史快照。 + +- 修复不喜欢规则括号空格重复、同身份资料补全及跨来源隔离;记录评分与不喜欢来源,手动同步增加候选预览、资料补全统计及未解析失败计数。 +- 修复 Subsonic 评分歌单显示与自动联动开关耦合,补齐评分歌单配置和评分快照备份分类;恢复评分时保留收藏,缓存淘汰后尝试重新解析评分歌曲,并提示评分已保存但联动失败的情况。 - **酷狗码导入修复 (#483)**:完善酷狗分享歌单的链接解析与歌曲列表获取,修复部分歌单导入失败的问题。 - **备份记录详情面板优化**:加宽桌面详情弹窗,分开展示标题与文件名,优化表格间距及长路径、SHA-256 和元数据换行,避免内容撑出面板或挤压关闭按钮,并适配移动端宽度。 - **列表长文本滚动优化**:Web 播放器及后台多类列表中,超出宽度的文件名、歌曲名、歌单名等文字在桌面端悬停时滚动,移开后恢复开头;移动端保持自动滚动,完整显示的文字保持静止。 @@ -228,7 +244,7 @@ - **Media Session 媒体会话控制、封面渲染与播放恢复稳定性提升 (#432 @pokemonred06-creator)**: - **播放控制与指令幂等执行**: 修复系统媒体控制栏(Media Session)的播放/暂停指令未比对当前播放状态导致的逻辑反转问题,确保系统与锁屏快捷指令严格幂等。 - **意外暂停后的错误恢复守护**: 保留系统意外打断(如来电、系统音频中断)时的错误恢复监听,确保用户在恢复播放时重新挂载错误恢复能力,避免状态丢失。 - - **Media Session 封面与车载渲染规范化**: 通过内建下载代理中转跨![1791824601110](image/changelog/1791824601110.png)![1791824602639](image/changelog/1791824602639.png)域封面,避免 Canvas 污染与跨域访问失败;统一在离屏 Canvas 居中缩放为标准 512×512 JPEG 位图(失败时优雅回退),防止尺寸或格式不符导致蓝牙车机或锁屏黑屏;增加版本锁与内存缓存,杜绝切歌时旧封面异步覆盖新歌曲,并补充专辑名 (`song.meta.albumName`) 读取。 + - **Media Session 封面与车载渲染规范化**: 通过内建下载代理中转跨域封面,避免 Canvas 污染与跨域访问失败;统一在离屏 Canvas 居中缩放为标准 512×512 JPEG 位图(失败时优雅回退),防止尺寸或格式不符导致蓝牙车机或锁屏黑屏;增加版本锁与内存缓存,杜绝切歌时旧封面异步覆盖新歌曲,并补充专辑名 (`song.meta.albumName`) 读取。 - **iOS 后台保活桥接重连与打断恢复**: 在音频图重建(如调节均衡器/音效)时自动重新连接 MediaStreamDestination,避免桥接断开或静音;优化切回前台(`visibilitychange`)时的 AudioContext 状态恢复;捕获并容忍自动播放限制(`NotAllowedError`),保留锚点以便后续用户手势重试。 - **服务端缓存音频流 Range 请求与连接管理优化**: 严格限制只读取缓存目录内合法普通文件,增强路径遍历安全校验;补齐 HEAD 请求支持;完整支持不区分大小写的 `bytes=` 范围头、后缀范围(如 `bytes=-500`)及单边范围,对超出文件大小的请求规范返回 `416 Range Not Satisfiable`;并在客户端断开或读取出错时及时销毁读取流并释放文件描述符。 diff --git a/docs/en/guide/backup-recovery.md b/docs/en/guide/backup-recovery.md index 304cdda7..fe1180ba 100644 --- a/docs/en/guide/backup-recovery.md +++ b/docs/en/guide/backup-recovery.md @@ -162,3 +162,17 @@ Content verification is a separate historical result, not a real-time guarantee. In records, choose Check files, select local, cloud or both, and selected records, current filtered results or all records for this connection. Checks cover primary record files; use content verification for attachments. Historical objects are excluded. Checks inspect existence, size and modification time without uploading, downloading bodies, deleting files or producing SHA-256 results. Cloud requests run sequentially and can be stopped while preserving completed observations. Advanced filters show checked X/Y records and the newest check time for the matching scope; hover for the oldest timestamp. This does not imply every file was checked successfully in one run. Details show per-file timestamps. Listing records refreshes local metadata; manual local check times are retained separately. Cloud observations persist by connection and backup version across restarts. Interrupted jobs must be restarted. + +### Subsonic ratings and snapshots + +The rating-playlist switch controls virtual playlist visibility only. Each link switch controls its own direction; a zero threshold disables linking. Links only fill missing data: raising or clearing a rating preserves dislike rules, removing a dislike preserves ratings, and existing ratings are never overwritten. The one-star playlist also includes disliked tracks while preserving their actual ratings. + +Restoring a rating snapshot replaces ratings only and preserves current artist and album favorites, including when reading legacy snapshots. Rating snapshots and their index belong to the snapshots backup scope; the current subsonic-meta.json belongs to user data. Select both scopes for a complete backup. If ratings are saved but dislike resolution or writing fails, the client receives a partial-success error and can retry or use manual synchronization. The two stores are not a cross-file transaction. Evicted rated tracks are resolved again when possible; unavailable sources retain their ratings but may temporarily prevent playlist display. + +New dislike rules are deduplicated and matched by source; rules without a source explicitly apply to all sources. Duplicate records with matching source and non-conflicting song identity fill missing fields while preserving valid data and display names. Dislikes record provenance and enrichedBy; rating provenance is stored in ratingOrigins. Manual linking previews candidates including the online cache, counts unresolved targets as failures, and reports enrichment separately. + +Configuration changes do not reconcile historical data. Raising the threshold allows manual linking to add newly qualifying rules. Lowering it, setting it to zero, disabling linking, or clearing ratings does not remove existing rules. Matching and visibility settings only change subsequent filtering and display. Automatic Web-to-rating linking applies only to individual songs with a source and song ID; artist and album dislikes are not written as song ratings. + +The admin Data view includes a Dislikes tab for the selected user, combining dislike rules and disliked artist/album libraries. Filter by type, creation channel, platform, or keyword; inspect saved covers, rules, ratings, and complete fields. Missing provenance is explicitly shown as unrecorded rather than inferred. The view is read-only and does not change linking or ratings. + +Rating identity migration and restore use a transaction journal: write failures roll back, and the next rating access completes an interrupted commit. Restore normalizes local/online scores against current file links and updates rating IDs in dislike reasons while preserving manual reasons and older snapshots. The temporary journal is stored in each user’s `rating/transaction.json` and removed after completion. Multiple server processes must not write to the same data directory concurrently. diff --git a/docs/en/guide/web-player.md b/docs/en/guide/web-player.md index 8def8635..f040bce6 100644 --- a/docs/en/guide/web-player.md +++ b/docs/en/guide/web-player.md @@ -159,3 +159,41 @@ Favorite artists/albums and dislike rules are stored separately. Subsonic can hi Server downloads, sync-download and matching run in the backend; browser downloads run on the visiting device. Closing the page does not cancel submitted server work. Inspect task status and use its stop/cancel action rather than refreshing to stop it. See [operations](./operations.md) for diagnosis and [API reference](../api/reference.md) for fields. + +### Song ratings + +After signing in to a local account, rate songs from 1 to 5 stars or clear ratings using the player, song menus, artist detail, charts, local music, and custom directories. Favorites → My ratings provides a searchable rating collection. + +Web and Subsonic share per-user `ratings` and `ratingOrigins` in `subsonic-meta.json`. Rating snapshots live in `rating/snapshot/`; `rating/songs.json` stores essential Web-submitted song descriptions without playback URLs or authentication parameters. Ratings do not modify playlists or audio tags. Current ratings and song descriptions belong to the user-data backup scope; snapshots belong to the snapshots scope. + +Online songs use source-specific IDs, preferring QQ song mids. Unlinked local files use stable registry IDs shared by Web and Subsonic. Once linked, the online ID becomes authoritative: reads and writes share the online version and other linked copies. If the online version already has a rating, it wins and the local score record is deleted. Otherwise the local score, origin and history move to the online ID, and the local entry is deleted. Relinking selects the new online ID; titles are never used to merge ratings. Files recognized as new after importing, rebuilding, or moving are not automatically matched to old ratings by name. + +Low ratings only add dislike rules when linking and the threshold allow it. Raising or clearing ratings does not delete dislike rules. Direct Web ratings record `web`; Web rating-to-dislike linking records `web-rating-link`; direct Subsonic ratings record `subsonic`. Partial snapshot/link failures are reported after the rating is saved. Lists load ratings in batches and refresh periodically or when returning to the page. + + +### Rating identity, reconciliation and backups + +Unlinked local songs use local IDs. Linking keeps an existing online score or migrates the local score when the online version is unrated, then removes the local score record. The dialog shows the target ID and linked copy count; Admin Data View no longer has rating status labels or filters. + +The two supplement actions remain additive. Saving settings does not delete historical rules. To apply a changed threshold, select the user and choose Recalculate by threshold, preview the changes, then execute. Only invalid reasons traceable to a specific rating ID are removed. Rules with manual or other valid reasons remain; historical rules without precise provenance are preserved. Disabling linking does not trigger cleanup. + +My ratings → Export rating backup includes scores, origins, song descriptions and local link references, without audio files. New rating snapshots also contain descriptions. Importing/restoring a rating backup in the admin interface restores scores and available descriptions while preserving current favorites and file links. Link references are for comparison: backup paths never locate or move files or revert associations. A score-only backup cannot recreate missing covers or titles. + +Recommendation exclusion uses the same policy for daily, random and similar tracks: matching dislike rules and scores at or below the threshold are excluded. This is independent of ordinary list hiding and automatic linking. + +Admin rating and dislike dashboards support platform, action origin, cover availability, record age, combined keywords and score filters. Platform options show user totals, including zero-count platforms. Click the score distribution to filter, change page size, inspect records or export the current selection. Rating statistics follow platform, origin, age and keyword filters; type and score further narrow the list. + +### Per-user dislike auto-rating + +Settings → Logic → Dislike auto-rating is saved to the current account on the server and defaults to off. Adding a Web song dislike supplements 1 star only when unrated; existing ratings remain. Other users and the low-score threshold do not control this preference. The global reverse-link switch has been removed. Admin backfill is an independent, previewable operation and works with auto-rating off or threshold zero. Sources are labeled Web manual rating, Subsonic manual rating, Dislike automatic rating, and Admin backfill. The preference is stored in each user’s `rating/preferences.json`; score backup restore does not change this preference. + +Playlist detail supports direct rating. Open rating collections refresh periodically, on returning to the page and after local rating/dislike actions, preserving filters and list scroll. Each entity retains up to 30 recent score changes, including clearing, backfill and restore; identical submissions keep origin timestamps. Old history is not fabricated. Failed auto-rating reports partial completion while retaining the dislike. Recoverable restore write errors roll back files; this does not guarantee cross-file atomicity during process termination or power loss. + + +### Metadata repair and synchronization status + +Identical scores keep their origin and timestamp while allowing available metadata to be repaired. Direct ratings and automatic/admin backfill share one write service; backfill only supplements missing scores. Resolved Subsonic metadata is stored in the user's `rating/songs.json`, reducing dependence on runtime caches. Favorite operations retain rating origins and history. + +My ratings and admin Ratings show pending work with Retry failed items. The user's `rating/sync-status.json` tracks backfill writes, catalog writes, unresolved metadata and snapshot failures. Retries preserve newer scores; metadata resolution still depends on provider availability. Corrupt primary rating files block writes and exports without replacing the original. Corrupt status files request manual inspection instead of being cleared. + +Admin previews separate additions, already-rated skips, duplicate linked identities and resolution failures. Saved scores with failed snapshots report partial completion. Version checks avoid unnecessary full refreshes. The Web collection average follows the current selection; the distribution follows the other filters, so users can switch score levels. diff --git a/docs/guide/backup-recovery.md b/docs/guide/backup-recovery.md index 2fd40cec..c238184a 100644 --- a/docs/guide/backup-recovery.md +++ b/docs/guide/backup-recovery.md @@ -162,3 +162,17 @@ ZIP 默认最多保留 5 份,保留天数默认 0(不限天数)。成功 在记录页点击“检查文件”,选择本地、云端或两者,以及已选记录、当前筛选结果或当前连接的全部记录。范围只包括记录主文件;绑定附件请使用内容校验入口,历史版本对象不在本次范围。检查存在性、大小、修改时间,不上传、不下载正文、不删除文件,不会生成 SHA-256 内容校验结果。云端逐项请求元信息,允许停止;已完成结果保留。 高级筛选显示当前匹配范围内“已检查 X/Y 项”和最近检查时间,悬停可看最早检查时间;这不是整轮全部成功的证明。每个文件详情有准确时间。本地时间随刷新记录重新检查,手动检查时间另外保留;云端结果按连接与备份版本保存,服务重启后仍可查看。后台检查不保证所有文件同时检查,进程中断的任务需重新启动。 + +### Subsonic 评分与快照 + +评分歌单开关仅控制虚拟歌单显示,不启用自动联动。两个联动开关独立控制方向,阈值为 0 时停止联动;联动只补缺失数据,提高或清除评分不删除不喜欢规则,取消不喜欢不删除评分,也不覆盖已有评分。1 星歌单并入不喜欢命中歌曲,保留已有真实评分。 + +评分快照恢复只替换评分,保留当前歌手和专辑收藏,兼容旧快照格式。评分快照及索引属于备份的「快照」范围;当前 subsonic-meta.json 属于「用户数据」,完整备份请同时选择两项。评分成功但不喜欢解析或写入失败会返回部分成功提示,可重试或手动补同步;两个存储不构成跨文件事务。缓存淘汰的已评分歌曲会尝试重新解析,源不可用时保留评分但暂时无法展示歌曲。 + +新不喜欢规则按来源去重和匹配;未指定来源时显式作用于全部来源。相同来源、歌曲身份不冲突的重复记录会补齐缺失字段,保留已有有效资料和原始显示名称。新不喜欢记录含 provenance,补全记录含 enrichedBy;评分来源存于 subsonic-meta.json 的 ratingOrigins。手动补同步先预览候选(包含在线缓存),执行时空解析计入失败,资料补全数单独报告。 + +配置变化不会重算历史数据。提高低分阈值后,手动补齐可增加符合条件的规则;降低阈值、设为0、关闭联动或清除评分不会撤销旧规则。匹配和显示选项仅改变后续过滤/展示结果。Web反向自动补1星仅限带来源和歌曲ID的单首歌曲,歌手和专辑不喜欢不会被误写成歌曲评分。 + +后台「数据查看 → 不喜欢」按所选用户合并不喜欢规则与不喜欢歌手/专辑库。可筛选类型、添加来源和音乐平台,预览已保存封面、查看规则及完整字段。没有来源记录时显示「来源未记录」,不会推断其来自Web或Subsonic;该页只读,不修改联动或评分。 + +评分身份迁移与恢复使用事务日志:写入失败回滚,进程中断后在下次评分访问时完成提交。恢复时按当前文件关联整理本地与在线评分,并同步不喜欢原因中的评分 ID,保留手动原因与旧快照。事务日志临时保存于用户 `rating/transaction.json`,完成后移除;不要让多个服务器进程同时写入同一数据目录。 diff --git a/docs/guide/web-player.md b/docs/guide/web-player.md index a485366e..c75871a8 100644 --- a/docs/guide/web-player.md +++ b/docs/guide/web-player.md @@ -174,3 +174,41 @@ Chromecast 支持具备 Cast 能力的桌面/Android Chromium 浏览器,需要 服务端下载、同步下载和自动匹配由后台执行;浏览器下载由访问设备执行。关闭页面不会自动取消已经提交的服务端任务。查看任务状态并使用对应的停止/取消入口,不要依靠刷新页面终止操作。 更多诊断步骤见 [运行维护](./operations.md),接口字段见 [API 参考](../api/reference.md)。 + +### 歌曲评分 + +登录本地账号后,可在底部播放器、歌曲列表更多菜单、歌手详情、排行榜、本地音乐与自定义目录给歌曲设置1至5星,或清除评分。「我的收藏 → 我的评分」支持搜索和修改评分。 + +Web 与 Subsonic 共用用户的 `subsonic-meta.json` 中的 `ratings` 和 `ratingOrigins`;`rating/snapshot/` 保存评分快照,`rating/songs.json` 保存 Web 提交的必要歌曲资料。评分不修改实体歌单、不写入音频标签;歌曲资料不持久化播放URL或鉴权参数。当前评分及歌曲资料属于用户数据备份,评分快照属于快照备份。 + +在线歌曲按来源及平台歌曲ID区分,QQ优先使用歌曲mid。本地歌曲未关联时按用户本地曲库注册ID评分,Web与Subsonic共用。关联在线歌曲后,以在线ID的评分为准,与在线版本及其他关联副本共用读写;在线歌曲已有评分时保留在线评分并删除本地评分记录;仅本地有评分时,将分数、来源与历史迁移到在线ID,并删除本地条目。重新关联时切换到新的在线ID,不按歌名合并。另行导入、重建或移动后被曲库识别为新文件时,不自动猜测和合并历史评分。 + +低分是否补不喜欢仍受评分联动开关和阈值控制;提高或清除评分不会删除不喜欢规则。Web直接评分来源为 `web`,其不喜欢联动来源为 `web-rating-link`;Subsonic直接评分来源为 `subsonic`。评分已保存但快照或联动失败时会明确提示。列表评分批量读取,其他客户端的修改会在页面恢复可见或周期刷新后更新。 + + +### 评分归属、重算与备份 + +未关联的本地歌曲使用本地ID评分;关联后使用在线ID评分,在线已有评分则优先使用在线评分,否则迁移本地评分,随后删除本地评分记录。评分弹窗可查看目标ID与关联副本数,管理端不再区分评分使用状态。 + +「低分补不喜欢」「不喜欢补1星」仍只补充数据。配置保存后不会自动删除历史规则;需要按新阈值处理时,选择用户后点击「按阈值重算」,先查看预览再执行。重算仅撤销能追溯到具体评分ID的失效联动原因;同一条规则仍有手动或其他有效原因时保留。缺乏精确来源的历史规则保留,不猜测删除。关闭联动不触发清理。 + +「我的评分 → 导出评分备份」包含分数、来源、歌曲描述及本地关联参照,不包含音频。新生成的评分快照也包含描述;在管理端按评分备份导入/恢复时,恢复分数和可用描述、保留当前收藏与文件关联。关联参照用于核对,不按备份中的路径寻找、移动文件或恢复旧关联。只有旧分数而没有描述的备份无法凭空补出封面和标题。 + +推荐排除开关对每日推荐、随机及相似歌曲使用统一策略,同时排除规则命中项与阈值内低分;与普通列表隐藏、自动联动开关独立。 + +管理端数据查看的评分与不喜欢看板支持按音乐平台、操作来源、封面、记录时间、组合关键词及评分筛选;平台选项显示用户总条数,包含0条平台。可点击星级分布筛选、调整每页条数、查看记录详情并导出当前筛选结果。统计按当前平台、来源、时间及关键词条件汇总;评分类型与星级用于进一步限定列表。 + +### 用户独立的不喜欢自动补分 + +「设置 → 逻辑 → 不喜欢自动补分」按当前账号保存到服务器,默认关闭;Web 将单首歌曲加入不喜欢时,仅为未评分歌曲补1星。已有评分不覆盖,取消不喜欢或关闭设置不删除评分。用户之间独立,低分阈值不控制该设置。原全局反向联动开关已移除。「后台补分」是管理员独立操作,先预览再执行,不受用户自动开关或低分阈值为0影响。来源分别显示 Web手动评分、Subsonic手动评分、不喜欢自动补分、后台补分。偏好保存在用户目录的 `rating/preferences.json`;评分备份恢复不更改此偏好。 + +歌单详情支持直接评分。评分合集打开时随周期刷新、返回页面及本端评分/不喜欢操作更新,并保留筛选和列表滚动位置。每个对象保留最近30条分数变更(含清除、补分和恢复),同分重复提交不刷新来源时间;旧数据不补造历史。自动补分失败会提示部分完成,已保存的不喜欢保留。评分恢复发生可捕获的写盘错误时回滚文件;此机制不保证进程突然退出或断电时的跨文件原子性。 + + +### 资料修复与同步状态 + +同分提交不会改写评分来源和时间,但会补齐可用歌曲资料。直接评分、用户自动补分与后台补分共用评分写入服务;补分只补未评分项。Subsonic 已解析资料保存到用户的 `rating/songs.json`,避免展示长期依赖运行缓存。收藏操作保留评分来源和历史。 + +「我的评分」及管理端评分区域可查看待处理项并选择“仅重试失败项”。状态保存在用户 `rating/sync-status.json`,包括补分写入、描述保存、资料未解析和快照失败;重试不会覆盖新评分。资料解析仍受平台可用性影响,失败项会保留。主评分文件损坏时停止写入和导出,保留原文件;状态文件损坏会显示人工检查提示,不自动清空。 + +后台补分预览分别列出待新增、已有评分跳过、重复关联及解析失败;评分已落盘但快照失败时,明确提示部分完成。评分数据提供版本查询,版本不变时避免重复全量刷新;Web 评分合集的平均分按当前筛选结果计算,星级分布按其余筛选条件计算,供切换星级使用。 diff --git a/md/log/2.2.0-6.png b/md/log/2.2.0-6.png new file mode 100644 index 0000000000000000000000000000000000000000..e419eeb4c90735f9297ddc3dc22a01ab899955d5 GIT binary patch literal 228358 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

)%9OM^%Zo^RP3E=!1JD%WRr6Uo8V$Pd)Bh`L` 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

R52PK2;7{lQ>HhDSfAb)8A# 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%0AV4_SnsZPBfE~@JUvKFDJGo>je;j8&25|nQpl?o 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 LB~>D+@B9A%RPud5 literal 0 HcmV?d00001 diff --git a/md/log/2.2.0-7.png b/md/log/2.2.0-7.png new file mode 100644 index 0000000000000000000000000000000000000000..d0552b6a14a81f4266161b2ca8adab61e6c9b0da GIT binary patch literal 139932 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 literal 0 HcmV?d00001 diff --git a/md/log/2.2.0-8.png b/md/log/2.2.0-8.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff00c73795203ede52f574b79674558d727276f GIT binary patch literal 332830 zcmZs?1z1$w+CNN42t!E@EvSTailn3pN)FvfcXvxjqaa91cL_>&3epnN-3*<>%=|a{ zc%Ji~@4MD@O>Bl8EAC(1_j;%FS`H6~5(fnZ1@FakX%!TdySpeTXdT#Sz>xuP^au(H zA<7HsXKEg(d+AsKrjYoH66h}Uoq}QLcP@q3ASul6@0|&;Fdwq8Hg52jeJQcl?97Iy zOs1Vsijh`7r%*_id2sioS>Lmcwfe=1Vrb(*%SD5?S2EP7LrAY+s1*TWntN()=iVx1 z{cV@FH!8D9<9$M4LSPv`dLz{HM`iqYSn7{yyS1q095XvXtBu3>>d;soFt^pYTaH;Q zg{XJqXx3&Fg{XPsD0{=H?2o_8k(Tv_0 z3Q^y#Ez5FLUg{qdRq#`y*_`-K_zJOee)$7z<0fX&)V$7bq)dj~s%1=uz(PHzh1}J0 z(doQaHV~5`8q+n*T?LgFV2@((bNII|P$8!_L`^|D!;D>D6J*;Ms_^$}e{SL5*Ggq@ z_~KUqv+$pSru0BFwEiLCC2SYnn3BQr`@rV{ki+93Ytah zvZB|E?~hl=7~{31pHRq7 zNsvb2B*=FWmkEhrh|VXk=fN6yYzYAY4_MG&fuGC%KI83K|En$XEVUY(vGd8~fpURn z;|6|?`x5;8pSINtI?Qnl51$wPS#^i2|1*Rl9_4&5l;d9& z-9sHUC(?4HwmFVxw@dp-*wnCOFn|m>h)tk*BS%diPs`0g9=}0Rm7RZwCJ4g=Cxzp= zqOaq_KeuuFxYKMrab)rT%*8mK%5I=XM`u<(rjw=pKFHMues153`r3g~%+yeRSV9{) znSyF3=}~iL!5}?Jyt*hSAfwRGo~WjR`K<^v?LTaUGz}9y-3YLy5v^cqdI3D?e>I!$ z;OEwgzx%-BDbErenB6AUeMg^*^RM;|?GH0w0GA8_brBR!Ai1Q|ih1CXFus<8mN3uY^YC2YZ#|$xIHeZT z7(-m&;%QvL81LDi9+~dvja!J(xxy^ymH#tR?C9OT z!Ty|EM7=1cAQU3Y=rHLZEP6bf(C%^VRo_g?*MfClUL~GZ&N^VONHQbFV@D>CBaF$2 z317-Z_uT*7OF8K9AYNy-$z&v4S(uK;=%Siw-x(FH?JWsx$^=zsO0}Ti-!b_!4Jj@` zhs#O|?_K`R+lS~)H1Rm`hW~tT`}Q%g&R#S2JeSYd$}TBgh2QL@S<1DTj(U<0Ke;aZ zaN*hBHJ=%b!gb$~s7(>w*gr!)scda|+~mIp@%A&w26L=J2|abu*8KD|mjzu%2Xk!J z(Rz0DROHX#DLzC;U{!sg-AAur>S-;riAZ({-kptC>u(eI5Lkyh>+nxbRJz_>1D{yZOJT zmk1ts8dRWQ-#h4_I`;n0NN0Qmb(xoz@7ur83O0dVevJt(_Cf4fB z!FN~Zq7KNUW+-HpDT<)_r(SRa{*%+sS)HLD6#_QJ4$|yaJE^=@*4`m+I5~x(Ys8&< zGQ0;X)kA6g?rz{}hgv;OpV?IWr#B7Oh5Pgfp21PyrYrkckYZy0B+)zil!8exYM#_iWITAtUPxl+pn4} z;qaMfDG)Eo$(e+P+_zk1ijfPJnvQ>=`l!9qm(yb#qqCNZ)@Q3|+|6&DO5eL5Jp710 zIeNs0Zun|a)M(h*-KR&s-!ar>y9nmma=q4G@x*9^cf&0~B!DYu`%ARJ%KHc)tp4A& z`@Jmyd0dlm^+EVINc=_)6W+M%KZ_safO#4J>n-cKBPV-Dngww&$;6y7<~I{n*CwN; zvxqDS)RCQFHU0-GrfOqmg&RGH ztkPj6a57csB5#VuB=UKCM_``XWFfHhL%xF8(n#=y=n}XOHH^A$7y+Yk*m{Ob#vUak zEG%3cOWI%@|<2t z^JIgc#NGGmXta$nU0q+L3axgHXShzD43{i0xZ}~P4Gle9w;UE)eOLicGSBqvIb80n z>(_IFIuAE4`Aq&ue1Og|?Rwt~f-ko6sWXfqli&Vz;vG8gv7;_VUG!F{IKsBMLzKCl zz2l;`Ggj2GrlN=C>VCZkRlHOCEF2 zxT9QXg*IpaWXDo!Kuj=7sT#fLV3X6WJLnr-@FjHQjDn4fq@gwylPu-IE$`U<9&qhH zxjfw2ofz?nA)iVUSG6nPxs)|VB%eoobjM0ayX7qZn#4f=`eTF_{7mEK^vkS${eJ%d zhxZL#EW}*5+G}u7@FsEKr;PWW`f+Q+F}Zl-O+U?}D1W=zhjw7qppW7w^Uj&gQ{_6s zZ>HmR4B#J=sn)mpCfKHGV?}Pbro!42yt*S24Uj7u9EfW{B%-#pOuPQeTFKI-s^Ws@ zb`@~IvB zH6dhiNIx-MYbS+s9M?&ZDr$ZnJ+)YQIyUf`4Ek-iRrj)jiPKM=uHoK7oF3W!Q*%Vq zF4Ad#!v9h=nDoBhu+YI?PK@k78cze zdBoO!Z_M`A*0gPfX!|~o@8plI#tYtas%H4sqTbmq5V~V&1Y-^egrjDS_>zi>z4vQ} zA1@xxtY*3%FZWV^9Y!6d&-m)N`owi+NKY^Qb`9Q4>~#`|o}LUOm1{Mp1TbalA|{4? z-(jJK-CS?BHf^!nSM(FK_;R;T8F=d@-tph&&E#zK*%C!MPYnBCrC0b9(`va*%|HHF zae2cehSB4?pILFW?A`)fA0|5*#T{I~;KdhP8k#-09GYsebWdi`U0?9+O~-YgwGHNQ ze1Ybv^VN90!tWe66z`W^mz&7JV|`?bWwqJO6@kAGtQFp?V}O)hTcx`^1a7m*Yl8Lt zVP9vosPV?i?vnBT;%4;g{wMl0Ym z4Xnltj~hn_jkwWG*LPxI{h=+`b%o3OyL?|yy5TF~hnqgo2tMqlYG`RAef*Kr|M+`@ z={~>z^@;Gpr8<;k@jO%z0k05rmcK5m@S`F2TomTKo`#8^mLol=p1kGW<~0keYTW+{ zn|ELE1y-ieQH|=5U%Mx;Hq-q5CI$#ZkGbspwMbRxPNz~iU`LAfO;F60Fc{rWe43|x zB@;bRE)Im1TmNg}mTf)zS(AfiYziT#F6%{?Wg|H{RD2;s0pgX`FG8+eiKEB{p1AJyo8_h& z`flB&Le4`X2R5{BneYqY&5&U_0h{TIR#(Tfg{NNJFmmy;U$Op6{&M!>Ry#w&i$3Fn znTWn#F<6zN=w%yvtTF^UO+j1{aK5v#-jGkFBh=-wk8PDaPO}$`};oa z#Z#H3*g-JX7kd8k=%0wY7&x_`AhttvRh*K(N1M$#A_hV# zR$HodDU(uYzG|1{OpcCvHG;V#&!=q*ELH7W*T1#u!Z!`^#m~1+417>KL%}Iv#i#o} zi5TVZDMhw^I1d~5wBBs*3~<(;T4y4UHN-ALm@++%?FAQasxFWRQ>}-j<=*w+JdK-Y z`)5=7wH-(X0fg0gMk5r_g(dE@pNW)gGl>;NT*dnD6!&MAy8&#a#B}QBXlL=}m~|~h z9AP=%;2H~Gt-1xdQ{lch4yCU{JR@A3eEk zW7iuz=a5c7CEhx#9|j$(x(pa<*Sij0tnk|uRIlmvkV9Vlgvu-Y6;=NcQ=d@h1?YrD zT>*9Kb9*p8@YId%UVO?Q__`J04g@F@&EJrVT4|02_oI{FZ+8At2d&5VT+n?R-6II8 zuZUZ5_SDfVzMYP<5|}GkzXs*J`|D9_zS%;aC0hsVq)b>(mg_Y-T*%CI$NVzd(}(Tz zzUhk#qw`CKy)GBGuY-C)rCX2kkm&w9opg;yUa;UP%@-d{r9wf_tvzhw=*mYzw; zMp3@|#Q?;+r(1`e>SfyS>Vc%5-PVVn`83KaahoPe)MKgntvc3T=%#Q0_}+NX6xluJ zeenedcd=CB%hMlX#E}mrMb#xR+|~FTIXd4C$1pnYHyRq79rJFY=WE1f zgXyY6XiGRJimgcaFh`@$e8X25hAGTx7Hs@Y^lA}F}3MN<@ zN{oC{UPI@NcbS=Bwls+iES%7!IO)ills)nZ?yMkqnszNHUr~N zQaPvSe3r6eVrI@wzS)B-EAoADlgf>RU8uxOZ3OC6?dzQP!~E-0dV;(IrU&Xk+oak!pnhitPuc#&B6vFLnLY9DsMxlb@iouu z)-HhBEXLfL5}!a_G$Z*_@k{5P>GlodQOQes1fQ>G2L=7Fcr#%gOya&LuLLV}tBxBN zZv-y;?M-0m+oY^g3hu*Tlo(PB|MaS?te@^_MFJ;;_Yo z%L?x#cJGxVCcm3zx;0O~G0TFMwTTLkZEJ)njN1fz*16SJHg*Bg;tholWL9L!v!tif zFma0Qm!1sk)%%1L$E0!@?cuL}(Y9?QVr=USB`|35!AP3yGVng*Z`Jf#|55L(e|0@Y z>(pfw3rH^Do=#q?7PMSKDxO@wU7ak~lDpv98GW>kTvD8kyXBdP zEv6*oWr5Mh>xOvrr^D;%{K-Hz9Y+STHXMn^}E7ySybKT zJXsZ=I-e_WSjVrv77Nt-Jaul;6BqGact2eCq(GcF%0ajVAW`KXP=SzCzlJ3qWK&=5 zzZWkzS!xNV6EtfRdzrS=bZK9wEv)CcpMtFS=+^N6Ry?6xn_~h}*%a6nVCVRcKEBn+ zfX+eTUCPA7Te|!Yapnb#&`Z8OofMuwKZxv?@M+meiCwncj)^3&rD^;k9%y@XPC-Y5 z`Mdz&%b~Y?IS|w}T($E`+;Rdcr|PP&P?F-tT>Qtq5M2peND?~P$Uv^(>R)~#A5Isy zuS60&3MLRgx7eWJap^mswI4n+hefk3xPb-zM5dZkEC(__#DIl2fbpHRoKb5KIqLeb z`Y0+E`OfT-@mNeu3}dV?W>i|k8*c8tl!=mCsscps%f=GF&cT(^U)8;PT%mob2(NM9 zi@B3EVnwIc%M7H?)V%xLuV26F?e?`X#dohZXDrgw8ReqA4iQ+b*H@fQ_7Oe^;!N!- zAB>AZ!!`c}$58;(dP)475j_SRa8GkNb3n!bF=O57qRpJPX|WxvRI56r#lLYopZK+~ z=XEKVs3+=#><2Ol*PvH#`>_FXhB(9Zct9VLwLLMh^Hd_A@b?3Zg3LgeCo7VGN z<88m6^dgTaZkqkfhw1MJhv5x;iH672A6I!B*O2+{w4_%&wLBCGbNzal_e-^xhyFH8 z!GyjI*i-*Dui*eB&V={#<3FC)Ur)~F95AmHz#f!5ZLwpI)T$oe)wY%feYON?+ip6h zD7^!5+XU9|IQ{F4$5nYXji)aH00)Qg%@E9UVpAVfSlnD$!dx)Q3exzwZ zpkH(>0Gg*L)go^~7Cgo{Plj@dg1>N^I7fM6ebEONL+fg^z3=YsqQ_unxjtg;SP_2E zD|X&Opm+2^{*&|R`7FVrT~~2pN&f51ep?QOgDC3e@Ui5pmzit%_P*r;3Tw~>?S zg9OH8*Wj{$(XQ!J0Jn+zw8??!g;$Rl@gqg;TDy6C;l0Y$nxfswbrCd;Z-DNP*o2?p zu8t+_LO8StL{68uZf&%vOs)(qNk6~tF$4XplV`#8>C|o~(f;r~Iq|FS1iq(qu_6t7 zc7TaTDEgtrYU&aq` zUTx#A_Uau*kc-3W%}cc!H+BtfaHeYd8W*q6sVZ6n-`TZnZyY22>Sky}yccu@w%TE| zg$PC24|%|{bZI1-B_ibUI5ceQPkcP8s72elnPLaS-%+y*hWz_P zM4b%i<=yg%ybaDM6GsJUm)EsTN3RaNW;^D|9A9}Oh=5;>z=L(-r6Zfcjg&GSz= z#0tA^rh995ZSBjsft%@;koB)(;&%Z%SrYb%fZiD8kC{m*kETahJ?{fA1D zp8nKGJ=u6O+}(+_+Pvyq6?FmZf3r$y0= z!X1EGIiJ4k6}|4u5x;^GT&g>q(IGCOwM~Gun$iOo0+f~K|PP@QMo8;{^Fc!=Z&;qb1=m0?4l&*&=Xj_ zRM<>rT876AOCz);{BpOV843h0BKK^_Kf-=#sP1J@>*=TA@w^275)I_iEO}=w_JeXB zo8~3pLK|rc89en5ou&_sZoOIa4EOWG(OD#-cv0+TNy>Y#nOs<<#I!WC@em8zD1L8Z zjL7-CNeEDLJWI8$*Zd6$0B_s(KYWG@{}nvvxDzv=A@W_x$ga?A-Np0NUVe1nX|z`T zW_L5m;4)-=zuYj}1awbf><>rzhp8k7@&Tqi*@wVW;$^aGh-KF8@zme>xEJH;kN#2Y zD!iW&aAVOKIy+HrUvPneG3GU9?fS=|OkeBP_OCkUr%|`LwypCutokB;!vEqY>52Fh-s5WCq!(PTu z?yWyhv1U4WV%itiF5b9zJZs_Ci>7@V@uthhi@9c->%C9Fu!|cUMkGPMO=Y;x`)!hoU4d!YgG#O|b7I%Z z8>&lozt9;tt-87);cajN7Z*3Dkk+-i>TtFL>t01_alekYA6v&C8lp?HpD*iF_^cpy z@xD%2+Z#0cKo(@Fo{>MLJbnhsP5B?Mw(`>(Lsbq&IA0x0b^69_;&a-G=Qi^-q@S1g zPe!E~93I=VzY(g_bjdvFN=zqjvze}?xab!P{!FDiX~|@i1J?W4Yq4Yv_n5!4QdG0BY9 zQ&TQfY@bIUKRmrS}loQf7T|u=;<7AqO``-PozR1 zpP{i%R;NoLd0e5{_FwX`79SXg^}W`#40Cv6I&g$GR>u8SX18 zNslw#JH|F^zh5!wdLoYGhsBLpt}%K!%lZHrFW75L%5#eT0QdCT15yX8a?zARfGUsAk#%*$TZy^JL7oHxilP|%5)Nryeu|uIg~Ja7 z=WhUz@*c+%#B7~vfq^J_E@w&_k&6;B$@*XEtYBDK?l;Gb&9ZK*ryNlMOL%zC|F`6# za_~(+CThIxhGXp~tXBlLD|Ce5HrMX=+?bN#5Bb;m9^h*@EQl}NRT-W@5pV}pq76u& zX^NEb!{2@lbBrpuK85=QTa(w$$w#L<&)t~&`Yf=}ZD6{uB{XBK4xUGG6dP1dTwka9RJK6wj%CPS~+*m0<3(VP^oUWL1D zt8mbbskm zn{WCKKxw#*yJ%|XTMU;u00P*yo6%UI zUBC05?&eT#5sq+V%6#JVvkyQQs_PX!ukCgB1-D*~NHSX2n<|84n023>H`Hw_J}k^e z+ziGxU^bLa^T=x~;X8mq@a=}<53aGt8d@KKf91_nsC`>`AspQv$pJuyV|YK7Adqiv%*|mCcz|2Y~-h zblJM-bFyfUfB`OqkkMG~uak{2$DNw=P4>AEQNT{fJjUbbtkkR#Y1xad{|cd8&?!5*+oDqIGalXM zCT7o2R_-aXP|LbbddhkKX<4Y9!fKJ2hWNtL7YFH3#c5Mut$cFZYQ?7#)?w+88#;%p zb>r1M&uZePm9z-KhJaN07_zfpx<=o7_AGn^r`y+18$v2)p`BI8`kbHdE%Qs6#2rf0 zsN#si+^z3+=g~hB4Sxw3{5#cjQ#S!7fmfU&S z#XaE>DgiZ;?PSGX5Nx(A$#6|;QhgRlRI;dWWwpW)E{5zNQwTZ+BMF4!L=(cKVDzrA zP(`Yw7+XnN4U~EwkwubKsKJ|%Txk3}#Q5dly>Z#Xmo(#;>dFz=(c#Gtf!nYW=%=VC zrYvKY+0n*Pk5o@kxfqKGfBEbkg$iGpwK7bl`}0%Gh+-Urd)iL&B^5jF^&mRARRjY|-mvk=FM#p5J;B zAU^2si=I;e!|7~<)>Y@^tZpW80)p?nHWgrLZKUG$2^di{!er5ai~c3mzV7I8CcFb8 z4x0cJLo`ior$Kp(*>+yivSi(_=1VH%L3|i(My*48j4*jp%i(?Ry~g48Fgi*e&t95p z?P#J7X~j(bafD!;|6xvSGg9i{YS`TuhHP;JB)k)D*9O)nt?zC@?ewhyeZpcJ`;*Vp+3ZHEt+t&c3SIvGVkG8_sAqU=@ zGUWd7R7C(OGGO~BK}iVSi+r2TQ}DR?;3wZ+_FCU#DZ2XIAz=f++-h0DtDpgLiGV)Y zI_jm}oIC+yMmxFq)vt*XjbVK*|HHU;5G)}?XW2Vx{uYS70V)8GQsCSe@XYXqH!L!O zytl@O{f3+~{W*$K1*|cVeh9BlJOjj!O%AUCfBlzvF= ze$cU+j3-t&#CNITV8Q3Rf2r2l+f!|9`Y6LA{rsl>wgf(_|24=rl2PZW$rC3NepAWA z8gu$)n#^mm+>Adfbk+{@(jz&{Aoh{u8&PhAt%YjW=@cGEW*Tm7w=mliSLh2mN&!2+ z*W4ZU5#9VC<-|x^%~}h%z^8AN#LaWT9Xx~7U0ghFQIm56X^{M&5@+xuKG|^Yc6Jk< z$ZjDWaIejEL+x^y(Ve}KsP9hgWc$prhx++xQp*H1=y&jKL5!El7>^o4+6NqlU?2sB z0TieMhN&MF+Vml1yT!(d2iMW%=pD-5k?GK=oM56ZtxQ8S(kD$a1fk4I9^_+9+IGLE}+ zD980m9(sHaCCv$4bT}wq2Os#j11_)FbqfJ}`@;WvxqDHk+3Jjd6M?|u@H)6H z01)E5>_oy5;y33P?GAFVbbFu3M#zu6Bz?pYf#0dH0ZjG`OzX4MuIRtEnt65D3nZ8X zj0vHk{(jww{;k^^ivE|Y_P%f`?|bFZcU#WvYv&sG^dVUw3o#sQf zXWIpG%KKJ-muj}4RqG)RcNcGrw-aN3dd92UClbSZO%l!Gm?G zpRc?>Kpy7r+W+_xCD#bpu-8C#{Coc*!X9}feo(h{D*;pOn?7N&kt<;wCLs=c4K9D0 z163l?hax}<6JB47oK5|{&m?xaT7zY%kNkWLKSc`zV(NOSn`G4z1pMxnrgL3Imu$ZeX zf7d;*i`>?=hS(cwBR-}E)*L4UvWuZRiY}+bM(jIMlWUO1=sA8c8hRu~ovL{;fM-{= z@vbpb_$)x<@Gk$NoYWq8Ld;cQED&t`QffThPzR+9?O{X&Np84dT{a$3#7iQSHWy__ zl~<8C7$FqQl<)MjeLf}2-%(+X3r{XmAwgLnY$sG*h=@_IQ2Far}14z1`kdku0$6R92r;j2>_24(v zymN=E0u6(nVTXZ)G+9!*h9nOATfGITCQ%~uGKN%gVQ-;k@R&tNHUn8{K0yZZSkydY z_C`An!LftR!?cfS1v!|@hfpU|v0p?xc=-jrx=QiowYEWj7L&e9cOT>deu4Q~H6>DwyVrp9 zA#1U4pbE17E@Kan$nBD`Wu0V z!Oz9vXKATx|62q({e`FUQ|U*#s#k@^bmL>%jK(OhOh&APW5=cE<+-vYpM5Gkfw0>u zOw0;49SPRyE~Z539F~6f7B{F1{vs}%TZWr2KW@u!v|L+mM~EK$PIj)Q@vWh54q@85 z(j5wuiLJsoGL(0BNS`Y3p{>r4%2r`M9h-k%;!4Y8#`2mx!nI*!l)@NWmYPBf&3VfD z#ZzXpQsGGby14gu-h#&y^U*~>V_RDf`rlq^#$p6US*ta1OxCtXM2CVounGyOLL&lY z(LU?Zmsar44`PsW1fg!J_>^aJzS+hL;J~ogi|{zm5&W{%_}2^AYyWePD{Vqzb`r}n2-$Ld#hl}trc3vwkVr2*)@UJ>!T0QIv#Ey@SkJOnEdK@yZ8 z3GYQ6hrbdm9CpGGH+Xjfic;RO#)p5sr}^7F|67j0%p3P_dJr&9zkNdWlUfj<6A^X& zn_reSZ-Y|pY3KS~jIf)1wDWw5VV^P(wW6NGoexxRTc)m5$@@t;^jHbJ)(iz@Ryq`* z8)T6ze=u9uDH_AXEGiCvdn~Ib_3l0dBPE;YZu!VcjY<%CM1((!Hbh2EIeP_fCeA1i zTc$ZB3o1hz70%5d$(_rZO;UqWR$Ob5*VahJ$!ewq!C+>XOi{-$Dq@zAR%2!@W?%)_ zsg*&#G>fEig&hT(M_%{+8Z~8Y2%fC8Od^g%Niphp4a3SKZGOTiR;8xGLN6KgWwkrc z+JR3%2#g4FD9bOSY%5_fs_#*`uXcMDGiDbxBI}TB{dwz`(z{VgYB#vAS!4@Yl&wds zNTpbwNGr1%jZmtv@RfxZlIUXyt5IYXPJO1va;b>$Z!Zj2k?E!!SK|VnDu5x|c$$wi zN*$7wtYY5vRfW2!@7algkkP4RRfqWFE~QqDN5%>+&zB06dHFkx8z$mzYkA8-4%7RY z%@A(3;xY!-Y<)mF|Ffw6tx_B@08caYEStBn8>d^w|KTsG0=JRc@+95tAIGzw=QG0h zjp$6K=Rc0800MIgn&Lip(cRJP2#?(a$%QP__H$(2MF;PajSh{doBXh!FfKfm(D^L5 z!QDCYlJhgSUvM;!O@a&$N;LNqE{aDr)tU<_Uy{8z-NIdkqy(GnCYl#;?Ic-fMcl0PnyWjwgn9zY=j#bcAHo5aQW`V}pqtNS-YS zbNS5AT9h%`bu5jX*8B?pdNdzt8-zuMiB%P|Y#CfRG^kHEB^6#fiN=`G&ZRKE6q3hD zgSLvD&txApxe~3vb*L_jOYu0D*pH9*^IbvCla6c3(r&Eab1|7+{Z4g9LglWRC+zws z61?B!LZ_HI(Z3@1{M}GOrj_{MkGZ!ta#puzrigt2KUv2F^YVO9&;UY8u7NuGGHbaW z($yjHf09?XX{>Kqpe=#ZQk|Kc{Igq^Q6&A=@F?JgSwjDmS(M#JcMKsG&&BIOl7ia?fRp>#3| zm!8@kl~SUB+90wB%79#D1#%Q)rEXng?L20bz7a{rd-)!LT&mF|{5T;2QRLiZ*$n!x z0$=^)nn25CW+mis{kby{QA^9V^5AI`gIVL)h}B!X^|q*`ZX6NNOc!%Dx-s0Nl> zRE$+t4v6&NR?VaR?4Wjsp0%fBBsm+eosft$Z=_gBDP#l?iYy|JSP7rI5aM9p3n(;H zmih^A#`f{77Rw#v}+aVZVtQj#gF43GDQDR#>kNBM?eIeiy7cE0HX;3KaZ`6 z2QOjN$1~pFWmDFocUsk~ME zybmjipt6XU^fVE9JAy-0Op$LP4FvNY%7;Nggju8!u(q0F)|inRNo7c!l?AqPLImps ze?J9;RGE9f?2h`&>2e6Ota5u+h-QhVB*Z;DJmQ%)Wu?*|o4|sU=qo3Lln63z{89!I z4a`{-%a9;;wX?=hG3Xw5u7&ng_IX~!GglA^gtSGWi^swDt+Dc#1j=`jb?(zl6)*ls@{y zZzA>wGb-y%>ES!o_507Y6@lNhZQRy|&54}fFEbt(l+gCP{Xc$y)>qN))7)-}$^f=R zZIpQKSgj@a?)kmjePs8xK3#T`gd-t(<2X4hJ(3J)_n9Jh43Z@JnpI4(`ock7%xemLYBT`m0EJS=h2AcJQW)mF<{1G zIR^xF{+bhP!kF5zr7IJA>FZX#JDoFVn4Hbh!ygNw9y(o%9@TD2Bu&W-+pwgFj&F12 zOiyVNfGp#S@xj^dapJ8~STlPtQA|w(B09PLhh0}HM8UY(=coF?Pi~mB_zC6CuoZ53 zY$NxR$)93DC+Da53NlgmX@90F`7Sd$os2hSf3W!ivJr!|ey0_B^)n-IaFe3z<%~vh z^56sXs%NRO3kqXnu>;d%VKY8Mn2&#reW;Hv%}fV2Npc;6mlns{6yKZu_Q8Z1I{K$y-tdM-W2y$#(^=FZkA*|BT z0fOAI5K^X5D+%eB6+!ZM(N$&gm;Hn%;gm)kSZ3iYczS%ss466@ zYHD52DFMI;H7%`wJ% znL`>8p;<|$E&Wr5d50p}u%Qs}^Kd<6x>{{FSx5E@aw(GiO7qOicAnX4e{CQ zv(cWYd5dFnKbtZETwGR1ACWKGlRQ}X>;?-=M3d81B!MfI`+JpjARLikGiF(`s zLxEhBkKF>1liXUV?3ADX1;g$x8LLgjwwNk9Ly3Ej=8V zywDc+dgY_LDrfk^#X-426dQ8Uv zoM+_DL=lEb_a0FOy6oe07PJ{k+(C|u2!6#N%8*i>ACKS8l}@Xq9?7 zHfdbkw*tuPbj9RNjXcptv%(cI_}$cAb_{KcYG72Yb~4pO*AoGq(n2a4e`*_K!l$Bp zTI+%+FvKaXL1q{ErmVBbu7|cvw?UsPds$w0<`2Ig64vEaIp(88 zo$M#BbUzhsT+27^mt?#Z`~c#!k3U7AB_Y@+NcduP&mP>Intk>(e>0vQw__qNn75TK)Lru1NK(QouUe5~) zM{O2{9_)}wZrj7+_WugsxBfd3TbXrM;jNXe)>Z5ksg4t6eUxpC34sJK7?)W>2tP)s zNK1!gXR~H!7c*p^o4!n7AUWF!Z4c7Wrk0c^&4WxBN~@_Aq0|&pa=m)YV3!R+Z!bja zj*KYQ;3Ir3Lr4+@d?F<(VaA@ankhzYV!ij#nvGO45jcxgsH7Zel{)jzM037$%@DRs zck5Du@!OPpUop$nxf6nGsmfcU390%O>Wk{t|2vI~txKUmf&TGoN5JGKkS?QxLp;kG7+GJR24f_lUEN(KQDU}Gxyxpqhn+nUr)tTy2y8{?w5cGfK~O3r?X0Y zI#|%Dl2P$TG0&ebQvrLy{*)R0tFYpD2*J!ygB$Zh+N!Ygt^H>ER&T*`OpWRkhs-q9 zor_m)t~At&5yPI^l1{xN8?{zdKcCXwzq7pBKxwPcZ4HVsG**yh#HMKhqUXNy=u8_K z=}~+#q3~ZX;D_}cKU}`Z2*`!;Xjyp0utnBn$%48EeY?vMH+D8VpH%%6IEX8`n{OEu zLbs$(UxtgX8G1ploQ8oG_J9H`(UCRW) zLyHfxWqXxjiIx7$)oAYN+?GJk%;{6I1u^?X``&gN$^C=rWCBg>64{{jc|B4V$p?Xc z!xD_c8G1+WVR#KBA6{rphuss$kZ{jkAky^fUtFTx?9_EQFP|%T&xc|?s9H8SU!`z^0ijdQ(~OFE z@XLlr$tEJ9`!zNd)3+BY>}>T`cFg52SY+={7)?OADy3b4g%5s-@QzGBVtFaXB_2kS zQ(&g^0|nS7*WLSi7}%QM{f3_Xbh{tLUT$qWMRYLrA3jxiW)@IF>0LLMXkGq>E5*a6 ztNB$E?|c^lbL*&J9Yc4;H-?o(J!L=zNofDEI}>sZ6CMHJswrW?q{R9dMtcm~D^LuoJO~Z$Vfhf*r+RfTWlfg1+ z(qS51HX4-L(Un=$$wW<>fnm>5DU2X89emNsg59`pk5;%@aU6&^&5D1blf*=zNOyaX zQmWS6rvUgTi8d)tF(IWgj3=a58UyVez9i~1G(u7~tMI3clb;hUO5EWD zzsq~new6R!kvPubIB1_qk%S_>0_{A31l&2pU+W{a>My>&QyW>)4iUHmEsDsEQM`|? z^1$HXQ+bp{BDEOy={T8xoRhIvq^)HA{h)vnaH+>zvg(_TIvcbc}9%~y5#le z8taz(;V}Zz{1-frE9gic$t088;-fN{6+LJcdLzLnAoEb25yiYqVAReTHLq|f36FIY zW53yg2(}(0)uFkb>*4tG;a09-C#cfWwFpWEGsg-|$D6b*lDpl8f*?$D#~?tV4I&NoS~Aq&O4ch~SF zKzHZCJf61e0%`7G2lk-I1CBd}fvy$Y|9^!KAFZ*8A3XpZQDVv^P}01aV4 zd8Lh3H$}_-!vWG1QZkQAyrPHGZ81ttu4W<8cir@3Let!ZMJ~raij2}8r3RPAG7I-E zdh|5?0*Tn3N>l;EMil0t!*l?)OWW}tr*S*BK6$Y6DE6CEjO0tYiH_N8%c$ds{or;P zkv8fcxm~-|aRmd}fapnXRqhfhs%SWimdUOK#(|=;VP=W2&F}<`y@?kSF2!_l^m1T0 zr>GcpOyN-WgI56MZ1S#aInd1IYD*Zz=ZL5fLU zlbkIRu+`93+b1jLx}!fRA#cb1D=zfsg=Ek@HyLKfgY3_7m^j|P4YZ2ZDj9E+yO~)& z3j`FZt^6y(hc|yy4QD@YwYS{kBaw-K}Ult`@tM z0l1-a%$DC8?&ZCL`n*(z@Majrr_{M-xC!P2@22@stO%fG; zWD@ZtnIQONC*gekaB9zL0(q0Wn(-{FF{aY$uhRZ^v@p^fqfZijbJaMBp{!2xs65F+ zOcz?OB}`h`gqE{HqNOxr=0xL6V(@metS1(vVx(l*MzFYSEs?Z`P`_HrrZ%R(AeE9H z(?n3Rr~FG~S^wjrP3F}9(%yben1(2$sYfSTP37Dc_u82E2FzQ}N<)8ikvm_5DOyooO?43^0^Qp6s?r7+JQGOd@2qd0bl z%&2?RHL0#F@H31ziQ@B|_+*TRUz9t)L_Bj7_`~Z15is)?qP{<{>HR1P)W0&f#SKGh zzU$A#^hs?QBRDE`t$kl5q z@w$k(Ok7Bi8KDRqOEmE^TjzK!>g@%vy3&3B2zq*_^=##KCScEZ-nq@WL z3vQw(T~=!!EpNBTj-{*MDu=*iD&qEsNWbi`2CA|Eg44Ao5yaG`U_* z>uETs&5&(<~Vsv|-#lz5pzv>qeB?$bF)07?D5O)5{V^gb?+)8~NFbmB_H4abeKo zWP0@e57~jfr{1aGy%ThAM;on#MxU;xjL=`7hH3Tbk%V6aQ{Kf6dC9AB<3BqudBsBw zz3LF^$@AKcs=HH4tOlP$9vyV7^Sz0~3Tmk4wUNE)&+4Kc2_g4SeU#1pqQ0uRt1g8M znnA5fx9}kD$l7tepM?!oNVF-pOhgrDF&H!C!#3{F=lSMgRV>frU~-a_1K&jB%Nobu zXTjT}&3Q0HoKCbtk$l`EC`7eVM`v+K8WX%vFrFh=ZY-hx1Ypp!;A)r0PTkUL_s!;W z_tg*?J=rw=x&yirO$qjSbTXpN>a1ga73I?jUjLZ)77E84(}9SLbj$MA$*$tc*T-TBQ*uI63kNRV4IV<9$Jp9M$A*=yn4%f(pD{e z@^2dL>)gqZ1tvvxE2~7ddDO1zv-dqmeZ}BbTqq>^0d{sw6HPq1;}RzCWNrJ*H@$7b z>qM3~nf2@j6E+!(xr_?3I#&0z}{!8Bf_kaW<*I^L<=hK0H&Fi>P zmb)bKPC1%$kdr1iL8P?xz##e$4GD&vrnsVCvZ07aQ?t|{i9AkhiLR(z^MM<==D;mE zaZyG_heEfK1ao5q6hR}x`2TFu~&3Ny$1o*JQXC}gH2m=aWPxa-z*u^_=9&W|%I zn3WwiorrX){{D`4IpeHXj6ho3bz4-FmmmQ=Pn*kHbwSU8#*(@ERaP;ra*whNt9I*X zmnB}q?-iy)9uTVrD+MH5yO9&nv(RKq@Oi#0%6K+!jlE}bK1DAAY-Je%A-%jT>oH5i zD^^ds@g|`P6@y;lyeQ6=$d!tu{mgRFWmo0lgCru&sti@{*54)~R@kL34p{RmTn*jW zfwSt9ClDdxrC+a2ryM*%19J(4jK6xH8?0U{Q!>NOFhK{Z@iZB$8F5H?l^io(IEhas zjkJHKyH!|Y8Sz;EIk1l(Z(QYtDCvK}B%s#oBF#}97XFCAigm^Wd+d;+#8H~5xjskEh@b4&E<2~>-E1BB6?N;WES0^8#=+F0mD2m1kF!}dR5)8CfUb9FY9 z#geF_G_!=bE!6s+W2VV=Rcwj<{lG|PA_ke>_->*}omRUGx(z8b6-i+V^HYn1#H>(H@ML`n?Y+BJDNO&WPM zmb6`UxmUC!_n^V=PP`asX+TjF4rtJPK32C?uPZu|&Xje$M8ZQrOu@WKu;tK=VY4yMeOz{U(3SgfuBA`uB+E5P|EII;b;xu< z7hT*)ToR!?VKRYSSV4eMiio_z(erLb$aQhxe`CDL_$kt+G7HsAx6WVwe7Z`|a(qJ7 zZF~er0+A=qI2!vZSteu5PkZYXl^0)0qPSKsTHY3|-;pL&@;wm zuu`9=W>(ilTU`cokyp5TNb}E&Iuc~*rq+Dcn8)~dQOm6whoI^{AU#~>u_wTdj7cqE zXdhiXmS~a(xHbrzciB0ti7@SkNET+Oz$cS-&+}_Y&qrD*ab|BPm|p(J0=UMXLA=@Q zt+^o&wC5tQUZG(#U|!(18Bm@o_!2IwlylBW2--cAK-rjF?iIxB*3H37m0 zxKK$8F|(2GR!~2NYF2VBn6Moh-HDI7Bl@rq3;aY#ut2K4G@CJ_S;J)1**I3v5&m(A zGAa=gnt_q-Ku!Q3s3k1=oAd=E-@D9mIk#rOL&}a9&XRJYsbI|eI~LYHNX7}0$&wNmW z20XgZpev>Wk?xgP_iGSdtt1%lQIeI|NRCl`)BF?c$y|~E%ULu*Za5?dfLRv+&Tjoi z_-Y9IQofhGpW&VKN_ta{fw`1?Iklo|lNZn3^sDedrz(<8!=buUma-28Q*w7nB?j|Z z>StwmZm8yR(3$*kiK;aJ;;3$7p$ECTeM4YQ{$VGU%0Y6{wXF9b#>#LpmSESAe!lUNP5Y3y^yJu&S-VUNzZ#SII_Qimh=)kB{Rzg{{nKO}FD zhMQiK%B#=Cv*7dUXF$fMVa)D@J5f+55r3BV4dO41Ub{lvH~t8YsOAa&A8P+Qdlqg} zFG%|G?oK&414hl6Uu6lyUI;eh&1Z`$XCuZI?{zQr*?6_s2F&Y#!8JeV| zamYTpomEoh`K`lz@o<;F!zX3gx>`PHQt}zVXYC2Mb;oz?2BcdUb=tyZ9YAqqAeXmZr z=k}F~@Em(@2>To}xp@c+SX*k1Fpsacx+>S90#7RHi;o9m@t#M67dU-8_-^!*dP;rA zFn7__2Ihc1D!tb@NJ_Cvp5?ovUgfkb3q?LUd0>X(KZ_uM%$-vGFJ@bZ; z>!BZJqQ=(+AAewv6I^@7KhyMOcUaZ1BD%JslzD$a#<#s29I5R&V!gemA`cv|*;-lK${yjfSVN%$qDOjIp}HCBZFD z7`fn6%}E@)P8R;RUNVWgq|b<-SMFa+g8pCYzpSxgaYmT|FoOL3TKFN;Es%PnbGoP=eDnWA6$-m{pq_#`plKxjRvM;x>sk}%{=z_F9T~JV{kd6RR?34QpLYIAacBn z74+1I2hEED;Uq+fMCQo5t<|WIG^*3WWmF(Uxq}3v8Zcr4&PphSX@@GVLMw?iR$X;4 z8E0k;tu5;o^uT!lDj$qIN6F*VW5D_flOH{Y9kkKb-A%4H&L69Fm;LrukD0j1u=4I^Bx?xwjv%E-w8Bj;BlCncd! zMc0+{?4(#kn-GMpFnv7u4GT?Ge3DkLG%)R_Lf+NlRaoy%`xKg;PW(>|3@{G7T87bA zW}KxNkhgk`d7eMjfiYGya)VBxzE4jeF`YAaUd>+`Wa_dTU{lMJkhh6$jLyl}T2N^nTH!%x!U6ZxU#iAH}=tQ7+ye z#<%UYoIH+0**1hW?jZtiX#`m{xZZ1+H_$@`*)*IRxbAg2R_@7sqJF}WvuB+XR+is2 zRARcdcjrw%^aK(}J^zDA$1C22o~@+C8E;u1rj8KCPg#hGGLnnjbXBm%el9su&I@)gRlHXpFYE^GxBEVw=!&n3ICuRH#?7`})*lu*?oQ2CD_nOR{+a7d zhSfSJ!`h!5NaoM=fy;e=@sg#kd{{K>eOCqm^IsL=^g&jKEEWytX*x5A1=k@NR9Sw# zWP_t0eUhV8%?n4PC)tjLxwyJbQIGbjxsPR4ghJz$XC!wm@6A$Yz;lTwS8m~?FEb0a z3+hig1eD*l=78eum)^^$vu@k_9LwWWa*7+A2H%(Q_4JfKqpa&>+LE=S8lbX2d%W04 zxejk4KO}+6zQ8jo(`TJ)j4rMrjXStp7=@g2zI1kSF&XTBk3o5M@G1)F$2)n1Md?-_fRWfyAP*1~=Ozz2oX|pZUIQoLf^B20j zm;41%fHDT|Jfc`R{TU}>;kc0JBA1vb-B(~cpg?s~^u=BDUi#R{%=EJHdb`$)@jA9C zq2S4)_qNje$-l$$bVW72ck?%BHz!CLn|c)Bo3 zGK3#3IETz!lH6VYM)Nzvk=tO@PC1(lG8tUDV0?V2a(VFiLm0sq_UBs3uWrW6a&Iy% z8N@oe+>M=))lOuMZVYtG*O3Lgo#DM#G_(2dHtCxHU^!gKxmt=7=O=d0{kyJN>q0UQ zRRqyrpeIrn<0~2|XT6&Y_u5T{D9e06WzpqBt_{Zm=a+8t!YY@dabq+~0&-sDv_kIV z+RGHT@_i#B;-~m?t2CQ?qf6w%vW<}sRHK1} zpNP3b;aW#x@Iz?AK4bD}8LP<+93}?+7m+W{c}8lc=qUEKU>q zv7~N6OtTbAI-|}=4`H?c{*o$QAw70-!N019fktTq{0+$-%>KPsu!-(O6UjF@#f;sE zkf$Irs?L~7LPpqSuc_(Y8DTU_0p;}~1!r$JJF^8*abXs4WkC+VcgLRr!g$4)u7 zPEzwby2nILnD2=x_rA66*z6cE-O639r~${0*;3<_?jano&%j3$6C@zRr|ocWY1iYX zB-A~doiB~dd@?pKK{<<`bCahUT_v7Hj}fqAxyjpYW4ZOg z5=2__&Z{W{Z+^B(bblL&B$b(1@SeLyb~SjQKD1+VkGLy%hx2gJ^M%Zij{;wirt~uR zhhh}WUO_(^iP8M7UTNgt7q@V)>r+K88j}v>+Hz1{>}+O=pp@scZ7b)AdzUp?VYfe% zVRL|sT$)oj3&}YMiip}*Z1=T3eEB|vRx6RX?zFV-H74qVd(FN|Ug|TY+6BOb_{~O! zxb8Ax{aP}ZJ+c5CXn$VWo5uI)AUb0MRQIJZZvr$F*@wMU@kC(f#s=6y{1e^mX+5Z$ zS876)i1)(Z{A5Yq*1vt7E4Lob-hc(tmmBc0h=KZc<{|81nPYd^Wwr>Y;;^i|yrJUa`TK)8Hc2BGV=rHEY z)R;YzG?}XV=Gph;Ys5T$ph=utOe@%gh*ni(HX6Jo6;s0rk?P=x{^~6?|2Eq5LXpi6 zuE?*m#&Va5Of~x26^wg+>f&!JoO50u_C+s?l*3llKNI}A`DO5>x=Pc z4z9%+KhmgF#a;+(KIO>}N4RiumbBfrHeymd|NH+IUfR2+1JrpiQVP z9M=k`@4jE2RFL}WOuxT7f6kZJPim59g_C{)wOKy)bv|}?F-(#FOgGorRdAK3%=M!6 zF-wq+RAoH>L^Q{*SipJaj(h!yR4wqnQ}@$q6(FwP z^Ha+fa`M?6FzM17X@nL|HZtFpvf`ge47;1_eKYjvjJ&>eXm4cK+3Z&s5s)>GZY7)c zx7zT!qq8+pH{;;)3Al%~{H`bY-k4!lm>ByuKxH#xK61SB+C-86bR1L1bSWW9z^YLs z3`Wpqpj&3C?~t_2Y8$@&x1VKF4-%}*+eyN2{;#pA1*q950j%ahh@Smqxu6?-D-PN3 z#Gfw<5e0?XuPT*!ZyY0}8Ckj7CMKm1<2+REVQ(1PqJQcEx|5qGiCG1n07q-gO;Q3b zlp|4Oe^z&eQEx-?GO)-GY$&LtZEc*f<Z zllTDJiQL3a=JDe1_CSN@k6EH;6v5V~c6iF_Roq-%UEjJDT zl0!M;ZJ+XlMOjh8yGep55hE1V=XU&WM)p58gVaRMdKN`PDXWau2Si6$9q;4`#LcFF z35YX@hc*AM`|j+O>wQVz6w|)>)|0tiYTBW3A5_9dHT4+_obzVUo_s=wawl~P<2Md& zY%+--uq%59>RUPK$6Aseq|e@XBf34M6H3j$GWBwj2g?vwojmZaWRm)`Vm65-(VY}* zVagXez7=YfjVb$<;M5YmaZVQVs(u~Us+`bN5w+@i`L?x&y1Y~)BAvT|%cWZ@Pi?3C z+Kp!}I!<49ez^Ot#&^km%+8C3jo<6ZQg*$c706kcRA4S?LCjWGn=x*)#0~>v5Fj9j zP%^I{eOc~mBrJq*lG*5J*I!=8QaLX6S&I=_buisNUczy-Sk5I&NTl;jF|!vU`&#w- zNv=Q&^?LTq9D-~#@laI}Ty<}rXIFGhB0nfK6O@8ILz?|i)SMP@YR?FwPV>D9*(*3K z-Y=_b)rDnRh;0l-at%udaV2TF#}GWo1qi25YN!18ytxmcyFY0rXZwH^H?ppGGLlgB zrB2`1|C(tkg4&XymzQ(U06G3=e@&gpwShJ9jZ2)wy7WFGTZwF4`iX>;j=q`m^vJt@ z-l^OLZn-O<`LU~;$#!y4?unA2>(UhzVC3~pZn+-Klp)Rh#I$r!hhT0$d7P(;fnacA z6otO36b`hxi;y~=Rt&E_XJ0v+p8R3gnh!RPHLkB6(bM2TVqzuvXF~4H=6(BKUdJCJ zu60k6qxXOrycaC;`{HNlM;*phB}b=3@D%AkPK!ct@gwo0D>& zyTV<@`0)PoJE8L{6zdVr~!^?Kt*rO|<+OLxbz4Q?_C9aE!OK(b-50?jd;odN-hR zOs=#!Ik@Owh36+`;N-}18SPLc3>9*3J`Wf{A$13w#PX6oIC9W%e=ylpEPQu^T7toW z4xWQ0_w4U;HE|xxx`i;%k2|4p`?0an?RERtwUTq<;vlIDNXbU28@o_5jT5)`g?!!c z7wBIV>Y4gKhCqJt!2d#Oz^?vCnU$|vn}Mg{8T?Ps+)cz%pUq&U)AZdh$uGh;y~O8- zS7WW6!VRlsUXeVa>F;)>HdgaHq)x7p<{WXGUu}R~2@kPU?2x15{u$WAE1?xh%-|4) zOQMBeu(!8~YcaklniZd}XICgWOZWv~U$rLA98E zm;|<8_4@9c3Byjui=kDeZ;>m?)JWE3JoF9;@x+O*ZO0DPZJXool2tGN z{0@xxbGdZ$x8L|k*7qynb--^djtdT}+ScQmU;o7Vu1O34SO3~zp&*Ersn7}I|X z@2%I!cJV^vMwFt~X}k@DpC!oQdddeB=ag|r(@{E(G%WG+y*E}B*?NB-X_uC=p%f)nDY7AQ=R5D zbzbFcI0$aYoA;f-eVFVU8&_x+GHHug=z5#RzNz;6}PU)s4rL`vSD@9$hr*p-v> zI@>>`Q&`s^zxyzP3CWgv|E@9{$kE?aUrw@vggaJDa;c$bmbbK$v?<0u8;r4e3<@rx z?CzvGCP#cGbY~LX-VlvEG$SCe4wEaCLu+-h%$!pJ)LvwZW~VpgxB-=HgxLzS$Y#px zK=bFw{aqcCxg0^xn2l_5{8r&@o#lhNOHs2)9v4jkIK@?m)%QU*R=TTB%=R0{(~k90 z_aLh6v#Grp$^+5Cy<5E0z989`lIl+F-%9xq&O@TK^e)l-A^Pvbr`D+?uluWQmO|UF z0_+xuFrZPzQXDMy7{HOCE={n|PSY);4Y?+2l0EX9kZ{Y#iXgBZBfrNBY3PwFeoy;2 zHj#$3&Uf}zfb~)Kv^U6!Ws>O5sRSGA?Xj%>l zs{yoJp~D9?_$o?Hi$qwJbq3Fp>Rx&o_Zqd(mA}rPq)SXC@It=7;}t1f_)EtZMwSAF z0tUyBa)d!eXo9EO$$oBj4?wDV=sHWLpxG|t??Ej5Q{`2!q;LI6?UE3ja=g_y}oFY0w z?fu?uAZ!a@p$9DbXsR9;0*J8$@4!2Yr(d01 z|Gy-(5nox#Tf2J)>BK?1a3zcR>L;+uug$woMlbf{ThG33Q`^bL8`@n(4KxKKyk=8y zl|C$v7=hqE-XtTW>JjflT6Im3J$^iL>TfLhi05IHWfCh?A`1_qG`0+S+osJ~UkS9O zTiiSBd~bEX<7FCmU7m;?x?k(AI2@F*TVs2|cHkD#8uxTw&eLf?cOvEb#iUY=m!IvA z8O-gUy-AYcegipObsKu0C2L-~TKZ9qf_C^4bhKY^-Vd1f{2&$Zwo|zwFNM8yZQf2X zVB;h8Vg7xN+E;gkrTv>~Z2A6N#7knlDUy~wINB-fchN$yk*H=OQ5(vtgd`a3MAw#B z{eMvaJa4-CX18?_XiZN9&Z;TiamT)`{9ieoDUwOdKB+t`mr|J6=-rT$KNO>2Qwd>8 z^1#jz$^_8Q{h)9fzNGRcx|$ye14)6rt80U1TqBTmkaEj_aI~p_ikrsr?O`W}wz$>s zLHiTKA0LdLoSW<}Sn=q&pC)EXM9MOofxx$6xF8XtuN%?kRB!a3Udh}KPP%HT2 z_kLWfm8_-B5riGvhPbpat}mB0(^go* z^hQlvxA>~mx`vb<$S31Y)-~DMo6S+W%^)b%px8Jmq~eaV1!yKv5|{rJ4S(bRz{Vx% zt$-bz-EYBY!otZek#R^W;hT~Fvgw1l9Ic;N4WcDY;g@t7ijc-+$H@h4XIBg|D~YL| zsoJYEL6wS{Ca-Vpg}|t+XNu7?5~#Xd81B-*+UD8EDtgy&@oa zA-yo+bkJFX7fUhvx?uy(5K-O>TvGY7Jnn7}QkDv*-ZK)8u^=r6V+K;-0cM<8c}|NV zkCK+?zDa5>>B<$3yKCyH;*BfNgmjm>FclcZr<{juw5PEJR-p?IaMja=W&%7LO zsk557`qJ{vp5#ZM3=xMPcVIUoIms2+F)o(w$)!VolPvS9P!@y3Q|k@} zSq5fUftS|`>MpiU)0PyiwvBdYjgk7&OotsFt~Ni9 zdPyfj#QQ8$S8tfDWkAPIo-#!wOI^x@$BV|nRCa^n4I6NsWizDqL?TFBLiBsNmn0^V z_m{~7%Mi5-Bgma-k~dVQOL{&ZBA?lIn4o3O+J3vNQR5cY=`w|HtAM!gMVfd3hrU%y z5PymK*CzuU!1m3y&d^;~?O!PYIB6;y+{KVqPNqj>h&~~85%gUQe{mo$J z`-lR`2%f+vPwickZ{z%UcoBZhYAHLDety#gM4J|&P zM~iL_h@gDTd}FK~)Va&iw;DE8=eODLWyUjfe{pfP)HPq_bHO2d&_`oiWV&SWXKSO? zj}89L;fFVN>3kxJ%xW^7@6}!o6@Pz8!SeMZ!}o^vIq`_cB7P%%SGKmo`t=!!I9Ta6 zT(0Frt!ZqE4{#BUUY9M!M)&P@(_0XANYD+e#qDIaG8vw)0X38oO)_&ikq^HLqGZ8z zAP6`H_l1@iqy6$ykGa^|G3S!nQ>^*sPtxf^g=deT>O;jO2bMD8PZZ3YGwuv5sj>-K z1+-?jBA9f5n@a1Qira~yEzGtrziIiE>3Jwc5zTP&qqCG@{l#14+y?~5#D|Fq!bESx z;|xUwbU7>h;+sAP{>K7{uhK{!&t{a;lgrm$;HDjU%8(({f!ZX>O&P@BO2X>5QtU9^ zUT>TCbaa}{v2RXwTlv@(&jl_Gl+D97`vc5?{w(w`nxBE%80=(_*O1Co>g2#Np5GLD zepzF(2>D&gD<$#L%X)MGOlMQmrw0N}1kL4@P4#+$R|g!3G@Wd%BRA<^&H~;U9Z$`t z`Va1a`0pI%N%1=n6=q;V=3{uE44_n!nf4k%!L~xEGDNwRofy+x0JA!?g>l=J`Vfws z@tQ9A)XC=i>->`}_M{2H6p>o_*uw?=rdtK>SSZr}&ya-O*EZTn7PB_w0U3k_ z1MSeE6CiIyZi)-o;J_hM{oGKahf?#Ee4Mr;A?=xOnQeJFsa5$RR|T}l_4#e-KtN#v zyX>~WWlMgx!#PH_IEjz|hQZd&AlArhoP;u&`FsZc-QT4=UD2ORmQ?)=`tLEN(nW)8 z&|W0HAoU&$rQqXGkSf2!p0$gFbA>7uw_pji8yN`+%iqgO7KHGCQb8dZ&&-h8B{^y0 z5)YwoCc(NXi|v`Cg;eTyK7+{Q3+R@erxpTk5|_yEYFMn^X6wv8Fk)T&mgNpZ|hGNG4T-u`c_n~~_1CW3+5}#%QLE+Bl zxt9lf3Dg|nbM%F_Ilz{J&K`LG4cqn%Ks}{cUfky{@=b2&ty&XZ$mFdiK@7&b$!VaD=RWb?BG4=HY;r`U>=^Z+96GJ*qKIsbYjG!jf3&i_8B>-$oI; z4{Pvv^&5bKHm!Id&RerkB{yDn& z)iAUzco&d_P6^+119Tw&Ob8ux^F0-+btl1(?8MC-hT6u zqM6~@;^|Me8(zFOXGH-YKj($)Q%+$JKmqyhzZ-038ru%D~mCrN%Ul zfK`_0vkyGax7G=&3u6rIA_R;RJ-x%T4M$Yc`e&@J6 zSV6=e+iT{_+;9!r|H#lbVI}SMI!uY|%GZUq`S+YJ)Tbs4Sgu=m=KhLmSQPb~Pa>!X z1(hRQECc%(OOk0>@x|Kn;pfY<<~A)qlJv}BKc;6D{sfA1$@_&}jy|tO{GOgQ{~0g~ zyD9hUWYqlTZwnQ-JA$IR8GnOUcX{z1v(1iI0WO7MCGh+cyfPMpivpYJBFsgvQBp!V z;K-IMtH3r9fV>r8Ma$awTb!o1nvqmq{+FhW8DW68-#r$;aob}ut6UC8%!jxD0$3uU ze*;)%%b$M|yTV~eKGAF!0vIFvhaOtcaF{&w_U0`lox50iY16f8Jwvz5W*-&e~vA&`^p^jjr(hD`5j> zqai4QVk=lcclAB;?>qBJWxRg@;$EAi{j9DHAt^it zVNp_aS7gj1vFz6TWfuVgPnca&R8gk4j~_3GFzvnbr(UqcJkz=cYtj{NNg$|sM&adv z4NcZXo`c6Ge?mf=jx~i!z|+R5aI{|O$7f5kt(HnX2;zDnqT)L?N-o&Hjb;WB1?X!(@tix!DBmWi&-#admYd66>~JS`J&?tJy~h ziNS5$J>;dVj}kwwB2m`NWKga$qpw>t*7jE+wKDP*dFM)% zd=dT!;8F!&JBl({%34NcDa$e|hELrWx9Hezp=0^fs;uM&oK~?yi+M8XLH9jZSH5}u zotU0lLZn-wc3~IyNO>$6@Sq``R*aF?lnxu*xm%{Rb2CWsd<$~SEc4@j<&RtGl z+)FO1l03KBKg1o`5M(r&-n z%nRYh>0}+JuQ7YQ5v)J=9NTGEUu=@PQvaxp;PC&ZRxmfby*Bs_=}P|^zx z{@80jm_9C3puYe8=9Ozd5^8>(?_R&W7XABVT*FW~OQIxJSoYT>B1?w%_2tUW>px-M zBDkt3Zdn=2at!%a9jVp$NkPz2%*F}4Q=2*A>}c@S{5C~=ZLCF`4T zyp4=zorPxXJP>l!qL`>Zmwq(+c?hH;jS5bMSTfu=rbA=hG-R1H-u8O-v6T#P9lJeW z#n?~!srGNxz4AUv?U{Ss?nn4JxCt-18PFlca_hUQK4u^fm1+2%a(uhm^elXRfhGP{ z>CtfEtysk8#6}+fKYMS>L&lR!aPzO|ahP+~GY>l*XykJ;cgdFo6Pid#{X5B-H9l%2 zo0O4|T61#GjME?yVk;$w>>3rKwx-d&#CQ&=%~-GJ9$o@mML$}S2nf+wGZ|z(@~I?u?7-NzS*gki-qBM{ zWJEz?JJ=}`r<*W_z=ZQU z6m^bx&Q3HryUaMiMS5H=iD29cWzDKU2rzll93;~%@`imuqVy!k9+P;bPqs4Km*?sW zm6Wj)kE79=n5TvbnNDRpWVd9Lc|tp}mz;KjUiE0I<@k3jY&B`s)i0&SpC-E_#Erj} znL6351{kCiZM`!~EW!fY?3`(~!gu=_;wTo&huM+O#-vq1_5z@DB(I9>F?e!~hQ2LR zeTbecQcY2c%peqeSu=9H#{aHa*uDmxsVYjO(|~d1_Wo+t+4*Jt??Us;|F4W@_$qV< zCoKhH(b4#8pzwOiQuo$4*#8ggl{N}A4IB`>dD6={^hE=eLf58bAXO%l-EiF7Y9Fpa zv;VqK*FH%Vc+le}0h`u88B(26RXzu~%rEuD0V9ekT+l&&rv30j&={J6rj$1!0nT8B zM3$f5Xfn_gOc}O&@S{-VeUZaIO+l4-hY~zxMo3YzF)s&4$U=BQbKd*Fw{4*Zw_9DR zQ{Xj1oKt~EDg`?|uFtN!Jzr5$@@UxW3Vi*0Gmq_0S2oUFc{V%$`kP-3cYO9cWFUrl z>D9JE=c}&|CY*Pl1xs^DTU=Ruee!Oz9Uk*)lEhUs^k5F*RW8wfZ-w~E*6!T!Bu~gf zPr+T+dEQ7ki5I>B8}2>q9zFPIG@;|LEAZY*=fN#4PCVJchx^kMw)Nr3C692VEm~H3 z!_U9xs~!GXyYn%Oi=DIKgN#zLTbA;H#d)=F&Cjpf=1mE|XlmZv_O-aodRu!jvQ7DY zXWK01!S=4$VMiE;X-vOc9A={j1A7eQTSq#P^oRM@5ze7`H z;%0*$GxB6lEKe2*1lqfxGN@}zJ!s=*QPyntzBwR%8>3|$3pCfh&VkDg9;j7@7(F!u zLjO_TVgEa`CQ4ir9WAW^)cl=>?99409-Q9nhQTld3yn&v2Xkh``%>p0>l@R|9!%>4 zQ$@S-#iaOZuxWhdJ1EeoDO+~S?!ghOQ_%_jQ}cNIYbL>m+1cuF6CUvemWO)o7k)f} z?c{H~o%&u~qqeZFHOK?2Qp;_4D^)zDExAgq#`6aFD>drnUlQy<#<=}qzf8~2`N6XEV8N(eX5>`pL=B(TFK0FP@+-}Oru9$qWv`ss23uEO>5;x&!=S7q`xpRr(_ zH6|M0$IRc|zi!ctI`lJLb;zS>zRUX;@d%Av5Pe*&JZP3zz*MKW^CC+E$J(v4-s#zq zt(tApB&YWAI-)AFx6*=nS5@uC;3;3;r^SHZ?>}sf9ZQBLF+6s*`VazMayNp}Y6w0C zzte?$t3z!%ZwP4)P_iP9y`q=?V*&4M04#ZigGm?xG~RZta+=e~`D(-O08CfZt{pGW z6#sK^kOF_}gY2?_1ZR{c<(}$@`h!FcDHpkEDa8HacH}4hMz}_7CNHXA?Leu{Q$%l7 zUcI26rF0eA&>#8!nE+8q=SOd}9hXoSxVgh*&#T-`3vl%Ji(Qiwrq3>EfH_ANAY1Tc zx{v-Xcmx{gfa0^?BTlSBepNiF> zB7yR@R2$eLB*FLS0f>jqdQXyiKqBGpA8(fN1cT|X)*fy|>AkWe9zAsIohhC*J?&cK zA6}h3XQuvsEY&+PTadjv~aTF<1VO`M9}x`2F+UX9hS?!Nok!_R=zF9F5; zFl>A>LIpTWWpUgwI~u5a|K>w4tQk|e_(|+jA0Trb9)^9TISl_g`oZ$m1Eh*q0%x7M zcE91%$A}g2*4kfhuU!3ekz;1_ZT*wEUGopFM~lC9FF2$fXjfj}eMfHFtlJeaOo)h> zf8u-p?GxrOw`=Dw3pg77*cIG$ne+P9pC~nv1p8Y5Ry^XQ{n^j+)|;J=+7nb=&Paqz04J+z?754;$(M!}KBP$@(+5n9R0dQ1hBu zSLT4M8?k{$T!rq;NmougA0q&|K>WV+IC}?9r26T!FWvDai2P1M!=isO7|W#bsl$1^ zfwF8^JZ`Sn|2!^^KyJsM09+mZIGbK#478tD@sJ-P;uop1^EpAHG$#$==+=v;D$EQj z3&5zQ(6M%PnoAW?xMg&{kn5CHq}b5zU4`Kvuo$W87id>@$}*u=tDpKZRci}m!>k@e z5XWc#kRY}}UyV}(sq<7ZqWI52kvjbg3SVqSOrn@nQ93M>wB+Q{s-FRt2Tjxpd9>$_ z3D68Vv_7Rz>5ic_au{1JwSm~uJ=DknG4xa=Jx?d~YFh#)C}=5sFe9gfbW7#AJ5^TVHueWfGg5+hq$E`-0W0=5 zi}W|z#QX4cn{7V)bEVktfK4l{N@wYCR8aQ;N3DwQn?FBy>m09qy%`L{WZ}z&b%275 ztITqv?vKMyPd#g1`EgM1!OW|>PA3BUQ`nw}<7}hBe0}j>K2qc+mG78$b$*@o4g31* zxlQ#0jp09c^NpBiLPd)$={*IjVgO?Mzi$wtpmGbkq=WIfMDZydC zHlNR5KQ39(y23)>)xKCtuLrr`%*4el2qq(*24#%F;$t;3UTOKjES2X|ycY7alw`ulo7R*AqCXPU!FVByfPJY1$l#DV8HaQ^tTQe99d$ ztXb+*I%td$FMflLhVp;0trVtOxGpp)1mmfRsV4jr^+IxQWg!D@qIzbY&^K=biT|_+zd?uv7iUiP^S)?{zlQ(Z=erVtIPgNe{*;RI}rY zFiEMAj%vA!$!e91H4VLc0yd=w5+y1+tGi^ifs%avLoXk=O7&>@U%IF-r@zsGUdAoeKKPqYIWb>86%5=D#(9!i~&>>+>1rdm%0qoVJ zb5!I9rc-TwILgVx97*~y>jgyPQ_Is}ePHbvjLlSRl_J-}`gr#*uUSk?Zpa~=G?3KP z-7h=fC7(&Ntl`xZI7n)OIIa%w8yj_1yU#iyn1>n)oUkng^%HDetXA&ME$iA4@U4pX zjfG-u`?VC^T-b@v%wxG2-BKqQ3yNf*ZjGvUk$%rN$8yNBAFlr+Mmke(`! zF<>)G^bKwlF&HdCRVhPSHhjYzga9VNj9eYPB0rv2u>&1N$MUI%i1a3&7$}HXYEWB> z0o!7jqfALd!VT_!l54&-9@~o}?wmLT-}31X_T>SQ2E>ZHyIddOF~yNVKYojlL?~Nf8}Hp#MLnzA-qmsNFiYF*C`;b|$uMTNB%MGO=yjwr$&< z*hVMmFY~_les!z=^r`Ao)wS!Ky`Qz7^{jJe8keb`la3+5&B2eBS*gf~qEM}{FpC+YM=*#{{Jx$pFa%tJ7Eoe#(ci1X)I-yO za~2BaP7H^%sWwoEk3up+R!CUlKifGj1T}@e0eY%!abiX>)($EK!W$Jp)Wo(WSa%*%Xl6%{BB#sic6}v)3VX~-jy0tYW!R!gp5Z*9CGjJ{khUpqthZg z95tm2kQ3T|YR~(g$zry%#ijnO0fkRL#A@}|x%Y9sb0v6ix0`K;_ho|I5iZM`Pa+Rx zWN4)hx%L{i$tSm79iyHlu%rvcsp&QpRzLIhG48rO<1lSSbo#!+r|WJ1x~lV$b(Fj2 znV7e8kfDFE3@b-c=c9xLnYYzuf6%Ir4tH9MS$FWb#rfCXs|KRftxX^Gj+hv^?;qQY)*% z(2a;TpW$oH@5h2!EX#6BWC*y>PpN>d)CsH3NSy6n=dGLM26d7L5XnjTC0;D*n`IR@ zaMfQkyP0KC;Vq!ynz$t)W#OaUY)|FrN~*ZCYC&vy5$hq3X{FvboHm~lU;3y}u0Y=k zGX2E$l_G;2wEZNDzM#<5mV8n;I+9vTct@z;Yfcy0!C$hd-~ucaLohagR#j-(*>Y&O zjJmqtH`s3a_99{ve9t6(r&E#fU%f6uWLK=OBr2H3rk3H;z2hb4(?8^c#z-b^qBDFQ zoOjmXF$D@~tPuCfykPWYZ{{i1%_cJdw=i5W#rgOBmT{z6DWxELRcHNk%gTmeDTJy2 zCAFeJmZ<{?1M@1tl;FI=DnPom%7*>I1fEIUJki>B1=Wgt5G?Y)+L8aJz(EaE2pFA; zuP|9^!EOEaqS*XG&Hf{TY85^MRiuOEMdL<(mgO6QG@4m9dqSpVUO89TpU6-4`|rLj5a;mF>45&Iq=p@y|21FS`j z`Qgo?&xY4$UmQY{qf?72T=|V6Q1B6QuhDco=6Dd7j?onp+|nkw$~MsF->7~A?uPq9 zgIJbh*$76zq)tD3k;XD)X>NG_g>r`#{n035xGu)?8R5eL>vuZ{GSFN7+D6}=R1RahvgNFZLu zp|xar=r-07k_0{;dv!Qg27hQvqn-KbER=pa*=9ScmLo^g)7|PJY-`2soE$RPf)F$)f3}vaw|2Y5h(Od!|q$(7l)~q#Q8? z!b4GSB_L%WP@_Q6^K8f@gUE8x6l?nxek=k?)%|DX;Uq*RHHayR&Im~!abQb5N>dfZ zErdlXITUGv%0t(`g2&1rOUunm`E&2;$@ev-@wHf}W=o-vFqdc#;|!G-*G1v7qbyTf9G*yfi}$-bBSYdxYDn%xr8N^3rF1d6xWg?Nz<-E8*Uo#2A}T=_ z+W3#I$Yqjd!8a!u$x4Pl#VyRxzTZ2#lcf?_*Z1KodBNKUZM$RrB2vUmIXhut#NMtFyGnJP$suV=O~Os{$#M`|a?p zTOXVXl2v))NznWGOxJ;zpbomxs|=$5@tge5@$z&yv$dn3}8{HW|91c5ZJ^hQGTMv1^;s~ z`@?@2rn6bpPtK%MLPRki*_2u1CAEJ3ZF~}L-83&ilc8kkMA@a7kyhkpl>7sK1Es5_;g23j+3?H*~VN}-8{k< z`028R0wJTMy5N#XQ=z)?k=~tNhfUgwnVc6lZ^0WPPzobg6K17)oFhii#e>$GCkiVM zNy+F|dsQcPG=OjO8aond-T$#02QtkNZ;{yDZewjcwh!^mJz872@2?J8zvkLL?7ac5 z><^hRArRcBU!JoN61e*^3XbKuMKeH##|JpknFaO{1Pl-Z31UGW znEAn&b&34k6$X3X>WSN-_1Nh@eh|0P;QnemeA~q$Aw03(zT)id~t8O6M4L9)SQYHn!Klccok?$EJ>vJ%oxoHfpSu$!%HRQ05P>jd)Wv zp-N)LP%$wIgcXsvQoC_W-bm<8pbn~0;ib2guf$bOXodgT#HqWJG-yfvIoBC>8(`r75Z?E*DiU{y$A_h(VFp6=$g zFTL4MR_3LNB3%J=l*ZW0W+_|;@gv;pNuT}6Mwlgjn(EXCQXx%t_89`Vm^?31dC&Y1kajpaE?ai2fukK6x7X;< z*9jcw0kq$Js-0)D7IwHxE`i-UKGWoyC%t_DV^Jiz$2Ag)88_ei8Q)Ex*O>JkH)Zrs zfwmwA&mNNP*XWBh(`K*3_vQoEHWESU?{K#TBnogVB7el2Zi$3p(CE`aU|=Ayzz>W2 zwB!@2k_$9o%PGHwg-hs{fv8|&P*JczsbFG1*s9de_eFMpn9GUpggHe{+$xIxu+99JHm>8t=tMIX~# z9hg&Oy|{y_*iaYEmg$IpyGodS&wMqz-;&{F>66xm!S`z@s|7V|@_O+})6-r>B5?bYUPV3t@#kuQoDFyeeaZJ? zu~E%c7+_+^Xhp^cPyp2VFoh96oQc!&TVXTHBXj<8+_aZ5&78YCykC!HhGtpmR^P-S zo@OWoD<7o=wdcPnREbmvhm{;9>$L!tY5pCJDicOUKur9wr4CSKYph8@HIv?*U{i_` z|F>24`YymQyNm#f*Q_?B{%xCIJ0-9hwe}tsU?%$njgshT5Wz|=sKgiY6i%O zFH7MB_2R_jP1ejy6wJq9q#_M-BP>RZUmB%CBROOMu!W6IA!82nsOdKJeHdz+KM?`& zOnX#SI%~rcvpQ>6r|IQ*n>9p~omMXALoSSw{Y+?XfZr?2^VLMc<*3SeiStgB2ZdCO zk1ywQ+-&bnd1vpM4eN_p&@D<$8r)#RI1zd?8rlaafRn-PzhICXy;e;gn13<(ZGwI>(LJSO)SU;l@m{D#~N|H!$U2EH~{*3vSv`q=xctxkrCS zeGWkSJYy#jm-$x_g#xiYk!pAmgW*Nq24RQ^SZRJ#6>3X63)idnlo;-m((ePJaw8!2pp&^@*$w6U>7P0+Gza62>{Db)=k3J-~F9!HGpMLH>3y z6FkmL`e}#jeh#_O>-_=d+Doc=pCkb_+F|E8`zR)B+u%ihLX2Jjt=#S~^gS!LeIANr`XiK4LyK5D)x4N;*t#cdQi_ zqj5;oU0y#iYnT|QtHQ0UNR*ByqF8R%Q@)hsr|LoapL#rXRwyv3{9x$;I!AbBULm6)J@rutMabN&5srdiiTACSa% z@!S^Eh-3dd_`a%bxA#8B z-fd9<$^TiT8d})qAk@#sRQNUJH=p2hqL3Kzu4nJ5lB_w0-Mml8tM@>nI#8IKz@tR% zl|SMJnf7)HEH73p@^YL_uZePvICsNj@0KVznLUB(=%@+bX0cFnV8C)a)-5E;YVo9D zNCd;@m086(S8cJWybE)M|7@FlEti%dBCo#?|E}}hR0vC*EPtmg7{_OAaZ3*apeUvV z$NhH#tzTu~X-C6y$YqNAN=CisMJDe(IPJBE<5Ot>Q_id1#9RpTxIL_iqou2$ie63+I%$b%k>#WYpBbuu`ydLeBcweFAT?0P0#jvZMHIr=g zR`BN}qqY8CSNBy`1h(AG<~3bR1uasz-qPq5NWOI6>B0-a%?QMBwjTOo8awa1rof>} zUpn~B2OYfxshRziqWl69Qm?Ps5?V$w!XlCbMc~&gZ;)9+A)UT`#T~J9S5%<{m8YX9 zs0^pD98j{zP@29QMk`>na%LL zYvZhUr^t<&Zbs-*M4CU%-DffyzWWqE78Yc@{6;fSSEmCP* zBO(qimW9t4gVy3jlC@o1HMxsh(0tk=Hw>V3fj9N4J!_b~Zl!;QU4MVPyt>odLXV$nk5?mtu9E}T)I<-!fV z3qd5*ku7sw^Dl`AM0+WrYmJAM7-eLjTgrLe@ggMFyaZ2sU^0uVC>d-ypDq^%(3!5Yl?vHKh~@W3^wi|TvSFO6n%IF=ZQbnwNfcdvi4sjkoOmYEwP zOsLu$MX-JU^?o@AHja)orTrAtZ0lWq*a2KfpBh~?m0B=KF*8;h+#Vx~`d=;p2lL1_ zal$T+Kt{~UvEO%i^9~zHSOsZ~>*MO+A~1k@4{&vmfwY~Wq^{AhJ(WFkV53nt-hII3 z=GT3Q`1BhiM@eq{ik%aZFj<6@7gZ#+&f7%_-_y-4cX#`_`QoYIV(+n^^zgJ{9B`fX zIR|N-12CK5lKbnRJ;k|T<9nhIPTFD-mC;gr*Zkg{<*IxLs-88o#c3btadcr(9G@XIT7}hn^194uXKhe#&X&1`F1nF zB%^U2X{>43@Y0Qf1u(kZY~bqsK79qE?5%vBLC$=)*%5=6gH)-0brcy(mISQn*H@$gR)8;bOP;;HgofmxXD$e!a%m> z)P_)rYTn<}TP|M?M!S_oMMW-{nxJK5c-eRpyzXWutG{$Qnvb*G@H5YMmoiW*R9ok` zijlb)9Ummtw$+e9+0gqlLY_9-+$-V)pZ#x?c}T$)Efw>F-L}p1i1_yh5&bPN(cuS* zY0S{bF#5v511%8iGVUY9F3?!;$(>JkyBLps>mSv2ERO$vuI!itk4&{<_J4FtOBl_9 zcmp>Y_&C1~{2g2167o8Id+mqewWa9V1cRa#AC>coK-vH@D~^jDlpSXTZB}yEvoyYo z_|YsC(kdU5-S5S|qi?v(v!9r#Gd1As4S6a>M6aD2wSBa@%I+=>r)A`lui7DkP(N^om&(f}Hg>kg9R*@aoDZCd^G9kDd!lj&6ya-tijE%nPP@Rw!6k$oZM0hTI zG~kIBARCRZxcq|~URq^R6kWq?tZaJsVCXj(`bc!?_T?7>W*eWo&2?qCt}?#{;;eUi zDnI@rGc$pKzPwB2E(NpLoTIh__tFY>;oLgy7z%7|#I zASgTko*2cG3W9$*O5BW-s9!0yGD38#c)@smSag$8X{88t4<~TfvCC7j-1=jTxeTkq zE)@jXU}tVDRC2yjto-V&=!MP6?)=w3?c-@QGDExlsF}Ox7742ma5YUWXfjP%qos#+ z;446jaVYc!gzlWU7LT>@y>@w?t~o;M?xQJH#lPA)1Hr|!4Nyp{^aD_6y{z@u+k4Nt zk@MSRI34@wy?BaRv>YQ^!}&o;Vd#>*oq%!TW{Ixbm*N1V2?X5g^A*l-W6yM!!10z1 zbyn{-TghW8G}Z(m;Nw(a)RrKZ{_2`s{fE1j1njxMplT??BUl)(N{?XXRIW&9Lxa4% zjELVLtmWj8v=c}O2rMi*Ek=w}UD*FKD+2{-3PlomFWVX0zDlCUbSX(OO__ zHaz6%nZrb~ipewu->b0sHaCDI)Ymp}%BaSBp|KzP4a=w=4w!;M#LRNK4Q-6X#p}6h z&$I2via#!LFNM=nRQp@ms_%=JBJpEHVG>3xjMHr)?ltPR0c@YR{SUrUvw>K}?W6t< zJdEB9UHQjMF^lFhfB}1=_+Kc-OucQq3UGezI^yAPc5X%jzr6&)2$0qMWEOa;lAB9P z0ps<%+s65AuPlvTxI|mwW*nVIH@x(QPpV=B&+Z|%=27lDlT(;FLA|;puAgb zoWK4|KMva)%`5v#&>AR^%Ydo~Ee#2kXQ@U-#Y7_l3#z$qd>Av8lI5oJoNL+WaTVAo;oIgk%l#I?=%Z+V^kR&6H=be8kjV|{FxR7w);%Z}B3R26V z2to-eGIYTO!H$DaeFdkGNd9NBNnRjf0tAGI z98vwlsL%q_B@_rLgVG`u72)Molm$g3&`2?tLc2RfLeBy!-X!VEG#4tMY_jALHw()p zU=0>F)59(7n!+u3VlWiuHb$6%K1e$nHOcBzo%)FTm7%r=V{i(* za&;3Gbl|ySKC!UY@owCm<#lqMYcvaoz8n`(CN+k3D_`WdFamBBnkx3yK%J(sS|fHl z^Gb6n;Y&+kwW)YUpQ3-^m!|+)z(xAijtz3thL&^6<$`H<&7sn@E$sA*-&b9e1LUhB z?_%IGD8;S0+w~kJ;CZVpuJP`+&e>XsB;-AkGphTE8uuDuRh@Pf6hYnAnZZ-?z8Dzq zUzQ`U*|Y8J+@{emaX_A!?OxnyWBuS^ZmYCSnHoBRN3H8>ef8WklLbtgrqA5EEpp`Q zcF{d6g2BELe#Da-+Gn|X-Ix`9EW$qcXfDLS?>lcJjHkylb+=< zsT~;TM1{p>O8b;I8rX{{)i2>*pVrU31k$tb+m#b*_#c3ItRQXfn4iLDU;1mcps~6$;r~)N`I(kdvn2;jDH$1`qPup8MvrX4`@9 zRykTj#2(;@Ps9D-R;QeNDOU8nG0_b^^13!SR#b;B$z+nk=G3ZEkyRA}>!Tt~F{LL@ znG~ppNhV7bl_9U$I_kradyIohHztbPb*Y&Ga%z zUb^#dFz<;lXjT%;N}b~!v{jcLTH zW)j`l^ug0uyPEx_J&G5%F6}&hMAKU0O>=11sN-0Pw5*dPOA=Y!S9F3bYo> ze#fg&cS|)+KF1kZDY}c!Tlfxg+?q6had=>I6YL>;mT;H{dxoT&iA70#n^ zMC8bPR|)vKgh*JNPqgP@OGqDDMwZEM-WNhefuJ*>x`ic|sE$qit%RvXNQJ`is>q6t zDkvP=9Urd2){!R8LaU*X#@aDSByhV4Ux|*z!rk;p;1Mn8CSuF9_=$Vw*f1fLyfJ}8 z+w<$!#07|*%oy~}lGl+rt*OtiHz;36)o7ml(*%60y+~k}?ZkXe)A^q z%k&2n$EE@$*iaaPd*E0sDOhbp<%e9yT(myzDgHm^=A_UR3g+*wdmkobWsH!CF7o8os-ykS99pN(zls^^8jY&yAK?>sc zi^L}w$Uob2&hO%EcGkc$f0}*!4E|u`W3PB*y0-4V*lgAjEpb13c}Ya`5S-gw=V-Il zzMaH(()IAZT50)9_uf;jx088(;-Ef7J3aW2n|E4SL=P^YY7YPpviwZedol=u;m-Q& z{~c|bVa(ZgYR9L?`!FRLy(HPDr>540X9^-jS+ba0FP(AV8Ift%K|D@!=)+Ole#)ce z@i#6r{~YSsa?f#2mJM>=$qc^DI1f|RU=<=xZb7re-ta-vu}N}G2kDF>`g;mpjrQ~L z`$L*>yZ_8hUYWG!vaOwO7d0@Y2k>b}dk)jhlH1#3+GRR5R$r9#(`I}o6;ib+C95|j?I#vfZF5l2lA-bOJwp7W#R@`JWg)sH!Ru`-@%(YCM_r=e@czI+!#YkN@94P|($l0`1|-N%_=gxHaWgYnaA_qxCX6=`$*Y@I5!g_~ z?tK#OS7i$$AlW_r!e&IvMX)A>@-=>7oyI7>OKbNY8}p(COr-Wbn#PB*986U zro~8&`YKd{Zr7gs8d6jOr2_HX%z2LBVDWU;EOnu5n0iItgV@j(D!y!ZfS)p}=QC_k z;>w|=AEo7{18ld#3Mv99?7vVU}~*=5XGFPl@5rV`TRnNR@)H|7cAb zp4ma>qd>0(^3GKtL;LZeNoQ-eKLu~%*TmROJ+@g^Pe6_xDBEp0w{6%=g!nEAQ1e%i zxU3RR!MhB2usH^Ix#{!=JK~}ZN6oW~!Rz4tFBj1NXDvxPWx~XHa{81VX=-;=#?KkT z$|`G0WFt3ASsAyX5@#D$u0TW>>o$>6C8SyGz8a}WI82QS2GjJ)Sv4YNDUP^;LwyQb z;MyPNei{<|3ll;D%e}5M8f@81%P5I|a&GYeX+EEdaU8ru4x)~3z!^)rSv0vb*SoK) zro?R=k23F^TMlcwSdjIn?4kkPuB;)p>Z%2zhlyoHmNt_gr$^klyNJ~s6>Qt_$V$M? z2Q*vIs;cyfHa^{yj>G2naLlJ`@RMKJlk{?=fS zI_mWMS`X+>n_XxzHs8NrMB;z7HQ58q$I-Gi@x_Dt&F4Dda91s2uR6ujE%@=L(5OVA z>`Hpyvl9wU`#@Mos-MJOjRH->>!DL zl=}U)b2zhKGlMR*xao`T(fM99BGOHCsPHb-PBu!f;b=2FAn&0tlrs=gb7=8-ygl;Ywhkt&0T|ITcA={(*N?m0` z!<(hlRKCB`zw*6Pws?sY>2)+Wk2anb@oDFPS0bw7R{U|kn=KeRw;7djXMN)dX_KN0 zGtH*-K2xIQ1G@LXcW)0Lz8eF+X`_NWq--r{Au1m^^?7NTP=K2uf$ap6fGracei>QZ z^glR^aHdF3xNwO`K^_*P)}U`%afVJ<=r7DBuHVVm#a{@s98#BaS`lXiPZg{h@cU5^ zOvdpL^eP30SCMWK2=@QA|5^^WvcctDbmt$YacnrLZFjyK8swG9YAJ&lO15~ z4g<8Q+o6j~M-equrxFNEh4HE6&zlz944$h{GP1ZIll?BlN}kur!8Mu(-$*}wz~K={ zQ{a2zcp17!72AM&M4pU&uSI^&Xsjr*&rDdCD{>kNo!;-4vRXQgkhHY@g8ASRDQaYq z^gL`;PJKbvDZtJhQ@)*W=Z4+nk&D#g3f%Lpi{ndLs3{YzA*4v--A1sRzb1m1q<&Ul zks!5c&P!ts^V=hEgiz1v2JU`)K0&z#Z6Au$b)0Wei3y0u?=mVOd8^a?HX z%^T1oQ2>aoPQ&!no$q4EdM9a;^G|K9ifBCjp5Fy)J{u3JABi(82gSlQ_K7d=`^aq? zj@FY*<{V}_(l1>GBbU}?v+uhf#8aQ18+>&JXKT{cvNmKhDe8m-+tObtIxT6nvGp?A zGMpV3AIAHE^Zw8#K5t)=Tb)gxQ9`UM$W-?O_mnM*4A^M~LHKfiD^)U4DKkvNrMvO^ zpr>*yM((Eb?dA$AP7Eo?K+0MIUOJ@(-c=wT5rkTO5?Z|Go(Qr*lBiEsBtN%zO~NN@ z``UjI4OF;>^XDC3AIn! znBaho10<_;7qjw$4IKw>n@5ij9g)O9j8dm#qkhLCu^hS?4Ml+{D)9!bVltygsIQ<7 zNeR&J_2uEA-(#ZbvwS61R(#h#&VM@gygK5!@5yz{^t7JG!9GQ)XMV-P<6~>R_anD= z117409dy1=uAKBeoW2`8L2^2?uSNJyynGopqk5kT+~=0KIUk}cUtigQ&^mlQoUThz zuTs7n-g|QGBeGPK65{P9S%4+{JH0oTZ=;AikA=E~omhpFitowS2p)z)a^td3l- zS6hdjuEO)@m1B2ChgZzD`<^X#ATdPW09aIp`se-%C*Kze;JTulWqYhLnWocw$*P|5 zt~+?kkPk2Q0gmY800ocfeU_?}y|Vdw-Y4{qeI633`E(PGGmn5iNq}KCE_{zsF;z?k zKI*|h4@#mLZk_h4ua3*gQT1~?l_cunnsy!m&KjPV8QJfh52h*Fc8jD8hOU0}iy-NnKnV$9*^EU{X}NKdxZ=Msz?nD%Y{EQDMvt$1`k8-J zkqxU1F2YbJqCw85mMaoQgez2(b~=oWAbm%hNx0)Hi>W@mX5R1S<7sW_#@G{*Y!xG_ zFr^}?INfcYn+0iP_(Mi%h)z-#!|_Hkn{!9T)!Fvw50(o@1bvJT7jYe7c%KrhX#Tp( zl_BRX)vQ-htQ1c_KC->>zK!0n=gE|L2HCRhFf=}X4NQdpy#UjCkS)k7_Ym08Kuv`v zJ~#wRNkORknC?M$6yv<2GcVNK%ocqpMNOTehQ!V8c;#ND*PeUXihhxy%Z}qI_yn(K z3z$sNblng1lb7YaM$d7hXO4!1apCjJj&Q3k#)yZjbnZQ|yC5PNk>(OP|4L}D zKssf)W-o_{&4xwf|4vefB!EvsHd;2a(YX_!>iPhxJ|HhN8~G!i)2jzzq{VW%V`nq9 zV{iKX09}f0JMIgUc^;6%z<1Ago2$9_ z2)a*29Z(#>TT+g=2&DyFX1$J@Klx_)+$@@S$s^(?znz>;;q!DI8sb}U93jf!>;%_n zdH)rn#sBJ5aqXZ^?JjFkn=%dMYc-Xl1!py*X5tf>ve@Lgh+t4u{OIyd2Tz?w()iWV z3D{1X$=c!kjdE2#)l8|{pRpas^A=d#KyL-OSXoEnop;sxyIYXX>nN~cN^iw=H}&M? zJD2Iuy)k{)vNnx`OykAU%6SgH7wHzg)S8Z`OIzsNOOe+P8)3MtB=1-!%>);Vy%`)s zk^mPC6(=r91W64iPD9w`FJw*1t$wlqO3KqBVDi)MiFCz5guiaE#=riNz}j*yse+mh zP*4S(Su#!IeO_OE4XpRPb1XvcDS2J_M_WH{%(&SynO0x?u;m~F`0|+n50Teh*ZQEW z|K2Rp`>Y~Ga}YVcQBLImg(pJu%AUXOJ1E&G|H00m=DploXKQA_1F{T79a!Py)NUAU z@pclT$@}togxlN#9$6LgppC{(x>wo%;Xu3@jasKx6e__?#AwmMoHgmpl?-8HM)cBb zhQv{Sdaq~6_1xdw(oGKdjM<3p6Rmr^!I*k|+%+_9sh8@!^qyKCAIlqI_6~l$k7_QE zHPdXWtnUZnrU(crab4KZf6Lz!6-qGh=12Fy6dx=ALndshH?NguCS|>pL_46Ys0(Zy z$q0JE0E0Ni<0f*zR4b$e3m+SOLpB=VYt2+R|D_}jwT(y|7+jsI25U6bng?QryX+OIqe_Q-JG z#TM5ps}mN*Pc0xB&gXC!1R(}C*`M^K6_WuP&Tt@t5&s6V8Dr`Gvg4=9O4gQDeO~83 zA#eG;i#I421tT*nkDYnZspVn!{;eVZ&k_MEGV^!TZERVf5xgyF&YQt`YL=DvUBrpR z^_0(5KdaroXMIRl-D!iKE!TNPRmY`akM7g9G)-=UpKySddU@~JGWAlq3h6KMdB)#~ zsf4A<%7Kvxl1l<%Ett1sk$)0mcSlKP{c`>NdJV@!z(P*^S_)Wo z&SxLjS50X+OCu(CqCIJupPxqz8zpW1NQR15T%9RZdtKcgZJIebj!e9tmo>KdQM?~ZS~4|*tX=yBT7yb%OE=fQj`_aQE0W#59l(H##Qari z=Ls9M!E8t$wklN+Ne2vL@_9-etN2dr-2L8DYdPZeR5)JX7Kf|yVn^rE(wKt2@h^8_ z*3PknkZ@yKsT@-kh`8QAJS5MdI!HDhv`n+}sRGx>XAQtoZd1IZI|p zJtsd0M=Ph6lPRCcTVbV&pbd^?HT{{=A(0RvCrcrdsr@%D{1v6gf<^B*nXZDHrHZ9rzp+hZ{ZW1pErXwR4^Ftoh zM-nmhbPY*si>6z(UR5X2n}yxD(fgn=7E&ZCYjMmZP*T6+cUDihq#x6Kk2`x1NkR|r z_)RRGd7aI$Dy)LEq^&uwev-s%M`9ywkH&);5zV>>sf-7njQwTPY_pEbF4 z`p4G4B>>-62L_YqOO^zE%56UR%w$MFOMEfP)55^W?>Daxfb>eo;R(or}` z*bRnM+GZ_03(8_K64$i}Jk^Id->2trTWVdLjbBC=Q*{)%uJy^%W3Us}-Df646)3M< zw-Er{N8v-?n!9?gYPC2a5YUcg{OjzWN>elpOEWe?!ln=u++(E52t+!`Mt!CRV5sdK zIu~XxpUxGxg!B4;jE^I|V)+Dc|*5j-YBj73_4--|?CPA{KsA8e60vd7LuiZkP zXl~>OD-Da;FBXjt1LL`ONv)1r6HQI&fyU@nRu;S1=}b) z6pRbvTP7vDXc-IIeH3)gaBAY*jMrI3*56`#fSxicLqntOQRLM}tF5ZhwCrEja6wN+ zuc_+3JGTGueVi*wwrFA5PpFj`dHhQUV-hk~W+kebj>&AQq5^U+h50LzsK4BAWYolY zmLCyld#Dd>`m{A6yK6QinG2`>Qv;Y}s|tS(isK}2vMNuyI2u>xq{+!uK&nsGsDDJkwV1DKUdx0?KV&d!YwOO365s=O}B!Zj)c&kM?{;_Vak9S5KvLd4-eoE zL<BqA&CA{rmVpvqaYI>vDnI zXgx{qPq}eC7psLEYo!6vV$F>zK6>e@9qD*bz!5@eLo+LG_UX(~hT4ojKqyRLif5xDNNFu}BW?^8f!I+5NVGJ93vM|2Q(YlxkKKq$pF=Cd@-2-FI zzLO>>{O|q-Qt2GdszXF*Hv6IWr@t0~k$ohZqU|W$WPrbjvkgw7aJ3K)RoiYl=oO@Vc3W zPx~3ekGI*ROpnIyHBSpwbdxf{3?5C84Y?B~TlERE2tuXu#wn0l)R0+gdq#YTe9X1D zl@Uk&r@#9DCjG7S{SF6o@hPR3WH0qp0#dFax29DfyNMZoQ1HkK}Ek|;FlX)5{1AYCPp)vgDA7e3J4+#O<@R@pfqJX zpy};=M8{Q~?VCpt%$vO&rfn-P+vQq(c%*ly+kkT$pLSZu#fVPIXX!ax&qeqB(|dc< zld$uL=JVv>{Gff21VeWH*Gd z)LKhblRT`N7<#B=p@Oyb89h;PspM%AtG@BZ5YH)ym}9sv(aaicF5K+T%&c$xv#Y$; zBD6Kvc5-}bnb z)36z6lA6iS`b1jIltkT@C3>Us+B6bIRdbFPk}a`>p^%SKWu!=3=J|ZGcnT&R)ls>M zesa=4_MhUKigPO$?VVgMR9%k0j@OGMVJS^y;XVyX0*J>Df<~h|jNhz{m)n>w>Dkai zlyoyQ>icgImVN|=^9vEUhzSrAl2WA|eWFb@g@=ocOJU+^T9!X|9+2{&r;~VK7ieDa zTR^LO*F0IE8&4a*h1-0hb$tBl?{mEBhfA1FM8q{Hak{iFHC{>| zzi*gI09m}vVd{C`r{cOl!thtJl$@X5xTez+h`x1!K zPA>~7eg6W*cX|)t9akplsKkmXAN6{XQod`~@3xI|37iPH+53r*q~xs+M$?mb)+@() z+WJ|4TMv&a91lJF?JtHTUa1-E6~8e98)a~O9nmuvJR1BG^8 zusG+4T2GuYRNB;We}&c}C?}GLD-_BrhgVoz7N-#EE-hHF}K8 zHT(sYeUE!0fU8O()5qHa0(@hxv({V7d0a|dUhL3r@`xF8051M?xt zmXWK|%a#VnUruIcKX=RkYcl|U9ak1asXvFPHw$_XfKz&a_v6oI#mg&_bYfI}t&OT+C-M%Ts7@`8~W}vU4p0=*O*tn6?ZtMvNl&w&W^B+d-MH0;4lMcmcbmg_&!W4t( zgxRPVO-1=f1a*nJl&k_CSTg>+qSgzmqps9b4IaeHt?4=!8)@-j1We)8v9CuZP7w9#;v_&GA#L=i(@kHzCeR@`#pZ=b56%R1641@M4;=irbcs zd}8#JDQW$D6Y;k!sxqOrj{6$8e;X&pig-`H#dQ(e{eIl+S<9_X4q^NgHiBeZh}T<| zn%@76)Sdz1h_-mFXNaajW#X2(0?yU7d>3St32K3Mbs-WABPvvt^vJ?NazjzQ0@ zHtozg>enY-tAiaK(xW=bNl9hnO#3r zc?aU)P!c8 zgE{k?mAeL_|E9k@V9;iTv`dHivA`=rf17;jTF>Al(m zS!5t*DyX1mYV>#U0D;&Z^-5Zjb&k;=dZ?Plq~J#cj?e>7AXW_J>_5W4D;S_h{5Zs| zt1lO@#AKwRr_QhG3ae^@;Bkkvr2lnEFhh0BPW7>GGmkY`oAE1}kkDIJsdrnK;tRc| z{qex=&4Pi@zurgP9ro-?1dkS{SiyXf&3zdyhl)v4_B%rXR(>t6TunSnuc3s=*Si#IC}}8$ zS~e@51HVMCzERbkD02!9Q8LhOBp(*n!g?<5QFfh0+>Qs47Tt6}f_r2yk7_D%h9*_n z*HdOk-?h|%hTSX$4N-|RJnf;vCoRNL<0+py1@|a@0Op3B>}R2cjV=rBI5hHi zt6}NB0&Qco%zg#wI7Nk}ZGpiRC1;>PR}rKOYcSMHw#F%GwZj;66YD?oQnP)fErSO& z3yhHB0XTa<=&wFQ>;;k^;AQI|!?fJda*hK+NyPFdxHdQ<(5VRQw2J9WjlVA7TgCCH z$q*rkwWo|WR!3cy4li5!7f0^q#;894nJaUqe^{&F0ytwA+1{+^hp!ETE425>>P0?U znag)iilrhCSK@v5v-{xYq}R9c-pn6?f5~YtHXi4JkMPF3eh$a+BUT&r4-SzuFn?$_7#^hP#_MKj_w);r)i z4Ettc4tq7vhrSL9A&D?Lv>TH{EZYmW5o4}M;P<~QC))CMcnlJZ9|!WSKj&=nYSe#K zxScZ#hphayW#$TI4rQdRY`Z`x#dVW+P8?&P(^sL~w`t*8Y8BE`vb3}uthJx7L`?^a zq+^TuC24u3fecAlnqPqSFe3S()T`Dh8Hws1+l%ImEVMw6Ucs9JE9ijAXpX#=a!g3_ z?MWb@0avyla!uV5IE1pEz3Nd#rl@M5H>|q4p9UG9+f$aq8jqnx{*6CKs_$B_o$nq~ z0N(cs3HB^I4gy0=FVDKpZiNl-WV%XVMc<`Al+Bixp{vJ6Tic{vzNN`-nICLj;Y8bT zP#xqnN$r$>nh#=Ky=Jtf{fjZe++x4-+EwCiv|44w`-S|AWDKVLi|%Fck@b}h_`rq! zrcCDYF9OT+zigCR%|bG?eT{?UNh%${|M{O2gUm(Duo@Z4eW2rdvs0_EH&`?rOFl{X zQ7$szfR~xU~WVehTNmAU_vJZj+KSzT(Y;ZAQ#)kBtYh-_3+fn$Uc8{okd- z?BhC#Hf7>FNmn~CN7?nVytc1`&4*Uhh81rT3*;`oc@VE@DF{a>?9PdPJaG~%zv zxUBKHlqd;KRVG$Ov}T{v=+-$y_M!Phot=FM0r#wbE%|Ikb#cPGGJ;H0n`b=D8|Rmo9i=T zog|?ID#VLYssm5@j|7Gdc#{x2z};B=%$(9+~m3Yb6& zAyO5Js8W%5B@q>(@;+Ww79pjaz|lK_PSwG$Tt#Hk$Ov?@5r=}Z2mw)%!4^p-oYFEO zraV1jJ*p9A^mv%4hwM_|qyNLm0h^3OB>(yLpYd5wgDHa53V$$1fg{6`yb`D;HC6u* zx?YO@&fZr034S(4-I~laPei3ul^6>$OAX-@>oW8lhaKuc@VGMj^~M$y`A0>vlxXbz zkC@zfG#^R5XQlSVlollXG%-R0`BENk3>?V&{SzC0hknTLP3C6jOO$MPYsD5iqwng~ zlB)L(bLBJto6X59w$qZ1xkgRRdN)3ZNk6396z@NWV<32y7_gVg{Gne@Ty96Wk0RM2 zkhMDj_h-YMw{oO2rEv)m&SR~1!-10*Lj}zno1b5+rqWcpS<%GHxNf!GB{I_4Ig^=I z<_!|jH%(Y2?dNHDox+~ae;dMRGL<2bHW4{n_cx-+b1H46&>a-%EFB($&;p7n!BCN* z1+;@Bi;_~}txQf8RXV^fE&k=_7Lmzt!Ab2J>1TPj5ibIIr7IS-xvt9B<9eOtOjk4FKx>!5Jy9hl9XEwltY|i z;SB#(>zAx-un8g{l0vE4^_dnA?T{f^x6?@gV7KZ}52nQoF~+VUEquKSnhZ^^@=TUWa%u7R%Vpis89ncG^O+b2gCz?N*wk-soP-Y^7PQ@`!lpRQnr!oR91Vq2Hx#+kMg} z{Ijff;F@S|suKragi9Vj*)mPI40;X?vE*$A2phT35q-bR=6@Ugfkt@>%Qc!42;o9e zs017R;X+o{#1=gzbS+qCBe$`y)H`w6HvFsT# z;TsXPn#$#?*G{wgejk^h@69>FBFxQ-mvF&xs< zrB2CRrTv$a1HsSAy8L=|#HAIY{=JHj>7Z0;SSz#X;3)E6JfV{~_jAIU zc^23j=-oszDSZ#@wkYMBhyyU+)GqV=(8l1vFL;@@Vy!cOL|*^gANDX%m>6D8MaUakahs+5 zwDMkdyt|AYViK=K`LQN_1$2gOR$PukQNe$EpA_^N>Dl;C3`eju;Y}oq{|?N!0B^(f zgmZ7(q4T<-%dW(5V@7mg%~zH3TWvm3TO63R8GUzPxpqnt5SbV{_lRt1-sr zsRQhsXH<-3S2C>>#RS4$o1RgwV#y4RMlHBcY#e%}d7_~H6@CQb-PInUimpQ=V8g8+|ET_m&ICJ?jp)$#K8d$-~r)k*Vo0Y z9(F)9o8*<1H%ATuJDF>@rpQKZ%ruQ5kHs{C*Zh6@gtj<))%!S4)}AjfoD5sInZF)x z(E)Qxj;d1ARzG#kGZg_lE*}x@NR_RknRx@(wYGXcU$c(EQ-#Z1tkt-4jP2}^yVz}g zqDy*sW&B;!)d@A95N0y&dvRZ^tiOk&uU@PG52l{J(kOGKl}nkAKs(&oshRko*;e9i z!d)FzKvE-!pxanra0WgN!%{Jx`4QtyN2vW4B>uY9Ooh=;Wt8&8HX}**)Gpv^diU5N!%uD)TBWr+2w4bBRFZ&PW-JG%;j0(Zru&>&1(LVyO{H2Ycxme;MVRl z;8=b-RC*gfF#PjqZxDEk2(|9Cj2k#$b+F1*=Z^ z4uiA>Vm>FXjjaDLn=Ggh?ry7-ht=YWsY!)GikY+wn$HD6_U(qDyq-EF$pDJh7s`OQ zhH4qr?g48NAD()<+uwiVp1?6#Y1D zJzl(lEzgGxjIw}(n4HgI^1u@Ch9f{9r58&&c|g5;=8-?g8XmyQeQb#yxWsf9#%Dpm zc#MbBdZw3VatA@LvOLGpVgAR$I;9HU?xq8lKG~31IWTk;S#AkZlV|u5K7IHvscW%@ z| z(r*=wduvdzhXfeInU)*O0VGNe0=3?%2T#q1S0Cm#>sM|efcv@m0;nt0%GesY027#t z2A|i2;>O=Uv&{HUCXutgA!}(r>=ic?{Ar`tkhlr%5YkY0+th`Y4i*Jn=Cy03#h>&H zbf(EkQ(3ipn|A|Df1XS=U3Nrv0)h!7ik@w+M)jV%FMyD_5UU*uYT`)qk21ztOK$f+ zZ4V9`Up1%vTzQwhZxT#lOA8?^Dw;t)c4WW1IT;ux*#$wBU&`E1Jgbn98*~&U6bUzW zmS9+-H4DQ0a7EBzEB;b3%z&80Opv^M*mS2|+o7yqgDak8=Mfdszcy1tJ=%bFk-c3e z^Zn}nZv3MxHt=yWNS|%jqT{Nj@O;L36joHTuA9dbt~gJ5=X$5*rKNvhaFatEXTbT=t2%H|N{(>}_6sT&^D;g+bsL&Va!x z`*v&Z_cUPC8+<4jLLeDkr1FcN?u>Pm!Vh|qjdBvT)&xt^hSErK!mc1rf0#J8dasMU zZS#Nr>u)DvgSd)cj}F?4*!}LI22#?g|E{5)2QJ?!+<*FvUrcnuJ-!1ej2D|ZMBTM#oB1@hdqRve?6X%Q_Rlf4zY*bM@=gjX z2bL?DFItH{Zt&J$gsG@EWAhg_cvg;?6#)2kyXxu;91B}D*UA9IiC`Uf{98>=mzH7{ zir}>h9<}V@F4BPV(m&fy4 zT{qFKpFX=cyQd3}-NU$!B6D4DE3LY>GbELueJN?_8HM~%p?m~_7k-N{!_9$^)QB3G zleF}@Dz)^X7qM2hs4Q^rns6YP6TlI4gzb;Av8$|ky2*kQyGMmj9z#bU{5n@sQ{-B= zgF+niq!{I{9wlL388OjsNyC1r6_eAy^u?4VcR~pwS*$97!aP@7w|A3RVMn|tL$ufd zqrv%P=Hrz1$2I*|Kq$;PY|Qa(EqdZ}3Me6P(Hg_!UaQqnPs!k&>ayT)6HN2K;h}Ju z?{)pfXx2Xe^UC_=epqYs?eRReH^Oo!Un;sjZGf~QN5y}6WEii#aLd~pqvPb6hU4>@ zrbe>DWtiFg%lc$ym<1lEL>O|-4Zm{{&b)qlu}Zi}?xI8cb^nPyV==AfI|vcF=V=fs zXn^xoYN8GVj>g1@BDqOu-72>Z-;vlwEZ=3;N)6;V6_bI&sD!AFsD%(kp!;PZNrDH- znNUez2s*Fo0@kD|R&`KNl~uxOV-4sDwc{lyNAjC%2TH6OZ0>(|0e#`p^yWlC+C4^@ zpbQoQ=KvDkgMo9PujO+%=brm87Vj%!H~8g%{C$f%i?4i~C=Xeqt^@SQ;$mY`IJ%tWq{+uYB~Ky#qCj83Jh(%M9f#QT)tSb|XIGE+Worq+fBb zo+h&3-*#UPF6G{e@r+&N*iBsqXGi-mW#;UuaXXE*RMcoFor|#T%D%o$tor9x@}Bv{ z2wXd$vs^<90(&+fq~eT*lkKoJd9AQ9DU1h3NqVg^h5{ib?W{Az^ra!>!Q4RN3Adwd zmdz|qrSa`w_C!B=B)+cr`)r;5@>*I^RwNfL@OMm2#*RQ!@B0HV7Aqo!z`y*pPj;Zp zV=?Ao?AgW2R=hjB$o_=lq{95qYe+O#UFqd9yUZ|Mdl4dkhh=$XB5#3nCoyz0st|^g zU60>7a4s?-s zwxM==&2U&8mRH54EETZoYcd7Z6F~=Pts&7wf(5t1-2-EFLeS#p-`sJRCHok^fWX!C z^e)F*GNB-_j&og?(s-KLLi{>wjG zfG-p1=lzYU`S;aC?+@|x@ge}2YV0rbHER-*xhwxs;LxN1o`chfzmhBkb=lK(sm7ME z=H$XCJ?PKe8EWb&-RAi2K|i))MfqefEP4cl%w|x$T>mZzVF3?8%*881ijf^0z&H0Z zkM({<0RKsB2%o~H*{Ea`BS0!va0?+d>cAfni%B#IyS;u2#*m^G8(ebV04? zMwOTXL=~}wa%ZST6|oGjsQx?&srongl28;-KZ1f%!%5BCeD-LAZfSviFNnf`Q~+g{ zSV9~Gi=vU@jl5Da%)t9Il@U#%Pcal+T>dzl*VG@Z0#8g>3^Xy1cEDg*tBX)JaHRob zVJq%Mi!GQvH%baCC}h5Tb^FkoFx4Io!t76&fMEN#EhvhMj_%+>E!y8*nVdSS`jl;`Zp#Wz}S_&lNSR@2dHs{v&Yr79?RI@u0JO|6ApfrJC;tO)oB znotN0#pN9SgK(q40oV*-;&-L+XY1ofqtYE_`^PHEYD?8FQ}VUOe~}D<;VR|<)!Oem z<$VbHM2`x2q}NcJtLl>mw8+cBLLVL~vl%~kx>VM{Fv)ywVvY7C=E{yL6XI|W{o{a% zmsW?ym4a3fYN_ywfs|MUwcfc$_s#xhdu#X`m`|9IjbJSqJq-n4yQZv>D4gWiWy*<* zO3%BEm&UV=OYTCqRlbR=NnH)!M-S{am;`B@P6rC#bwycwenPL|P6!s-iPxb&>FM>O zabNqEj|-ASfeuLp`%3|p&2qNfb$GPlnni@U3*q)7(aU72bR*Bj5py~9<$r!VK5fA= z=g>1gd0k}i?f&@c&WOM#4WCU{rCXvcd9_F1mCQ^}&qo$=o>r9g!iycUJ*+?QU>>FU z>w_=?ypQ3sn>)nMb^gu%^n&MOpy3DM)DUg9PWBghfhDyBg}m7gWWB+pV(~kM0Pe2d zxmK9`#BRPH1tWH5C47)$?K8&uPvm%FVBPn5t1#9Gf&tahUYMIRMlYyPfp~rbL5X{o z(=p1Y+3jhze!6}~hf~s*S8@GO%EwJ|W6RadZZMGUT@TIzbdu}SEC|(8O#-EX(VqlO z3bAkabTvGD_g%@%{Ig6J2HvcZ)73eTdMJUA57&91ay&Di6HvV8&XVgc;)WsmC|*|? ze76?dsQEB8*3Ud%A-G*aoLa(UwHA6Wz1^4`xuziJjeyr_;|fl8=A)O})1;(dVokUS zyWiYb@?p~(%c&}Dx!hA}Ckx@M-ul%7l};M!=qt-Vw>EcB*eVA=cZRGaQH+0lwrg)1c$am%3)}IEkx0F9HKmB7!SngV(}OL ze!9VlnGA~(O_r!4U)dvih56Rx3@Nw=T0j?Q9dV0GQ zrjYZF`lO+BFGTI;=g0NVL;Elru~J8V=f+k=s*Ro6CLiSY`AfT}W&X&HN{OjoYdLq3 zn5s;&PJee~z0OUS_PPS#z$h*@Jh_r_)!092IO>|t(bRHZLQ60Gu0!4Piut+ym3%O zf-B5|Tdv#Tw45cxn9;L2dI*T9FftD?=}7o$L;Wn6VW8e8ftVD>()Pz$(2M&*`om>2 z`+={Q@nw@29KNUe-Q-&F3e=D+UER>PZXpMZ_NA&cWw|;*xJviP*8PY}`K+azQhGNX zS5Y@*u|9@ZcV6&Mg3{G7p$@tIusA78ARQFm8Oo~7h1WsjSc zGsE7h#$|%56x2es@tq>6VydDlGOtRY>PjVEr9w>TKk*8-t<%zD7qCS{1}R7(bpHMi zh!aOeWW^8su#9XlD55M~OeGP#5DmqJuzV^aAU#$wOvCbLXM7NN6bn%i(H~fpsIU@+ z`U-!Ds92R5;ArC+3}Xc>kliOxRRsq&$qvcB%7{t=vyjUC=OCIP6$!F=E2CMoGNpq= z|8fe+AR&dM526@Qjy=3@w3v3Z;FLNk2t_F zz`ysjao#Nw){V_i;7RQ$uu-fW$a9(X%Ko*uLUb(6;Y9xMqVOC z?2t+ltftCuEeJ^Qva(ni3an#l$i}}rPP-mTT_~?6<9sbH;;+-%TSSd+9xp*~YgLk( zGn~bA3`aOCU>_oi-e|Q6{Zwsm+Z$?&_`FMN=MYPKwt(CL$ zH=m|<7X$BGh|{NObd+A!_+b(GH9Ow?131GGFZc7rBaZ;>&WGo>H;MUdy=$ZXlcBYW~%^Xw$N-67f+gpLq1v0T#%ooE7Z zr*gvc#qOeOn|S<<3@(5f!jD98;a64mUf2*em0y~CjFItOv@t7W15^N?#CIeG_N!ws z22J}c*<{Pihob1zz`wjP7#zv{4P&YI!8z6+>pyA1Udzk;{!tiwcKTs29+@ZMdsh5a zl(mlRIx0A?_MN@j{$Sz(AC3y$h~ZPrWEhcixG@P*wV4J*&f)NCf7|R^IdT=@DBi<~ zS$&ae3@!GldFcWBKuOo_`oeF@4?8qg2~L2zq^#1jWp+P@S-Eg6`3Mbj4`{6)v;JuA z3AIhY;^Gng0y%nZz;6_OeaCO?ej=vDxx?|aK`nN)R&TwDK^x}P8OZw*;Ju~Q#H*Nd zo-}B>6%VIQSq0cifD@tihDG!VsPw#w4X0yv_;1Cu@XEvB$_9T`$}EG77rT+L__0Y! zHnIlqKeh*`fQ;+v{RDj@o{NSuht`;xX$~(l*sG;i`+0}4=khdKN>lbT8M9e3znk6g z5pRC5qup?V{AxkQhCY_ls%0Z-Z#W$CajT?_Q8O_S;<~mr%34e*UAPtadkTG{F&o0; z<2rjFKUM-?wT_a<^Cf7pHLb1ZfTL`GbFG|_CQG$asf2X7PbJ`H9aa{jOTq9mqwcZs zlT5co6^L_%{R`)a85FQV%WwT;64VMj<_76s?o17gTY#oa-jt$3nf< z)B1{;$?iPU6=ko_;ri%$u<4|QytnbAFgd%M>q?H4UR(ZSD9*9iwMj3IkI3Axygdka zl%zPl93AGksu9p|!NrI8?h8EWw(@YY`7m>OHk7sZv2JQqU8-_HG^REpJk z>h*$S&T0NyG0gd39?r3V8edN&bPuD^SM#q+JFm5e1dt_KeP>||Re(SO>vZW`n}C}e z1IOvIJsq!Z^1Zly#BWvbaqv8puvq(KYpP(cOj&Q&|n!u3VW z(;NOng7Dv6z>+u%J#G|q^*i)H{mZC+nPc$3(M|OqWQ+6Y>OUh^zZ(Cy>X3~I)Vrg< z?q_)DUo&ra?fIzZR6WrS)i|mE65=nHOZ?uk?i{KEBK*KCQat=+RQNyMVT}Pboh*;3 z{n@3V@l7hRs%~0Z6HW>{;@?{!A|trUMYng+9M7^VD=cd~d08S1AoJ&zNoH!7Di$nw zSq=>+Xh0#or>E10ii+%lHD?s0HDvvVY!*@Af){?1O3y!QRd=*w7BS0S*JC7?r*~Cs z%1w=%Wy-)?MtOVZW!Gp8PyAlQOngvlZ#$t0a_pPtzH1sPDy>gn9WGrRPx&3)q)Ht% z9$kbrL9yQOWwUr3uphwreKd?GAZPp1_nn=kz|Y2*{HEbk&686f#e5rRI# z5q`a%t0}w*>cb>s(cqExJ>!}TjR68dAPw9~n#=6g0=~z(2SH?6F(EdV!M~@I1)qHG z==CcR8TI z5}x3Jos4Nn6$N5JVH&Rld|xI+cXT%~AhWbpiw}xHbZU z9|sbKUOH6pdts-ZJUl1wR<2#qj8Jf8dNP&DnxGGT7H*WLUuwZ80ZknI&}G26so#OU(-H4VHXn14CBZ zQ9`-Olh;(sqRL1oG66QY1tP+uqxl}G;u1$?nnGn0Ek2GjoCyAzrJ~8MlYO*)O%(8E z4NNBWT!2aiw>$|6^F@X$4sl4#BuD>Jgj$$76OV)9?lE4*(g6}Cf(gw7ou+}jri4c} z++BG_N8&zSMD)*J+S%gQG74nIb5N8?!6R5KJ!GKxJa6EPTfcN3fk;v>DQ2U-6Hv#C z*B`QCF-OvX%gV)S<4%>7TqsS|ycN%XojZ;>WzT&T&}7?G*}BteVCRwlMTTR}@OGXf zCLBb9F3Ru)ciU!-;=4sQ4ML32DCV1G?h?;p>U?)3j5bzGx; z2}Bt6KB2bNm!yHgmpq)Jm3JTQ!ugpDF11R=cooc~4dTpYR%}7LgK7*s^Hq+~a+dqp z`t&zL0JUs)m*d>B4Q#iI%3xfP`-L$T#Zs=WG97d%98#>Ic>Q3#K0ZP!0d9S2-n&wP z97}4TR3=r6W|{e`){+9uj3F>kV}u)G-qL7}Ah&rw2riOFNkhgQGwQT6;^;8Z>sQEP z^!nHoHBI_6pEND}7S|vb2oO<$h|c4rrk&_Z{>(Q%f^c@kzi=CMx60?>3vIFPYeR7mB0h4xFd$P$GT9jw%nFMG(V;rNm5gW3kt!+QI`}{T;cYGLoYP~aK zNQ?qFQIbEYvvctH1j&77LgV{fjQwJD5Q!A4>!L}+CYjJ-&IyoRgOr91u#-ErQ457o6<{beb|}7|`lwV0SWpBP5FJ*;p&>sY#RF#+6oAbgQTgC-yvYZQ!$RB_A&SAJkB&)4t_7f!Ww z+Dj~|0xh}V-4XWg<)m|ZFNj)TZ;ggeU1r;y7zq(OJ-YfXy<#8Kh{0o5X=UYAyu`7j zsL|;=*swiDY78z*)7d<*C}3nA51zp5;&NzD_D?g=La2`sA4{B7I&1U${s79~YBmoiqjAh1E2ImPMRa=6r5?bEiW zZSKbN8Y5)kv{CJh`6)l_Hg)2CO86y;V{R*)S|vB^hzsS;V~dzh(7eUEu~@~E>0_AA zzvFZET$Q1AtToXZxsvL5RBb)njARbAT~(LYV%C4lci8EQZmlzR z45ly$t`}-hmgB=UJvW6juocRFaC=#X?VR&rb~M<1(sdfLPOAPZ=j~$hC6bEAga6=S zVhurlhu-K@UY5e=X}78x(0x~C?Y!N0<+kbJ=HJR;@ipGQm5t7be-;=C4HsS(#=wWO z(9A-;{hM6O9fzK8XXNCKp8l%qZL)9cD_y^A`(Zgi=y}mNPE{nOlzE+~4?3y3yHzqB!Ppb8G(>O<>FT;@h%n@^C7j-M^Og0+4 zpR9(t4B!banDWf(%4%>4^kDKB2@{}43kI;tVt)wEX{QI)FL9IYq4m_FQF`WT#7oXe zWgY|`bGOJTeY!O)Sa0MPqSrX74qk@1P8zu$;c)kd8UDkbwyiJ243ZD0ELOPzTFV_? z&^G{`c8QN-ZR5>Z5`mMk;x41#a+Z!pDH^sqM7k96|*3+0@nAXU9jb+(keX>(BdM zwTth^9B#9IMlo&r+n3Vwv4LZ6$PAEIf$>xVxdp)-@O0T8o~+JyLZ5ckN{$+dPjB_lXeik359Mg~^n$PY zxv}O?-mfLE3wrNu%iKJNYSu95ZYLT|HO+>CI`?p&lbkhC821S+)YRcacGRoKql{bj zjo9|LD+u2SjgA^6I_~7*MeSk@1MJ0ibVGh*4@0pRd;tBrgY4xO-9=O0gDvrniJ1%Y zO7?_E(8RvD{#nO1@E1b&j2$%&>Qn9c@rbL-&F*Nwc1H7as(a&MqMobj)3O=Du@B*H zz$aMW`_EaZxtrc&(&X@EbQ8@bbZBL0anlOlAVr0aP8uJfCv9#u2){!4TCzW&;JT>B zAb*nCiY`A6F+Dp%VvFLx5~v~Z+?md=EAgK0u@3-0Y!t}<>BL(4g1#n9WN!q5LHWsy0y7PJWFlaTPM7W?=v z2wa6#FxGgclBx-nc!k$+va~lCr+(4fBc$9_(}FMMC6Ecn#G^2$$XR{L zPU^0RzII8mlBMhhJn)q;i1>tjc-54+(EfCPHQ5F!aG9>uyPir%r1cBCm_a(qN#F`c z0S}5GANWRb{nVR_+`+qRhK{fNDwhddR%-2xc=261AcW}_%h6BhtEAoPoYWRasOzS* z@9BB1hD|k`97F%gij-{!mB$TnYq>gB7obMsbu4nr;=?)tyGfGQS8Au0sd;+0e6E0m)y*-S3-Ti;$A2=W^At&QlZ&#^`|wA1mIiCP znXJdUt6ds>jkH^n`)%}uO3-|FhE?POuI$M}itoM*6B-YxA#IgJcBA}OnDO-dl?yyKph4mRF| zHcw%FW1F88n}ys$oeQ%hD7wcHa)BJ{Vcapv6ELp+K!Sh?@-K8K$Kb(8-wrJI7wbti zJu5qF#LECC74j_G#YTFyqGx+Oray-Jl`wg{yB;u7 z|ye$M(z+3#?)DYm@YpK z{oCnfw~_i!`RD;NQ9ecY%L5jrHClK%3OL-QEY5ZZrNz=QQS^E~%Go|(>u(Y_BjJTd z@6?Vnv!elnNh{7{ZX4k(=~#CqO$XmqEWR z@MtCQ35{d^==7T`%HD_e_qn#UP2NqT-QGNyT$tN}Csx2qep5Z2#oAHq_XS*6=_^OS z&hC9K(+8*Kw26UmS*Uo8Xd7k;Ln%fC!_l7K3my7F=m93dxyFx{V4$@Nb))uViqtnS z+*lv1)#6GG^GC07!;_zIL^wx|I7-u{<_q+d{YRMAT_4G*cQJovn=mtOV+WJxfZuB z13iM?8+21B{?W>vej~q<0rxh-e@XX#db9y|bY~W|%5XWdTj2P31|sWMI$$O;z?NWn zW9B3gGXZY>?E}nzjt4UR!c7uzm|?5`Z1~nbX#vFAUIzCDp4btwtN?8WNr3j1z1(p> z!cwD6*&Ge0aW;Ry<%Kk~B4P>TYC$ey*3SCy%-RTj8s2_|zNsSB!45Ic z*<-Q)Hj-r{TdYg|`^i5`&Fw~J&`G|to99q@Z|oHB_m-qoJgiVfaG4-e2N&>p zmBS!cS_KvC0;VZP(5!^!VGFd1@=3nuLnkTZu@s?5N+BzTSHM20%s@-}AW%(#J*c67 z1&WC#(om_TlJo=3e!vGt-}?{v1ndO!jB+m}nF3~jEQ?-6z(*HSy5Uz-R7EBQD(Hb< zW4;74A5AOCXq*K_gd+AhP(^h$0tQ{RFuyP6G~PwIv_nV%|EZDK$F0Sl+Usewfu2$v z=>A1^mFOE}Wm9SP+*vkSvZBNF6w!?t#g}k*$U?lOXFClAm!EtNnsGbj@J%dXd>~3)81|Xk@kV zGX2b1KDzPC^LmK?2mo{^=IE@uoY{IrgM}N@T0s9^5xqF|k9@$u5BwWpnuJ|7GT~ii zv(WXfPFKz2ZSOd%T$nVr-XrLHz}23$3XQ~&R}05UcvEtpnoxK3V!?dmT$srecT;i7mYvW0t+3(2Y_S7G& zeMP0?B7Avs<9jWdou=0IIOLn$NEz zJQ*Ri=8!tdUJji(8RJvu_gXd0MiUB$KY?5O0RSO~yHOwk2ni&JF+6zKuVC3g>$faIouMzI zNrE-aES1=X23g`(6$|*?DxOhDcqVc$^% z@XHe9japu20czp*r)l48AymyL&}zYg4Ha-dfxhopU`rA%kFob*c}L})wG2; z4EhKIp7%`#tHklRo%d^{B7t2Logt0eM-2i^j~30U-*Dsh~g3(sY4} zBv^ZD=EbN+O5oVI0w$;)D;Sv}!F6;*k zyj>n-ZyH|+mDA|`ETZoWJb_9e1uZ^dBteQ@CuQ#`%Ik`z zLf;r$#pG6vNMTXHnE=C3$cP!4F)BECd%H{()8!AwuyrzRg^h-`WTDBGFtdJJ$wz>G z1HOk5kc6SeP#xm8@X{*X&dyN4asxQNe+;f##YK@AIb9e8eXFH49m4wZf-dj#OKZmF z3Sf6BW1I%Z`$wIpZV&!W(&d?AuhaTJ8Cj3D8#osBzO|d(=bG1IOZUHF8vPUWwPH+c zMx1+?&CqZ+XBQ9OXrl@^Wr3EA=$~69c?Wgcede<3k}*C{C1}dmR4aU?ksq;-oLs3B zqs1BmxWrMYw%+i74u%XuG(|6(LqTTaftvJYLJMP*KRMpNavRc z*ZM=`e(IqYDL-bnP5SXL#s`ps_~R~X!o54dMMtpn{AdjJ}uQ@ zAU|y|MZ*QFqN-V+HDb3W+s^}QUTNnlKD9)cBTc#HQWoYFWzND`uN`HA%oZcyj6~B% z>xvgAD_HulNFd=P<7%|v#xNSpM1`%>cVLDM6e|iB{`N*}I%8$wzQPO;nHk*`FV6?^{)q6Yi_{xT z&Yk<${qxT3%uXgdo87aUbH3+uKEji${^gFN4)V3OU`0~r2*Y#HCH2&gp0D)MbXZR; zi6$TFoAWN5oXfIcHTf#+n9>M60@teV&4$F5>#m1Lup9Lf#F2uS^YGlT#GgSNZHtow z(uxTjQ`C#U0jS0v-v8*hIh_CQpmQ;P&7RxxEVAdFaiFiuUj3)>l^~_UhzG(#UGl*I zW2v8@uiB-xW;x6!=LSzFwS;5ZY{sEQ(nBshXhKfMpB`?sJiS51q5%F2l&LXJ8g-p?anrZYXtogGgQjgJ}GL!^C*KyVb9Ac!m?=s8k?;r z2TQHiW90ue<}3@yhK4%d6178g9Rwq={yDYHyUok;LGL`JmjJG{-VHX#jk9+jm(>1A zn=ToX1h>1F_ecN*Ym(nYpykM6(xG3!zsYkI4hUq+Q}-xSCl(2#etD$(2{U7Ies$WV zVI1?tr!zy7TX)&~YI?krrCr9yDwXd??-HSy=&SFj669AR*^1Pf3a9v6QvscukG*LP zw7$=Oneu)xIcG+^_--5o$X+z=BuYB?kIFI$?C<(U-Yz28bxgC&_#YFx=ecUJ4Thq& z#@5p>FC01k{Ao0qi_H194bv`H&@RPY2|Ps|!+?INc@cS0_f&bl1*mY3>2KyA6)k>n z;&9&yrB}o$l*9~qToJ^sPBWYT#R7(gxL8ag(16mK_=nIaW~@;WRt~rk+JV9Y*EF)@ zF~)=D|9^s;u25x3Xl#7#f`Hd>uJO85yD~Mzn7ob>$|^{m<}{&nuN^|kOi9HNPeEBj zwU(g0t0bJ>JH7BJD}W}?@iXJD&G?iwnDp|-@LR?iqdk*mJDq((d2zpbF}7ohU=^Lk zxx}M6dQT4C&d*MTh~u1sg}VHSNuN;GD*|;=NWZN%I;ey35{jqrQ1)>;7m9o%Y>(;D!QJe=uVskm<#+U&`XEahy_O%|wi?dPLun4<(=%BfH+~t4YsvHGCoP{V z7rmw>DP-Oscv_``?5+7JMPCSZ3z4UbmKBk@lSnpoaLMK_&cs?n($2J*)r%>;VsBM2 zHl|LKFrB&)X8D>ia)&!skah;q@I^GC_6RPE82U)nE$(g(3#xNty~RFRHd? zN&38>02mqw4qAz8zc18na<^bY`{c#a1lSwFj}pjLp)u=ZHnen!@TLQw%DQYJ6(4;csx|L zhZ}NXdacomN>)dIvnqlpy9u053Sg_lFah?lw``li$eLLV2iBY|S!HeX_?xEaDTkLb z&2uAvIBd0Rxf9LH!{*kVL>fMub~PbI#km?P9&KSr45K!UFAw;95rHUVL=Dc-d94daG$8i+j4`(!d};?1~JENb~?{T zV?pI!v%Fwua&g5YqZ=In%53ItF&Kwt^~7mMRZDUkWAw z1wD7MgDp@W{ye6qXB$p5U=;`J=4XWkVZQBVH4?qZ%2XzIxP&|?_j`F!!+FH_^dh1z z;nT#Q^d_m-7pS_w?hjo|4)@&}p5)0Yl@aTNRYmd*ydtxybv>}2ZfH@U%6ua4IF(Z0 z0@edFC(Zni?E8YP=Loppk`(xV&c1!5acZ1C-La`?RXw8AdDAY4ddVheJQ+)rgtUOG zSP9;0%Jf20RmNB16RnvHZXJ$KUVPJh)FmSjj1`ZWyqxrAl6CdO&MV_MkZDy^x5h75 z4fg!U0t&8I`sV*3(D0D~kJmAhS}g`)c2tX#RIFkS!#h=ZR>s(W{>*w%j~VoY0rEhm zB zCK*o+am4(t5R1ur3)&uzoU#v@tehf&F#n59yI@mL=Vw|)TTiOz(A{-b3r8q@BmEQW0RF^LE?z67z_S2Na zF9S?+nG1=w2bjgK$j=ox;$o$R?#Z;?6&b#9FN^cl5+v|%hky&Q#>9?4cFxH-oW|LC z%nq|B&Z0(Cz9wE%_HL&9D*M=ZYi35Sa;Ax0Bc`%MbcyV=l_c6zB zVgP90?7~z#nov8%XSd0wwt0^=K1P%ntr;EpsH|ri{|Gil>sCYuuv#K1#^o!wn<>vrC}7mFI)|v!`3j zHx4dQCeB}|rwW5?2u0dAaMwls?Fs~#PE+m6F!7e7Vay5>E@t@RFkoTJ ztLQ+*L5_UvOlI7;$Fs5uUgTO5L$RWm=nx11&?W(d&B<5ceCDt|(_kjc&!OCARWr*` zErnAayucv?5=9R%^FoMw>IuP2`u@EHw)l;Y->L>)JP8d5xsaONRrue3?D=J2gH-su zMH?N1)Bjk74+6Vpz#hSjO=M>nXKya1ZKvGgC%IHe2ML4CYp3C?;BaKe`JYcHE5W1^ zLw)w3IDw>^_^RylcYwNby-S0rXWT;4YQ6J9qAW;pjG|UwgRngX4p$C8iDHE-&%DCe z@fd0U1ENHes<=QJ4`KU?h$1MSC`%c6z6z?#U;Y{1C45lQmCl`8Yvqk@<59)xSiU56TI0;H0fdO`8V$8E&m*g)Oq-jW(*1{7-t}_ za=}?<4DyCleHS2~0V}=nuja-v)`yI0YJg8A38CN_N(~UT#+MqS&xJ}V@F=Eq3;_85 zJw2mmT@8+LA5y`EYUrnBTXeWBeph*&{?_0OBLxPVwZAp_WdSjuxUrh$T)HD#zO-Yz zOI@_MD;T{S@iliH=AbXkXSpREJwu2&VpV^idsHZVDh{{ep^b-W&GI}U9g`cQkh2}@ zTe4@_Oi!paDvb#p`>RKwt^<`gt888`oHr}+ky)GzM%OV0^jT7t*Kr~;xF$2XwVCl9 zQc;8;esXdzAl!jEJi0YyLQKst-p_+dTa6qRiUp*Kjj_}jU5gcFwUu$$264d%vD8`T zvRV|MPI!(TOS(RPIS!T-jyQ&@KAzNmUnOnkL4U&*}^^0hM-kFp3zCVi-6t?@g5 zNql{`oi|F|i<}53=Rq2bJSBpSl03?F<|9(eQ< zD%eI83+iEC4HXkA!f$*AD$57|#1R>c4)sayrB>n8+scM3wcD=DYFEnw$23+Soampu zc06)_I{L`7FQMb7+OnYWFM0K(bgJ?OtWg3oX;bdnNcNvt9j6BX3ds2$^!$AJNb|-q zR(DzGL?k<-v6$9)oSO#;C?jZ+sT7s1cR=2dGXUFWbpRnan| z*olKlu2=cXW6fxW58dsqtKq0d#``JRVcc^4*Oj~|v)9RMz+Flc)+lUfm6^6K)Stw) zgeys+QjloVQ(_z0GEF zIqp+QzzVxX%bSOBH5~|B5-2dj4(OwZR&(?q5(SPCD^{t(L_pjU01z4<_dfKqX**jo z#@z9nfI)7hGAjI&rGD_sS;Wk`LZGc|;Y1|Rgf*$DK_LQy>@^YXwU7u{sq61u3&M=#jqA>3(H$s*0@2FFe z-LPZT={K>HsvKzQ>)8?9^x}amk6t<$zf7%v@h_oBac2X=AwEKuJ?uBlC;15hGG?qc z4Y}fU$tcIP$=Zk9qs{%3UWjb6uZTi-dNyOG|p7eEB_vhG+U;pXdKX zQSn`we4?1MK5;!6u>QUN!iTt-tb<$E?5pj!;NdIV3qfsqA-XkjWG`}Vb-quHn4dyA zLL}*jUejP$&KvxS^%{jIhU1elJhq}lS&A7ArIj+W^i6>>B(>!a3$F~xmYYiq(q&=K zr?VO8%;4-YO*GHOx%Q|~j-hfwQve?P9md>KB50IZ1-Vsf7AJe@LdF*NE$SEFlySks z^t(8LyWavqE@85?9N$`FRtc62QoFd=EL~OQ$)cCX@!X^>wiNPgW=kun+-836h&F0#fd5oY*Jk!T z$P@TARyZrPj^9X)GfCr%85Zh2C%?b3^8Rw(qWgGAdQsRL%vdW0pnaGT-)jotz1yqF z_ENF*>J2gcL6gPuLRkw38C>*J?HcYCZdEfWR-Ik9~gssEijl z7W*=$0?$-Z=_6f#7i-10ZCC+shQuDb48G(4!02-jcP0Z)f1moyZIu!@HGfT>ZELOb zvW8yCqn{1~Y_az=iMN)s$a?m}$TURmA)AP>nPEP{AERIBB=cHgW3@F#Rh;1F+_u%P zS{8(=fabuzxSfCm0ts_2F1&Xv(>1S$}!mitwY zJ_6(hRyJW7Us}@mCV25`)iQ+_9|81wQ6-Vi@4~xjoQgC;oE-q%c_Nb{G({gDXtiu= zQeSX;4!E3z{!!HKJ?H^0M7|Z^&!LdsPPq0GjlwCh zVQy4zqHTBdt&PLLC@3v9xb`e%JyjgFmQR+oV5}8A?;Clo&3OU~rjF=+Owifr!Ru|s zBqU}baF#A?(C7b!0~&}4(5*fAI%BWFpQJ0B?K4E zIESATM*ed>2ZK<0SWrX!hm^B5SCM`B@RZUDMP)t1VsVUEFW#7SHZ~TGh#CSyYq+`f z!vPM@Fxm(DNg892@=S9q(1}nuz!oZ4qM#a;9icqz&CPAAK^Pl@Ing;Qd66~^b(q3v zjb2!6Y#>k_Pa6PE!lo#3Bd&s)a0=swsstT;i z{zqO_seNp~8&!jGYmAex#;dA%Q6*oDS?1(6#dyv$4-h_LHqoxc(H~E_9B+5oSR7_8 zy-`yG(NW&Fe%EM5X+*^!tLQEjjoKprR&1N>6wL&=;V|(8ufGn{q+DD4SU$Q(cIZm< z;~Om=+0JI=i?MG_#zWI4j9(DkW)C0bVCaZ@ZC-~k$2I!Yhy=!+oCx7bw$9IVk1rc0 z!O4+nAL-C;vK(nzb%;1y$zxt$mO>c*JM=J|7GUJOyN6lK-=2|jM28wv=e=knVy{Izs;bNnM*49>1-`n?%bmqub8$~{b%AvYm3!&bG zI~-y?e+|fpkQ7eX+c0Phuo~%-do2aVRMuW6^b_1?Y{P#-H)RG4+WoRs($$#S zQ)=!efZd{Ljz9K|%VyXWIYs&P^=(M1)Ldy7x|U$VKgQZA%%RQI4YJae-lXp^L`)P3 z%E$zyS+S(Cj)VS(6x4+DJ;-0dLtvPVDqHwTHcFhBTzkbnl5d>(18BbJuc9N84#vp5 zN@Po)HC7(1@=LWNowdeQB*ZQnT;dr`!x;I47h97Ebb4z zXUMt6<}*gmcN%(#7hL^LIh3w+V#lqpngndp{02L$%or>BItxo(qc1<{%^uG4LF*`b z;I=sRN&?^L)}QXX)R|qveo?+Yb_|6<;CgWM7*}GaV{w(LhfK8Oo}EQ0(q!lv+Y2Jr ziTBAs5j0i}%mS>!lmKAbkz(Wc*X#M&s8X*y6s%??;Tp)L&vGh-IBF@*M)hfG(TP5j z%W41RRxPliC3!|>LZ;(?VBG@zf?EvItV*PSI?%syH+c9cFT}4aCo-W*xfeH8o8!!L za^>RCq-8S>H?7w}Z9`_=N%Sn0>p8kwgLQ)#LTJk&leD$&ByRh$ZoaEnX=uU9S^*(_$lKYx25SgFdb`_anz`km5Z6dHS zuj!Bwz1k4ya=QR4IZXnSi2O6g`>$O^5L@xwJJtU?P-zf&Gyg{Z>OtF!ha<_#vaE#X z@bpI)fUGg1Hr5Wu{h}S6b_2EGk3YP)VWBkyMTm!oUe2{cB=E#yvb5w6jHz<67$0se z+Vpj%XSL_B4qE{h{lQ{7Ty|-TF^WiR?RHjDY)2NgiArb)7J}@+X~O@{{el!(k7T^_ zaZ&1Wk|&-WvD^8o@*}ZqIt^e-qzH3l8YW%f*Hg8>IH0b#1nN%-S-cyVO8}4_ZvpF` zitNqspwyt_mCU2DOF7}7%Q`p1?x~EU*N=mKkLC#5zZN#zJ4z+4C^xpkF4M6+Z1u^HlEumalGfK(ebA+%+w!yJOrRpoquG>liCu%;u@%3Zd19 z5=*f4Mi%s-C=&j(?AA0h8U5vUmzUCK(pi`wcb8YP&|m615hrzkjZw_0>d*jx(_ycA zc!gG%w$v#mHQ;b46SXUsPTtK>i#e4Pyr~Q`Lm#rxP>I}_5m7rGE_of@dfZX4a@=sf zz4)S$7Nbt5-EJ$<{QKY79pW;<(*A2&M`vRk$3vQx z@X(Jh1~iQ?&BP|;-Z$>6^XA9|_Le`fP;%WN2|3saoX7~p_RP=|q(~r$aUwAk{t{Os zG7O>g`eS_@dYEJ(nM=$%4Kt=VPNpl(o+DS0ICy&_Q%s?Dr_;czLC;`%8UM{${g<~2 z6FGkj^ugAS+^@S4hg8GfU#58t9dEBX`bId`C+C0e8m~3?+vzuR*_K4~Z1Q#CcM9a0 z2z^0G1xB_PdJcFJz_2M4KY!4&5eY9coch?A;7#kRu9HM6-h(9kJMuQj#fUq}lftBc|+5v|4WsgVok~ z_H|@Hd7B3UIgR!h8#XB9U01NeHC%9ko4EcItQ{0oIeZq#niObqgeJ~@-D48air%W77!9+%nF9J|~bt>bZq$U#9 z6Y7sE36VG>%GAj*x5Tp~MLHv+CCHj*htz27S`e=Kb~k;FZ7|+B24uZCUNZ3e74A>w z$x;$gUqXCCvf3V}2Dhej6ojcSDSUX{*E%pswhz?vuE~SClAJuw>zQ%vDfB-Lz?eh> z#3^PG_yu%htx@sFRfhY}ePrpgmRGWtx1M=Y`l1*F(C&IeOv%Ev4aSP$@Qq3R|5WBsG4b?yx2@t0+sbP|nfSzrkp@MB$3jeFOmdeDzf;*zkI z-$c5vEGzG<#~@tU&w6eZ*JGl4K66)vUvblV;K^o${<&%a-K~5ujhPB0z}lZPQ92xjbL#i*ba!Tds$9BM#i-ZNxy{6KOqzbM zbWIJ-;8;3;Qpzzt$6Cy@$ZF?B4q?XrKejMd)^*t`bq2bkyAxYAxp5W)xj(aDCe>1s z%{+5)(TId`SyhWV4BsjFxJc%X?Bi|=f07xUwMT3*42N$pR-RTSsi}B?K{X`MDY4KN zogmm?O(!U!j0Tdj4aU+44#vh#-W$dBvPdLKSt@*;aQ9G&T8}p*t{bE|1`FB}>(ERL z(uf*uakJI|T@%~Z1@SA|`(p)L1w{^ZJJjcDBLY*J3BMdX3;NSCV96lBE4E z{!s*FP8p6g@g=cR{w&)`GWFX8Os{w_Rbp3>skrrFPWM>i+s$ z`gxP7lUOb(W~@qa9N&uhCaWjotNAByl0~YhE>rm(j~OBzcEAq=m<94@;=_hIwjoZv zHg;!W3};uZ9kHtqH;8Xt@SYs{OOV&H@*A8_SW|BYovF;03ex>_Vwcp5ykaHh)bFC3 z6Q!K>|6XF=3w~<-g9=TvfQdEOK+%~exO8or%c3_Mktl!E9dF&e?74Q_kF$>?y{Am`)(*7C}KdzCOO zs@!?Jzu4w@kUQKDRAeNRUqg4okI0b(#47^+&x%Jnx&gT1Avg-0uaGl8fuBsRAH+VB zS~qSaG$cWrI(D6b`bDzD zbd1nRu#dzVz-$>CcT=m%zw41=88lE2w~{P6x)>OSow~5>;^^#tqEtI3%qvMBQWGoH zHI!5Gk`euvl~_xDAY)eG$X8D!t+{+IjIs2k(BN^(u=CTlVTSM@zP5b772hzh0$b-e z{D8bJWKa;IBS!t}Z!n#(-L*SHK zTl$e#+$0G@&ZY#jSaB#LA=MyqKbVYJXcCc#viGl#kE2hbTi*|_)jOTHlbabzKt5iaeUK@@Lc1`p2?x?suBvjy$1>+zFy12k+`(*TnCve^GL7!g4W_r{l5%qB0Tx~iuBR*LNeZNC*=nJ3*nLuf-@CzUF-h!0BmdWsQ_CV>HR{-k1W>wu<5h4WtV9iF{e88=|J4_6V+=gLXHx11*nGA}j{n#(yAmsPrL#!J3@Xt5jZo$Z_BxiM2v68SF{ za3arUq11E^YP)oz)RBvM#xqaKvdF~$QP(I?$^kX_=P5YbCBe~QGd|GBpW*j*7tNZb zeq2D$j0R<}m01FX=q`b1gMQdkYc?PqqZQA4@7uRAa_vX`c*zNZR}hUm>^iZDY5Bc4 z%`?L1V4npuUlDAY)5paN`K6WzaZryH?!elJU8G6T2ZdkwI^W$W<~UB~pm2J`_|5kV zdgIX`yz|psG7=j{vN}%6t?-)ma=6NXe_~r%O|2^B7Rhd{%?q8#cX32jSsKoSZxvH8B2j5LUfI{zQ3FU0wmg(woD*!%n9p4&pMMYAkS zcN+a$>MV=lS9dZtv+~xV(*rP?F-tIurBzS=UCT{2qDXH9h2da|gV3Ai77G_JcX50wV^U0J0^v2cce8 zsS6u12tG-kVb3cpqd;6bUxWf228>q#|k#P?LI=r6{CT#+^%@`wtQ|BvHoH;ZQb ziX*I$MA*%gxs12FN!$4XsKqb#h;WkI`N9UW4*pKZaUPTopf?`Rk7O|TYZDGO^h)_2 zHVpf^yT21>`>bc|ZPgro>R6)InR04sDpd-SW*`XHCKbC=c5|y+wM)F%MqF(I1`$bg zaqlsV!IDx=qwkkgIzN$#`k-b^SsznEIc-!UrhgW+cl@Ka_;}_c;`>NQr%msckyR>>j%UM|uLiFs z;|}_&Px{~ernuxheEVsS)}p-N#B~03Sq#7Vr{Jkbhq}VM-}U141yPdiU4t@8eWhR@ zItc(Fj;0K2O%e^*uLjfbh5&mKa($&fTv3lc+^`aru!n&(qU-1ZM^jxIa`zV*K=0i! z5<%PixddT7O23{7Yqkm789cl&JTl_h!C9KCnI8B+RgxiYv#KtehlIM>UJC~zkC@6+ z$I*(X)V?xtUX@`nL%4bUwv^!JL>^hCq|3IMP@}I#HNfCeWo3~F#_f-5S4vP#!^W4* zC#SJhzE$RayG7wbKCqU=Q#Er z@nK?vSA<};F)FZ$EwKnX%P0Z-0G}FVKw*J|s_G2MskghF?B;6dkJ2N=Mv1Zl&3_58l4r<=aG!SS(YJA&< z<=+iOl1id}%Pm4qZ!W4tCE*TcX3D%(bD9Vzca>yi1Q+*fByUl{92eKqvT z>OcE*pRb7y(3ySR!l(K|Xn%T04gtnr4>EkC@syqEjZ=wf$72w_V4r!6H-NwN3|L^@|Zd&(ZggqRwJl0|=#*2Wm}JCj@Eu-_ORa$1-8 zeHlMjp_i5IA{_3!$R{;tzAP4sFz3Z7@c^5sEt@?EEB96GJC4*{>j+SRUjbru30lV{ zqfcg|iEM=ty&ZYbB;tM-)kHLD9%H>Tfdenhi~-XRfU#0%xc0qOdTl)CGP5}on=fd@ zS7S(sY`lgYk7UF|*?VpJgP!obox*ELi+`eZv)U4CM$LA2!tefsZtSyf^id}5q!L?L zy?1O~3%|_V${~ddnG3ByT82W8n28RPO~xnPp^HNgaH?#Lf7R5Z#5RxU^)_<(JoJ^T z+GQ$b#xg;I9!?&|z@?Z*dT3}-J}=hHF6r_tN);eHJNG;fPQzGdWHf~s_HR*nf=0}^ zz58wBOs&E;sf;FZ=x3GYMi3Y%y=SP>_A;N3LrYd4P7-<&NDe^%6@v7prM-6nY0E5P zcdi5YVnFW?D^s1Wp@-NYz+Y_p*a2|6GgjrS+Oc{S>aVijXPjX3fP;#R$BZ1Cq*{hH zW(9A(o^cr|z=%&yO>p9v5CN*BNnm!4QdD0lniM^xA>c!5z(d2BXn^E1Qz-wvAuUS` zby`@w?V*oDiR$`r$}H-ok!&Qo&>)Tn2-LQ1ge}CrB_lCUM7})Js#J-sRBCSMY7|LMV;-I>kuW-e@A)^e4Y@76GR z9N2^yaD5N>g5K)~FOhcWZ8{bxMP7>2I?=dO!-3AT6Ih1X0^QK!tOEdit@AghQ18)v|};`Y*cZtPUqnD@nIQ zLU$o!fvA@-I#l zxREwYj14%qadA9~D}KK98+vB^TEK1WHsd&CE6md>r}^pyn`+8O(Lh1_>lU`Fz$pZ) zD!O2bH>N0UmG7vBI-k^GMSiL6m*i^YW#r;YfaB10{o!OD^3YSO-yh{#IDHxaaru|y zB@Og=9w*_l;m9(N#QLvsT`o0c2oJT(x8`=IeL0S<>+YQNBlC|pw|u>shYSN>-n@BV z7Eu)qRwwwzNI|m8oU=I8LxzECC|OQfe}4W~V}+{$Yr3L0*ipL$Pu&m5$EXC!CAyc$Z{x49fd5U%>-Mi5)$--U+v6n5>ty&6wO!*f z4m)qA`dW5>&#ymt+S_&w!akmjnM)x82*+tpo zn~A5^LA`{5Y}!F`B5313(NFs+Xd77QSH%2fT1fzpMsD$eKEd?Xlc`+;)E@^}-1buK zd$-710|C0&KjR}+GDwQ~e8WG6>zW**REs05zu<@91YeC@KHma0Y~G@JGYfu%$5ls% zxvm?Fz4#f4y~iw7u;z@e1l^=waZ`4K=i8kryQ8t=Vg_!j6v3M$yVnWs(19|bf?%Eg z`DVfDZ#u^RtD*GYDP5(69o{~zgl}V34 zGj9?+Y=?@#I^d^Tlo2_3M(*q*XKiPFFaNLgs-^@aC{9d7l)Vm>J8N3tPj6RihcEet zl-L&DmsvFE_OTyuojw8Nze4t$Opn!vWY2$K^_Eb) z96U~PTJMi2cv%4y(Z6w|3`=XY*n}m%MsU1fOi@2m9;k(z7JO8H4wWXi%B!BPnTn5% z;nZGFBy!R}r;El+7cuQPAaeSuJ|v@UYw`X8#5G%VDRY zyuQI^MsRbZ_l9*oW~+z$4hfAT2!;PAD@$>J^N z$CvH{UoH_{FRcc?2nOtZjMqD=_a7ckxHMM&h4YhuyVxq!_tytm{0?K4Kk4G| zZh3UcFTH^#+Fzqe(DB3?plG5#RCnn6S{e79r775nCIfmOKWx~*ROiplp(|?v9$|y( zO8(hlgQiMj|2>9I=*mk4+#F+0$plTl?cNl0r`5GZjlTL7F3LZ&^UfwrtzS_-RzI>*_ zr3+vF`)r_lLh!>*b-dmk+|w_5`Jz6)^UiYPV(rdSU$d~T{cH{DrzrL3U>fTAVJjzI zs<2Lv1hfBy{yyGNgu3$5x;uAK;VR>~`~E$-jED8lr%CAjrA5^IYyUb{?N|2}1II=6 zC)a-C#^u9@No_v=w}LWN7$qdF!;VQe-Lk&D+^1+oe0Ro@z4 zeBJch2?;(f&-x_y1x8~97LP9tISsjYBy)t{y&S77 z8I2ZfdFiY5TpN}6YhX>|JAcfeQc;q~VCSSO}mhKdK`#6J1 z>W`z&k0)L{a`}el+Xx+xUnSG4ch+v~-$Ql-GMFR+UO%SJ?SR0 zyqGZeIu7(1JiITwNgv{Tb$|Lr#_+#bz}K1}hx!n|pbL&#(qHW4G#f%6q9T%l8L6g2 zglFd~WGyQbk_~wpejy6{J8RZrHu`w{+vZ;30>+|!HIwh0mpd?hz}oj_pP^D+I=JY! zMf2)E)1^bZuv_!F|Cv=l)&yn$`|{Xv|c%5_6cuL13yPE$(obRYW2Kn?p@$`#N8 z@tLf)41wa`X)`ICu^ElnHR7jsxYoi|GAM(?7aauF)|{jHPpdbj7s$A$c^uHnZRo_2 zy_CI->E|%N0pbw4^{`?g!&`rjs!@+1whv6Q1*V|hx@;kyU^;8fNTJS`Q!YOHq&e_7 z*HBArvgVNoE0ERD!NIF%Z-OM`p9r=6+WL^;FIzQQJrg2iERNp_0GQ)k_XlK9Fnbjg zRwe`QJwoRW_2GX$rjz9(f?oXyN~sy~E9f#7-S7Uhp=1|4t7Nycd^>W!bT6vn_k|vQ zIp~+b?3VzIdA7#4ARH#k)CgIT;=5&-d$k27AhIgOo^IXg=3!{G?E8S9%WDDJ%#{ z*UGhwv&8Nl%$BG$uy1vvS%G(7!*wSKr>7#+3p<)?mlRQJp_R zev+$Ytij68>EoARZZXRjBg8*bilk-t{<@ESB3ncFVx-Vw@-@)#$|rplzCbFO4Jw9% zq!`uWJnX+cheQ?^p5Yb@FFU!^uU^v8*c@aQ`CMgH2Y3=p2>B%$1ky5 z3;em_|D@E%2`c0^-1pDELZ!9pHi#Ql?A7&<>Ic>QrP`92=I%#9gg5^J^3VxK>3bOy z9ZVISC?O>#X0H8y^pfz3Z0}f(X`FT`PCrOYi>ry-@b5DOJ0sgippw1s4;UwAks5tD z?6ShQL7HQjBeac(CZnM7;@(Q83@IG-O3n&6vJn#hBM>I|Xjx#=O00q^?T)#%g>Nz0Ow z4u~@abJ0*MG03*(01X(**1!eRD+SybhuyOZ4A+xhs;~^cb58>M!RjHI1x*1NuM;SL zSJyMAKOZHvJc1-A$B0b4@uPSh0lnOLzamXnmnJ-eJf@>s?e9Y*UA{Q7G*6ki-v3J2 zJia`$AWx!S&=58<_7y3HD*W(jIL4Xkjd|w@!>(w;Aj(u^^#zR%RkC@3HiC~ai(hjP zHOj)1nP}c9Vww4fA&dXZAm5jicV7mh-UlxmaB5~If5D{WCKK5Yv=0cHHrrajh>R1> z+l3N%O&-@}*3yZ~Db*m7i0m)gYsyE>W%&8Mj4=n#`imlx@;dhm9wUdoTAgjYPZAb) zwb~m__z0i>(QwVUOzY2Cmk{+sX_Zux{Gf%OU+1#bvgw1<)`cW@tqHF$ z7HU(cS1eTbc7c+cDmBaD3z0n3WII;l>4o?tOiz~7LXqj(r__H)B`xSZ+u*yvBHAcQVr+Wu zESG|Hz=%N?VVmBX*6Hm;A58(_8X=AV-~?(juh<+q!|rm3+7xr>doC-I>xtxLjM-72 zLzVu8Eg`B~)HB;}tz23N-8vD7 z(_Czw+#Fe4GqezFaXs-jeawH&Pw~pZRFq$6>UZMnR?Iu`ir@DO=8BEGaqW5+$+FyY zKLm9CZ4I~YliUnTuJ=@PdPrg7j2x#Bg;{vF5j4;?XgBaF`w_PizT)k5150Ck^qrN= zmrB#GNE=%@fHi#h0}~3Rfzu;jkC)Vgm##T3yTv8WY}w~5DNg7#z~2+LYH(q^yfMXe z@@JD~>5%j*lCmH>m7kBBroQnUEbvVt!oaQ&_j30P_{KPFfyJxQX3n~8eF$><7`801 zgjnbav0REY@1=8gcF826XrFDHJH&2$mEJBBj#IZF=U-P9CTw3K|ByGVFQkJ*objcj&raQ}jn|w;?VQgv;74KgB4daoef`Wy!-f0YIUjwk ze0a~k)u=q19Duwi?T&*A~bRUxuD!~vB}EkqXhB~tZ{Y; z6)%scj;>IGG$3sjm@R-bVruPpzldU>pjs>0wqo1Uc!sqf4a+s2`+f^E9RxV^U*4=U zf1410BIvpzY9IS>U`{6N1&o&?G;S{v=^BcqAq+lI>lO1@Vh(d_{3v?W(G<3X4?2mN zPB4%CzWDBAeB=99aVy3h<{{EJ>xz<0?-m9p)Y{C$6AQ?%##ZDPpbMbu5k{%r9q$&g z6Txg(30F7#7^MA2R@UuxCRks~L@l2$QH4IANxgE?z+%+dBzsd%r;0eJ5adR0om{o+ z)~h;65H%;6wZ=VBjY>N)AH)B+Lq|UYprH(4m|fro6+|FO@>{c=L=NS*Cd)13U)#3* zLa9`R$*3KYC(NoBo1j$5`E&AWtcH5{ocmrl*i9Cg-2Y`-fLt?!nAkehYu8v1F4kaL zfLP1db@|E5pNM65HFFB)40>2?l&}r%=#!R#H%S!?#qm?&0M=h7QOqA$75eH^>$3O} zNf$g-$n>7R4=r=>u?2x)%P^9Nui-KAbXN*Sd?8&|JU*U~_1gac`XWH(wM>mI-+-)t z!xm;Ehsbx}t^v-R%Q*}L!_&SeKXP=<5xEtxZKf#85-LD}EttoAHH`WVp94UaKw?5r zvmeftqF!(GBk>9?qZ51Eb8@>8W_wlK84OsDi{j)@c^jo@h*zIB5#^IbHRW#_m1X3U z7^|+n9lWj>~Xnzt74>F|Zzz-!wU;AB#4J15XsG$(EpE2pGnHCQmn`o;O z^_SrTbrr`{nxzQG0$vpAK|Vj$-)GfhV>AYkyKAOa8FKdEJSsQ)^F%Y$xN47x(&W~z z+5=oROBu4nzYt|&2PEzdM^aErEO%_V204{9?xyra-*WbO3N{m_or{Jq6Dx~H=;+=w z`?TJvLc#%Z?*swTJ-Ou7xcpc|iwz7XGcT>lc4d2U*ln#U8z@SV)jUZ2%m3g$5FBS0L2$x@}vn)IoF2!Ns~yXFWx;jkuMD^mCgTmv#iL+O$c zBcG(~e`{Ri6rvGZr`Xay+c-h~=~)fM+#~k68B~3wCyZ9M&`9dPK_c0Glp9?6Z{e%iZ_X8JFXiYqFxc4>XLtAzv&0i_fy-T{nYw83Z74z zzZ8;uz!6#^h>c;dMdUJ9k%oWQB2RA6gS5{2XZB5q&UukS=0FH+XB!_rCzoc`Rr&Jk zel<(eHgxq9jqB*%OrUt8+PR@jA#Y#V51{h8xtrP>qY;4r@&A6y{`0P>==4N0tzT@J z>6ptcslUf0#+fob)y)l~9}xogl~=<1Y2Xqp0xSZ#R>7YJ%5E8+7bRa_$3CCDo*L!!yzr!d zeG^YotGN-WN^a8id79cw04G7*j~jGgwHknOKXqCMh3B>}6c4J4KAjU+&?x`#K7Kla zq@1)E5hWISU^cU>2*5^+lvbIhV2NcCr-}3(N4R-5zPS0~%{Eux*>TZaEkKV7x-vEd zC5*XRrf3l1&%;iu;$AQJ!%2Z73RmlW%Q4mVSN#_2tZVI6B5)GX_{t}aI%KHme z`=bQK%TSuj3)UK?>2IZGgn?))X6XMS>not5TEDl6p`<}VT3V5k?hZvtq)R}hyK@Ky zq(KFgZjhAjp)u(0p}V_g<~yL?dw>6LE!Hex4a_=Y|$lAYQO#a5UuA>tU;(aZbn^!Xw z*bDjErVN;egmPtd~J_&KcbLHil~o>>a{M^^zb-aw0dp!+B%M+OesY z+&xm*X0`ZQn4aM&(pDt3+EqqC9w^RPsQPJR1~kkM13jSAVIkFppMF&1>YIPT=374Y zyP(UNGN~OT(xf2Cu;M)2?TuMep0~dk19;l1f*`t(;`Af=Z2|#(FxkKuNddMj(%YuD zu&vY|*Izrj9IiURqgx5pP?mjf;N%C8D(-rO!ky;XTHxhEO)n8i{AJaCC{@&L--U@R zPB;Bsder+14&$v5&;kj$5r4?S=fyC-qg6fGTh?qFZQWl>W{b8>-CHgaQz8i(-~1Ng z*~MbZHA$(hohcW4@UOA&hOp-nWnR`De>w;uXF#uGyMy(S4%xd3A)a)f0{lM7b(KwEI1!n-~gttBjtQleoZ5XSI9?J??;yP0_32zL??yWW6u^Wqqm2Y|VKG-0{xXXd5V|aM z)lBQ&RtcQ0j9l1(g8LrP#7Hrk!9hJ%wu5fccY4AdI)`hX8mZ$=(U#}ZMfy(k6%sFrQ^Deizy<{P4SX?;J2@~B0wVKp1(2T#A5eTbEGFyP+}c*a1$ zI0c~TEife*spr#P24wdEF2Q$%94c+^R5@Q}j-Pm>z8w9gS+;I9zsN7Uz3HZi+FYyy zA%V@HNCeRFe=BlUX=n&;Gx5< z!Gm|q{?UXn($Q`3CpXe2T%wj?!Xb2)z6Zcu?rtbj15*GI{ zHFA*vBU)=(&(A!|&}a6n{kmDR-Yy=eB$Rv*b*klSeoyLp<0G@*R{NZND+QY5?F|oxXkL%*z8y+%B(*=--yE|{^3q>3p1UCPH1fvh z4Xa};LuR6n34b1Wk_^*-fpD81(^;0AKhPW~kQ;nWM5#kHVO_6Z=B5HdD=O%p-Uu{f z*hFi7vDv4PDIa7=JC!kt$AJ3lOW9>Se}JWqz`ZS&;0FaSy>9=lM1aBiynBmG8`jqM zEog@sY7171J>~kBP0|5krPOb@WhC=%BFITCav3;0S1JUQIuYw#qeA(FX(nx7F(~>B zh$j4p?xNJSjOjplbpjP1yJ2e)5cyh)=#T5AUuU(qJty?x>@p&ts+BBDcxfG@M}cDA zS8Qtg66SL#%FCPHwQ0s!*d>3*X22~+^9`Pbu8D9Sih@6x2NAzn$jgNe^Z`I^7%r0_ zW?rH*s9ul?a{&x;@Mwm66fg)YjoE4Wp7lk-EJ z7{h`9gAJkY<8`5C-ePb-yD)^IP*kT?VL|P_jKY%D7n3v1$Wo<*GP5tOkv&} zUHnEZXV``&w0?6`>=SHQXaA|neoLo@(C020Q%UGRoqMU(QcfyyV@RjB*r?u!fEUMj zVsCz|KM|o?TwLU*6Au#0$anIDi#U-X0i){C9FZ+u(i>A5p|3mQOkN*|sT&4TgVN4X zNjoOJB1=VnT3`-B3Y}pYH7%J(4sud*_0YdG1WZXa$h zLhdNL9AwCsTThU1oWtyhW=Z(!+1gy6h<_NR%{NY4n7EJ3k3FVS8Oo$hT!@dYcNSD3 zi?2gaRaV!rawQjC_Wot~!h?Wt9uPk$%er4!Gn`&Nq#L{DsR;z@;gNxHFe!G%bMKIs zIs1Ht@bo_Fz)$Yjv%t|d1n{= zJpg85 z&N++0dk6LRcxo5%7|6Mq^xF2>A5evZ!jk>{d@-XUI7!d-6pweFS7$8x`C@;HuuP}k zL*J{2YpNaB{~;}!EACcq=xp$zCQG|0kd}sXX&;Z4gPg#Z$y_}sp;6_f{@L!R^`Jz0 z>z1hEInhAV$^4y(EIsAgWp13_Xt2w;_cb&@Ly`YpO(UGQSrx(9$PQK3uhtf zbGYjmqz9nP{VRJ`DW_B{-&8vPp+nH|lf?wosba-hsDGJAW>wdrS)C^KDe6ohDj8?l z12l$tk**pSd$k*_1`^f?a|^~RTbf6)w?BR4MMhxZQrsQl4TH<1lpa(7eqwTTsVp9VRL@Lc>=yNQX_!d`!9Tft_~O z7q*#Ph0_?5!}~>&xu4NiRa}-GP<1?_A;k^c$tYZ5Zw<_pKcvAdv)qar+mt&az{z+m zz=Rco{W2daG#n`p<)iGvdi9!eDNPUMn-;A8>FzIn-WjwlOk>ge33c}jaAspmw!Zg5AvbPX-s-aI@e=8tkl8Zg?oV-@4<`f88yK(kb*a zlzjB?Y2dq2>=G-i_&LLG`xNsW+$)>u1i7OV_w@)gy{uG8L*QNSM+4fL?)L?EZ)S*e z%R6^nKVVm-Tco8JtLHmpTj3L}S05=I9|;UE5izLeE+Z~G?0eq%0VweKSPo8%18}VM zwYgJpLZi%|jUf4)$c$9`z1)zl>6I4|>5Lak*n0ZuI3>tm-sVb{jk;}WV}^Q)ThmI7gF`hsbqXEXS`7CsZCWlk(g>UkbDe zJ(>?2FRDi?o7+!kxtm@kJ+JYjd^hovgD)sZ#2Qdur*{ySn)kbG{( zHP_&saL)SWABA2FBH|$f9HPhz1i1GJio+>Pi>LW(zlQ278yfM=kO|>DD)qL=b_;RN z4Vw!SG8wDV?1(Is0YthBd6o3Y5ZdQ@MY!$>B_!2>PZ``XPqEz4D^KrVw$tz@pXR)7 zVh(ZO@6vQ6R%>6hxITM|wHGMHD}h{S+&K0X4~!SUZbvw*HO5{BMLkdmJHw17rB9dm zUNfLZ6?{`fMUk!k*c^}yD7I_@3W3UYjJg>;iBW|rIPuH5^ULGO^+aiNhhb7e+G1e3 zQ4Shvrqav9ydX zx+8r|u>0HO&EHfC&pbyp~H!ZLsAn}FTdHg z`80kuQ$(_yHve$(>!{6yR_uhRerUwHt@9(;l*@ijh6t#@>rth?!**)++ZCIHSG*+z zHe3fv{yHDO-Cb|LHxWc&T%ZRjmOXmGV3Y4^A#bUUVpp^N@GT(7{Xj)qxGJa3Y@k(> zsbbOzBjJ0kO3X~Dw5oc zVC$|;q6(!&P~fHVhaJ+sdDFSOfWBjlg#i3*#K7&kWYM<^Ho0Rk=%EnbBz5Fv*53X$ zv=!-xfE%kw>#N6|kY7i_C*}BiSFDlr^H01|o>0uz`}U~TLa$|6YIsS#GVbf z+EjD|NA?rA{nA(rB}CqjR;txB4M$V8A(@S82@VkCd7%RzSj=IgkM5#|w)=^wpy(H(@9uNa<%eR;d_*Bc+Rm=k&TCE&s+;xCapZjV zjiMykp!$W7%ebSIDC0el2DC0KAC;+FQ)CnpZ-5&ae}7(E{G^NOHT6U>=ErGtoo{L` zSTYqR2~)UL%cqH39mN7&?<~;dH3xNTDJVK+kd&4?*dr=l)M<7wP#e$cNE$znM3F5H zPPRaKQtkiVZm>>R6ceW)*p4WXfW7V>NtU`Pal4b?lR5r7^>6FFbYvefJuR8PdxyY$ zO#A*^xHZ9-g?2`MRx96>;Tdu{B_vA52X+N&19he_5GDFz(;~jH|Eb(&8!;xN`i=yF z!p&B`fNFVv{O{G(rpcT)^|=y+9JPQ&w~!8H#T6gCm!$FwZB{EzXQ*TcbqfhuiUs*Q?;Kv1fV<}7h3(Pr_U$LcT=p~~%Z(_! zGldu@DRQF%M_yL$>a36WRL=FjmtVljE@Mf+Sf3qQr^xZy7k=+eVX_o#TC8@5X-lQ0 zB>gUBfJ1w>*5Dp7B_xXX<-cCl<7qtPf0`po`zYk8)2ICjhr--n z35P=19PYN+VSFL??xZpj>~L3$aivw)(=XTtm^P3Usj$}Dcy;mP>>7)~i!}E+Hrt3W zA&GZHFuiX;Y5>2&OHnGl_*sRND=8Cmn0Y5+$%5XCFPRW_w`|*b4k4Bf5XuAs>=hi883c-#}T(Y z5i9cn8NQM-{KLyADNT}M(*o-`gB%C>1AF2}$EXFf$W$4%Bxe<0soS0-V|mPHjHM;+ zGrZ_>@O$@oCer16jy`3Z$?5Hf1N`Dw?4@$jbb2WkP0xwL4dxUzdB+Z6vci+f%c0C4 ziWaI)uw=uD*fp$FVt-K3ILKCoM~U4pNce;Br%WTWd~GTZlH+F50a zK^D1)yUL)T4)u4|5QqOu9?@I88FFvkM|?>=Oz~Iug%s1G&hFXdd-3 z3x(F7p`c`(>|oej$<`kvn2cEed_#y9)@z4NA!5ld?3y{ z&{KbZM~NPmD$=;>IUgyT9UY4Cigi$DjqB`PdA>?*Uz>UiR~gF3%@06&WZt~O5xFyH z)BLeW=L$m|B^0xwUyvf?-P?izT4nTo_JG;SrUdXC1McG*QshTZ8H*o>Sh$cEKSsuz zQbW-xP^6fOKltr(aEYY$Jml>jHDRW`58@dRwTUS z&Z?!uQwwZ7v*$F#myt&@>bLcwiEtkFXGM^(ct864iCS1tcHOGKpAZ10gE9WIz@!$I z!yI4_Ik}d+`!E3G2W-+iJK+Xp0bftUknH1czlrmI@S|Z>`S!EKF!zyl@fC4y?lXY@iT?)< z5OSK2gK&?SpvW_4!RZIEVSQ>^G?L^W2JgOjAdxon`L zf3oA(arUz=S-QA>vm8yKn!I*U=2@Zcbk^+nFNSZ5byFYm=I0Hj#op6ntd3Fib zn?-pOZh(bs!~NkLp`q}kohOkfcK3HJ-{^x^KtU6YS?Q0JBCPK~#twgTyZ>zUwva<9 z=Bu4OrhJM$(dCK;oV99N-E`4C1?-mDDOJWPh>rpNKhCX{kJ;T!sO?=|~Wg zO!-YJU?Ua&{c(!v;-Hu{wblZ#0bA{5WiZA5{GwMY-*9Q)t7j_u2pa97DJzFtAY#DJ zQ)?%cub4hd%(WYGO*$H7xg`H_!p2bG1>=AV%67p2-skPjOmQHem1OUzK+w$lGX5BV zjuM%XZNHZnB5y@c!od0jejYgX_)i4Cg`6*NT<$e(m4@rgcp}@vs7VV7!O!k1;Q)l^ zht5yZH-1t4%)kA2*L_pi$&nj5Ex&yeB>306M(A5mZZ=Rbr`O#HAGujRUEC1{z6=W8 z|16)#TvQ_;(Rb+<2>yd2e$$!n8vvQx{g#`;0)SLUyOD5P6> z856$&m%*s^6xag$C}(uFDGs=fCn(7-gT(t6!P`@z-01GdV| zkyYH^QHljbsj3>z-$W=1@_F92!Nsy*6QI>vkn5J73v3OIH_U%1c=G($9?HBFb!CG5 zMDzVh`$F(|p(XJf2Ul*7ILRxPmoutYPm15w+q{lrXWs3%w$5Sn9*~CF4q}BxkH?Gt z@r%DcyQ!Ssi?-Me{ud0qWAV>p$lhOa0R3?^3j`>}p~YP@FOu6-_HiX4OjTL}g>I8u z-gOB29Ppa9EIX743k*=3F`gqC>}>92Tw53r zM@Gf?n2=X0o#y8oEnbqToi>M=6$4bleeX)Ssw9sk`MYQ8H=sc6h6R&s$K?9*e^bH~ zGxC{AwyjD^1#^HFUCaF&UrTSk@g9N6Yl?#Re`%JaRFRKkg6MlZciW?UcOub_zLNG7 z2jZ$zc1}HZ>!DQK%B&`MGPA(YUwh1E+_;%EjyG#gi=(c(F;+}D^h03o8i6Oa$OTQ|?oCT^)2LghDsmf&;R zro_=Tm8ZG#(6pA&JhF!Y^ZRH#JdW;V@mwxkX^);g`@~&mlZx%CXaI-AuaArM&ms&s zfdq+e{YEmJpv60u^j=8Nf4wM1QVYc;o*cP1Tqm2xVRh`gRXR-p*68<~7<)V}=ii5U@?o%|0hzM@hP=r@<{W`uw&=O-`D5eJR3B zg<9;!-(0t}C?|HNt8Jmx)V70^!XZtLu&&LNQP#dhVb~mG=Hk0AezATH4GOBAo3YTouh)q+F{73WrD#VzZM}+&I5R5hVK7l#DG)T^z7Zvk0Y~(Z*GGJ z`Q{h~q({MjvV|ln7M*TJAkXJQH4Vgo*2~&sw365zoRP1kT-9)xogfKLX56tygCb9@ zOfW7rkc2)Hu`7ta50|xHw$C2~E{@aqq^hD{f^1{DSihQn#q(D*nC3@*!ydHEPwdh_ zjSrC`(A}o^0ToZ&qQB`>w%YZOg;@RF+pP=*D!ZROMH>~>w$teNhqXxp_8SfQ5MNU; z%5;T$DNnx$MyrPSXAgw&UH}Ihr*VZ>uZ%ksF*m)0FMK`lW%G-+vCqYv2>f&-`$4{5 z!<(Ia?_Kb6fO=xrYH!kB!_w}w-$kMOoCh{cHBA`z6iQq47Pp{et`2zYwkDhQ6rD*B z2?r;sRWbLF&erjvJGQ2Wks!!WkLnap0kr}d4X2f2-I z3n}8Kc}zVB4Z#?yveteTuKh?K-o<97cD>((AJ1u6?Fb8&i5A@6f;M*PT}|XGFoQ)2 zu@E)JVCR*?mFa4motZjp`mK+xGQkF}FaeIM!JU115l-_fjb z%ZQAWJpg9^@e*Ck?<^dR3aq>WzLHrZ|?R-<{B#=g$(ZiF1Dm9 zjHR5beBsjjb#&kR;^nn>l7JnBphf8i6|qk5n9_I7-KRUo=TiwWCSrRPWZN^}%=TJ? zqQnkBkDN=5n)>SYdG=*E8kZ}kYit#?&JWojP6uS1a+~94F-m(=g=^^SE;FyHSgYl2X>{5;U7Su-={`bVtFQH)m)O7HEZ{5F;{(E#sTsj=3Vr$V;HzbMTNipPm6 zn({nd0aN9m;b+_LH7(iWLlFbPCzLV5DaQva6}kPgq<#s8-jXjL8CJf6&pc#&&BNl_ z(uzUjK7^IqbN(<}Db{vpvSIw^3R@R&&YZhflj%hm;7g_*$sSWb6sWx;+)sChG3rKn zrP@ef>8jZ_!(Y{AtOw?(h28dhoi`p3v&C6XGqBf^cC%mSerz5-g>Wr^SA5;K z+{Z4~=%=kvAH8+io;YALh7dg&lU42=Vp56{x#$2Yegro9RHLVJw@OOi)izpwCxKCn zzFcsX%Eh=DqNt$cR5`u0d7(bZ&wK0MS}N968AG%`tnL?QkYUKaLYpvB)tS|{^o(h^ zRRqgWEn(-5HdM>w4-Sy@Ln&hV%_Z2O?B-o9rqY`$+;%jQ{;J(t{(U!iXi5-S1$e}= zG!hnu&rxq_>=(sO%%^b@&FNJ@qM?55^8M4epYJgSb_Y)HU;SJ z&zPU+Lc4Mj|9$HQlJ^rA*b?Mty9%^EwI;K{?NOp_h>LB&rCw+miQE1hIk0c$IcSe2 z<1~1|XFhjbcVy%X&)E^FhQKb9`o&I;gK;UZKXyT2eY0Tr))r^ew zB|*5Kx!|zP6pM7%wYnq=X?XefgNO)$!>C3v(1vq|C6FSW&NFhH%xQ^%miG@7Qb@; zDS)^v=@;lhML|--$<V-1E8g_@9F1}p#+OQOy3c;$E4xoDahadX9Pph^(p11dmN{RpC#f__%HfO6WTOzf zp!Q(iTd{B62&c8`;%PdrMvTi8fv#06B`_Az0HmWBVY?P~3W=V-df$DwZBHSC`8VJ3 z_tk<86oD!0@ro!Nprq4Bu=Y1}Hbwl;RBuf)Kmm&BP-}hgrM*Ry^D?BGXfjdzRbhah zL3$H!Uv&X|FyQIXk}Y**b@x>`Z&3I~bv9jv@asiJ1WOt5Oj=JDf`e2OGaupOMms>; z$`&7tD0kcw_Z4y3MpEV2m@3|?g4W&NlE`ixPj7Or%1i^9f;LSk&Nk=@s$wdu9RG(x zz3rC%({WZZq3p6;R`Z(leF9BkBCAvs6W{31#`Xe_{^&;nsugdt1DP9e7N0z$MtCcj z=#miWy|>;NzzI2kq`17h9wE+3iD&;_sHBc>w)J=k>};Ybx87^A{Iz&G$T_(w9PDv65#dlJR}|4;vTIML2N%*7aVv=uIEU?sV6+lVK??EM(N?U|lh>b@bEj zz_%r)1n?Y-NbHI1E-^~Gx7s_T$ii+RkM$U%CU5(>#@B;^@5CFgI2t}CxDRMn&JA)I zY8m;Rt1Il*jkgr_o=WVu(9RtXheI4JGnv2nPP=i6RPVK@ylvU1Sx=dEf3*|P7k8h) z@7X{&_gA?Wlv(u))$?4;73?#n5odWe#{6Bz6<59~-0)4a7i8PKxi)(rns?CLTDwfT z83+8Z_WSG zrdF8DdeP41D3NKrsa}RlOwq$9K14|X*;@3m4b<1yezx9~(sOrG;CjA+p-&t&wa-wP z(v07J>agoq>Fnt*W6y%dGrw#bU@tGmYFIavu<06%7Mq8 zrIxL2*_BCxSHNtMZw1e9+T$9e^B=+rNGMFQEguJ(4z+IYnG~5+G2H``4lN^415vBx zaPk0i{d<>9Q}I+tYhVW0xDZSh{`{`78s*Uvbly~mF*g66!0ArNZZqv++i;fqZc%WH zBw^q~kcENa+J3A#&ZPT9ymFF6>c0BjY4;kxG6CD~a8=eUtLZV@Gx$oMzTfpxQMtzg zeTVE&hFM4uzC ze9_ZM=C(OP2w-o_uLLm=@S~vu^9Vu9^9Pt$>o6=OQuf`^yfgm*)ZpEQ{+6b*@&Ln% zH@IKRpN8PAD9||fgjUGE`Lx@xO=Mr?*xpsgV}8-G1BLHJoz2le8{GHyX3m2s?cutN z+6GsV9EJ^&FJ=4o5XW6WH5QyB*%_h-NR85)4KaXI#oDW3Q%#GcRD7YW45csGsri^e;x>!)FCkO2q; z-lx#`&@Rns^I$F6*9)HL(O3hy{-ngE-}94Z6__|mh?=z7g zQ&^VR%$HF}_WMZ&Ij<8t8?j>m&q$u0bt_-kLj7;E`WzX^41MPM{op~){bFKHL;uWCZU^o|bS(`x zTt$F95m%&5_nUv#wO6TSKB=7045wc6zXWNzqqOEvAyWl)E1>0Pp1tayDMigez7v*qDr7dseJU-e6$`1+hlci#vkDAnMHNldUnt(Skw+9`4$8 zou*%CWwpBFWZdf-=;2lo0>ydeVk-@LxY6-LosFVcIi0n89P+uBpBs|rt1Oz!1oJyy z9JU@Wq7=3vAgcGqo2k%0D-q=CW>2c&&~1D*n8{?{bh6u}oV4(Mxs%Muu-fO{12&QC z{UG|a0~V^;3Uk%Fx8% zeL$*=tjCzwZTq}9sb;%jPwkn<8N6ZRZG)>aBawcMO?%`c{c4}Kx9^+0&!io`q!Xv< z$@fg#LlU%p(f^0QmV83Y6-Y(`C>j*$Fp%q&J|oe@+Fk-K2N)41fDEB;Cz1pq4!iO~5ww<5F-08hp9AmpHnKz`T zKtX{5HKqyC=ke$VTR-G@pR5gXrnG*uH`H z>^M3;&4_P;U2XR};K?m(abg&!dowv7La7{=Ga$7q-F3?t64zs`7_{WBPE(;DypJbd z1LR(5q$jq@v-2i*34;o+ofNR|e4V-RRI{&$Q&+oc!+x*8++-GFmnGH3#?_UtZTEWG zmRQ`2Jx(8dQUQ>v{$K>^srOOwV622)gs(Mk+|SUAe@hP_Fd#ra6UutKn^5!g2B@Ae z+{{}1zSU*v$o$3h13tG@)Y^XubA8!+1`ATaC_oTp%nCYYNRjDW6?Wx3u^GRtqn8gU zhQQ;l-;vtt-d$5ypgtXe(8#7b4a^554#XgNM1xTb+xbi6Z;!DCQor5tj2 zD0VipbWR*4evo~~tfxbjIhqFcR7}KNCyBA;$-gL4(wT68jIwu>?CN$dE_@xIk~2bu&z%i-`oku=T(q-R#YAmfstP;rJLiB8xoG zv-1Nf&aQk?b=!!|nH!wPgKo#&b)`|wNx4)y32W{nZ`yodBH^e%vml+UdH1VK2%cfR z+s;^%wPziiGe-m{+fCl%oW2{*P}pu&O04eA#6f0w|JGPBc3bm)XFuLV7Fbtz5{)bs zwx|@H=6t$Qs8#xzCl5d*pK3o)i@5b934r^yJ&m+Vb-g=cLr_q@9{%!2h7ndfw&$i@ zuaB8U3-Kf*gXdO=nSB-;>i099W4Po$!aIW4{VZn=ONopxj+i)O%vOC#8rr ze2b{+8!4aLQ~w&dKQ6|N0?#{33}U{`BK|Bb7};w#E#-h4mcuIJfC?7583-X2o`2|O z(9X#k&TZ7-WZ|uPWR1hT&S!QvAmr8+nWS3kA+0AhdVj6EFm%1V=%zNLd=gpjF?NNcRxf6fXyKXf*_Ku&aes74RRxq2vD&c^k$qQ@ zH2Y!|+M*?caMQ9qKiM;3kibza=ck#Ba4RM>Gi&X~DJj8JB?3mR5my9*nNw1>GoeID z#ap@LBk}ChU5#-5xG#L8e2M*iDI&&R8uEya0&i#=L<7D1kqqG)D6Ti*K%n7Xv_mAehLF@0cBl_Lgr75&2~00&9>Yh&3i;Rz|- zRD26d6d%cIUdO0g<`HmAT)Omogy8~Hg3f>u)uLU(td^fUDFkzeT0g~MCOL^Q;R%}d zUwLg|No>L5UP{XnLGCWFK_T?x4|TlkGVYC$mvT=4F&v|Xle)Ytr@tLPJk7|5%Zb>HH3@fHwkRtc;TT3|u zqRQ^6(u=IHTOrE7Q4NfcVv*LKp+wTDMU-+;I8xgDeZx+?|0?B8s~_@TIZx!Oi6*9$W0s z`B`YZaf3F|ruGAg&3Ahcyp+*sHTo6EI&SMa@IxiDIj<|jR|4+46GA3!vb1|A!MI6& z?$gF=J*gp!KR*>3d7kv1K@lE5U-gdDxJ>|aAe=z(L1xZyZeJkb5B8dC8qeYD!^7}W z25~}=evR!rGeot`B&pW^Uo+j9a=-|S zoG|pp4#1ZpON^Ir?s(Z>`6;8?BhY@7K3X2!v3Pz{gV?GiC_L#w$!9-TW;3-yx#WG1 zK}go9>>ZzcIe`JdqHoa27y-cz3Mj^~!>~HP%Y#0WQhmmp7OEAtBKfA$9xA@FLVf)< zS2^V%=T|9YZ%%>Vey$t}zq;PhxJ!KGs-~Q8@Fs!PTg} z?-r$)*EWjxdRc2;vR7M60BWwE@X|py0vA79yWdbDLXas=Lscw8|IAKR{9@a&n>unH zk6MJDIS%;KP2;)4EJe4SI<~LXHnT$&YbCKqZP@+6ABK8B6V(64`dw7yGh#39XK$Tv zj2Mtfe*+%#b31-i>Y^kI-o8)L1W-Zy?@e6*EO`OB)RV(*vdZ|s1zWF4d5dGxrDUoW z5>OqiytF`VCT-Cqh?T?56!G| z7d6w&KF4}~o{MQ`4CU_jy824&`V7dBtUK%(XLY)V`5>w>_HK7Qh&FYhO04K$5}Z@UwXL>0;XC zfdg>B#dik$pbvo4squmY3I8-e7I-L^C|N?6CbYL+xQjWDJh{93UO*ObNoFjEA>g+s zbO5dlcVGFFBSnE6$$Fb33$<|qEB7L_F0Om#$INu^Nu%ueBRRS3avTr8`%NP1&6q^g z0EhTa)paJi+{^~GBOlA#iZMmlhq3QE7z!7%j#L&@G<(9pu)_q1tuKMvUoN1qpyWxC z+RLCECG8iz#=w99*vU$MPzF?9aLw#h+Y*AM>UHkelKan(8%ktb5Ss}9I_EV80h}zU zKsXHAX$P>ofE_HZ7D9-jepgM9IY%g2vqSH99`Unq3z%_S=8y%Tm0xg?lSEjKdCwcy?cWnHHzvR8{5BiQ;V5) z{74aY4{q^q3GF|tU5ehA&a1%<^wh+j-y5zGIPObXFkYX#{zXgUd7QB?sUrMsQ3TqA z9-Qz83iCs*FZ$26d2GIyh#lKIXqW0Wbi#}+W1ZkXqV1?fPG`e8MAr(yV(05-?#Ax3 zBx}YFV+$d)fvG_Ej_=zynFj?tm!s~u4G7Y{MDZ)2sG+hfXW_Fbe-R{+XVf-2uwC|I z(5;n35Zn_!Y^mJ=BZxYOf9E#fl~o<3(e`fxj*OBE+KsLGix+nykccS0>q#y(r#GeK zp6tEqL>NAL#&W4${X~`6=J*qTe3}dmc+lJd`NsNy^s>vh)yAATT)AhJ0s3;6y+|G6lRfR4*mR$tw=N@|w<*~+p+7PpwsjUMe{Av)pWNAWs z&$0sqY^NHXyYb%oUi?a!a~THT2M!rY-2ZXZ4~Yj3IJtrmtBT_ts0Wkdme!qGi#uM8 zvNdx76$z-}TVuB5;@8WD-lr{+?$DEg5L%V(0V(JHePD)I?KEO0eiDAuXZ)Sc0N?CO ze5#?t!28>D{8LTe(fhwbGy1tUeopZ5H@WI-U8SM^S~f{C%h@6*JpXarhB+X9tu#hy ztRP3Wu1ZG?HNa8clio4wmXAGW<%ZNV33<6eti#BQ*>jIB?TtLQO8tfk6W|3~)jQK! z1)mZU(j3~j*HXQ`0A(AnEru)8zp&(T=za*5|6;O`rUH%Y1mb$r92Nao;hTO<3BJT( z4Pjo|b1kE0pf|gTqj1hBDe+pF?kF-N7rT{q_f)qjEX-dI6%U%>tHWkc3S7^vok50v zL6ZJ+<)rFom&+QokTw5V4BRQ~_a-iawwn>t_K2;`QR~Z-En-F@T3_CcPzJnNdx(iR zQN2Ax9MX8g;y!!QP*?&VY7N=OSJgrexTyh{(qrU*g}cAGXjJ538oR(VHDQoP9^*jV zjT-356tGSBH)s9jz5goXqjJ3e58D;0;-E*g%^A<`C~C!Zdfo7{9Hn?T+#T$@ z`C|>fHYRbsRj{T;0&4xJng=-<^Um*mXx}V^S1@Te+aO)NwmOekf4dxH!!gUpnJDPLuyd*mboPV+TBE-q#ViJyYj=U5gJ0h@$r% z0}>ZlqFHp~dZu%YEjGf|9F+G2Xm|RA&W@e?soz)U>s9I?*k6tSHH{X%|xq^Xuu~3pf%rQ{CrhW#gTL)RYNy_)}F8`<;&xhc-we5fr_r!bimWx z#6qHb8ncalQ2o_fNAL`w{w%)mP_^EwJ6bK(hagXmkr{cMlt9EnH%3NAY@pS)?U#}6 z@RNWW79j2>1*fTejsop`9knKKyV?Oaou&T#`LjF52zH+J1L(Grgv`dEw0=YvQ{U{H zkAD8LH*nvbE;o+XN)2f(6N9>*1CYkdGZkOD~c&*HXY^;MMBc9ZCsiKjC7qIX!B zQjmWA6YGovx&H(DTJp?)}(cu6asW06t zztsA3MilHEz*mQQfB_P)Clm!}jXwgdu{zKi!y{vXvl$-{ot!D83Sag7689b?fn0a) z#f*0piC?_>nUmlH>xoSeJ(n!D*%GmbAWjOKkE%-N_D4Qs5u)Ea8CW792cNea8rNUf zm-?*)L+Yrw>Mti%!GQX~>V@3lZUb!_MNk4?z*of6cA}7B_%~lxoQH9yM~hsZDk| ziYD~jN?G%aq`7{twIWY95(lpSW;!YM3@2PDG;jOn`nc~^k;7#L3fI+Tc}o2j_&4?{ z=%e9)chzcc$$nmIwPl4B}vK^TO?C4q6% z#JL#d0>NDS4>MgY`3^Svsb%ti2U4M7T@QZjl6!w5$Gm!uyfa$$+ybqfN}$KUoGWx~ zh)Z$%TlPKqzZu!P3b`;DmNnvEHUtX$A^ir6yuglhDCiFe@BfI%ZTA?(`4KvQi-kcH*&4QK$i>Sb^V%w_qzvxFi zWFR-W$5h&`VkZL|?eE_J!>m4-I$2bAK>x|*Pb7LnKu*i+@umLrTP7KZA*?<(`{tpT z`j|+JKISG(*!mlz$k<|rVlM;Q2%2?~M_Mz@Lz#tP`UtRGWN_w+wmJ3N#D;+0?O%AM zvAF1h@t+O@464A0qqNT9^RZ3u_TQLn2H&b zd=Rn*(k%k=m+`il61vv(s z(r=%D-zX_USQ=aS7aW=UzB%|me-U6Iu%ZpzL;JKR@yjETqW`1XFtwqmW1|MW;4^{AZs%$yODS4X?}JNN&8-yuTYU#dihUL)8%`n%rVzi|35 z5wS6(qL&7kI3h#Dm|6_E_nWg$0=@+v=f}Te^Ho39Y{ZgEB|xSUa#$MyjJKT7p|t5c z^>Zw(!oi!3ernbP`l+?C59)0mwywRE2R0@-#)Ei{+~vjh(>wX>)!DDnnF~>$-Q%-h zK;-_n*8u!cg}+|i{Z#8dbDK_=$U)qrvsg^`oc(V1etrt*z_A9Lzi!#T+!l!ejFdA< zNhLPonJ(5JSsB0HN`8QW+hKua6qlL4e=NQ1$;HgGi=c~5{foHPi@jtcU@NVzEa%*b zx@EMTkOUU|GdkQ1{hz}UI1ou7QvT6*3<7RQtel@ASQo5kAmf{CB1XjjC8psb+8Hd8 z{+(N^=F;PSPCxa5#FDX9sGtLTr#oSMd@9AG_whTvlNL`GY4s%`t0p z?3+e{(j#2fR&4+Y%r@!M>MJc8BlG1eL~Rt2Ewui>-4-v`z+Q`bd`qz1j`H#p9}t9w zI{t%tbNi3JF);>W>et{ka+K%>vC@b7q~abB_&$sO&Pk&w4dOVoV-*JS*hBBAmt(#f|8MpH z#Qkj@m|4KW$OIRT^S5Lkh7`Oc81cUVYN_*oALRdDr1BuguB`dF zKY1_P}sjXPHJK1 z4q@$Ip!{Eyrv)CeM1jkwVKARYMe*%sP9;PsWcZUc=w950ZjJp6J1mx#C_w0va_3Qc zm&tkE5|q3N;PgZ0giNsB&V-qt-Zf-xHCINrfSRiI{HaDd`i|>2q+@(Ut0(!eh)vM@ zV0)l>3ja4Jmk7f3{sy;HaF5}!VA4MDwT^gdCqw(|*=+!O(F#wKqL8O~e@0-pltaTB zH(S#l%0a8YAl4`y3BMy%q$F^+&^(l2lMGCJ?8X1cp0YmSji8$?N*r3n{(t$o!~#B1 z0Hp*E%-&K<@2ytA-cq6DR*krQ$j$oaqmz3Z(Za;17pr4ZvYC2_)E#6g`AV+^Vl&YY ze9(tVycyI(4*rQzbIap~)#xhn5jL1}=i)7%Rt%Xbk`AB*ly1N%vVXTMctI_l`jZR5 zGOjY#$=h_{O5=rO;995B(k%727a%Z0{3mlo2;;%yncn{=OZ*V&gZ(^>4OV)Sj5cX^ z+Q{kB^-XBI=ZsWak9QWXqNzZFO6I0+Jx2Nkv$nY(fiJfSC|CWU;CAd1WU%(! z9?T+yFKBec$n~zYOFxp%C`lKcYU(g~qMj|<9&rAB$bU-T?>7|=#xlu5SSSAE;9_3G z_;0l@5hDmhj$ySo%H9+w)X$rg(Jh|fm3(&qSI?qr*hPW~n=k4mE;bz;I08$VzS{mS z@mTM&T|(BN?J6=f)3#HB{i`PCoa}$!tKOs=P^Cl`?J(~5e`vJ?$B4d{PJmfm=e8@vGk#bTkvgpHp6v!h|JBji9q zGhj=71-EUHMLk$Zsg8EVrg2K8>~?jvCeAlpzm`9uK9vHJQ*d;8gfI#w%Z{d8u$g43 z&Eth0oR!W06w=#dAeFj}X%ZT@u(~=*@J0Xs*uj5xPy$RAF37n&_R8$}`ef!FfP{R}zX;lhdmPRMvA#zyF#F8(=(|(OPYA*f}s!=Wf zKta3-!vC)ksYI#hJFd)C9fFaR{=W}Ki9RJgF;fV944c^nc&rVaIx$oVGKjw_*PvE`bIW0Y1R2T#2}5{~CeHoTKV6?g zh-eqS(f?JS{{HxXzi&`A-1!?Ju#%H_3y0sE?0Jaz5iFJldJ~xF50)A@g$%@gJ6*IG z`B!bujmsB4Uo#=?RK{8WpRLsgzJqFr+_%E#zc@4!hecdaNbdG3f`6*5+Z}U-0}!fe zqz2Ih&aewfYejuy{_;S5VcVE8K zsyVRXaXN1U#uggPOXyHTAQ_+|fh@S^z8Cm-yp?pS!%dN*v zuYcrIJ>sdTsguiK+C<_UZ;&xmD8EfJV%(W>$?sBYf{dxq| zkgL>968{H~U@hkcOxQpO#P5q~mfx!Vcrh>e9-4W5z=pr=qtP+JhsK7o0uq%+K9=5t zg;a5CGz%3ynJ%-xi$Gj0P0ZlLHhjH6Sxac< zH+})$SAray(jRZdday^~fkIyC-7Vpf@2Q`A<3<1D#n0aFbqFUkGcVg z2>(jlCblr;b5AuEDIqB)^@UQOPX^&)1c-2^kOpcn+Z8q81`j*E6ZsMz4XLE@F10rf z<-Hq}2Z03Fp0J0HOXBS#)2_D7nO)ki!lx``Q(yen-%~Q-k+h~M=eJKQHX_((rR{$w z@V`OT%VaMsw*Y(?*w_xb1N{n2@8Kq71b!0#jWt+9ni6Y%2p!KEHL;ZazSK)@W*Ntk zxm~D@`(&)d9jcGuazIR|q*G^r^u-uY1By2SL>fK8(|1zqgc2HzXok~2I}x!P8qRt? zAtCQX^bR%boyC0Exm8a7HmnFs`XaOZH%b4E_m@EcJ->SCxCM>=C#Ovn0YR?^B*v}C z*TJTHWep6iPN6!1T=F z{o7y7`xo|HUyJ{8*9?p={P$}^((4sf{}%x5;DSD3oW}a=eLwOcYRs1N&Ba;dSCE*) zUkiYkEKt?v+XlFgmT?T~5YVST*qPH6EvVSp0HPdoCXsyD2+`ybNC1MLE;rSct?!fO zoA`wqjdIvN8IkXVdWcY~GSGYOD=S$){@$}8S#t2$?{@-#ZS-W6-I;%Xj#TPT#9hnc zpRyCTHo>>+;*U~tZXMs(u>J|V!VH_zuqiDF)se;`CPSEl5QQyo%uUKj{RkM{gpWbw z`rc%otoFBjY9tZdKV&GVc4;q6a~{Pkm04JsZ+e2=F4^Fjhf;d2CrR+GxnWST8E}p! z63gb=M`@=%brslCTJpkZdw&-PyePt?BaFF;t2D5T;rdMwqXPI_K!i2q@2@prv4CCC zRlxB)MC4Hk@{cq$=@3&@&8LJKHf`g|+GK!OsoF9kO%YY$foKLJLgiH#C|pQSEn2KP zzRauU9=TtZAjkcq9M**TzjsbWM2W?&S^ZLB7zRpx|0p;ykB=%x{8J=+q4ml{dPaIy zdR?1u0xGbsFz5|MCC6$qJo_L-I)q%U@~p!51m))3p|K_>4?Ev5m&(TVXnnd=ear;i zCPTiy?&@TX?8K?MrsmyR-Nn|=)jQhn;A(F~kV3f4m$2F%O~C8h1hT_hq?$}+B>?Y< zm+X|S;qQjU9Hz)708Tq4Kvev{zZU%Ez-HsmFc~DJL^)}!hQ}=7CBsj-(f=ix3kokk z-)lSF!zd*tVtWayyrTfD#n1{RIm zy{dju+cf?J{BpD@*8&_lf%Tf;-unG2D>o>u(B*nQmph=>YFv?x9c@jcW@L4=+xFG% z2-P1&7ibTpi8|M80L9fgghN@=xB}ELX@n^{YewbSn)C_|tHb}Q~B{~jx zC(N=o^%Viwk>d6XxcCJl`pb)`EHPS-4$@VWh)qFn?r`k{fxN};BLN&eLxYbq^c!z8 z7sB>J=iF$e9Uyvg=wmyUUtbkm9dlXLoEb-u-R!S&T^*06+^mced+bhIxow^U$uM+0 zN{)aZHcxZpFf=6QdZ$tEFumitmCV_6jc|@Z#E+c&(`jHKK3=TG0f>gn-$807cdDVq z&^pi$uR9OeWHCwd!QD@jBqgpN063l6mwR00H&>0F6GO(jQx%Uqh9jq4w~8#MA>p(#UY>om_rkc% zGh=+w1?<4^18Bs=iN;-1!v*$E!(^|crlJB;-j5v3wgWZp2OV_xi=(bQpH*O65Wh+0 zBf;uWGKGAEUO4QciyP^Ba35agLC-J-%-d!l!@&9?c3-51suk8x~x}Vo&?ll zUN8!21QpoiG^Bao$Z9~+mMEQ(z`}<7czXb;<0`n4sUcaX?3qI+<;3k!lfr)I1XF}# zE?K%0N*IL{x*vhXc7j{r)4*&LAm* zte)+o811Gvi|T!K1jf>H0SQ6M-%t9xWA0zoWHvnDF z^5te$TFaQ08_x!dWp^wmiKa>22c*Bf07mU1_MMO|BSNApMaUCS=AQm5bM5*WkSepR z*Lwi+L_g3=M5E?@Ykls?s0FOMSocoth(obHO6AY}xBt*Dh`h`6CxFPw;GzmX+5g{S z_2a_FuQmjg_}V*%si`q&sQq$oB8VA6-mVbJ-FDrDoItl}*1!(xEr<_C-1ezFFQC4- zO9&+0>{xpovLhg;dmf>Uk+}|{5OcnBn_o8``=RQ7Iv^Rwzxvd`AUucr+qWvCZfWL= zL`%0!;3=?Mm=QMh)4gq+wE)Ut0!2XQ{cct70hIIFWd;+Y`IB;hkN`qb_QDQ=wAczA zt-rx9IDG=IQ0lV$9LF88$#^l!;`_6bq-BS*>o* z>|nLjqP;*I%U0w&m?emI27RwR9+Ln2;pRA68i0{=E;&)^~N(vRaQ1=;>_obWD_ zg&pCa@0*`ER>X4-NQu0VFU^PSmC;FF!%v9EH%{v}kV>T*MXyYgtCw3Q@tGg{I3EDj z3^bqBO77ZV;n-r5Rm|T0Xp_0#r7s1#HIchIR`0w`@qz4~F;%Y856H&gkLBg%_GyQ; zahroyS$%CnMI|MNM(Pw2b~|L=v!$l+Fz)m3K$Fd%v#=%>A#8NgebBo;P%Jt8LNNp+ zOt+&Ah63P>V&jeDe!M-#ymNT`qDfxl;nz$Qf)ms4ciCG}ByDO$Cj+sv>u*n=F$;X$ zkN+b2+ar_-)4xFgnEfL2GId84vYA;B4HuGQc$sC5UI`CfC7Q=LSvsZ0=64UNCqm1e}931-E zp87{QZSRo+KYuHV!!qn+7%y78ZwgV}qO@wLNA?uHIn(t1`N;BPD%GTF% zk4z z`K`ISCB}3yAnYTY%ktMn_cyTOM#!!@@9WV4Wk2$+(Z6ylMGi)M@8V&L1rtD;j(LoI zar_c>hvD~cd<^kg5pv^&r@tQ)ze}1mvOI{*5;3x?ro-dygX9f^8?EL-;OcO%<3ZfX z@P%{w!3RvErQfP}b5nDi4I3KZw9n2T&R))xf7mJS1N6pZ=Y{O>nVY#l{V-CS(e~nA zzSY2t@TnSSMc~2GTRF#eL1rh+e)vf|xEwle1Gdq2o%Bhz;x~`WYdaq`}^9rd*l* zL?VW+rtq17pN3F3l7-c2qo)S|vx%I`LpN6~H!|l=dN**cNj;Awu75K_AY9i` z1nn+LDxHtka*4N2OTb`Sa63MQ-t}+7N<>tN48Mbo74K9S@6m3U!36x})=}htoSvT! zpt|hxl0pTX?Le$LzMGB2uw@&um?<%xEZYu>kIz>xV^Xg%0Ftrr*_2%%=^xA2R8~|x z*g$2zIx7=8ZQi)KUKj;d7>>}NU4*NNZ?&|_q{B7qjzbH8wFDxL2+?Uo6NdPcF-XJB z*DcE{M_(b?!YA#O&$G^mmBq@)hJ+^tug)olYM^iz0&cUuLxM?=QrGfeLC=mB?V1N? z`oqs%j(0|iW3GvN3+bt4?eLD)cn7UH9efJ)v zYWRsN>Ls*_7r@~9+gsv4Kh*%kYcJ3ugKr}54a9n-&J6F5BR;Y#I`@nYB@xp*3Aa>J z7|)Zxm0YT*H88TBd14DVJHHeN$B`FUzYsdpRT60}NlqFj3~<}fj}E^)UoD?H`yeEn z%C8>;+N+grr_*ly(G+d@<-pg6yr3HLlbveM#vSMM%Q zXaiwwBP+M>8l@$3-dY}D9)2?hAU0Nv_TF0={iRA{&yx>Ar&IVsv%ujAzQ=F6j1Yc& zC)WIR_3WvFfBp~rQ=7)*-jJY+q)^NfY-3SzhX8F)9&z(mky~WnT>2l7;-<1$IQ3VH zr>X^}|LcSNiBTT-L>AcDiGcDyYpO>9Od%7Q=)H4kC|+|ul6vu79tS6lj6N(=TL28a zLPywKE%=LGIe=~UGgZK4C;qL%NC?R5fVa3c72GSd>T^)%am68eGEF;kCU^l2ezRt3 zoa`}jGzR=g)`5KSol1QpQq5uaf#+qz{Tk9yw>B_GbsW83{L_D?`QQF?ssPrmkaT$#-$HGK za50X~hi#ubDGu9ugw8mBieJVr#(N{+6EIMyFP-CB~zH27d=!9N((GfyRv zA8+EJ!o5cT2JQ7fMlYDDJc!2E%86&=nmL(LwIy}d83sNsC*!tv_N!sZ{7tp)Re&rp z7sUnYYRr$zjZm(e`U1~`DvG86bkb*;%Fr30gVf~q)WzKj?bC3ZhZ&XmPS@9N34{)f zQ(llcdC{|>t}+Wl1oNX*hm2>y?ybM+J=K@z)$NaH9HMbon@MXLXj7V#8=_Qw$_U2H z0=clmmNv1FycO50;{P@O1@vmg2T^m6U|BkK4p9wis=TYdc;_Ehu=otHLVLv0;11NP zWs^lh+C?INp_EYv-}Ij2fR8w8&WdsL#zy=K`*)DZcW*hL z4H|-c3I!xqaDsf_v8>I#lZk`r`{>Dj2FUB@WV7#wmX$s1>wVGbpbB*+jXoBWWl7c> zFF?4dRl2przh%H8j3EUyb4W4%vjQ7qU>(v|f0_xgX7;IZ{Zj14Mlv9m6~$fN=kLd z5q|y{7mH(oNT`m0m6E%(b8e%V8{;$9>D{WzcXrES7j_ckp50)_{J_0loBDbHGHoTO zV(%tO&ax#_VlVe-+Y+s}VD5OA^t4B76ORS20Y)MtIciTNEatV}@q5GbM$N4t*VGxy;YI#VE&tw43?**Vk1IYpuTIS~D|ja2)+u zCH~~FLz2vMFK%_`W>Yg)DewD?s(?NugiD*`;Ns?NyVh~)Xb*|(c-($0xZa6yzY%D* zJ=Z5z@s${NE%2FDa1k4UeSsi2^7LD*%&v?M57(Ukl7=}qm0yTX){Gq3o!v8vb)}8NLlai4H85 z9sSRWdLe+iFz%BvS4P|bfY;}K2mk(7eyT(1ZsxzKEcFn1Hw-j|AUJR*#TKqr6f>x> z1aCkM;Fr=tgXV~!FlSmQCC z*{Q1Wu;j19?c9Ql7a4a6`{ileN*s=eW}BAeX?hYkjIXDhq4jLn^B1JM2jH?TsRcQw zlPdrK+-a*juEdTWEXM^&aB;+Q6*OOmOuFc?kXY%ZRzVDtIoj z531=E|Md*P;tYr1$pA>6zUXWzNlsN&HGF6K{AjyY^2Wn;=chW`eIVXmdnCG)1kdn4 z9b<4t4ik26`yp`5?@}%*$TwGEe$2bB-ovnlBaq=4GWfpyvnv%99s6FYCm%!QyWbbZ zChsnRekWF_RDtc8yM=A-U;31o^R`h=ea*f(r4XJ86_i}dtLu-^gMRA|59d#5Xz z8#ri1%J&dOwN)0HH4cRf5z3cR5(N8MM((%+yCJf=6S)0sYl;0vAW(M*ecc`@^elpf zR0s%ELfYeu$b&sLLEFZN0O~?F(Wu4C zxM>UkGmd`=9~P3Iy-e8-X7o=yK9CgMptO;c-ds1`!ypI~U1|<&&Ni?bu{IpM_oWCAs(&u#QhM;&xJN>G7jx*QfWq9|jL#*Sx4dhFy~LKf?fW#N)Nuf`zrFd+1a8lgA{%c#Nu* z?>P*BP{$whFoXi${Ni{sRD{(|#4;$U>^>a28U#_sbXE|0%P@>xbq9XLWRd)}!&Y^)nStwgu*6tGJ{;=e@@y0Q|pGh`Yszh$+O(ZL0 z!pI+A+K*b3)~3p6gs*(BoT)Akcq5rS1ymP#9%>jBu|prs*I2EkHDN8@cUU59T(TPU z|9x;&{m00sDRIG0GeC>Yz1H9kN@CkN8gZoh^iOxmE}7BQfO3o3FmQXVOon0WGOVR~ zm$H8;OVfL$#q!@yA4IWR8#J#+y{TBW8FO5#k#^47Ss%H}q%Rf{Jiv<7o!O9K=wKBh zV$>8{qxQI&fb8*a!m66mKc3K4my*rPkF&?p3#;oEU?Ot|?ys3A=-LaLbherxZN_c(K#~Ty+v+f@r*$=0+k+>qVzjNBy$c{W}U(_>^xii#YKs14x07AHg z(>vW0Qp!mlrmX|N^?U78uMw+`2_5=Zp-|SjKy?4^Y0?tMiL-|!^_=NLZ;kD$mYT!b zww3FoW7KS$*J2Tje9ne*=-l8?ka{9idZL{8e$0oO)rL}1m1yRE`FTax4`#m}ieP$A zcMr^dbIklCs`K&}uD8mh9O|&OTxUj#2U|DLf6kQ70?XQK~)pk2> z{UR5Zvz0ieZ-fTZK0LCX_`2#je}JFNx{wLj@0ab5(Y*uEFfP9z>Gu2pPXi&U@pF8w ztpkwDC@8=?4U638MdZ7^v;rPmXN(FA@p++Ds~-5*KlR51?^Z!ItK&BN)-RXB9nPlT zPFr#p94u!!oL_b%)!7)WCNM+KPca-T&-R%vF!G|qw#G{_R(w?-nh2^^i>D)CQPo0v258O$@ys{?d}j*46SMaG`rVq^%zpC0UFz&NP$oI8D%!3HPQ+Dbv^ z-9)}$BI|b<-gjoVh4U{C?@U*7+R?G|Y5{nZBdUH}4Lem$J|tYFB~) zvH{1w>&Gs|^1!g-s>;!PH!J#HPoa&dm?NZr#TRM&VX1|m_k1tU#i61ckD#YI;u=zI zKnB8gMp*Z0s^gOG?kd?&ic*W~Vo_pe2#0|z!CynDBkF#d#bcfmE)w1oy8hulo}8wP zn~|&ZMP7&P&+dMU$D6yJ%8u15dA*u^Up)dF+*oqA(C#mkO1<>+kqP=npV&4@_gq7d z@*%jZ&ic7on;+cKp+2TqfDion{_FCd2bLn7@O;$X>5o(E7bzCV!ta($-%&lcN}ZJ- zK6!jssP1BV(_^>Eio|W#yB&2wyy3I^Mos^m)q##yegcvsEAeVuif7lGzfICu(}9t@SZF759zC8;)YQZ8xXFNYM`7 zZmSlK8uu4^v*5K6xUlgf+$Fyk2&d;o0RH2>)#vrTH{ojNsZxo~yLXQ^zDbq7p$~Vk zNZ{dF@lGmgKuZ4lvNCJyOPv;#zOJQr^B@<0eg?0jS-D=zuaR8*7v5-@$^}0ZX~JJV zX^3hqP)Xau5ONDvJWLb4i78PI4m_AFKr(9zBjLksviW$?(>$+sxmkepOO;QlG^;PR z(DCLQbN!`^_-p+KWP&CKU*5(pf9<7{>AmpSSYh-$+L_Kb3eDke+?iUhMOmzuaGCWK zdid00vhKWnAphdT3f}UWTKuzS-QFZF!?v)}Smc3J3=#;K>gkQA8aDc<+Hcb272bK- zIDB(m{pc*!O+CXX8ax19daCMAL)I)$4>gjOf2E0DfbD@6cfK9_ReJU2>SWLti7SQs zr~dwu7;5dOjpy=F_wHBC%E{k6XSNAYA!&|NUv{vwiY@q9BT)8ZzzEG41PvNeyjXBO&<6uxP`y3rTk|7z6 zK_X~#HfV1lzT0b2kgIIP!@FWRtS~HT7~p?@xxBa-^}+o^Fu$S9*_ni9)LvW*+BpS3 z>H2b$cl=Ff4*tUj*H@ReCXhThvs}9Bx)Sau8PSZ&*y5vlEg!|(uk<7bVJ$2NG8 zAG$bCkF~9{7TZ}3Mmzyyr-{le8aIrU^P*E4!I|>d9 zA!RAVNG_W z?EtB=2+o9`GNHr>PZzDbeCm1acHNiE$IF}Eo&6A3aI;2Hlw@IJW3a?o)I!CEQnQ2{ zkBECyWJe?2`t z%h}^R<@!;-peD)Cvz)67AoDiW$}k#%zq|kVmuQNlai10o8`}p9D$}0A7sdC^4yy0o zMIz(3?xw?4!r|5=jH*1bQec~B2hH7T5GE2crNi5 zc2>0I{lyPa1@fM~7P7*YH{71n=&Y?Y+Ex%Rb}$i~7_G$3C;7B1afdZRfG{=hb`9HE zAB-GjMLwVI0R($HnadN2qj(x&@aR3b(=^6S@w z4}On}%gV$^u#Tm_zBst|<45n$pFf$Hn083T<2gLzaMKC;h2I=Y|7WKM3Tg_?zzP7?h1j^E*z$YFa*9b@H+b!2SL z#P@E#qaPymr-HP1JlK5{<>n1<=`FIr=L$x z@EJChtiH{CwPJ~MoL7lSmQ#h!gIsK18}8}h;zSQv)e*h|!P@Fv=Vtlc#w@q6@YU(1 zn~rvQGg;x*$(uxdecr@1Glb4Z&6OuZemMrSb!6Mq7bj_=>X|YLtTO|w7~Euh4zXe( zhpnN~IZD~%JbR%nir>NRn3bE%oz%>NMu$|KoIU8lHX4a}0Ea;nKOmNh@yEmP9W&vOrI=V&w9El{YO|`@Mv(L6^QnTsKqDgTR z1CME+H~pgizA;g}3Y~Us=P4MPYfMRh{bPaPZJnNKt(Nvw23;6D3V4DQRaFhCgz8WJ z_5wyb$A5~BP^jr^5Bkp>c)h?uLlqc?Mh2;@wahYFsH{D-7PYue2wGtC{ul!))Q@lJ zls}Tx^cl=Qe9Ttid$SeaGltHydRJalDDJk>7|`CM!`GX8$QDr#Y2z(s$5mBK(YkuS zGQE+-^S&kBh>S~)z<(-2cZ0Skkd~=Sl%Ng6w-GCtAt0U5j-T?~R}?PaP#WXGQ8RAg z5-A#p9R^cID1j3LLBD=wpkeC#Hf1^-BA>}4p%Oh&!WrQ6@sL|X=A421n=gTp*!ulV zi@Wl|ODf*_dfkDf;`%B+^#oDW;qRBF8CAH=0q9XVTkTCUKW!JWtxGtB*7Mm|q(A>! zq*>(u)U*pn?%P~k!iUSwW2hWzZ>((w zXelXw_0HhQN{Kl&LpTz?FsmaN%OEECG>f&pn=Dg)$X?oOzcGAjF)-z@tsbYYk|F{F5!Bsn@8px7k*=q|K=lbOG)p|Czys*}peMG{T^& zrjq$SbrdawMJd?eOK5XMvj6^59pU%nxSx2XtoU<{uPPMBe16%=Fz%)F(KUn2j{g%rJ4%lxbAH4ow(# zKi{e>Ej65Y|Fzov6mFEe+{*QbN*$hP$*1!N%iqIY?L}XzXn7k45v)%XuaF78->4SfnpGDB!u+ z(p**ZbUg24v>Gvs_fKB2T#tXBrd*EqazDUd>+IBD%gvC)-cFS-hOkZsM4DO9D0+U5 z+5-zKH19MLrcv|}7vsrNgdgf=#ncHf-259pYtbW^rgV4nI_~H#1bivMaPL57BOxA# zY*5Q}*wrf!r9XdVlNGfk8PKi>QO%Bij)>cd`CaC_8s+Q71x9OA(Z$3EYQZ(U#PrW{ z=8Tr12rV@CiZBpVR2~ynjxT6zwfM5O80?je2TPjS1oV6s(%~?2dB+;S8b{of)6+Zp zBi8lR)6<{(F)^F~EY<5RKj-3Ftr+Llc#Mg9Jym&q;!K8bOv_-N8&^!5KIgIx33ax` zb32*#F~07jU|CAaj-u_Ua~;c-ihN#S<~uK?X54CFk&1t};vO(MZu)R#vvM zH&lD$L5z=Y%)pSVqAN*PzF|$Xri!r&_ViK}zLgXz2)2 z66Cp#l-Nj$$MIg>Rf573i3x5R8k%R%h%_q}*qk@k2ER(rR4&>db=rUah<|l0U{gZaQOS&6hU9SDjijpitT)p~;o(%1# z?lw*x9DMR_n~=Nsu!sTX-*Z7hG+aEtB0`WEV2oRlwnb1k5hclp&aDc*6%N$$d7W^d7W3G*!1MU~AXLh5y>INBFZsp~5Y$oS+WDX;Yd^Qg#-I*rq=#H{PS%d3>- zo=sd*Qk$#u?YW4E<88H##qo|PV*v5*1!OXdKGJNtZ#Y?EYGkQvvpG6_hH8|=Q;q-3 zbl*gskJvFhy^sP4!^(83LTd~|=nk93ME^9C&o(rk?&-Rxk{pyiUX{!;No(Sg^OKK#JMZcJrvp{rSXuad$}m~fhv3zTuON81i8NoW5vYwBTo=_ds(yBU$%lFv$F@3Ic3o(6w4#+f zL$`(Yh()g_UiR!@wF@}eEp|`W25Rgg1bqzaHB8AB_P*@x4NFU#zc?n_tFdL~ME8eq z6HIW@n8bT5;CcOQEA!dzK_m$CB`+Cr zmI(DXc5kAL(5xrgJ0a=9jhAOr8X4&sNl6Fk73M}pcn=9{m-^~=rj9?iX5*}u?1hsE z*zat$Y)>8wJG`3>?!uHQsJGjD68~cPm%rcPd!8i_jI4+Ooa9?kw7oM`_NxOKZLxMu z=RK|`r0^ByC*E%v#tKw^?nGT{qZ4ss%Yq})L0w9f`)Yh#G0j3%$NJC>+J)I=PBig+ z-b1pKHn4@y_?-^d1{RS{$OJtOD`H(E_aAmm9qfA?wksRAzDhYhKK907qR`c8`Dj>e zXKHM0zPPzLo9kHqF}m~YLI|8S&-v`laGB>>^_K8u<2k+THfONxH}5~}B6|A`D@{7) z_%7-t30el(;9MyedOx&?d4&f!nS;AvW2~UCf|&s zr+Yf_Sry&=>Mx1kP(1s4aD>w%&thw^9fadvDhpS5Qn9l`c*UgdcoHJP@C_0!!f>AGvp4}+&v&mxS8NFZw(i{7oNmo8IZMF z>o{vsV>G?cqkc`qk{a&+b-Aka#_f2$&~}x{3?aZDpvlAI!$XfioEgdRT7KvUzkp#Y z1zH-Kd$d&)jcF__F^~QZ^5}}*vGw-Mr>q!ngE|lIQQ|i1Z zvY6Bw*2o>p(=#%1IPDKYBQA&cF0r`SIo;F7XVO3}!+mN7!0(0oV8-jO??oCZ&?{~2 zZ@%Nmm8A%}hxyonatt!-`~KAH=-fAJV+E4ggVYKJ+mi)tg;>6w(F~7`{p1t_kOk)s z1XZ+jb>0}@hT(VJZx>DZa9&a2<%M5Zy0Grd%)&y@TYKTAQueMRt1sC~qh6dQyc7X1 zm^Da<4q4N#aI_ka~USv?}AAUvMFpGJq!cDHjslm7OU71fo z>N)7({AuL)cu$FM#H)_qXDB8MeUiC~<39Y(v=*Qe*7mbP* z)v|u4I|B>Yk!p4n3Ak6K`a@=2s+pr<(a7x6zNqIfiVzS!i{i00L@PJpvY*Qyo9&fM zJg`^z)+%$Q;`A(xjHazfxjc;=Qlr`?=w7#5>k4uoey3dpKE#Kz+!$m$$ok%s6B7@J zhM`@|LcU3Fn6xT*od*+X<=vpJLd{<(HTuA1F-`uc%AZ_l#ILU$SG{iBuX>tQBcx+~ zOh6!h0RcC~ro{0t47D9rg2mym~Cm@mng=N4dX1U-?sy4WGe^EmBFR{$BYP+nUUdYOiL@H?JcOk{cq4n_Z z;kYrH4}UeWn|}z&ApZ{leBE`&_`$FDgGN^7ID~}$A*i_4zP*74{LkMPKkitndWJt+ zebS$4W%S&tN<$21DtG1`?0WmfgJ1*((=6j3;iv_yr+hp@e)6YY`MFoi8(M zYe~#f);NaN&FU512bW%fmb19u`H?w-pGK{Nd4KAw>1t0J!=8!$Ug zm9ta+qT+I!_wT2w?D41OLMU?FI8(WdD)ZeO_V}Q~!nG4pYNciY*zcA*mq#dA&JVYD zwDQ^oph$r7Ex~5Ew@YVaY8Xu`Z<$D1?TQP$%4b5>XUDRK&dX=Nh)aqm@my*55cQP$ zbkc2Pn02!oa)UHFV*bXc^9eKW6QVW-o{7o>;dk$znw1x2Z`8RXkqNlmw=Ow(N63|ux?^OanZCAF;zE4O}$!$s!Y1Vn8t zx)1BeR;|#KqEIcoo3by%HVHP&Y)L=FgC*#`ahknxoT;G)5%Y_~hc^7m$5-@bxd6m5o)@2_f~-#z%?=eMzV2u?FhYMBx0f-!}Kfs^I@ zr5TS%4pIYyQK<<~Yu-oSr=tY)vUvc@)8gLrCe;#<;_0Sz{jeFjr}X7Z^phA{dyY54 zQM|MthI5s>T1W4FUB-HhM8;bq9^E8a_EeLzUM5cLrbT~ofgd{M+n|7e$E0CB_<2B$ zko&uKU$W+_FmXRN;}f@=rV`L$9nN{%)7!fP+KvaFYQxoI4QQKO7pMHK)Zp}<>$o%M zaoIetSVuBl?6pBUG7IL7J+pkrl@Kz7WTa*>Nvqka)vOe}4hrT0moII#$&r0mSvDYi6DvuE zDt|10IAUb%nGmS22tLs(wbc83iZ-Tafb%!IHw&X1c&#=h5{l+CJ$vr<@x4|SKOw(Y zh@=z~995i#^2&lPg)TRvpHfr2x(e_{^B7zj$Z-=`2=>-K1ozUtPvGovglg5>Ul7^3 z_y4qrdq$m+p^r|=L}E(ERf#(ISP`n$C^$Wg$s8bL6MHoP^WHwluj^3%HXHS*{4 z1Me&A*F?nl!MvNzRuYhj2|<^o;AhrtVbDgnUINMkLheGV(wv9BzM|LX<_I6#5Rk(1 z2(@M0nXmaA-AVZq`A%X$0_mjaCm6{yMK~?cz9`6AaWxn)e0@Dpa@9uWk;JjsmUVp% z`qv59Gn~+i><|BsueX58a%;kdMI@xVOS-$e8lF|STr}3NM8Z1&} zP-iUjXja6c?2n+Jz1$g}p}iDN2-LL+mWpRF%cUr0DUbh(|LA`iTnWN!CHR)p=Gtkh ziopIj<@hufY%kt>q2C`1KZ~&Nb7nk*+~Pk~ls>^QxRfQ%!ujm+@t*P24_dSvaY%hX zKunpX1qLYu5HS9X{p@J;Xj+JpR5Fs_ny)tA1?eM-N;|OkNJ8aK`D7wIxXw6~ z2;}V!c;FjPxDiA3YUK0MM5y-6Z-MH`EiEhu8j(W%Sp2}d%Gz&GnJb6$rOTJto9CEz zOZA7Zr~@|=6RSmn-_zb(r}EQR=ygWVR=ng}%!FA8pKnHCzI34U3+SyDd&xg>RIEPo z5>>f`8p@?{2+F>gO}x+GEWhvNbi5ZpLx4iS@~t)}5O6kKQni1ve7Mn?`I@??2;rt; z?=Y;?>da)^wM8dL*Kff&Xw)=1jTth)2m+_X%>xdQMuA?!!vhwBmNuolh6-Y5V zTphjl7q8+$k&7?S59i~VOLA$f79&ZSz@&fM4<~$kZ#Rp|HJ)x-KD|_EHg^wCQ|s~1 z0hI(17>v=Ab%nYQ>wc09?Bw*>>00Z=5DHuLKp=lMSX^4@hT1ryeGX*MYH6@r_lv}t z?Vc$Ch-j!cZ2)RNL)BYNNtr(l2^oma$|*(netET}2XJ55ETDJfN4pbmUW+6SDT%}5 zvUl}NJKTkRQYsn+sCl*4IF2{5&NhBC1^kgTDW6Nt46KJ5v%|BhyKiO48Ks+{^Ggc+ z-~QYEcmJwpk}$JLPmhku60^_FPD?h9yS#~4k`NdDB9-PeD2lW@VZFp2tZGDE+=NI> zLXym&#kZfHD)7_AO3w^P|J_WS?ah;Dc)no&XlVn9cg!Ya~ght*uQW3h&%z zq=-aZ)?%sXfu~+;o!5Idf{^{C)@Y$-2FuUT`uXwBjvbatxk)e-<)`Zfx45Y2ng>=$ zt3)gc8Q*zxv#7)XHxCcEFG~6y|X!hXYVMWxqnIGLZ8@5O0mYcj_d+RsSCLl(kI-tM% zeK|gg!))`VEJveLeG_bCW?KePs56>hQeK{!Ugnq=s5{{Nt(c;7^6+75@sqc5d7j1| zRd##ZE#jE4ZST%5!)xG5gV_R&N8uBfyuhq9I~02OSA2(~GM%_x-&cl$jDm>23(+g$kWQva8us(e)-3C+Lb#;i=dvD08IB4rA6R#X z=1rUs0Nns~(8 zC-G`_EE!)d3fx~l3{DL((Xu{f%Pmc0wj!aT1}|C+#SwVZJ|naB=XB*5=y?Nasv{a~ zZ!bv{K40PBrnXM1~_AV#@sI`%bWS8nsfQ$el4i|E3BlnA<`O%3l>FVuU4u3@^E6ka^u-$ zP#ooHg2Q3+V|L%E1j(D{69LlT03Xy!$ERe+sOj@Pg?L}VASy!3+0qO5%vR@+NC2Kk z-ren{>a@0ZI`p@6s@jBvN5Z~++it%(Uas}IFh`N!`KS)S>I3K%*tO(9Mx7hY(m_Ow zSZ=kTSY2&@;jMi+;zx!eRoGC+=E>sp&MdPYqBGZnQPU;i95XjGnDj4? z3}CCZa$}#)w-R)#Us7U8hFk(7MzgxBXJ=Kl2kf7D0V>Gcx=yQ+Z)#MJ=%vBhUBSA( zz7|kLv#`px4cUU~PSjrN&xR8%cQ8x=I=NTF=I-3YxEs9zO|7wQ9T^!o7D=n%!~$)N z3i-~f6FNv}q#e^&J%Kds?(nZ)-`QMG0D+P7gwO5Lc#huFm(_L!S)^zJEBd@VFc5;J zo`_oa2cI6lT80854(IuK;^Cm`Fvlv~$=nTzme%3cxO-uGY(s7R-Tk32W$Z>kn?inz z07C|9@!aQ==hTTOiE8_5enf)xQSISK+{W4Rr{c=Y5o|966BnQgIe5yk0L&VIC^N>K@ zRWwXD1{8)%pk2*-y(UA!+;byvWp`M3g62$E{;nKpoWXN1bx1|fw~aR$-u;r-W~DRs zSqKCRC5oOe+qL)ZFTd$B12^dbq`LZjf<+kx#?naneTp_4+RCzDFt>xZtS(FWLy8tP zUqtz(>n=%Bx{TjI6vNPGy+$!yqto}HNlweD4hA8Mm{ri_+k?0yTp-B;Xo4m)93gfE zIWg0y(k@8ZQK5IWZ_O6K%bp|<36B>XPje@FVYP-VQu#s-kYq$SKZZI5E2rz2>41Pxf2yw({!|v{P#quvu zq$Y3S;Rgzl(0rEp!bopE8I}a?FvP6N7LRQ1>3^hJVgIE6G9@*9Tm{@08X6k4(qzDr z_N_DX^YszLv6JV$Q>9{|unW+0K|*oC&4oblSlTL~knjo0V+ATWXapc)mJ9D&Tbh5B zV;9G+t=$D>svIJvj`=>FYgcGr(`mAQTrT3Oz+Ub=aeSP|URY|>`+N*V>;1hJb_4DG zdH0AB2tkBO4Z+^gk$}tMR9;}>t7d&(aq>;T8B2rhDotz5%w#1flheKd01f~RcE6O@ z42U;`Fe@mZYy}Co^o@*^TAZY`c$NV2>;8_9MyH6hqC2CB zm25=uE?>gXRKVziLD)Uh2xAx;owk02Hd1rybhd;r=1Ws ziM$BA1?6XaTw=)pRzSDXmI*hh@EaVTYGQ?iMpoBgP_!7VgR;@$W<8h*-Zf*#8awEu z2JY50N|dk^zbsW-Pb7}K75m_W=t*$Le^#c@&iq~o;CJ1elrQ@))Oi==vrOIjEvLyOUXrt1l<6QH&l8yllhrET>b z;AVZtlOWH2-SNW6%YrvX9fBd*he`S5LaP~ciTkivDf_)<|En^0$&z*9Gy6!dIO3Rc{Bqjv||O%_dW08v})Mx9!r^s3*rEc_0S2cmY{^??7kz#f7_dE5}DP z_I3Tgxq$DvdaLi|Dwa#MoAKuM^N2~3X?0a<-7YG0?gd;<8HtEaCk@Vg9g-RJUe+I0 zgFKitQ34lOWQhHax(ryi@-_|s;!LxNlXW0m)b0h(u_c8iM&A!e|2u9bA;7dtDf2;TkvlBxXQ$2NV{ zNT8%<3M*88v$jrG(!Al}(&fWX@&4%6<|kUl!Da$h@xAq`<=wyrp+wZJVQc=DtonR;nBt<>hzJn`~FCUYdmXNEJF~;y63A1J@$KdLS1Z(`igEkI#yS zchPHA)cN~A0hrZhwI$rt!EeKIA`5&Vim85b$u-CQ1}F&MOeE1tjR@Q70g(1fXrQjc zkR^zhu{asl_b8fCC=$vd)9abSABTAgm0|jje5c{w8Jb4{3TL3c<<^JJw9mm^ib9Lz+1x;AK>my5rsw13iPu3iNuZf zT)LUwvocL7DEI@Pxbh0JspeS`jUFka-Gy-;POFXXdZRnSF6dZgBL#ujG3d+!LZ$aP z`&v|JYB`_s4XA)B-})Fuho4fbq98D^{|O2)Hm&xyPahUbaj|3WwTb3@zf8+qxf*Ja zsvUL-z=hIjvVz!f=%R=#8g9Qh?~i^U+5sZv-SM0Wr5_;G!ERVA!mJk(HEmh1l z6gw+&StAjLJ6PTo0bo$A8N+BQn*b~8i*_sNLZw|?Id(50pOe6PrIrCP`7rDLGNHK?{EknPKA{#&q`QZbXHrl#*P1t>|!bX2c_IA z=Fq=nv;aZa%1ks7Tx;oEIv5@p6riOMdXviMam&f}Om%C_>o>F}$-qiFYOF@?_dd!s zFVB#G7pb^Ns@LZEb8_2I>v4>e7G_%7fE({S!U)jcy=(bG9WaD*M8sKrR=A2Rm#Yl0(^07H_5M#kB_yr zGjKU7w2EXyO-8(bE*^WrIy!3KV{;iQnwvLeX38zp6n@ZEp`cc*Ln1Db!}|GCjINxP zfa2xMWM{|J&d9C3ygYJBeGQN$rQAFjx^Kmv zCl_n6{O`T@H`tV2BW*mPqeFhw+2h&?2zcM(ae2U~r~?WT-S$>`4Q}s&@lW}QOChmR zWwUa0w6xbp+^6Zc(sWN&eo}C>&btoU zv8HGylZ1D|)4IZc!x!L)JTMcz_?oRgDkf^^>sQq$-lCbvPdt?3#Iz}aNKzsqFJFU; z$U2)~sMkrpYxDqWxw&2)MXSx`rZ%8vmyR(f)A0(|`0=II&y8oO9nRy2b+#wDg)(#I z_+jWYc*W5d7c9zl40_ES9t$m1r>Ccq_Fmz_wvr!8W(kX1U)dkPLKW2QRLbS1eF~ms z2|sH2Wcfao*==N2#hX5Lwc3#fa7TWDFbQ;8=VwN%Z#Rpxc|KQ5C&GvXKTpV-T~7!s zMH6y(gi9BZ`iBAc#GM#{w9;@h>toBme(leMhIz9a8ZVwiuha8K=R}$ER;A8--9m+? zdE1d~Y9PfR_hw9%c9tlb8P5D6M&DMy}OkM{FVQJlz$ubm3kEj18?Yhb4KY``O{ zch(Ip$SL(pk1|UQLIUTC0o%rT;}24V!;#Q0sCU_!k02uqHgH~`VKWLv0`(($s3+M{ zS|2!R^T5O8iG`tkQE6?duSb6)zRyfHI*Ou8=YI8b=O7OA({RjWRfBbUGVL}pDk>lw zsdt#^q1Rd5Wb@n(gV#e$ciD|n10-Q#D4 zVgNJ>0mD(&*7T!$NM8?EIBZKFjyfTF!V%6}nwXSsa?{9+0IGostxlJNI(wkz49J}s z6zlBh-FfhL>sL#?HbMB6?l=B^!m|}mW_xOz>x`Z|x4)|Br>?6%n(@b9K7V|9CfV6( z0kn8eS96u#<|E-N*4 z0l=zjmFORIN*%cHnk3E)HGhB>5B%R-`?dmORb0w7XMh`LG;)PgLqbBz(?5G%ZFAxo zt@l7w>NeY7?(JL5P^a#XHX&T@g(ce&vN_llj~@%Ra{m~lRG7wZms}a8U1yB+P_%(` z!AI~++td1{{8DyfBUW#iR2fi`0H5KV1jd!$qLn|RqT)MXbAcg76vBPtEj8r zZqsl~V+S%thy^$y${P?(i^NfJ8n=}J1^=k1D6okvAWPaXo|#=y#YLqUb=-YVrO<5X3>H^SwQj;$K4m-*ahJ(MwkaLXAZ&;NvV)j1h+ zN+Z=&UyZWc2=tKDe6ITTKKPrC59d{&KZd*o2^63U>7t_@%hjVsr%uwTHe5fL2`@;X z+&3^ao&BPMx)6}XVus>(d9+aYDSf9ze6`8m9iU^A>2xCN<*l@T+aI-?q_zv(u*?d2d zN{N}YV|b;|@j=D=X|Yb~DI}!Co86kn@w!d+RpNO`h$O8w4#&q=IA)_6Ya0i6I2iZ0 zu}%GW^6(f?(@GX!`Ku-Ya;~L568#ONbdPD;wqPayvUX--psplV)?`57%J41l1>f5l zrMD+Xz-D+$G)nAWT)+i;%G&PSbWJoX08Jx_n%}?JeZe@}Pkvtm7sue6N|;6bPkE&4 z(1_@CMS%tO@N0_q?%iJSgls1=9ox5ZZsXe^OimJ!t+ym)fsT*{lM&r(5ln!>z{;iy z+svHV9IWaME;J?*5>*7tN5NV&Yv6QeyqoqaeZQM%DUJ(d4_ma5m%}wkIPT`8wtu`p zA)dswG~GokJFECXwHGFaTg`jZvAZ1r;RE%`(5SFJMZNdNMJ#3NrP`aIt7EHUB1Vh3 z3e%5N{5A*(W9b|{5Sf6!!@GR(RA`_9IP?GvXO#{Ogu$fMY1yhZ16!SV0LIKEW;3g*lY&T5#HcIBMC+H_4ItzxCpXdY%u>(&{3Z_v)rn?I}t9wC+1nL zc{Mzd4VA&|s)|sm-0X3MlPDr00^oc13s5;2SURB@8+8KRC^oAjb#8VY@%h@2AYq#}$U%9L!js zuF0=jPyNy$bpdy#bNsw~*vbc(+wD)zVPVXVgkzZlxl*-305>Ht`mjCnZu9x!MA7&4 zodD3z1XPW(5f3=5=66e2jgF?t%AmaXH_lBI=4kb*N9XNDx+iW!d-=jz1w3wD2Cm!B zDU~A^9mh0h?ADsP3j7!WWtH%F*V*?Rs_ly1cJK#8|E|wkPN}?it!edNl4#Umv;zYI z=+!x4F`fKG{Jft`-iEbKDNM~+s$%o)j0hx;Gbj}W;Mo)i9ITuHO>kO`l|pB@Wa~iP zLmYvM9q64{-Q8j^Og;#{R0C0OD)GhO{S#w|MzCFYp1B74_dPwI6iC6d&BnFiU=Vy` zRl6x8%03z_{Fj1{V5;t;X9i=w8@E@_X|$V@z2m3mPlw};tK*r>pKQ$4Ik(!c=_up~ z;O|yn+yLt7;pDNf-5n9TkYd6X5K*mfWSk<1-L5%d6213a_c4W0ERbCPBPMKAt3(8d zp=_u&$!=_&_wQY+tc2E8!}5&?&jIL7Z+b3C{h* zu42csUs}xAC&+FlsBy>COfKVJ4#&8j-QOguJf5D|m&Jdznm972ppn7m_*`Gs$T$OB z@eZVIY+gr~;%SxA_?LHsz|Cxg+>{lxYYwBgXWw?mbV6X^0UmU@!+IiZ#v2iz`)Bm3 z+GF!=%t$gY?1}SyfY4j3X-!^lRdn@pplv^0{7;EC%Sq>(1L@_wV0iF%ndWGI;P{d$OEm0{VmJx2zfQF zHpfM%6ytd}m!*z}b5F3Eul@b__)c`%>`YcZ!vbv#XRF?y^Emme_FV9eHUw02r`xuo zI{}f9fJ0w_DqSnR`YA<`xW{0WwfoL!S|`x+Ge{WBzUHmBN$FFzv3YR|y3zus`(5oQ zk&mr(SR)Qf;6G(0bC^QKciBe*Ln}S!D#ME*<&j_-U5JeXvb`PwAv`Q7BDKL{8`7A~ z;PLWi(IX&X?OWXt6e>tgL=er%_6OsS+wgEDLB>Elub)5qY1C}+cVBRf909ye*DKlrqJsTL%@T}w#(UHb!qUc1NUbfKlYGhv3nOEgfVTtB)T zx0cUn_2T*T6JW^mSz+yd%zxyh(QP`FmzO`$^VVtcxJ&!FEO0ord11YTvXXu~khcws zK?_ajogt*eyq2gdj_OfPucvfjsuq8R+nBm z|D1=i4101%eCYRnWF`jsUa3PgckW*3*X!_5>2%vHo}-I8V<3j7F$kVdUn&s2AZ*XH<<#zpb_C!6U4E?jmS-3F(t0Yb#bgAsenxhH=SkT3W`lReFN z?>d~6UXc9bW7kE!B}cK`gV%Y%g5{i*FeR0G?)Qr2=@`2)jJP2-%a?_!XT8(eQlk?< zfGH`jf{4qFoFRX2T7)*g32f8}_LwjtgbtB9wEjAa*AJ(=?QTU}47cE@?(V9|bTjom zUo&2+-k_)lqp2`~7c^MDPuC-Atgw8Y2^enBBU`Bg@^g#bRm5KCl^-e%5q<}JB=E`v zu(SvO9V$Z-Wa{*|Bqh9-Uk=moA{rC>vB_bWbUYWa!5y2MW`lu~;b`wrWIi5Wz21$j z-_L5)Mt$d7CDdD&#HVMtdEz> zPW#@nC^RHES}oMz&N(6AbJM3Q=3jDpF5Xbe50k@W@O&olf#0Bl2m7EU zUJJam&2J$UKtbBI)p&*SCextFb+JP zY4EpI@i1SSIq4bMkC$A}u@yWgMZ3Ts`s=aY5~Cr>zDt*sBEV$+-ZHeJY(CD_*7R~k zm*w6ODs?tOItfeY!VGF=4x17O4iS)pNvHne{?sA+ymvXS*Ww7&m7OAr=lEQ4f5uaI zEqx{k35$AvV2a{P@yIl6Yzrx*re^l5(GH7(tyck!*Xt3^A}`yU-|%SO)&$x9{_;ej zN>t48aF)*^29;uB{NY(m+0l2c0ByIuW2=#e$O*w2 zgF_~ek)R%mgK9d*66AJDQwlAyyW!m&%EK-*pRKs7W`WGQ<%fkqupi8Xbp=$LE0@4#AQE)H*H{CWzx~r{@1GE( zejoIW(vZlV#pl9%JQu6CXOindPhXFbscArIv1%#YroT* zC{q^})Q_BPGy%vh$foni2tb^{$x^%*cJv!c5Xr!Mw4uZ8B_@lB6>bw~2d1kDsHV=w z6xT_if-gjYjW^9>ZB8Nk@>5{y-qwy?$z{9ar`W&DM+1WgUP&-`tigC={q_fc<(`B5 zaHmJ{VMDStFqfAt(T*P9<(L5J!|AvV)aPTa4bN34d`wQabzn)%T8Q9D{S%n^m?20Z zYv950EWs)^Y0nndvud1u*mZfj;$hAH@?U=`wp06jZhSwkKL?$pj}*kbHHgxU-hWWq zBXlPQA`Hr;3k|1s=asC}>Rm2w6vh25;g7+=c^cNsMc)%z4`w#J*sZ6*BS`TTpA(Zmg5}-67oP}{Iox-?q-u#rJdn2; z4;M97gQ?zrjOu;MEJ)(b6Ym*w3QR4K(Mi-ozb`BuBj`!rlwm`!}!IqX<&EsM`6AT9nU>wgWtRig?EttKRB*n*} zi2nTyE*IF7G?mel^CFu*x!(-Kc?`epFz^%c8z@g#qfGTeAaYvPonxT!F^guA_6ata z`mlhwFcB%|HNkrNL0Fq%jK2iAe>LF{wKDp6k1voV&c#bOIUPl&e-`l*fx)CNnYGW) z%L6pXuOEjK(*YASR`61tRi#|Le-P*ul_U>0&8-5uZwy~m@~9IqR&35=?Fy&lHP^hw zyK{hyX`hWGr}]GwBK^_>st(n=4$)mz2G#ZUS)a6?M;vu`ZL+AN8c3MDs$d&y2Nj66DI=V;g#J zVdUWef5nO6J6Z+DYA~W(nmP~15A+Un9nGu(GUcJ>gpX3&R*);FM_j0c=G|ww;j0?u zuM8qs7DmkfLhZn5@;&N)Ww!Cck}t=&_Ox~eFgK%4+!_O7Dk?b|cU@>m-)*d|zuGQe z3%}Oj!u{1^hzsrl))UA%&dE**`V_V!dxYi8tqyDr5fqDH>0iQFq_diE75$QOprTc=^gszsX_;TLpbj#&}#h~p{Ku>B}jS=_ibNTBA)d8VU4I_HnI z>yb(#zm2=?4ld*-oUup^;d?;2lQAJ)C^1QDbR094A<+^`7xr^$m?7PB^%r6xaVTPgavObK_HX@S!_R)d7aX9j~cJy`BWd; z)S5*A(OV)--Wm4ys7z@AzrwT=P@+Q%01@B>!)DgdxpQr1^y2db@g2F0aj7AX$1lRQ zXHbB!jbM6Q4S)RwQ{dF#R|D9eQ6c-rK0&|#p+EYH1G1!?83_r?>0!M6n;FCN=V#^! zpx$-Qe>Nd{*0SqgrB=DzgT}}R6s@uUUaUW#(kB>%mD9a%NHo7&x0@A;`C{dGku9_W zWpx)VObeHU*ZYh~}FtPQVqBS>8^LIToI;>+7Dl#fa`mvVJ{uVRUU^ z<4#o>iB8M{F-}gp{Hv1}PZd2bC)c3431W>P2%=MJm>}@3WDijZ2NF6@S=X@qF-!vl z-u_*2{x$uiG6gK{XCxr(ij_#bgF;8fMn}Ut=UoeYx$u!idn2m;X5uk|ium9E`s^$1?YbaQW z>5JA6^zb>LpV-E_Pyf%p{Mw$jGq_1G6!6L{u;+u~0_=ZS6(1}YIk+4~Vro)1$jppL z{!3|ia6`wGOq0L4fT~0VpgG?fk1k6S7d0i~>zZ=6r(7o$D;-nJ6&z`rFU=t{FbHD` zDzmvEg1kOtBBgGVZMW)`11cxST886PIMj6&p#J#FME>_%3^Dk3slTz)?~bQaX2=hA zK9v1Xkp8{d|F$m%iYio(eYxbGRE}m(6^tE;+HYSwR<|lp! zNrv`jZ`Csj#{a`v{_7#yn&Bwbh*p2}=99>PgKtUy{U~i@a3QY)OT=<6yU=ja;pQ0w zAxTG2!rmd>T3GoGl0yRQ0;&}gO%G`(B2de-9jYY9-_e@zaUp~@3S~vrB7Q@|2}0}F z#g5vK8}H}zO6mK(1TnQ(IadE(`rqCGs7rNW`~MYH1{uN8{!B)~>wmSYodE$T*o>`Q z>_7>+lu7y*ee7xf_Huz7o7xBgQH|JU|5=fZC*ol(X}dZ|+$7{Y%$U5CZi$arR#T~W zoTiL@!RXnD-!=yrlbPwL{)8~!Mqe;)@xQ~_pWjSt;$!yF3FiIZive`=JCH!?!h%aL zfE7X|5PwMUNph~ixq{g$#ZFuc?Pln&=ijd>^#l6LLVO#2z$$3J{SoEK09XVeoXPx% zEzNPf32Zl`coBpIay9e@0kRNrPWcE}L=e}9e`63Na0W9U-hbljnhD$_&Vvb@g1|oq z#n>BiI{n>v0B0CN1Qkv{)Obo={LEf3s+pZ>rN}=(@oIxHw>nrHTobSeL{cv8!+1@t zHX*UT@Am@(9H4sss>H?`Xu{k0|Mc1YWuqE{uL8;c=cxXEAeV30g6%>R0gCnJp-?a+ z)b!G*dAVzp_9YG6!#-VLenGL~sBv7tO&Tmu$#Jhyz!&1c&ghXroTysYjbcd=L%jdT zV_+-+Nl5{OJ|?0{sI8m;DwTil1#=?UI9IRyu%-*+_&U@W)-@z9#wM>&e)r@wQAU2` zJ7Gtgf++yzM6#wKg*sZn(a{sYr2(~NAeKHb#ssGB^=FpLD$qVG#X+b32Fm|^4);xc zirq=!Nq@a9ktLQ(y~4iA>CCxY?SCQzfKiNJK|m?In+oTaa$vt#CdBi%uzW(jqny%> zB8ricr_1Uq`j;H@knPt{oW9BZ+HK0xdVA6y>|GZ|P@!Ev5?}#ULXIFV0yv%^PerX9 z;C3T(89wl>|33ZtabVn~tWvPRl$YNd&Xou@{I7nu>G4+*{X)?G-B@9W8BCy5Mzpaw zi%Umdb!mR>%bKrK|2YN!@eA*>=_I7eBT10?l=wF?nWh57mvSHoP8h7#iQMGou_6eJ zp}kRnB_DKvG=Kf~(yxt~_;fZ0i%a~Bl*Zs4Er$$R+g)vj4Wo7*Fh+(cgAA*a2q;BKiwHuP8#E zqCmUKAZ8)_wJt>8uycI+1f$G+9O-96!ghGEaS1Y*3NfXbIC~LswEMYG<$ygYY#Rki z^%){Ep^eyS5sv0jZ?ViW!h@?y{eD5Y6&T1%H~W;(x>xGNqW8w|QS;At%H%8A{a&yd9`H-*l;!Mq!_fc|`Eyjlu?E?Lza)?tpS@Gj zymM0cmX+t_OW;DuhQa1gv;m+`_D=2uXr`D#xR6F`Mu5mkEW~5I#u?)>)833%z|F{_O1Ne zn|!;3i)Ufd9~F%H7=9DXNM31X;+;;FKB~kd_0K#0E2JTT7hwsuvycCvZp?S@^-yuc z_-em2xHCF zrcy}b>m(4FjCDA2A)=h@K^T~b!(hu~&ih*Gb!f)6c{;I|Qb8-Tl`fv^!`VcBHjE6I&B}j&uP>TRk_Y zzJFQXJ+@#sSaGy$G+|Nwl!9AH3#3p$+L zwgm?3^<)YPw~5xZboo^>v{}Yxca;%u>`n#^v>>RtE^sG<#cGoG?Kn0O=(n2+0DkZ* zx9egB5BLWy2%{ca$HpHmDHqx$;gb7VvBGCIWO?y*$xEUsw9bE43tt&^m{z zP^A5MCOjrMCe#6`F0Rc8Y!A-OBC8zg@&8G2O#li`9aIkVfKK*e&2Mj1CyRl*4JUrG`E0L>yRixT?I{AEjZnMNLr^PP6nCR9wHFO3T z&ArF0ULt{~`@+Ifs#Xez#iA%gVQzc*>_UID;dYo1!|RDm?#%mr<%tnYdI$&z4Gqn- z^z>5w1Ndwx{<0)m_k-Q^fgxo14`JY9ckI#bn|^Hfr8aERDRNJPJ5P%kz!(^jiJ#Wr zidq5}VdZaW(6u8});R{cVAssYyvu&ia|pLU^*HOEGh2Mj?0d^(y)_aq}U zBax!)0-O#IE~w7fMdIxd#;`Xx2I|JDnZ^SV{}y%o=xP*^PY>Hu0MQI&*T>i=i$?)A zR}189A3PHn3;yjTfd)usaE&CMq#z6JAI_D}l^_Qdkh-asTo-FX zeYecSzco3Tj~(f;<&79K={-zfn&XD{re&$0#5LFij8q&C2LH{!9lpk>k78O(Ka^1< zYJWj{M5tzPn5AdUcv38SrW{RE)cg0JaAqH>K1X+x1VyEAI^W(-y*xPRKa3M9mnbR} zZ$_A$)k?01`f@~rX%}{Vc|Vom2*Q@h~er!Q<(?;MNX z^LX7t$A}3$MUZcOuikWMk_g>E|DqfP9o^)9_`Xq>?}PfxFwfOtH$0C1)ndKwn>PeJ zPPeDe{)(@&phSOl_j^gRM_wj|=MmwbK5~U^OKo?zKTy&c=~`oEFzGN8SD11oT7BG( z*~{AZmKU3N;@FsIk5xMv;D_}?WNC4G;~mkX!YLLPn)yxN4Sn?E1lG39->(jE0nuO? zT=r=ASW0Y0Z`nCaz*#~a$t^H7DrvzJRJ(ru>94S{Asvn%6t z-p|x*Up_rn9nNhIe7BvB0ampj*|*UtL)SGwB=0H=i_3*=SXN%RDE-yqYO1 zXp<$jX%HRJ<^O;YhF{6UAPd8_WdOs`!eJ6=_BS^Wj+b{`cPsFG5(j*j-P`z1xVX6! zD{1+EsIM3;o?J{EuzwXW9R`LK6h&p;%e5kMr=((6iflPi?EywjqWJ_0;`soJPJg+NnJu5f4?%?D(kUY$BO`;|`60Ha zN%MRN6TB1aS;awR7jVQMzvZ@D@;A=UV{w(fFRpEDWZ2NHdkK5_VDmQ@&;?dFoRCE1 z1cbHnrA{*wYY5z{@82Zku~ZCfSDQlV&DV4rPXYo1@dZ3C*Rnj37_l*MPyiMGS*N2p zd7{?vd|5JmzIv82dxb743JM+u#{Es&CkqB(i)-@CTz`m(X&l;}=^j1HFinVD=5uS# z(VGyU_g4IfHqk^Zis)HnVUnc#8>IiqRRQerogg6({QYy_TU<62^C=%P2x}}Kv`7@F zSMSaw{otV_F*al;;4Gu9&M%eARE#E1E2&k={X7U(Zn&C0zoePayxiW+k##;k-=tlc z$!EYI!1bU&&}7SZVEKqa|6rD(EvKDHOkpQaQb%aUE3hv2x8;4{j|q4vTmWT&Lc z&Rd=bXp?^pZ28N(a;5sVjlXxr%M=z7`F>u`i=#ad8z`>KLH7E1<3O`gp;v3pR+sZa z&q>*7Mw3mmeGY@OK%us%i4_?W^YhNF)aBy*ywhWqOyDs36d74%xMQJ(ij7X|PuE?9 zgQAn~W&Xp}N79AjI@eD&nL64!^x2(0E&E2<66j^BAE#Oh+g{j+o*UGZwSbP&2*Ztg z@rNivR@)_NVq&Y~n#7wESDE1X`KC;*M%(44q0t|07ZS?{Y!D`LPPo?9ffVCxfS} zv+j0%b^I`#K>d&3Y%_qf8^`vFo08ptBZzP;#r_RQ0aV<>$uVs%Ogdi8RM+Ifn423g z##Pr1ipnKJiju2mvUmQn#%{j2*B*tBWu&h8_10*ABd`;H#r+jcp#-1>a9QniSf9T3 zZuAl`8Xq59A|@e*MWdeo+*K?Vh92k*2{97daMFki%y@FoT#?5aZWle92u8Sb`>{8@ zJxqE`7Jvmzl?@T2H*&~Ld$OJkQ#Q$}0%#8ofJTA*$213dAzgL?^CWGt!DrbUOifLJ zAr9R_-QvLnz=6QUH8L}++@Pc(m~S`RJg859S$Pv_iA*M)JiM6#rP!=F!+6FuI^t}# z5VYdS^Ep>mt5BTn6KzF@mF~+8i0x2~Ue|g5hid`_pER19yOI$awI*w_e{cMN{IkXj z$3YRUTIE8gR*^yV$#i!H<~S=2cukgvH>fQ}rgKDwg*DXGHPlzD@aY-ur52X& z_rY-P8*a{Lg-^9kP;7`oqUBdjC&2&VD~++i(Ng{-Bt+@VIcn6TVd7^(8CcZpAHK1R zM7yNyK^QxH#h9qd)cM(6u39D@|2chAitp3q?X=#@Y1j)b36Z$N{q2z01t!18nvse1 zOrhD$4_60Vu7Y~Nl6Q|k$yd%L)9LBz%nTB#FMTgj!bOFEgmhcJO33*_qg=}Bd;s{_ z;v&TZ4kizTI2>O%!?hVEpH)*?$jCCCNlh(c#q=H^=&~e<0tGgJ+XOmGTd;OR?f)NS z7T^hDLcqACWJRIarh5ggw1F1MP?&6muQ@quOT!eez;9aI=Uz&)%iDE)g#(Egv+nt3 zQunta3jjgr2gR|?y*;ECwwB!7ch6p4SkSIp7mW1m7>P#nrI?)*^1x803rt!c8N!lh zpvfNys9QrutI6VkWcSwWDd_mcO1JG)%~qZP7(opnB29I5ef_}U#IP33@Q9EWxBY__ zbnoNk=EJQiqpr`^%hjfL)SlY3R+6%^N0DW7M~({|)>l7el1+e#s7b1-l&@aSE`(K7 z>2>dk*C2#HZg+kwMm!O4*|{yYzZ;ngz2db^~8J1pW@#$UdGSiwK9UU(^ncpzqB;V+@ zJKgPE;U=jj!Kbm;RH2pOaDm!I?LQ+T($c-h_01S~rP?HkgEOLHUQUNx zD!1--JF?QJ8J=E~$Wd$#g2}$U?TLyu?J+epp|krpLnzpSo#P864+F2fFAzeb_7a(q zkO?qwaV;&)P5^y4(7?*V;;5{vqFovN%}6Z2t~z)Pb8=J`%6DD2M`T3|W;tKaHkj8H zO#+pgnwy%Qeq2-{EapY&1)S%zL_i>5oE2s-{Q2aOFPGsH7np_~a_nAy3Q)UQ zU-u6tlTH$x!bG5gmhNfFaJU&?2AZJD&X4w$J^%x1gQ%OhuX~zdp>B>^Z&$gLLljPf z;F~{fk`GT4&9Le5&s-FWE1$*}@Izc2+&5O?%&xSU%ml#lXmZ5o*CBBAfKCWVB?_da z{z;d+XpDV|+_1qp`NS5wiOh4LyX~0aWTqf-%{@@v-wOA_YKC>I^1`!g8&EBNz!*Z~ z(Nea|j6#R~Rl|ZHi5-pSdcVQ`mqoBvqr=PUANiPMAWiI|pJp)6~>NHs6C6$chf(Vb51Y z9Jxdau8kYAj}YY#M=yFOqNHpn522|1I;tqNI>R0W#|a0$7zSGLaRi|UFhTYejB$El zx&1F~TN&tk#6bnj-2xIs=DseL7hw8C77ynZwMJ1LI}!#V0FidMp9gni!yN0TaseBl zED~~EX=X7QeN+DUxQw{ySJ=$}-WtBkFrLYO7>r$OU%z$M8+-?gVZPd&9~mi^CQLA2 zi`c)$4S#U;T-Rx&TO2PDz1-%!S%~~$Lo63_dj+T7GT$&WqqDr6E~Sqw4N7-KlMrZM zwX{4eDUqa0$vA$vwO3Y7&;k>I;9!HoI^U`pGFQcblSl0{wspvtNYm&YLnF;71o|FaT#`$Uu-6%I8+lw*)5#;;KtG9tLpr3pyWv7Qq`Mnwcs9<=J@flN z^Tt=>XXZN3bMLi|b*$q{XvGm-qF{OH&G-VBN%w2n$^n8}zR~(KrcM#Euy|G$w>Aa9 zWzYNwrpjIJ8uTZkS+K+l%$~077MlW|8I}E zUD@i&LLpe#uks|=fd!8p2}Fpt1eHC#@cUJfr)Nld;WloQ>WtN z$k$LQN7(|GldWekzDz9G`ZI-d3$wKbWnVc@zbS$0O09XSo_{?s4>671&ZXmv@fVoJ z(y|I6O9iQZwzq?Nqf&feBY}{^0ikMoF4Xa{xO8HuGN)^?z3Z-zaVt_Sr(t24!S^?w zaP8@1J0v9{I&{{UB{*SSe_zA!9O>DFC;2{D1-ZRTg@bLjupWq`Z^3t|KigXPehQD( z-@~1mp!}xg)@N$Dv(|vi1?z*E?q%Nka*$m@F#&ZZGJ2;w!8z|jI6=%ivj6lwV34T& zB>S1HJ?|CN`yg<>6|yuc{4y}Cp)!LVEHQ1W-g)vsxf1MML<@8_cq@kP9yq7eIXZ%}+lS%~raV2<^ra*&Kc~ z*57s9gvj&o^bQ$M5uU7V&y?7My2WU!@K=-la5rtDVv&kuU2;0y$4Rh~Q}U}6D(6$S zS;w{Tf)qqb(Rkco?7M5`hGbA2%}9Zytq3QF(}E_|{yG@Q0Z;;~b|%3- z0_cz_ldE1ieolV0fOE3k|Intn2NwE`0`xiIDS@_F`j~x(6Po^a%4T*J{L?MJ$gR+#Tl(Iz8mo#$EPaCQbfvNtWZm&C$B=lk6?b*<2R5Mwu3N`N($>wL${DPeQ1 zJ%84TP3RMZ;UVQ`a-%;0UVzH-+lwyBNs{pqFTX0*y{n4NtG8p{flAn`0?ZU-{`RI@ zxZjT8G0iFF-Y4NmLwIOe-K06s%p$fauf$HR5><=oVQy}jY`f$`K$@;2hyI)7e>;z zEHime$bKl9XKj3Vve_tGLC$r3PNz|@MoN@6g#RFXf5g^!sQJ-CCSWuhugYL!X9rOb z6Qa__535>f$fmP4mG+!)MYi0#CT@!U^jk8IGhOIx|7d~kO*JV+=eA-zRuH z+`N;Gfz6Gja3t<(y8!NbT=_DqfV{l)g;R#a0ww;?T^L)fn`N(U;+tSz)PTDGH)T>@TEv@ zBYi4QT&9E}Bqk0vEvhAcM-nUQ(NphI9y%Uj4F*R49WH-Ng;F3EM2E43N5IQKcpZqz z@V-_Mg;k8emyWe7%+v5m2%6242olpGDXgi%yz{oXy>lgt&(Sg6QGU-BnWH${$emnb z>}@t|-@8~vJPZ5bVYNORebE1p766H9(Y()!9C(e5c%ZKDyDB!jySJ0^1FM{zB2WxD ztJVE>C<>uQNtfq(^YGn{bJRsQ>*2#x>=xUbr)zxU^uock+@^aeG~#)d1% zT^o*W(hlb8wQVY$T<22vIW{GeVAE!za!u8nq?%r1qF0+-+fQcY2YtK6eY%=h_RlvdwQ=;I4zTQBH2%2_cK@n*knG`8udK>?AC%k9y~jC}Lm`c2yXrQ@=_ zygrRa?Uqn067JeP*Wsc5w-0WR#k9GqO| zFAu-_=`)6{*y6Kzm)ZY<2smGKxVsl$EF2yI4d&+d@Fn(#ng;uWxn{?gwb8BEd?OLE zVXrtj%O8HOz_v)>KMXyu*f3MAfm$Oj1IekRhY9C&}^)KUvRFQP} z#4Y(@9}p&X$knvHyvNC|rAEh~7Re)sH49yej(h_b$-w*fsHjz~^$8fVbz^{;+vSJ> zxhY(%lOey-V61;`Zf=B8didTo^7pst20t#b#*(+9 ziGDaAHF-K!F52xExEPvs*h%m9&ivY5hnq5`m-&p!t8 zoVryXmrP{raO&cTW!+2PRY6;p=AmVN<T`?cfZz>H<999#q0_=)~OFxWqZ! zmF5r2ckr({9_H&U7M_EnzG1x zK07|1^HVj3!yX>D&o-LF3x3>Tm7lkK2smtXMs9ub=t@2xW50unY_y=$Ao$0E9q?kx zC(>FN7*+dlHv1|6HARF6Aj?ob&dvCcw{ZK>9kM<#WygNC!r;$yh@An?p)f3{;}m3M z!=)%7V$fV({iJvLeV9@yPQsqT>Rrpq@Wx}@=tli_n#*xZ#9}a0q(<8Bn(8v)=<5)C zJlpSVHhaD0>jU4XE{-47_eeww*JSRu?{F;=fSi62p!5K6%@m$DYfHpt!j?oN7#+Ut>1M36y1J<#_fZ@KJg> z|K^iQ>FE_RJPwsZqux^lQlm_Nga}^IVTG1~rc?N{ z!B_7DA2z2jBKG>Tnl91x>F=avWsI+1x8Z*(5uLpmo(%y&B^)Ur0vo}V#!pfo;zZz$ z;lFmuk@kG@!u;dNl4@EUh<1fS!}k5z&ht$}Ye3>>6mxUDA}-QjHU%BHBOcVR2!RzL zd5XTAMI)@s)lL%rGPl9t<1 zwK>^Ier~R{Be_-AHE*9f!|ToQ{3iWl=|v)14ye%RR)NffQ@`0<6HoZJuLB=s6D}BA zW01<&yQh1Qz##j7#jh`gCV{m@(rSJF%AgZTwYzqb;^jUDuqpfR_B`uw zjcST!F2f|7XGUP6Y)|ibQfSlnc(UHN;0nJEOw8iMs?HnzV0-u?e#%DE^7%ah4=*4H-=? zt)riEyeCQdzMArqzl*f;eIx2PuGP;D3HI;9u~N(00Es)4_|u@W*jbL~evQ9!0hRBSudd zBWe&+cfwZ-lcylnNk}<#+DfjN%~M7!@}IBg(ftqu6-_FL@^l?uf#`)Xu#6nZnP!&d z_hjde_X>uPMqr%pmMm#B*pPA3a4MPksoE~`od}=w_H5qZRy-&l1)i>;4_#;|x%WwIaeqdPfU#*e zEXn&#+$uI~bddFC3Ada~G1|(EFgBgsvSLLZ8u-z5JMk*4g^2`-ujtg<;StGUjF;zYT*=FT6H;H|xM_wNO#!vCAyp z|Gof?Z{aL*x^Shi6ABnB{$FE>4f0s&RNePWrxfMAselaZ~Hhzwi+sI*-dg1G)ecjad-= zDH($Dql3loC*o6BHN-|ugZGJOv?QkPXokk`#Yo?xLX$YZTz*F(f$R}-I$KGo{mFrd z%i=O(SOBnMLW%6ks>`H?Fm(H4Oy`%m91iBocDqiW;B3b>(m{wW4#&<{!w9T61cik6 z=gV%U+erO=Ne=GkZ)7@$l!zZ5nhC}WKI5x#s4W5Sey9%bC)HASq2DE4-Q(n&6DtL@ zkvbCBeGjAs&mHwlxg1}nAOzo`S}8&Cui0_M$;M?`@TDpfI6%Tj`qkzwoNzKbfJ{$9Z9+7 zGQaEn6cOG>M7av7{o*EW&yKDKIs%?I2a7%_pBS0O6pJ;o7h8w9iP)!`bSy1aZZ41e zyTql4c=CPOfhgWRvCHozKtn@gG*QR|E_vzZ%P$j&6N>PL4$(9VwL(l(>(ojNHKpOK zhF^*C8HpDvUM~#2mUE)5Zd}D0>p)YT;d|C5(1+rjkYw@1ljR3<@Av+Z$GR+Ci+D$7 zof1;zCTM^I!@9}d{ZlX@mZFByk_ei8xg*|U<2bP|1Ufu+>%DR%u$KM(%Mh<3zq$R; z=RgzqzoGQs=P3At_Y(szqctn^3aZ*TVLT-#&Ww97+Pbn(6F;z)s^|~&26ktwkp)c^ z-KJg^Yt)l4zZrl3rTO0LeyYG#OH?`yrVcFP$kbrlzQqKlgLSWR`c{7m`t#P4MwGAa~ z!vFpqvJ#=J6mULX@?rntKhXJwLO8)w1BHR-yV zAn$9t({9Nrx-VD8edR>@5H{zN%Dn7M(g1HCU(=b(;W=~tgN17ChhnY;jf-IQgM~Wl z^OYD-QxZ>=XxumtUAHKeyg&I)&UloF+j>~zFy-se;D2(w6Kn|11u#Nqgnb%>Tc$m& zEnND9)>Qtg*Ks6mDeU#1R^S=3h3^|vZ-zR{$}FMB1MaVL9tHZc2TC-A;!1}M`q_J^^nbK~tGQ%j zg+k?0&E_NjUVxIkzPb|deCk!fkA^GXxqa@KLdZy!1L-HtobF@d<(lz@0wxU>X;`xV zJtyF+<%CYQ)vKzx+NOcYVxWF3vdv8{Az6ye2QTiO1l70?iNs_ zJ!9TrceQh}_>g?FKWIDfFk54NaV#Jb`iiwt`?OlOg*KJ@+h}aaL!-m1@VoMyV4x@u zxx1wClN7!AL9%j3>d0IA{Z-P!3D#@(=?bc7;gan@X`!QcDJ7;`AQwMs8TGRaIj zq~g#1{?UlxBtW-AEirmx#0Q%7a@{~|n(#v*O*Esz2=s^&y>BY`sA2xC;~$?GHYPe6 zVtpl6V{}*I`&cbTW!o2y{qH~=Eak>RoolEOK$#RxX1?+$_s&qnr=9S1>#yF6Q5BB0 zgR4ZfEYJ1!^)aF>#)ZLz+yVJDJ} zBvULU=jvF~Ik91@b}y?>CmX-lHX!3?)dmLbqf7%}%^mU0AE8;$t898)A<+Xy&MON7 z{0^eH?=XcJUww+S)v*kQq6sT8SmP~IMv>riR=+ZNeUgibal!KI^Ketc}LKO>!^Zl-h>iH4I<^y5$HoX9L=6w`fIZ@S1xs)C94 zJMrYxdI89$j$q^lw^y9 zx|WVWNo6snE-cp-7Zeow9{hGJU#8h+Q_8f#&Ty*Iaz1f_S}|Y!)gOOsj9Ef)#FJ6p zcOR+7ymGnILqcMrtrVjF~6O;np&Zw14MYMFF1{ZOeeD*Pll#}$~v5VY5>P9|0_o@C>T z+nOe6#i)Y~gsEsvSvQ}JyxtwwF-Az8lzv)^+``Y7L{ZqsCEww!CR~wlxJW)R+~+Z&2%mref6A_`x}yQZd3x-)^l)ZqA;a*0_RGK! zxcy1WtS%9pr$sX%-V2cbX7@sW32U3xd3YKP!p4N~yR-^V5<&hIK~gEJb~5!-GGxei z6c#&VS`Q18f)K`MEPjB>mPpZ#tFLbIlWLj$uWdz?$8AM_duxB~Avv`$l_Pg7c}810 z&HS1!HAyrm?Py|^A2PXSQB4=>0Ahy$XAaOxx{I8pHA~)8=pfj(Zo)MUbYR zp7-q6$L0jimBpa}KbI@2BPl{aXn2Q*XIBpk-|z=TpGmwuaI^_qF=>8TAu=rGKUwqT z!kjz=Bq%)Fi_R9Wxrn2?!R4&DM7agP7g%W#PTreJ#@4!LZm{E)mSRteI#Pq){Qc1NYqM#gy<>s4mPOQC}c#H7W+$H&IN2_DH7bF4J}HQ2}ad@mZ7 z`-n#It@whopAO9+ZMbqjn~qaSQITRQryUg3J>{IRun;31BowEo?*;OUuf%@uG$E}2 z=TXmuKqadLjP0RCTYwBVe$SJ&vZ}JG{xhcAI2a83v5W)v6M+{YsxVHBuhkN)$^&U_V1vM;4TgETBIHhpzsd9x`L_3PU%BxAhsBaS%7> zQin#@rxqP|1~m06Y#g`eA2acQSUCeO3Ia=!IBs#iqo&w<{Sc#p;Io zn~eaQHv777#`VUv(tdF<&#R!^4lYU%65yDnd$EElFh-O8V`_r{9hP)l}04@rnoh zN1KDeOprffMJYH(yKw%q^g+dNH2IME(IZJ|Qdi$t9)#B`NHAtLI7f7&EP6yZ8P1i4 zI+u~;Ur0CU1I*nE0jGSTNIq!}4r6hol(faMUVlp8f+DNb4qH8NMxyHT_H@B-h5vWi zi@1SNvpXS_F*?@vb=zxh?&p>)X2$wM8Z+IvbQ)GgdV@G4zuSd*nDqmMEz?U7Mi^(U zXrQB68N=bg0?l#v3n6Nv21xu@<0`CSWPEvImlel|vUleF$6Yv_OV1u?VgoS;J{2g? zadLj0Du#~V*}QT~=CIZRL0cde?C4Ql^!bffAu_dS-^j$iN|rATd7R;I-Z5?InVK4!>z@PEY~GfEuQmQ>m*rSXI&aI^A@7ra0Wg25Csqv5{f5=cu6nia z0@&$#W>_J8mUTxAN_Kzh^mcEQm#WM%y}ZzPrUqWL2VR)Zi7h-sdzNEjSc}I4 zXZ4^-D%L&VtV4apYPS)5{JFYz zTw6=a!}F_6CFMag^Zai@)lCo*cF+>k6P6;n6HIb&d)4x#+2!u6@1e4(YInR8yegID zRu`0kD|tytc^mv4QsFNS0HdiYlTN*MG*7Fc#82|f4eN=^UhQ`yM$GP`2rsKm2&_k$ z=JF2!rI+95teIc?lMUuu?CP{0_)=ROINN?8=wS}NRYr(dfo{1BSP3UJb8(VMhN#e=2G zUfm$pH&a+QB=_>=D6`gMy@9$MY;C$pawkXjpkJdtS8)&uvq{d(AdQK- zv5SeGVOUup%23IumISG|Uu{^}!JYZ&W0r(cCaianIROGz5LslI^8c!i zI@oX)lOWuK6-qyEb;m;LU`exZY+FP0TXIkxu9sdiQV3y(#`K&!wW${^!?6qlWU1SG zLw(DEXkr7TOdvwavKRG|E$LPo@ihL_<)9r$JDky6`Ap&@M2e3YQH?bW0y+55#7CwJ znZ(oztJt1ko4=D4h8h;jS1Zv2k-_}@?f3JQnM#Mni&8{P%Sq@U-x;`HVyKm7HJAKAffV=ByCB0d`xnsai`{$YmR}2+!VZi`tYl$G4yQtq;D7O{)PbPK)1&`t;dc+n6lJfA2dx zUtE73%*zL8+-(%<``9&QIu?l7~>S||^UO?RMvJjM!p~Fl5{;cchV|>KFV)aM3qX#~`tO_V-;4ELyjah@F6xvXQ z+30(h`G+4YQy~jFeS8P&C$U{#QGtq#7#tj^7d&u6n;G&~58sLb?fpN&NCo6}BnOcc zqi(LTGSyVLDW+xrSl|fC^emdFEzTz?pf$!2u6=AR!|kvP3YI)Ife7|k#x%Zt2in4y zCIKHG4L^0IY|?G)gSY=^0Y6oVATKQ-Q5B4YaAXItImaR&1X|#h2~0f#;7wwEl9G~6 zdx-39Eg`$RyHll>^S&rMzP{ery@!+alBfJWNcZNvX{d)a0M_C3AnnY)22rfFXe(Rw zJKvxBoFo%hOxPbyyM1vsbC7b=@`~HyBwAMZWGHJHlR7p=0Nj}~+2Ziy60*JD?r*zN zI5h0docW(V)!15Hd3DX{U4&_V2#*7RNMm*4&L9(hs$^ch(%=eUeO?2D_Liq_Q9mRF zzLB%ZgMtE@he)Nu$yyN(6=!*K^SQ@J^|_xuBw6~4@4+jf#lxSov;8}3`4z@fx1^^5 zfr0#Z0A=5oGfv5HbA1i%hfFYDBiq4Fb5C_JUN#Q`@w0E~`*JDWm<)9WVkH^GVn~FL z3ex1~%WdVCehMS-MvWFI$~!xA(9<8LZ9aV8u)aDue}qdPakfr$)j6K};wV=cb%nUm z&y-o4PMICje<@qK4A>8UZ;XxWI%);dIAUp1+%9`#qjK#J<}WUy^D~c~eU`(U`)knY z)$XkUpQQRw9oo;!k7YQ4L&erz8ZiSkj{8y)hsET{2_Jz@x#K|Kf@}SErF}U zcnpk~jWM!$X~+NP>Hi?-WgmfsXRg3lQwiO|swjMx%nQMsI}t*^(Ri6$!fK_-srR-^mU z+4+|MeAw@62Q(u9uuTpL2-Uc~5t~-!LsyW@(*x&Ik!pMr5xWBoaBdh@Jm$nQL|!Zy zQw23sT7Nt4q9`tgSk-RMJA*jc>AQ|$;=I}J?(Ty*%O};Jgpt!=HbKrKU|J`0TH3Am zp92S;SoE0;4=paV>{9~fyv4XLl?SMyTyE{2D zH%IWM5K_9%)sUCvYs@Wlwc3?y&i(om$z26*Rb8B!YBv7m*E{xSUH_8*8&dZ zl|IA`bMKzdJUI2SUKU3BW}vvSt}yc(QX|q@zHP%58EX!|e5;F7(AiZcexWTj=Raf5 zxG^2FbtAocBvLT8T@>k3{gqCa2HO(tB^2u`3FZV7rd3IHoXl}@xY5BUD31~?LC=#r z_}*{Q2~9@Fdl?tRs?RC^RSxa{%ym2l zwcSaYXpt>)lEbY(3+lWn_R+i2TD8i3B?M1p;7A{>l0-wUS9Z+p6FD!Uy52qm3bsuva&a-|zPhwF0FQ@247JVH_Qk{pIUC112(o zyJHsuAC%%a>^ZS-Z+reiwaXNpqY|-2VR)74@Kog@77dyI8us;XW86Z}dOqxT@A`%gZt zB^PI)ii!$UzIygk#KF%Ew!G`lB}tFP&3&z#lg6v}8$kP+D@~NE=jk{!I0)dr86*YA z+Yj6zwU&Z}WMyv#iJLpD%CHyYY4W%PKZG!jF#d|h4_)7HRQ)i0F?PdMTRU!Gu1|!E z?t1h4b0=eDPngTOrKO#n9f-t@{0w*ar&2<#br(R5Nfe4}WalXtOOx`OtHb zYZTVb`F=Wp>MUuYY9C|LpcRzJlvCt>t88?UhT;*5^m0@?A=1^3r^+RtQo+*4xUSfq8u$ ziA?(vm@;ODfsLp#@lu~IRwZ6?=1qQzlMmf&EZuc09c8#Cs%2nI^|-k|-f5A1vd}0| zhTgA3Kznb6|DH;n$AhR6qYKMil23lNm!nW;e%1}Ge&6|!+wFb@AXeaDV7R~Cu8m~& zQ08}cc5*uI!K+b!`?ezBK0lZIm}vf~$jE^Z1sNGt^7ef;2r0H1jg|!`pIY@E9*15* z$w^(?kxGN!n0X5=5(*}fd$4FW5HUs|5Ed}5-IDSTC;YdCWK{V06~a`4zIqx zzPIkHwl*M6Ang1U>~q^JhL(+pfJMT}ldr*o5e5v7*ddO#R|HF7VMrxKN-1BC-*x;! zrL~&Y`6p7^YL65^sestzy7~>+$WJ4dDVb5EZ+mc9jW?tZSq?e1=8&fi(dh1TKpR10 zLO3DofR*)e?QS-fs8QQcyX)|(+l&*PmanLKaJ_$MEv1eGuinDQgGY(Z6Z$V=9N7u)28b@BjJPQrR-d-wkrF_hzg=Vg)P02uF~>TCbNs$4uHrJZK#j z$v~vm9qmj2@n@8U7RKfE~U5 z$vkejd`Hw5W&`96zfGpkhRdnsMU+Zp+4dRPwAJ+u!(<9dJJq@}^fuV-+Nd{fXd_aa zPvF$KAc~b46{Xl-XcBv8{fmXATYQgxY!GSl)A) z;mDhs^~34C*c?Rj=paSf|3TsNr+GYgW0#X99oaO_;hKPNN9qEek69p$8C*qWVC6J?i&_4f763?x81YM%!(tiEoKK|SBXbVC}54x98o|orY0Tr9W4|l(d8ZH$9 z=~r`?WytN;@EXV;IhKe`w-pj*3IVrz8+tS}a&8ZX>N+;b7A#kdUfA9;o(X#*6o0AP z+q%52mL3rcILrs<@7yu>b|u~Qq*FcOr*Wu_k3UtE9{H~|$xTEZBlJmny@}fG$4DOd zGNNSRLn%L+O>9mDZ8QB}Rig1dG9|@UVE>9hx2+X?UVbdscI*mtT4?~X(`eV?_6)VUzeya5h`aDSg3l zm}xm@0>jg|A@!Qa+S2x50U)g)hcP8GaG&iD9r!3PDJVq3OYIN8i@wws^FaAv0GM7V zomt?EzM3p*(9_$n-I=ht_^8lnI$Eg#pv~8{wMici^R#8((aZfPouyH&LqX*v_hBel;CBYxtIBs<#QdF$ctpvV7NJbIok!2gdH z0M42|hE_IxG`JyP&}010=C=W-Mm)NqzSkwt#wtJiGg&`!C^8@uBtrci=m+rV665Bb zRWh6!9wAi3Vy5sF+ENAN}(Gln` zG4x;9DH&LaiA#k}g-JzFUNIV3_yp?GeQB=NzIl}}kRSE%d2(D`e>ib5Pm4nlsFt2@ zHwrNE6|(G0=+}5j=gZ`OJ%v5xaa^(2JVZBDssntx@pP+# z>)?NeYqvcM#pGFU{qXr6Znc2lC-GPae21uW7!k+m=89sgAL>n`dYzmHy{B~A)$^e& zxkd-ZpS!MyP)7T5?fjieNCH4g-^+qlTwA)&1Woa)1EHSKJ2Bdo$$WY3pXv8tc?u+S z985PW*|OA>8ce5$+6V;Hi$*yCVIQnQwtTx|N!`kozO&x6Gnj4sz7rOCRev7DbG4_9 z*@po=e82NP=n*Ur@Omf>>AQ1o*lo~aBX*$OM@;^ZUQN5d_Fg28o8>Kg?{ncse;%P* z0O9VMza6tL;x^Qp$u1_lN6daQCDw^V#1$luhK}N!N_EHqog+;07w;zud5MhlE<;$t z4FNBq3K{2~R%ibW2A3ByFf6F4sF3t__=SD{`|ZlYE=ZnF*dq)7OSO8uaLU7>5dZ8F zwc-!E*M?FRd#${HE_NXwHAu%s<`u`sYyQa_Y(e~DSZ)YM(SnZ?Y@2K_fmbh?QRs19 zds?E5Z4;R%P%m(Uz%(9rB%VYRMl-Q@OD~?!%ObS8wG*0UpdAIaPAcUWtum|egNLMi z3*oO?OD>3Gh2Ht;TA%CASsm_}o5L|lo_O4EFi~+k>$RUKK>7YXr=@_!m1?p`N&cJu z4nX)e9a7X4#ab&Mx~`P`P%M$f72*T)IgpyvtaYas#l*g8`&PC+Q}tZT=&%b(iM(qu z@A?m|Ek-y4S#s{OP-jcK_V-kd$er=ognhu-Y>*o65f%?pnjNXuG&9u2Bz*a~JPSURm{dATAy39*X(`-T31v~x z8dmqll;e}z!)gsB59vv{u5s1+Rs5DgjZ5*VTdK#?hd{-a$vj!Ix9_YLn>!X3xY2OH zwFFSWpX-cX8`b=zReMjR%#ap(I<7-BL{zrkXSAZ%z(!PIg4f&o>aze$Z5Ng7swNcHa;Gz0bS!iH)(ciCzmE%_ z;I^>caee~tw&amjgeOASIOjN8z9o5@QWr1Y{drSCw81NRWEeO&HMIa~{o}Jn^8y|e zWq^81M&5>n^Nrsl`Oo_W${WB?_w@QWvq!gEwGeCOs zHHhGLfCI~^Amvg)J^Ja>e(Jn>gpd^U$Z-*pZQw60I#$-CJkb0mG(ZsS`ZH)SeK{&d zS`r*2*XM__g?6^ZWBWW7XS-T2ix+F<%XKWrB|n%=kCti?ic^a>zRLXI#ytfEeSNkw zKQT1KRu>HX5gFLJEKE!lYc2|NT@#LTwOXL^R4SQMt~6jfil0_KlF7*G0Uxe#DBj*$ z{IA6aT#HV@(}p_vz&dQlqow8km|Z9_$5%%r?Bw0tafC*G;eeh9{<(g;$agdTFaspg z)YJu_CB;~s^-{4F+=!$sA#cwXd3kwpr9K@e){Xm=%Pl}~d4{{%6GF7Jl6(P(VgqqS z@~i2@c=-6FJcGDQlOyEnw0O>Uk0cX2WD)bBTz0E}`%I+k6 zDsUSB9Ge$BYs*w|c9i_9XsPE!EH0oPQ8b$Tfhg@?)Kr9+$gDS<_%J5jqD=x~a-PB> z0S&Ho|GFw^wc90#|DA~G0*{Nm%BXZ`yXZ5P9>ulWSS3_hO) zC)}8?%?(BDh6yc)y)RpegKf!j(xu7hVwBDB>DCO!#H0N2hNM2y9puLWBVNxF4J0`< zK9LMFsK&k5@Qs5(*I%HZZ!rh?w6s5d6t%av(|-|tP+MWZLVrh*+bJ9V zDpDd?_R(|mf9r6-XV94U2oO)IZKr}ok@appmrxF5S$d&}MhRtvHllD><$yI~^ZcOj z<~%*Y-(#xJ-Jt|Q`{Y_R(FB=syQJ%jnKfe-o*(H;PK=NybX1sypD*-Ps#4gj@7Io* zcw8O^oK3k2-hZ{ae|lv!QLu6N0P@Utc^)_`?rw@0j{yLO{!2YO14FIJjGULB%kRz6 zv?S(yc+UJvmzqAFhhkO-2l1+%n9NM=+cYleolFvdQ4=6LIUpP+a=VmVm~{q48n}@N zPuGOevAa~GK?TZ*^w9R@+hqQj^KZLqr4scAy>^NH{h~b9W&{V1cMRYS-g*BPkYH2T zskmKmFt@^-QIom%odp?QfXZ5L2)~_(OcYqD8tj`OX)PveUO55C!%4kpJ`=K}@HGY_ zy@PXmmjO(f!cxCSU7j7B8`tm)vFkVd^(2crVFOOH_;GWHgW3 zecYNCzh7W~30|n!)KqrxZg58DM2{j5OS~NN4ZByS3H_KS$euzrO`L1S6nqu;-*2}NM#O6&&Jot=_{V35lXCMI@+`+Pet5*uL?6Yo($&O5;4r?V-fu4iNW(O|M#~ds>{p^v$Kkb+~Sk z7F6Yyg|VMoZmsrW-Ry7c9M(Ocdvw^b>C^$-Xjn8Gg19zU7X*0FtWKAmle8QyX&2&F zX|{X&cdcWm3p`2HL#glG2ICDuW6`7B3lv(8%0tBpVI-A7W962V#)R{WFL8&{b>^cV zDz497{b27P^4!QxLl$B*m%9}qbGyHq+MT@jD#p;6g51edxKj8b|3!-mNgj)SO;`3v z0_q8M6=)%NSYIkLFv{GYbzO>*ZsreAkb>7LdKy=ax=Qx0x^CRPUAU100Td&v0L5#4Srde_q=i^j&`MYF-4Ajt%wT6?Fq$ua?Clw|20OE6w+9DKVE6XF^6u0gQ!RID?dQF-Hvh4VvB zSj5k%L0$vpEiQUJ=pR$W1asV1cP^%CjGM{!`)p-)q;hdKGprqx zoppurhdV?Z1fn|HY#*2TFrw2lc)WtuY^sF^?wS*GJa%r+kyj(ZXhwgHNS{JGjL39N zOWGkYx4kIpe11j-mltD;tl5-k+eT&e>D^K1g^G-YzrcZdd}q(*agLkag4+>-UH?-e zhjt#_nzM5f+$`_T(GRzZq5SLRw!0gqznTkU00lRWO07U5K~7a>Hm|h*43DMYSE*Lh zWRV&x2M2V*JKeqS0%}bWLjPz1YB%S*Q23q*z~lY)bA48cc}B_8Hj8M(sp8KW{g=lb z%g?D)D?c8u9MlmKC_tx2C={!g$#yt_CO5=FLa9l3Vz#Ofm#68;5aq*2yt}*C zVTe~$^Sa^hj%&9>OF|MD)JNjkUN?Jcq7ujB&ratc9u!`7rL%#W3FP{_A-p_%)>c(b zQ?9F%kE`A8z7dFCf~y^$LNN-`IA6Xtc(P1D2}~9aw8-iWPR2i5Wlwy!ry_ZU$wP?n zvCTD0Hv4fsIEVZNo_!)3II}E^XlvGwy-HETy}wOm6} zdduQ+_ngrQS?5H7RH{=@IXfRcJ5udDZ+2UKI$M^OxFD6!HPY(EDg&AS>f#%pRRO7OtNs5Y>#d`* z?7Hn?5V+~?kP_(zk?s_vQ#z!(Q@UG3Lb{|&x;vzi1_9}m?)tVq&w0;#e%~05;qVUx z?rUFb&o$Rva~3{5RG=650baM$1q2v-Ip^`Is0_Va%9@a5Ci=JRTv$PLM9w46TD zZEA`2FZ$HxBUG&0+?U(m21q|NR8$SAR~C~7zgz4u6_?|qEbABYiGDV_>D_OS9p5}$ z0bd^LuWQBrO2&OC60q0gL`KEBdKp)bw^lyxnwod6W!iPt1#2dMamMi_yRg*1@diM- z$-Rxzl|{HM$^rS~Y>WHF;iMb)i&GUoI#|kk9(z_Z&q(OYWIG9b?*BYt27(R=OcI)! zhNWH3inv&>DF2#=3BM!gSV>rm5u$lt zL3{tIcUNLwo&G+2_oAwju(F|HHFTSd?C$3Akw;;y0=41WQSkP}cKzkeL;Y6gqn1L< z6V~l@jv%wV``&sFM#1d95^)T!NDmEtcZdOR7<?)mjUVpeB{Wxiw>r7GUvIkt z^dm*?x&TnY(Ni`t7wocNsQ|t`?iSKfVH9fJPx>B4AR` z`53{G_FWAteLU~;`nqaSCOj+xg7fPtmf~+9a@TgT?)@e`F5z||bob}ULI)U>PmYgW z`L`F^Z!@`GGcvYlR^|BGz2k8|elkfab}=K|mA5Im>Wb5^F4gi$dshDH?(Uoa;y05&l>T!RBB5O-79Y=Zef|DByV;@3wZu%TJS zU;qDcR&D<`&T8L1-N^Vw7dG%jO3JKQ2|D?)HTLw}HM5Nj zms$DvVE*i4uNE8?_QS)&c3JZ!H zeOsFX@G&LgEHpE;%{~N1dCu9QaC)#15Q=O0ePcfC_^5qxZOv%5?17joPi;uv=MF94 zr1MUIbjg>16pzbeQjU|N*7DWe`(K$0=5%x5;W8@ct)@3$eP+=vYs${isaWQ_<$lNz zxO2eyX7&(P+@6qNoGD0_y~glUaQDff)-sVYH|KG_#-;1p&dquS8y8m%NF0B?2$6=z zsT8`Yc`f<#tm$c_XE#^!gVWY9PkKuE`=J8e<`3jPS#F2R_!!4Ia=XeS+MJUAeSknS zzlzHdr}DMi^D~E%lj5rw@me0^w3mCEC|}sR60S{13{#WCfwBExpM8Jm*23AWu7I3K z5#z6_npkmpf`noOYs6Ae1%u*S1_!w&CIoi?S2#!Y2%EB#TjE~7;6OqYzc>7Kgyiee zP*b2`S#`?iu)ekii{MN)tk`S%s4vK0k$fZSNvkm87u135kQfrcaj}M`ZogMJI3hYm+SYrLLYw{dl zZMsw*q9Ux=Tw7b!=CX*4XmSyyh1m{B0-J@JxYt9X%?%Ae0`bar5~Gejn)CGp1U?iN zKKS14x6xwVk!b2GD-$y_kSbb#xahW0XX7?)nOIgR_REpSj$Fq8PoLVY*NYb!@#{*Q=HPNT$WP=p#jE_V3WYMb zpjo+k#iZ@}d)~=lZoI1A)?;CALA^{55luPfxd5O8qIDV%tW+x~G5;|@{kH|ifYIs{ z&V{r@u_UR z(5c8U=;d>N(?vkl`5qof=jIULuY#Qa_+2p!*NmvjGrtJmMW;6=FeW;3P7w^36q3?=M5cg(=Wgc^@r5KxbZM-X6LS6e{W00q3;*rJ1rXxiwl}<;%9m zU`Pc%1YngmHuBg@H=e$qLg-zJtO0qwxJFaq&>4JgY+PJ;68dw>*4EZbk+>lFyWCTs zkrDuzqu;s}E%NfckMUoRM>wY8gbGDO0qa(5d>}(VZhN6+6 zqM=Fh5Y}q@Eia?H9xl~8^)K_C{2eQKmuXt0;CsgY z5LfCsMnUSo2L8g&VC*V`KO)7*muJ0Q*zu$*zhJZ3Peh*HF^+%+YuMbLthrO{uPwxk zSvfuZ|AZw8gJ-uAbq+LU`Y1tLGtJfuH}bBdyXxO(Y)EREfq_9uU?dBg@K`(O4$Hqdy00E8r;)Z^~+nrMGjt z517$z<|HqaEyCNDkJ{cWg`g0|&GOjAQwIBq@w(Z@A^_-{$?Jj^(Q|clCv3o|*Rpo} z3tQ;ndQqU_&OQ!{l=Sgv>u~6EndG1fWg!yqdn4s@Rp!bD$J7D0N3Ai;b!%tK8bkEO7EJw?8)FvKRpgEC5-(x3W4rFM3L3nDyTtOB!41 zTI-GM=njp^rP~CgJCGM^YrVr`R>cUr58C5#+6rXmq`+lJWYH&dBMyt!ZV=vnuLOhv@>n715sZbLy<4Fn<8E_g1D9SNABrl60 zpQhBAEvc?$$;v)s)<_pDsCL42g8lI?V}7TX=zZK~*GfRR!6TK4NH!YnFbdbzIL?l? z-L<7tf{B#=E{NkZf=HkP$ao5W6)B~Owm_?91Z*<=R04axtp~lp3<<%=?}>;gtt7<0 z&>;8pVJu(!!w(6N($44T5i`imi?YzOaI1x1^$WK`cjh6$F^L-(DWLyt;*`6g^aO%v zSv1@q{KD{wx}_(&*A~NxAfe)Xy9R#a7@rMkhOa{rY1<+%S&aSKhy8C?$RU)Jxd8!U z8SpK~zNB&C0e%RPt9BS_!^@-P2A%gZy-b;rjVUP;@yyyyw`;u&+^tRfyBD*?sC;!t z@h|5<#{2I%VAWQq+kAC^j)vrUdroIPaC4S~nQcissF?k%&`7k-X3=Ns+ykuJ zm1x+7{Q!Y%%%TnQS34640$ylg5aYvzTFa@z^89>>r$@5fVQVWZ4%emGL%y2d6YD?V zkbPsLqL9$gZY&;w{^>$(^9;JXT(^}X^lO$4IHw~cD)!gE`U$0Ce=jxLIUT;6_VFft zc)WAeig9sq>MJxG%M>dKDBnpo?`s?#?y05w;G zxdFgmmU85u6Hxe5)F2CyRf<#)uP!YcuTwR;ThV3|%YGVCu#onWXlNp7GYqg(|E#4t zpoBRhmus)>6*eeFz?Vl5?QeL0Tmw;|jTMkL;tA3%eK<1q1~QIeSF_?BFSTn{Q07L!%g-6nl;8HUnRE8E)-~kN zey=y*HALzpqbNt|dU`t0g)^9%!vop1E-b&*BbuA}fK2drT>~FuTV(^|@21KIuoYLw z-J9LJpj_|!@%7suDHayl$NtObTU%{szZ23-CM`xy=x@wD;`Muk4R#bxl%E$Hp{QAk z5&g+!%EN$6RXpT@-Mz^p-;hWJIc>xQ7A7omBxMtGi88zy$%SaVPp={5gfvOyFxSnT zou0*15M@Rf09$EQ3PRf6rm-^7(vF^$g3$&chpF`Ay+;G)SnA8OigvDs59^;}E6@w? z2ne`6&-3D6P~SIuc-c#v3k#DQ&5b_yQnE6$`tr)kv|e?xyI|aiBBosL8-{xzr1tR8 z8WRC<8aqoxBRgz?*`CiD9o9b|eQ^U&rg)#uU=W1N8km_GTN^DE8Gnf;PD1{|>7lB3 zBQ)`bP`~b-X0kSLj{5RN%z%rX%hlOg@d{Xcx+PkYXS)x?wE=xC%JsFw$X+x?8TOle z-hXHk{|#e5&%Ys+!lBSRwTd>`Kf5rp3KNdIaW?OgCizTuXJC*pDDsHW!l1eoB^mDs zNVJ!v6;Fk5`z;u1MZK2Rg<&(VHBH`R;4G1C9pr>#!RYt+o!?+k`%uGPt+uh^2_TGV zT4z2BzbFiF=&Q|e5?@HBkd(Ou3`#BcwoXKqQDpMOA4>@R@4`3x-<_~dn^EpBV`Cy> zVm{TmYfz#bu@GPo*p?v1LQxn0ddd3ElGb0&lN5iCW!blbK-HiKrpOEDBD!}t)?V7&cVk3@~L_v!Z#q4c0$lQ$X!nEjGDrKg3HpKIb>bKy3lp{4r<361mdsC&T5 ze}8L>GU7);EIuOd^3>G%5!{c^*qx)D4FW78B!6r~%wNC4_GijYwljURLP3-&*JFNd z+-EYO4-g*097iy0h)e13e(qFRUHv`dMTrp{^2WE?TFFBiCT?zSN=i!qnsVJ+TzbuN zm9Ki+qk3|Q-}AMvF54ew2yWu5UH5lZ!?@YFY?mriYm31o)OxA%{n^$b?^`)Jxt&;v z=kkUBN_2!#?w<&=2=7}^glmIck;RT-j$Zb6HQc)~_v10RLNbg+QrLJtw{mUGymg*(Q zZ_LvjjM-o6(DWVZ)?nNaP)?{nHd*92(Zv%;W1@U&HqE(u)3yJ0!A&bVx(k^#wNvVi z|8M$VQQ1f$oTr4hqE=-|yqytPE!Kqz^&iFL{^a1%r9tn$%WAfy3;$d}Q{B(vGw6(+ zUtP0C1QR(Z?1b1uM4X*ft*Jw7@wylX340Jq!Gts)6NWAc`bbK_^=P@mu0JLN0U1^8 ztlDlRej=B~X1NAcdA~DIN-~C^-Qx@`-oVa|<d+!F=v9Z6MZ1`o1kE8scf~&EE0r9f2Zrci(TKzMQJI|g^Ghpg z4ySLkf|FvyylSfdm#4laLJ@8b_KD8e6l@Rge(+De!$5Gz71^&+vQO7k=gO0N&fj() z5q!8I&)1?ney3iNRm$v19Yo4}V4x6NxFVfUno-{>Ql2*% zS^LEB^@|sCuX5w|8`Po04BmRL)TKsT*)M!t zX=-Y^Z#Zat9Qwpm<+!m}kSf!XE6b!L^IFsQ8avi?)ruYC3XU?#gr-kb)P}tEG*8j9>IFbC|i-RkQbNBkJ@V%Zsqv zP}!WT>uggo{+1NoP(vPK7e=~luciEfpV zR`>Kt?$*{8D70>4=~jau)#jZ{rp+0DFSUM^zxr_RywWD77%7Xx0^~I506Cis$Bhom z(Ngl?pBH^|+Gbp8@#sHlce`(u>L>g`^T^{NH)EYbp3bb*^zP>%&3ef!e|J}RByfdd zGxm%}p_m_>9~5vKwVbAJY-~iRbXdP_bTsWJb18&#{CyyiIon1gJEZ@i2>yfs!TVxQ zO?c|ZSC$wOK?v+jv)k;u+G5JNZ`-S-TF4kX+Pmz%-`Hq9gYfE&elAnb`5&Z5W?7L?{KBUa`?BlTk2?18u zidb(@sPJJ{WQ8WpBnZ~KD&t}Ll0`@^GC_nLWYH0ZJBcIMOitc!+cE1B%8)$(?4d{D zfzMf*5yqVlQ=wQn@HK8jbjTHyG%Ug4hIu+gU_$#-=xl`#$X_!o{PQ{jW~$i;Dv4T1 z=m}g}At4a6;hl{QlNXPQAF0C`QY>Ethp5|p&Zh4|;qa?B3}HZc30`4t6rBcp8Ge?M zb*UHvG7#24qsC0&u!|;FyNAo5Myp-q*yy}FnUb75RjO1g61d>lS{_K0N|8&|2}S~J z#(mBfKMKkiBcMOW~90=iHsATW=Rh1v~==r;3?m z$_6Cr?=DGEkWra*@;VAe7+%}Ft8&^7=@jz>dvL37w`R)t;sb}c`;bskM>1aQpT2jB z|K_;q-2)8`t^N2DlYk&94Gd1WY-SKrnP0DA1S+I2e4X2Sg&a>_YTKF`6NC2T@l$@| zwNRw`%D@lS|EqIYVF5;05aZ)0r$OWH%0#2lJn2%(EuDooB|$k**qG1elKLIdPa8;( z*Nqsh8@N6{elYk0Oga?C{LXnWc7Kq3bk6OWvwGS0bA+m=!7XBW9HN&ThWe{eWUNc} zMc)Q8)l7-~u=47F!l2}xJW3C+GNUNwy-CFXT1r1aahjV4rQI@>wIRtdQ19xx)ldd; z5iib3{4*o>Kl%c_)6ih@t84SX6GbaLMAbRPYfPJ%j+my|F+&?Pgb0WUw`_^21C)-+HmG z#B9tT20q4esrXsReJvhNR*a1Ig0Sw(4X=!E?|(Lupd_W|Oge1!S{huL$ncQDk%%;-&4>~4c+pfweG8#2@ z7+sH?z$NM}gDdzh^-8Q2=@-d+#02%8zi;=r8I&EiYL+`XCUV%qTs6s{0Vlt@yQ$6l z-&>~p+uKs7Wy9!ys_iu!LB~tLr0KMkmN7Qm^1B%)MHeaB z1L>#Tf{hXR35v;ZGKE)6>F(s$O-V^KG_8ZEVIV0d~6N%xpN*%%=$kweR-#4Q9F%0G^%|#esn`rvBIUo=tuT_ApKInn!V+>NlvQ-SQK}J<6Z3+eG`7*TDaQ~A z{9m3t`sjvHI65TH*o{`V&B)&sa#d^eFMP@LY#31TiZ7BB#O2tPd8am}EXazBWtXWe zt2*g3o%uAJCm_cQ$6y z@!49mI{0hJj5>o+;h<&wJ*Q_ZvK#W@tN)I0bx)+Xr!E` zyC0{|wwT%gqJqLc0!YZ=_WUN+-(TxPD?ZKtZ~@h(O7*t@B7;|#M9`aG@zKb{B@s)% z#U7XE80q5xIX(T}=FqIyC21O;n*-$+MIwM$|Ghy0fjA8iX$15Rc0;(|;T$z1WIEp}nb96vBbf@{ zmLenwk_C7}oWAq)1Bq$Q372mhd_XEbf?dntu4u^!l`h$z1Hu587eIar~A@v}colVWBTT zLe>s9uicTg{1WNwPbkF{yr^cSX%z%Y!yXv$dwIWyFzYuJ43ytpk$t$oE@CJD_i;oj ztn&Np-AC=7QEbxNVCKG_P;6Iw`tTwPBa_!deozA*8IN)0+qNH(j7b#Y)vkcE!Bc$3 zYulIAgGpaS4sBi`YeY%h+sZ3>PLNtrb5x3OZs$vtq01vNpy?EnFRpzqq*y6xmI5 zhaFEm^wCCJ>TMYb0x{%t^$t}8P;p-n`yFUSnf>JhC<)_MRC)#z<2CWM&E8w!fpjhH zg1?e7f3i4eS=lr58$um6w;Rh)p{TV_;v$y|o;=iFjr>ZCkiz}RK0~K+|L=MI&kvnx z0OkAS2*C}YBSrm`{7q9Q+@Frk%wfTCsy8r8vgn~Y8AnGFnJufkLqQ8?tZ~l^?>Uoi z(1w-!E_3nkunyH1eSA%vG^&#$GnuC*dFi*-khM0-wNGm}8_*`={e!sf7AdKzK|yf= z3_Iis;1CK?!8C-Wq@>yx_&_w4;aj>fwCC4bgXa1?Z&GO^iWMQwL+sKq|CTd2R^jIV zkOqH$s!e!r{jDS(6WN{<4k`^(BSGGh@d%s00q|;Gq=Atpi!ndWsNXSkgO~Degge-P%=l1y5_Io@MPi+9;|D#H4>X(0BlR=B0Q?eEVBo( zU{>OwTg;@*IU9Lr!c})i;Bsd_lLzvH5AS{)MLMb4Jf=NI)r&%ZUGZ~;&m2(=ECXuY zwTH;#*>9r5|HP{wPZMTA|1a&m+Hd6N#JqwZ+^>Eb)#=0-<-}vEbNkD2xUnWty)Pe5 z5V9>3sl|U|xnv**#2vwZc#1IX)CMy;LiJs2GL%Jy)rpf0f-VWWu0R#K4qCPpWlRPP zLkEW`^S6C$^mRtII}uTTzKE(N!9BPT>+chwVxqJ&p~*e9QXrlP`3tKu0WQYpRTIIr zyiyM?6m3+lXABgoT^G7oo*2c1IpGlYHR%~co&NW9c)x&{6a4#@K8LhTG&{>U$Jxfe zsfWTa#yX~@)q@u)Z@OgYJ&EojpljeJH|gmZ8~YpOVKN3>+le`NKrqAoK*nH((HY*YhP2Wxr|w*vP~mATX9Q^JGCqBmFpO-*G8}P>1z~|=d@?9h z@z7j*`qsPH#s3^)Wlk8O`_ZAKSA#Mob6@79Kdrl~<$b`2-A@K54wV+!r@gblH~!jr4Y;5&BNr7e zk267#sSfM(&!P1aE__gpnfk&dWt&fiEbeZ?;DaRY-pwr#csD(ULDDqr8Ho4fBg5sgbhJ0v-Lc4hsV_JxPw)SQ=0FkE5Y!m`FV9PZ!aMxAd#sKV%9DOl5^l(0u&)(+O}7_f547V7G+9zSeFoYk8@W<4q!C zHiS-{!@$BqE8BaXXu5>j04OC#Khfnjsh##k;*W&BG|uFJ9HX8HS= zjV1>q;CZW;YU=s%J|^iC0sa#e^(11h?J)C$kJm1hcPpi7u*k3WK8(3|m^(N6f~VBp z2HB*00kg{*P77tLTEXJU4PyT6|2`xkbeIXQI&~2dLnS5srz59(-C;sigaY^R!k)C=wKpgL zgGB!L%)wZNpfXLZ|8IdtLPRm-}b5;7|$&cSNtH9v2Qn?q&*49=bQ}E8j2^$+*RyG!^8*lfBnh_Cf(w^;NV8dTsAf?XxicFUbs^NSPB}N{^1n%g@px#r7Wpb zk&9V_(LmJW?AaAf63e2DnB}epc{eaI-^etMB*a(iM$;aAShcI z39E$SL2Zyxy#*oWgS&W7Wj2fgi4g6jc~=nI+{yPuhJrVnms^K?8X6ie^$|}uhrmMm z*<-gCTsRAqE-7ha{)&~OBydz@Hyt)Fs)9ufgueh2i3F5>-tp-?hZmZPiWqvBM5ub0 z1y$4fB>q_Di-(J~k_s5%E~DN9^)T?4Wt!O}mceCOt#ac=<4nhtJ{(PBu2vSk2~-(d;M}<=$E?7#i6jt)f?6%HpAY|jzj*wD}|aTIR}NTJog7a{oTI)t#6H=vF)jV*OjnAc|ED(lNmBF!;J-T)Fd*WCf`&mo+cyZ0fZcE~L7go)&661= z)A@i$1Bn*-GY5$iMC~HL4~a%tl^EWnAFb?=2}xwD>B7rkqlP=yK{MhvcEl8f{CX1w z)wdZ$FqW(n6f06G@x+f7@NAMB{yTvGZN`wc#iC#75^0USpN#7q=&`j6m2&CDwe`2j#jn{`$IC%K@ z#Cpo~+tF0Xq#fQ5eWF(_?C^VRl^|kAP0b^?*sXFK<1$x0+ZyHnaM1Cw_Y4_t*p5{T zUK~3a?OH7oh+u7}t34L$m=b(&7-UP-N@hfrQ~>kA2bgHTjso&;+rz#$doBgZ{q`@q zUewtxvH|xNSn!O@jEWW08B}TE8MN!1!IEOJdKt=%ifZpRnZT)_%kA)B!q>6%W(-2Y za7rUXu+b7+UPPW;JSmej`rQ5*EgmVUp{?zuRf0Z_cpC8=LHStzMkgSSdY;RuRsHOt zLjOtOOI><~fLEK@(WB=DaVC#bxqB659oLLGySc$iA_E?>cB>^_kYse9(ZDM7GbOK` zTt%4)am}04_s96Xz+OfIQxFWmXt~WFSAd5j@0n~aB%QAwzEE?5GWa>k0T`h@n`d{~ zQ%!SXU|{HpP@~ny`&#}nbE*SSH7tZ08u*+C%VlT!Dl|njt2;YT_nSi+$6dlhj}P#% zBs_Q+7=Bt5c&<06xC2$o%drygD1A&!rn*Cy?=H!LfUc08mR6dxhcudyqeb}98|XN+ zs!jTeC`*;|k$}>xghE%6QNpy^b9arptSOzS%h^d;GG$pgKWbghD+SQ&Ik_VYz(j5!H8-Ha{m8R@Ye7ahiaI{?6@ldaY`1)lBw$S&^(a!z6bX zhx3&pt$u#7RNFE9Ux3jj3vv-q*@ZUMHDc8AgB);kux7U$#fcoQ=G zh2su?pSz-r&XGihudS^K*sJC1BW$??sL`?x79~i2HV?PQ%4yu?@%ct_%-fsYXVQ^58XoUph!SzW3CMG7* zvm)G^F8lKm)go9H6kfJ%eua#s9L+XwFiZiO8;rqYT1jz9QeJOPyJddbkkHU1dNoQ$ z#)F4DbS-yz_(ptjLiW`6w;)&bE^Bs%2EDSUUP;3~X&@HdSRMhcnTo$5LUxZeRAs#WV z8nQuk^$^y~>3^^=D5`4kyhyFTGG?h*6n-Z7L6uXeM_qj;c3s1d>SSy5XX>kx&EdrL zz)byUA~hHo7z&aIp6LpGc+rIbxXA4DrG{UKx)^(4A;g8K{9Wts1gGIlA-i8)aM_}$ zMEv(h?f7>0W=<8$4+?4ghX)5b)#4`#Tu+yX#9X$&XMG2zOJ>{q#-(CN7F)emK+!Y= zyL4}l8@+EVaSZ!o()}Q0B&B!LoZ!lTb**zT`uyoLvo5>8hp3-I;&&!czaq2-kRzCx zC%v9Qje?EKMNP-@a?M zM1zl?ziUNE*aOmP|4S6C>fp3IpKHg?;l9<#*k;x!mn%=>0Vqkk!210hcrDocb(=5A z)k_U?3oHc)U|!CgpB{JJoBhCZa*EXda!*O`fI!ZAcXtz+6Qhto9i4MwI-K0Ovhwu! zFjpZmBO`B8B@)<_D}@e!=KJ>GNOB0)SjSjO_|>vIJo8}vV}lg#>7gr@FS!%71zJS^+?!#-bw+t6GfijA@}va! zpxz(q(f!dfe;XP)f9R96k_C>X`aT=k`I3{3NW$)3&9A-&^y0&v9btf^HTppJYjs=@ z3kH$(_+`bj3H9qa3g@A!S0|DWx0mO~17)f!Z9e@yJv9dY_ecSAJw4Z>>0ZKF?jl$3 zT0Nhi7YD+lU+wZ0&fD2g%Oy|ND~yrwREuq*A|UuJ@tG?=B~|Fnmj6ItuT0Fxg>3}J z&1E`O+*UJ;b#+`mx97qrUwDj>dN`cF_zgaBCV@TZ>+5TJi(JXr63wE%kNFIKD1=L7 z&$OfW)G(0)hwEI1`nrOVA}F`Lm*$j2Q}`U+kAhB&KZyVc(Qb0$ed4PY&+4;~nPSxD zOTd#Wi6-D||C+NUfdM_@qG) zC!gNTV4=@)d~6?TKai69_d;f&D{r063jnaLxP-ZNnRgw5CZ<9H39T^WMUL1j86ouj< zFh(DT-R@(FCR%M-Xf-2?Sm^_z5U<_IO@O&@S=4b}EG#aWl9(os>Fu4I zWRsW=Z(SH1AZz@v=&ML-GPPjm*dcd146bg?NlVUISxzNqtbP2ylO)7Iwv1l+-i|^B~wfrGU zk$y4A7uH_@XjL<5*I^Njm1*l?Q$OBp4E`W(cZ;uiEyu@;G~)8^W!sL+-6$w-Kk{Yy zjIIqN^xk?qnSg%gGmC!4h<4pb%Gv9we#iH+VkU4gx_7N!NhpMqM{`wP_t%5lqxy_G z4F>h)>56c~LblG+^ogYW?$@(5Da23n*2czx8w<6yl*~2Cv|)OBZUt{MT{geh0)*mX zzJgcgjB*oK0*X18-Ezc-tN@Kt#d6=LWnPPLI-|OWThvFeP%@VUQZ2eb(?m|h%gd96 zFq9#nJ;Rt{HEU5LK2s-AcAWp_v)@2j9q9Loral4-Dij}2U_U7@A7j2)E%D8ltGqLY zTwby}J1EP1e4)s2ft$`kC*M_M*Bj|q4Te<{428i0)@13_+MdRA%D=W()MV2=rJ8eFEGgwfe$_>CZK(=o4q_-R4rEhW!xb}1q%m9#_#UF z@?kf#-EmaE{Sq2+Rg3&M*)I*R#`b5Q#~EH4w*ykIohdRN^G&N%<{3V7Q}cGujo)nW z<2djP0`t-1<72QO`+|mw6AXV}a<>}BWx_lYZ1cX^>y1phMa2$GPDv4M(mTEaILGyT zXW|t%H?T22)Tq#7P_67JPLy@EUg3A@!(ok0U}9^1$=g5v{%tTJTK@8SMZBf&G44^e zfzY-5_<8$l$cLGmASv+=*T*M;D^gA>k(@vj>*RC! z#leZb1!``p;iK;Uu!g6a{gTJV?1wvodPiDGq;# z#V34-`MBMP-#rE9ZURMvZa6`AcjUE-9$4~e^?qeb8^Ra}osXVq0K+B|1NCN+`^Hh% z8g1*v3uV%+n^$j*i*5{u-{exr7NKZrT2g(R)YJ_B(Ls4>Qdv_OCui(W!hjr|Z-V#v z*{7Dquvc4nM95CEPEOIm!F?Ssl22Mk$&ZEm0}4IPcN})#Gi<}b!HG~0$5Dv2Hq}B; zm8%KZEO27b#fRi90F|$Hz2$PL1-6F9cHdl`93%vg<@QGb<4y@+bRzqSb}NJ7YeGUoY%EKST9}h@|J!#>&bPms`4i&yix9bFv0 zCaC6IC|{`@93C$9zF{v6P9Y!$NdPW8l}d%dzW3LN(tf5P^tBXZWi#cA+*X(TCTJv_ zVE={~7^*3HPg{hCcLv5*98FuzzP4U!`S2iA3Gl-o@6eO=ehp@QF(m@wz*d)|WiTv! z{QflloHc607!fv2URxFIhegYfm?;-kNEx$WJ{ z6L1w7?oc=t$Z>JafSIU7sc|{;XquD4n6|}ap6yiOBPfO3^}*2ou=~3nDqm%cB7od% z{(LO8H*(8uZ)&u+cXMj@8+QuvYYRc2KI@hUFr!6IzXqA)paZp-Xqlg@dhz9HhLi0l zH8p(FE1f0#@a|qz4WUB`1)W<)rWy?i24rL%s+S3vhqbD?Rn_B~7WNj2a>a0`-;(ns z#s0{~WDGk7<~TVi>B(6+BM8}Ea76coF!B&yZ+XA7wEoj6{%7%>9MXmjiHaU+tkS~a zKtn)5jt&Eo;@ZlZsrsHJ*z24$b93yENEG4dl#*^36ynz7xp4NsB)00qH^V#Q1CX%> zz$gGn9?IWO!i!b1yF@*M>8oNNO_=2fd7SdeL6Hk)#pKvv8+|{v=4om!LyZC>DIxL1 zibwcd;Y7N}m&l(5Kc@aT0Eb0_XE7c1hv0|sIJ@L^+?I$FJ4vviKkSTgy` zm*)bWqBQ}>Ft3ooeWM4Q`U-u*t_~KEpf#ze4nR+}Tou6R5>`ZU#86v(A0elvYVRSMdPxswEh z)2)+nO-*4NICR>s7&4*V{X58aLRYfh%42)yV5pEZu)^+-K_exFgDXaTI)P*Z7dE`? z13`Jt^+q2J9}&?V!9NZLpDB&cUYN{0w35v@1o+OL8g_vy7vU4s?sLbyJrb10^gmnx37^+$2gS}ve0;n)oDM-8 zz{R^)$H53_yq*nUyR#)G|LqqDf+W1gbcvdhvl}}46%hRip9(pga$v z2nI&PpCX&WP-${y>-ub|^4Ft`x9=Sd`e+K3V4;9nj>CK@i&$R&L@0N=4xIEzD z%-d>zNVUgSLjL@TWftyPbTo&lwRMz_euMpPx76~>2z+8e>*EYvZ7|Y!k@5Q#M?zcg zYbq+(o35-z(QHmOwyG&jq>Tj9lmRJ*ng^3p8f@F81|GA~l^5=l(Zpu58NUInJm9sh?d*~`%+M&v zy2$t|tw#3VYke~n*-q!J12Q!}X5aRz^wytXtO9s^N)%qs0@!F3oKV!~n&8Am<=AoG zL`Pi%XT$Rnzf#?LOfRZ~i~U((AqkI0DycNEjPVr{`3t*C$mxPe_ZZi}+*@B8#tc^Z zOhMgjQ8@BYujQ8f6$;be+uOc(qv?U6F%6B4b=DJd8(EE@_!6*0(U9$XGjv09!3o3cY z7c_Q^^ong-l2lWSJ z5rfBHZV0G~C?O*ug=~b(WdYOaD$D8bU;`v^0h>nNX1+;)lAT?qTTeL%U z8A0D)Mxd&J+#5lst)-_HTd{}RRxkX*_lAa(VuKhZpXB_~oLX2S!#MAEia!>?igb$1 z@gcm6Tf$L9eDjI6&UNHe3?7vK+I)?%-$6tHRYK|H z=5(`DB)lSXtov#H{3xUKE}OD{mL!ypoqbP)|Kr!D#Ikgzm;r{H!KtC7ibAp+T!*7& z7<;^MYUc9MI9-Z4Fb!~CYLIzlIg`odJ_X((%c2;kDP2Un9&9!-46z9jKTv)A(ac}GLy3JL7*aR|cOfr^2 zFz|4tVrN(Op^n_T*qf2Wb?-og`uVWbhz$D6qnR>n6#ms?Xq*&8ue7Jm&Q8p5!D;N@ zhmn@3y5lH@C#WAkEnVMUm)q+EwUykAoBUtU66Q}951q;Zy5IXxD66DMf1*GMlkoZo zyXk{LVn{Th*_&a1nLpEQ{_n?OtF;c^++ujMTi&k!5rRl(qWf2q`|yiDdLtMap0>(P z86l%H=Rv9cmkQ+YN5gp)UXkxlIm9I1czYX0A6f~$_`d?9a3FNbgH=w{aDT=lQ}{jQ z1z(;>i|H$(=#rAi$;rjLlY$XYg0M=A=uy{^v)*vs)b5Q=uP$Ir7I=ga%ZPttduRLSQv0JkX5utsF4hd0rb%IW)cKL z>h)8zOGk&HB2s!<+LF^|k8OyQxVwA93w_Q~-IAs+U-l#ME6Vk+a0X}uR5=S*F|>ec zp8n&+VqUm0pcs+nD|8ptuYL;^YP1ioy&TFeS1Ws`wLx{jVIqw#L*V%f;M<9_VC1B7 zy;f2zEF&{BWQ-86R-cC@CGWvMAXY9N+Vw5(YOH6g)$Rs;$lxd7 z!SI-Mjt`r!0Li4=?Ajw@J)e`3n0Vp;5Gt-sJ7WHFO)9o!|MfL4eMKelYkok%y*3$; zRw`Bdn%#+AA+sLBEeu8h6CR(P|ITE4|3A9kIx6a}-5&-?k(5SS1Ox-e86*J7Oc&feGc$!iY_yBIQI__wFq%#e&3 z;r#vK^miuI0SfrWZ^Zu^z*@1q}SG;@>y((nt{ zO*sOem(ZIgd1n--h(Q@Xr;|7d$m`p09&ONm1IC%%q zfLOZI;a}9%)PRXd2n&NE=QL|mq;HaMx?`4OdB!dAUJv`K?+76gA`|ylJ!E9!OaHk? zn%Y_X{|y=MO?(Nwx{#L^pePV4yNsNlq;3-AN6$C6COao3!>Q;g;c$b3!|<-I|2lil z{%>bbIo{A;F{22huj@1g_^0flubGk&kQ_IZ`G-%zIUAk1DCLMk!lGW%ScWW8}QI3SH{G6 zAeuEa-CtOi=Y$t36(d4pBhgb-XNpJWO0KKq8w9Al^YJ%`W4BF7;jICb#W0xOpyNK*Cm^i;*g1!t3^ z=@0@O9C!km85tQ31J6?TWGL$0Pfg~odVr4s865KB$jK+GT>`L-u;em}yF5oo*qC+s zsqpuOv&{3utcz}WEX=oGdJBMt5ZbD8utbfNz?xR!fA9ns`w(LiZ1)3 z_TX$wWGk|suN4J=t37NaF?XZE`i~0p(f(BSLa%GEPw(?NUFEfGyoZBmC395@tO6|9 zX{NTO)~($O3re~Bvs>8GSU&U7&Bn^gT%LXd(8zx&NUposTWGj6ob&ljTX4pUbzJLg zDcAx^>z0GR`cxbaV-6VXB`CH9 zqJCz4+dngdL}}orL`Fu*?(%}yxjmRH=@{$_T^YwBfY~)2{NV`_BD~yBk+&92x1ylI zO$K~m36GaTWHaDSCmO}TYDXoS0pKwHv(3=BlCfl7pJQ-F_kfFvh}i@-YYUtx9c{sz zgW6M7)Q_GnCn9{yc}ae>$Jv&NfkCZ7#|{9G z3p^i;!n`V&*w_TowsOHu3YHVd%{r}W`b;dfI^l_F8~l0Nh5@K;`+5^=kbLl%c$VDLr;bv4{x zwm@+y@#FmDA>px{&>iMecmetr2Qva3!EAz9YcdGBMknULJt8#nXu8@oyba_3>E};6 zU=_8qQIeSx?%!gD7FPB4c#I&sIGANH2{w|Fl7YF-gaM)%KE6f)Jr2!>Bp%`f5Yd9Z zNhY9gVqy}NpnrX`33o!bVZI7ZZNR*>GxUfrMEX%#p&O75$t7?R&Fp`{%xz}Yk%_Xk zryodcLf;%OTQ7W=FMB5y+aJ$3m_Zr-ip@gp5y%({RZ2vM^b8M@wgJ2n2dY5_9&JQT zez4?sMZRh*NR znruTHLG~`r(||~W3G+4xx)v!X$xy~q^8cNoK$y+s>q-AxA%y?&4Z~;DZtOB-GBSW5 zLax6VrHA`v#2lIBw?D(+b3fv6o#u0_&R6f%^SwCfGVyiXp3wP};@HNS)U}dC#b<)| z_4N037zBSAfa$9%VN(3v`hT^GpQ}K)*dX^&?2j)%`o_8aXUrb=zZ|zU+ zAt|Elmd$=`I1D`M`AMyIiOxPCT1@(*^nq||SU26d!TpxaaYNczGVW6r4YK4*>Gq>M zp=Vs?(*@p#d@vY@noSR>Ovbd61%K==4;lmj<^XkGY(1-@pfDoX(jwrr2c%6z+|IW1 zIjbawQ~-9Uag19`yq_?cq|YzvPGWKv%kE|MIULC~DT0p&K(RIWBxtZWkmoau>ptEi zWMa>N$ofpvl7|p2Bz$BUcoc#N8VXX(vf?dF&MlCzEQ^Qr+4IWB{KN&9Xc1O+8(WTr{Kvl;df2wrWjC zK@1!mB2D`V<(sf%lGrDgdkZe_!Z-;32MaiAE(WlDgU=)M@3={#JthvppH;v|;17S% z0huW?hQVq95ZM=vumI+CiRDkY^g1bgh7nMh7wf$-g007^xl8)P)LEJ6EUb z8s51wcl`n?eIAu~j3gK2O!R%1UebF4^R}QXns+Ah&u=P+_GdM)>jAF<>?=Gz53Mc! zUp&6Ok}TrrAxj-fxmO+dG5&;zTAWSIpA^Ek>2FEJ6|eOtz;JKvt$^{c$*2dZ-U{rW zOa@m=Kzl>T;RH&0Q$QH9|5Z3tZURWM3PQE!25}}Esn)&K)QI(*8HBG zK+w37FW;6vc7~wK*``Segy&D^f6riZQD)%n`!6QA^wpQ5f`wFIgal*gQG`{fJKQ+a2uhe zKzY|>;K%M8OATry%|FBVF;8ZW@oI=Xx(IHk%phP-JQaYaL~LFxHzJ=R^izONL9P0u;gHTfrF2rp7`;wey~;lP z%31N^l4{av-pnt1OsDmn0S&RB9Ip+1a=-8$je19L98k)yoN&b+O!q>FE85Zkh zoz?Uvx`ch_%ilQ}xG`$cKgJ=1Q;Pokkaz8YdbkQ&OS_2AA@EB}9}7|27tIm)MjJ~- z%GqF_9tA}Ohf5LlSC5k97)Zi9bcR0o72)ay52kfOh4N(}6QdvLhN9qtLrDJfqe$8YRL&?=p7I{#9FbRByY-dvKH-Q?6)c|G^=I0U@;m7ySFuj*1ECZwQ z?j{Vz{o!;SNvQ#zL{C@JNReVTY2i6E*Qwr(}w(Kti4cO95Pv0yxgpswhQFT6z& ze8!;=LJs8ykY9}5TLd&>O7jgaUI7MGBZp)f`O9fl_~ha|YDn`NaoWGlWldl$ZxKISJugEhRp&?eL_I~yFv(a7jjhPbeGFm+5B_Jz4L2rK`3~O0s z(01#L$7*)u3_cF)5xv6uObdC27l%1UOiG8dto5X@`#+sw6wIUz)xp+S)mWh)M8FGt z&MZ*LPYqLx%R7I9R;yY2C#PDXHcUR@>AC&yvHB19KV;~uk&Oq>ffI}hnoNV+m^+s^ zaXM?*Op-b}n>kcSlN{Zw`x}-2g;KoIAEgqrqx$eF6EW1}83wVIgdcG+95CaMs0-%& zntFJnwWBMPrMB}S0s`}PSSjcqD^{ED8Pa<^`SG1Mg*()LVE zhH?L##BeX^*7)qC{QY_zraXPUE`x$8|LqNGzU+dsff8_#_v}|dP?#hSY=*XlR!H2Pqy&pWLL|FsYCy+R*Lq z%|ihL}4CiKji6O0s5i_d5H#5 zs^<35`7+6a>R-B7;GZw`lU@3b5m|yOAWKNE zb(r=uHO8wsGK^EmONx#_?$_e_1c(MVJpC@*V~{^REWMjM|PsTR4WQPjU-*+)M5OScXEK-5pdLjCup zEn+;qvwcBSaaq{0M7w zK%mCq=#m1$nOO5&->1MMcHlM9~L8Q9u_I z0exNKgZiH`QD!2${U7T9OjYs6^5KQI>t?$zuW~Nj;1XVH9?#RMbS+uTz2nrssptW! zKc$zWS?_r*H*{A!BNWkL_h+gkmztNQ<9RJLrkS#%^40Rcy=g}WS}Ta_;MvPJA#ar> zhZ{6Ejiqo&KL|FmFpd#ZSS?=2H8nOMD|Z_3dN^q}*%*%(#9$**&|P`TPW)8IqBw@8 z)~+!)9(#+at*!OaEWlel=NnXKvm;n}vD)>90f4mq=K5E5;lHwWOj61x-n3p8 zXnNSWs8147GrUElSYNEknTX2ABIFQJFdOG#tGWs(IM%-_aEDC)A$^T5LS8T}L zuEmW5@+?SyKf-^$xYWqQJirKT0JVddg)m1H#e)<@N~$W5DS*Eqk4#5NGA++$MB>9| z@r^YVYi@{ZbSxO}Y8h`S$-Wb72roJW*aE=OFC7l7pVIB$HnmQqhaBncC^8knUy_*V zfG27b8GRMFgu@_Dwyr1H>d`!-e2#QJT>^7ZK!Cm&Fqi<{l6CqgxTGXP;8@p8H{kTO zpjG@G)zHvT=UM#qbs(aDuV#VLb5+$iz-1!A5|bO;oNdFS?7gUwf|z{-`cYozlV6Qb zTFq}U9%)8l=~l*y<_SGhj*4}k7T~AP`!2`Y+uKJK4NXko@oifc%Uc#kUf(wF05k;w z?LfEI>Aj^T$Wzc!Q&*>9_Bvi!2e~bR0UC~Q?|`WvnuMRmd?!uqm|OxeG8m7|Y3a)< z!U(?=@R;1+oCAc@pg_sScA?SH*;$z#!@kkW9V96(__#5I==S)-hQm|DQ_lHZSgCVv z0-zPcoZ}rBG6P+=(TI7lB);*Wg5PcqD7&TA-B-G80FXP|pFNF)yyoGV6O}!fJ8%;W z2n-A{@M<&&aF{MLhFg}%Q>qaHLjQq*0gP7_@F=?%hm&=daS?fyzZem)DLW~HSDA-n z#vI|Z(v|ZS-^B2>=z#bp7J|?rL%HqES@^|Wvon<~PhKV#hW~|N{pZ5Fb^ z#0QT*O#&kyrA2d1$1E`@n4M8A80kp+MQ|hWwR;8WjJpfRd?&CvpiuegLLfvih*Anl zUb@^bzP<&!BEYJ_`x2IbO{ccB+SP11Y0Kk%(?5F)`L0a?g{xAmmEd)KB2@232$z74 zM1BM$Z=1(QQ1M*OG!z0^u+&ee`EV_WYDqf;O}w!1g!8d)HEX~aIELEl&)!ien~i7WUC8*{XKU9@XxBRV zekt=hHH*M~0MpLoY`ruAE1Q2O}=PzD3mYO^;6 z(>~zDSP;%(q0!s(;Z8JbTMY!qpRNsh@6Vh&ZqkE|bOosXb|)YIB_@Y2sr6l!vt z4ibK{%iF7Q*r@m3MC}%j5dj|(wj^Z`X8+W5wpuzujtW)OW zE8-a3ODoVGtwp3q=xHh13AVZ#v0xi4(Lz9<-POpcG}O(cbr_YGJN-*1FiglnJ=8-8KWQ3)D*3KYE*;6Ya#hK(K?m3h8QTx@aU9g@S$PSyA znGATHZWL*jowx$|A1!TP2zFm45`0Xd@GTn##&Q%gkW#>CPYew`0{8;`b^4g>gX7GU zeKaY8hK5CFcq$Jd+Rea2Y%PN9&Ot%p1mq?!aNmjY-+?#~@b z^MvW&={C}>oz}baq6d8r6!`s4r2-L4@T+c}inFQdCRn9I40b05#KZ8O?E)SLi^D16 zx9cIXJd3uL)@Zg=o%ODm#9%9MVlil>R|j`@3kO94HUUAx&CLy*9iVM%q3IDyn}kX@ zh6ej^p`pom7j>*)prwUaG^>RwbD2f6+9e=9>j)T5M$A~^bE#>FX@25WdtMI0++2c` z`~cDrZDJr#2Bf{@cRCYmYwbc4XVTW@^dNDY5m-e_dHExtYO~*1`ds6+UeLT;+K2LL z3x`jhYM^mDR1<56IVN;TdVST(B_Tzx<_FGQ+sa~$( z<_3!>j`0U3Ts}>%!&{HY6b_Z-(4A^b}%PJ55w_bYE;Hahz4 z$p!y(yr_3r4?&tm#A;nlgj$BjTY_i&1ZKh|5LDnoDG0ws6Hm&k^zUgEJeVTzM-Sir z?sHoLz>3)sgNJ9Z{4YzUc>mhNKbm>|=P=I?#47Hzem2JO3BN=MVx8tS+)_5x(xZVD zCg>KVeJ=XO-1#~2SZeM|1Pvy~I%IrW)VEXmwp9etqu7VvYV}^=J;Q>|Kzh#MZ?LyH z{m3wdd2|6+ggIXUsQfpQSeNJC<;J@%>11#SL3?xg-sCQe5B^amw5kR286ps;=Ltut zGMX-Xb0FE=%GMNtsBiZo8N6T32lGv-w5F&4wC4uS4ed-1W!K9jGlSvLTseesQy|p^ z96kUA1?SQPwO?nhc`be-BVYp&^ZJc0^MS?l9x{n+mVhz`^2J(*a}U3}>zQg>YdeEQ zDA*vNa!FwKSvHL{Hnl`(1=Ogmfx$N#Wg3Y{fJ)MWf|Jrx`&qVk_Ga?41ei-W{#n1ehx0X9FN${7K4>{*x3Q2GbBTT+AQepsJN#ryg1R8rb175Pbl@GHhUi zbKB4hMD7^3bp{<46dR~*_vI;<2*QmNf5hZG~Oc(8Q0c_yA54BjRU4Y7g5TdpK4<33mjZ#6W z(KgaZfpMP+a8Bk@emX za+4a}wb>Up+0%nj^0xlR80FbjRthtaRB-TmToU`z`U{a#hG9N``Mas<@fh$9RdJKn zgV*4f+V%}?hY($(-m%xZeSAn+Ib@mItj>-7XEr=S9#%g30Gj3gOf4; zqxl_lk6{2J*}OS?7=j^*Xuj-$ z+8oVgGa7QY>Q@56O&puL#Ne=Yy3r5oLEOv>WslwYMIJPAVvTpjACYlCzrLo!E>}K2 z$Z65Zj;%xnZ9b#><*I=|mu9)A7fK{wmw?qSDm7lD3tVkZLot}GVJCBBSwL)eDa5ur zQTZW98viRy`fjy}3_SAIpAy}Yi+zpDgYkxs_gu~CoX~!iwu?DnaB2%gDbST`Rmipl zoYm(am1ZNOKq7oF?+SH1UB1b=d6SSDu0*YiS_b6%s%fQfldrCB9_oxWo4cA7-$TjDnQ9=_u%Aphxn_6tkseMAHcRj)=Ic+775Co;|0ny zFHjD}pZIWoyM&94eSWfD=zWWZ#O-#($g%{6uT*{?3A$J468`2?=U?3;+vu_4n`%K$#+UKGFU_V871fTS!W`e!#!a z2{}5)Ps8}nvk%gJdZ7+z9pJktBC$0CS>Z8C!yGY~=^&L_4ADIj4$B$r+6?n$e~B)T zO()<~LE+Y;!}BF{_5g|8fR&g^OoxRzDzg)%-Hbd_QuBLrc{~jGF?;L=jmnyjad}ng z!BnQyF;livCxn^ZQEET7N#5_rxy9pXeZF^?*PGFTiJuF;ZC+y&FNTg^c+Y>zq$-eQhca^{<4i?F44LDI$7t7d6bajQHW#}ZxD41zb>&4 zzt7oJu3RMW)!#I_TN+!lI<%wfAGx2p%{6%P14#i4!kM$Py&xq^xzFP~+j&WXybj7t z`}+?-bP^fUwsiD)XqWe9e z-Q*&iD=eWEHJ4^@(if|&1d1sB<$I~<2fi2DMQyD*mx0AP*V59`>8qiQrknwhchsNE z-VwBd+hL%!)oYj=|JRF3Y{sI?fGp6}46Ss?1=!0sp7PI+@E)c_sKMpsk7HJ@4 zGlD?Ot&!E0gg#gPq@Z9d&->Rxkeu6vQMYA@r z2+8!iJm7V7JOw0jLjy@@lA!+$kRRb&xc`2nF0*8B0TjU-%l_g(bfMi~LWJ%Q5BV*3xJXvp6isryf9$DB_!X2c1XFnf#=95D zwpBBJEi`=W5^Se19Y{eyQJw-CR{N?|xHlmoU4!tjuv=&$Ff-YfLn0~6Q}*_QKefy2 zO$IFVI{W)sK6D~);V`$nbv@s4Zhu6R8Vp^oj^}^G@gK(fd!vAOw&8#yPd+Xd_P@&~ zp28EQ20_M4oHZ)p?t_S*;|bKUGO;n2%NQn>8tstpGkt%hm+_?mtv_7mPuzB5fjq5s zL4B!=CWmM8Hcmvs`nTe8r=Em#E1wTi+bW5QrUu(aHgSVwn#T8J-w8j^#{Fcan$Dsv z0QbApWYW$cr-^MeK{Bn06~SiUuhN<#MQmN)d2x35pxa0P-|u}jM~;4%BS)&GVA{AW z+mx?i6IPO|c&^d9c|o{X;xjv=Uq*j=QT0E#?aphmQb;JmCJ&okO&WBe7H<>)VU zL*#VBw$5-S>g0^&aw@qZYb!}*>QD}7TJ>V5MxpEUEs7|An!WFX!x>YCdZ|wMOdMRC zVq&7eq@iABdf%XXSR1~xN-bDO%wZ94ma&RC1?OyAfY-DeZyji`Ep;vrRKJ;N=8GOU zjIfI8mE`y`N0!)40?Ld5pP;XKKOwH3uG~v_ReJmemX_-maR>80zCRLEszJFdVnZ&F zpePq8eTsRfNuZLi2)D)ZXfxkv*hRl~dy612?cich%w^>3_OkjZ59Az#_5$r0(3E=I zU6ld@PA#v~6*Y?l^;fWQfDm|ka9C`i{}?tJucn?XP)>G?C}@B3adw5_W9T+EG-w+c zWsy@9{^9dFVg{ikajCAbgPcI5KMPcKq<Q1RnNSI&J8l)1kM2 z0F2-b9Cm%G#X?hJR6y^&lJG=T)x^*!8?1+PL}3FMk<5B#43KyzC@8l_%Wc2~2^eQC z)4?+?=M|n?RP{@+^y}zUr?c19ZGza$28VSG012XlGi!WtaS@mXke&XQQRj~^Y6Py4 zl;{`npLhj!bi)Mz)eI+?=t@fG%iyrOGD|qY*qz2nG3N+vmGaAWS7WtuguWqGMv#0J3RiuU8T?oZ#gagk2hJ~GT+FrheqKw{czjLuS zU1SXSnRay~`Sy^*Qjouv*yX(RF{a#{SBiSgP*#=}n(Jh|he?6Drj`h0WM5xq=_ z!zPx4vqk0n)x}-Yc3{!QHGNS0h0|2(?IgB&sLQWkQn+^)={JWXTir*$eB&afL3O2( zcDSXiV_k)Ue#@5lB4L@zFWC>ITwJXknSw1501WKUoZcZk-^`+)Q(29FGxiveUjUeK zT6Q$4IIWSdWJnn#dMD-~F5L<~fdLI?;T{r<D!8FbIgWzQhcb8dppB?qBrHmKsPMfBu84kNoapwNZv-I%DH!P!i zxe>%&b{1`eLKG?7&N<=9L?4|+M8yo6^lb9y`}?zP_q^N=Tm0rd9XI@mhhG6@djXrGvl zwe;r%t5)CM!Dkoo!7$0(*nLCK6Y&ocfQ`BNG{$AL)qO!!t5T?Q38Dw0=FppM=8lk2 zPy#;IJo=t>l$#Ew?2cp}_Te&sR`|yoOUjpHY(QHZoCErofSCSML_m)~u|NFt5n3Qc zUlz7Ci;g-@%Miq@b=sCRGFk(ZJce);kJr`KAJd^>imz3+k1bZ}<-tK7nA7cg1e9Le zC&mf^(;glRWu>JqV86*Q*^o{Er`(I@DEVYQy7XhyPmr~yX0~LqR=x9ORCpARgP(p zKU^KZhBYC~1ZkwelK9Ny2*8+RMd#b|nb|wK6+mvsVRL7+_c~s;+@-BzySzlZ4mBA~ z(Hj&4F+vl1AVUjR1A&|kz}KCx&n;7dMeF-pO?-r1pg}<#3&e!#%5d5LK{QicSymAi z5)u&-CWICees5?5Bs{=q%%!&^pBICa0upKlC+6k|%dvxC`2GgicvCE=qze{nR$~Ay zl8v7-vru zb8>W!o`_=nEcgnJ#jO}N)okM5;{Q{R^BHz?iE%d^g$+Sn^rg&Ccxf zi9DT3tG<5p4=Em780{@nx@Jq0FQ;$;Wz}@D^@&v`&0K@Z7h}MysLGwu{~q z0fAdQXi0BAHy^}2@zr~h1T4Bp$ozcY1WQ!*z1pca$3}s&`hDqMXUp-hkn z{Qh9R4s4DKu0X_5z&zSg_wtgk9_~7rj3rsE(i)JF?xOj$Yb$^w0}O~<2}{FWsvcWf2;#@X`r8mE#GO_U z{D(ucsUO^F`<5evVLTgCRWY8(&VLVzbks(;7V`A!*u8E99tG%gr z>>TMCnd{$M?V3vFb-W&z{-co8_?#`OAugBjw%zycn zgZ)Yde7}~eZ&_oIJ(>3=8TMd+_^x}*tm`&Dd+!R*yD>ru#<*JlO- zJxVaK@sAGMn?1>N{T+Lx3MTW0rH`}e`2hc^{g#= z%go%#IYyQcALs09%jhvTuFXH|(W%ot>D4c;o(!{O8itL8x^0>lb!XQdHdIVa;zOKmXh5EsWLOxEkxuRTJUm=s2sp68Pah|q6frMwEo71J@Q_8snI*LC z>(5%ywa)mz2zP>7X^#)9_69~$hVSopS4gE&{O5?D0~rMb^R19(4Z>To2UX@R`Y7!` z#@%`rCL3FO-`{9X)Hbo?$ydIFr&FyF>g-QQN=iPA(DfGqKj-;NS|*RgK)^ zKRei;O^D73i%HE)=5opCR5U!?+HyXf2w>jS1CzJy;+0O57fJydbA>=HwQ@1tnI7hc z57lG&p)qs{wO;CxckVHBd0ShTwu>f%v6UXl8aFDLHrAK*?m7)_+lRQfDzCwEBG%a% zba9|tYL_oKTW453%KvQ0auV`rDwjfz172@Djq^?>0vb%vzz?4D`NV35lny>+uY2&O z-%V`FOow1=I9rue-N+EAo6(8ze>ol17t8UEbvUx9yQgz_SQu947IxJ|@_C@AVM)Tb zH_5u}lN^_y#m;;~4BrSZ2slF)W@dlc*PWjOsh$y$ynI>fvL6TrtU}O%st(+Q(~X94 zvSrkgBt_I3K#O}V^z1Vf@^umL8)p1Aotyw-_fYA|)VocVbIjBoyy$wbYe~Qyj9-%n zu31?beQy%rQ&8fem|`&>t@pk?a0#H>xrr9vH5Ub6s6 zR4Y``_(SL26Zz?7Z$%Aj&q`Q!1u>OL_`u z;~+SNr2?dYps#_O8^?FiwdP-uv9Ym&g0;HyFsuh)@{yI5MI+(+1RE?JA6m$4GznI` z|J!UxZ8usY6$vB)jljJNASWQ6)CQbt-iRT8FH&iyzwq|xo4($~R+QBLdJSI(#=O<0 z0YZ4Z^;79RA{TUcI2I7j7aoSsOk9ri;>DxUCJ1~%F8*0mq^+%O&l@S{Gro-=>2757 z{c@Fxiz6frx0n4HQ5!XSWJ?i9i0cMHXc%oI+#g@orTr1nZnuOj!8#`JTLb~9Aj+ix zlVGgGQeXe$-juyB$B$XpJr{fXe2wgH(V4GjKnu$P=jzUim64S|F`vsFtd1Z!n$Vq& zg@hj$I~zOK4`%z5#GW!ONdlpNY)$GzRkt?Ec8&d`o&1MwSj4k)DY1+z?oNDknVY_; zJ1lxl++aM)uF|J}pWbCY~*s`o*jOqME9#ADab%DTM@D+KT5bjbtMV7z;rU zziWT@hGRSPsnAXIkIjR*f!l^Ff}?KS$csEI=tp6ri+ zgtaXm>-tl=g`;sg)l)E}rRF?lyvjDS^ zm+q~Ic-M86+}ajiyXsaPG|62g5s%mTr!(54p0+OBp%k=8T{6Vy&vh!@w!iaJB6?o) zs8B0&`2bGfzFX5;j+oysBZ4|V*a zlmDi@DEN;KhB2@7j4E68_z~`5#v#unFRX*`oyiCGY_%Z2l5V-L9o&WPzW5 zym&9&Zhiq~Bn3iIUrAK}Lw^cGO27#|v!Yx@)LUv_(7A!l z<`5ImLw~0E*FEaly~%DfXEl{(lgz~mfU2vDdCv+^$7u)%Gr@p=yrWTQv*oV*8f3o9 z922%jv`RYq>^5#fN3WQSvZyD3ttMti^V8QGUzSu{Ngp(W zo@)T0SuG?uSbh*e!E)Hs?YF1f+D8ziFp>%XKmf?P)59jy%fm^j+;@2&nh2dN_|^ZO zHuVCZlliDffe?$H^vh91F)B3-_6ce?N_+>bgE$bU{7 zbmXk~!X-3&7PD{vS=rhJP8jv9Ot$08J&tb08R+Q)m$IF9Hoa$tZnI==RtQYDxv!IW zcQ&mX#sN^xGcbv}<5i)z`C8plhE0Jt-EukVt$4$9vqECYzHGHu6BA{FD>zY{ZOiC{ zYoMbfUbuXJ5VT5(eGFzmFnLa&p??$4pvG1$Q@F@)vOeNenIF&)D()Q?no--=eY9kn zYs$~XLeDe2Ik2z2fbfWT9(}M2@8gF2eteFyC_lizM*Aj>-8CZ<(*qW#tdOGdN4zj3 zz-#wX;-<6gGE(-Mmk;J*6zi}(BQva@?oZ5~eu4dwr`udB*=u$-Ddk@Q0m3){(8`$@ z6tq3isNL{Q>JP7wBhX7BZDAAcVXv;ztX+dm;EK)O!3)2$4wk@F1`A;{#=*C`M$L!C zVfnloIvO4ta%mpp#GLpuQfN1*R~CH=u2l)yj#V>0`GW1!JJM~^FWKtOI!>w=Lyhn} zWH~seE$k2M{?1eoJU2dbPhfWN6G2QjI=i%d@*^-vBv^s|o#o&B>eSJA%_uG1p{liTX zeEj2~ALp-BioHu}yQ~kFNE;d5m-6&kcgF{Rywe2v4w^rdIKC1lB}>c5=r%}y|E7^+ za7_$zJ2iv<(DcH!;UJ0IoeK!R^8aLA)Vs`|?o|E+(aoA_Ryx(kXQk12Qr70oS>mO7 zr5VGr@E#-QlvD@>j9{Ao)A0^;z#@bw_K&7aNQ3IL5LC;Ma?Evo!2yXr`$E`;4 z$Dy88P~oLnYH$r2%v|=SSnY;?0p~S{zQK37yLwM;Du0XK1|nZQPR8&@XduKM3-OTE z)xNWfkM+R1rj=9cvd!T+QSoF~o+$bgvL5blNs4Y}tE)YO6R;qov_ygyihTBov12|Yfwo_wGK+PzRU-R^|x|i**BXEWWz~&7G z6=;;3RD#MdVaJa4kLF{|3kwf5cL|Zeh1;E%2dr(GNDle6F)bWSqZww_WH+oGc*SQEoL{BcQKoysIjR6E%n&4H}!}RNo zu={{f^CM;?a>3&#_=wxtcgDLt$}5!RMR-7d{_~H}WSd0MoXgLP)1H+=73H^ zxxKj&Vivt=A9 zH1~A}vOK~+N17dS{A^BJ19wv{E_s{N1Fq&-P?u@AbU$l^db=!sqJ~hBm*-*HWD}9D zwzgq1jZbWWkHEZ0Q2+?js?3d7=jP|)L9Hawbu zhZ>M}t2Z>vmGQUta^`G;not|0OVm)z;O4VxQgh`(|?%k8P4l=$^)LZv33lYUU;b&L2G@)!{jSRI@m<VYJ+9-;WEw3bVJF)0kzs zx_|9osr#b6SgIA40x9s;uMC#Vpi&&(!Vul6vS?+6+M6a_Glr3j?v%o#%A$`io|MOfxm6 z)pXP4RXbDkwtjb>Rr^P$r~VOjF4K~L1D55jTkj9owJnW)j*49Car|v_eE0W+Y5zBT zuC9*q&17wD{cUFB&s(>5+vQVx48cO5gf9+eh=?&pDkl%;Z!S)5m#XzP2&wD1v}d@d z1nEc3SUMzQ8O^eLW9hZ(@xH^b^e?9{%iK62eqQfR?t4NVT3dHxC$E_|$*4eqvIQO8 zU@BL+{`iljv?a|+UR63R8e$b386Yw?$d+6K*ZW&X$}2_VzNwy}%`Y<|9(NJKIZj!n zBjqfzb7E~e^`So+dC$U|y2GO>2nh0mqebD`kiDL3G-$-IS!;mc)?)2yg|q0lj$*X5 zQluGI_z#^Za){MMvrbkgmM_eTo7l`L)}-Aed_mJ%0<)yY*ahLGQerD9n$G|pfSNUW-C7vW#B zZuqm5slju!B@+F|VEZ=y$w;^4FIOiE1_4liL=Xb>U=Y2G(#_7CWxvLoRdLv+@Q4r= zrb={Wbj!s>?yHlPvZZRYrKe+U`&%1j!x@HSt`;jE`^R5CV?hYw3cKER(osX!rja+D z8&w(BZq2*m2%WGuZVe3$m*d&koj5K8*U%pnZr|Hx*t3+s-@m;2^!Vom83{2zCuDzl zA^l_IkU%~1{T0^_QPDuSpc`IcNMrFH)Aw!#+lXw-LAvoS?#<#&ZzqHJ#lr5RG|xH& zg2b6Mi;8Y8=Omwb?2X42uv3x{6PkABTqN`glz6XJ{$aDmF#HfMv-3bT6T zOq5(@g|t4`-Z<=HvDWbx4OVEyaaLwnn@eu|B);JYiH(Xz=z zeB!%@p6vvJ+y3M1H_Y@+(CZpQ$EuuNP)Qx6VecU-IH6FhYJPTsB=iQAoA2Alt@(-m zV|jiCgHC|oUc6=I=1k|kAl#D8MTzblF-Hlny6HtOhRF%D-|?H;&+<(KcQGDDO?Sw7 z_oD?M7nSOz^KtfPr?@$O|E?7g6MdMdis@7=H<|9O({TkL*!juyDcT`_+Ex4Q`%KVF zqEPjnDQ@`J@M-RlR-G5VYhk)mu|~xn*jn=jVwo+g_NEtsYUz^g0{7JsMFK`#EI3{( zW18xI+qB(834<**Ejp>jvGQO{XDM8h#o5If4)OMA!FKtld#@|OE`m<=Lug1lId9L- z-p;diWosM|Yx*J-8J|hO{%hxkn2ot&KtQ0k8H|TOy{LDIeYzU(?cX}2WmPF>BP6jg(}LzZO;p|kfOt(LG%@8x`UwLXHu3lpVUn8 zi}RgnUI0*ov+rJ?j;om8@1;j1vSUWb3roCir_MkI_$ z0mR4B$RvMuzda*iGmtJ+9Rz|l$Gh4CZgP6;-X!i}5L$F|v8``z{^Qf~7vWqvr2>HD zyFQq|1rVT2a`ldY^Yq-*Z_nh{v>WZ$fht8jAVRy+i7=$kBFZcjpT*_$mnV=-*D*o@ zuB26rKxYEY5_5W*g zZ03boG;Iwk6A8-c*Yk*cD;W?toz0+USy2A=J?j8OMcIg6StdTe$|AiK-$+d<{A`mh z5%zi^JOou73gxL&9|3p8=mOJ+V09{=MSp~wSrg{NZ!HP=RmAlto*umH6T-_mzk8=a z!)#fVqdxt8ipL}}0y!|q!a(2C+VwD!MbLL~9>wi52bhZay8D8MUcaW{52c|U*+6|! z>+dXb9w0O{Kv?KvvjZmUjx6nEm3^74QY+t^W-qm=ECYu?w$y3~ZbOcrbaWfg9TAo^Hc3f4E749MKpf`5>ni*%+=ooRWe%ipihTpDVd*};TNDEx_^P! zAVHiUjlP{2Kf_3{+5Id3q%FJQ4!NHouX|yBenF|{j;zadQ({sR8Tb0)q2$5(qm`#4 z#LLga7uPYGQlQl^ZVB_JuUKgm4H5-%34o)JT{Dur8PTjMhSiVd#B-+RuT!xUVkL~8 z^7_cHgn*ejNLjOF5cWUp1Uh$%9-JFPiaj(mDb3#GH48M61)Mr1|_tsklQ}c9?X^A2L(|B$Qe*8ik{yUPEMK!Z^my|*6Q3H#&*<)>Lk1Ob zD>Xhr1vY2G+E2@4fN20sU#MK=YNgOoDI<^#&ziT%oS*Ofgk8_}av^W(91niaS6Ntt zDSx``4uMgN%_`k4w`dv^fL#j~ycNgc|9lWpX~bMVQ{TZ|(Ze+QeTWro3|kev3!u zgkjHHAF?p&2DfWQ=~4F^RKIV$cE1`w&byXs*TIvvvp(&O0XTm^5Z|fVLqedIs z3?P=}S3O+Y0Hu~^*N>Ffb`J=|Ous01EWAlzC-v=~!Z7*T{1Cnd&<9fm^H4V~Gqx(} z{o<+!rXyv!V1Y=?Yi^mP>oHemQ^AK&>|r&FC74c5;8VTN_Z$JU4G38&?Fy18QiVN7 z0rLZ6E6D>F?M!#vSfBgz7oc50IXRx~q~BpAkszTaF?f91eOmgeX&-xK2Y+|A&y8r( ze!iQ^;{&8})6L>jgdCe;q}=&-ab%k;+Bm?ov_6@8nEn70z@%R5$L9UrNxr4(-5rAn z>|@s4d&F&$f1UgQ;!5Qs3_80c&AP3_{NV1s-s!KBl0l60>C2*rlBg`g6_|r{NF3~3 zUpTvdleLtbnAU5?Yc1%4{&mpuchvPd9wFYEyOF_GV6It+j%o>rsBC7xyic*6WUsRC8#gd) zR)x%(FqjzVTYua)j;oVf_@!lNsa4JA>5Wk-tM#MdO?~F@@B=B~PGIKy?sp~5#3&WR z$`Ql~pFXavj4Dw4%0H!&>e10rzd5cl$y*#pa19We=77D}xJbzN4D$_=j1`(_PCc6B3+>GnCYCgagoE%Lv%YHeJOZk~?JH1dDdUuj>bk5X*T zME*?Duwh0=M^S}cbZ$6<{tCbbT0vH-U67-F{xin);Y_!xj-!M92Ip~OtNAN=Q+0ZH zB$TJFH`Dxld^^1l;)a1?XN?Y|0eZ*D*P^0r%gf90JY#wz;11AOKO6Bh+kSO30;NY)sWfrINmCcx#GO4Jo7aOY#mfv-OXGVbNrR5yb z+D_L`&;s?Kk$CK$!WTbE$iDLmSxgs|=O^TU|Ne|Nz)0Ue1pl-*iB4%l4h|Xrte1S# z(cwmpFe@vIlE7pr^WG6BGdN;1S!-@K`)v{tS@~P5l~8CFYXZ4y)(_nR8&gRcVOK;% z{m+;P3B2y$xzI>ccx+^Y9D*`XMLT>cMHG7|hC~T`J+geWg2*T!1eX4qKaBMC=BiUF zjE8+om|Qq|dC{QJU<;yPBB`FRXygT)1rby|ktmAK-F!pyToRMwDFxc)FDrfwLn82Kh%3&4;%Ph-s@_v9tO7eC}cKJ}WF3`GlZ)hmi)%EpLrX zD;pYo#Lu|&V$p1A@$77;TK{BtZU#f?pMS&QSRrf7Ekii5>^DEeqK&$Gmx6#Z)6 z=sw})3m|oN|6Kg$#-PNRC_{GjE7$wJkK|;e=qJ%aKIjr`)Y#!*LHKezbSqwiip=XJ zTMe#ms+%w-SZE@Kc+wl^i1n*xXss>>)3h>c(s|H7(53YXATUtp6I!cBJ zXplb76d{G#O*rK;RENc(GT_WKlO%ey5Li%nRCf zU{oGVh#KZA(i&KpfL;F4U7r%gt5@C0J#WW`7E*}`LDFJ=3mFi-32@SI(kt9VJ~5?Y zqM=!vi7{DTj(+j6B>7m`>|Kl7#ohVqZ3qcP+vp_2kzu-%4xS__aEGWio3DephR8Us ziWc`rp8=9I(uIb_p@p{DZupR@UVO4aN_b(9HRh1^q=cmP{{4rowhsK^v~`9k-734x zR6;`H$s#p6lY`&1IkfAHDwdPw?qII8Om?I)gLdN-V z(DeTP;E?EOI@WGZP6ruW@16wheU*>W5qKO}q_LTvfJbO;zHYk8hd_MOSOW z-VR^G^b_P$Apx|0wnqB)mfA7`-g0B3H4{h6O4B2(QSuh%{(>q zFPUjW5IrteR=$|zZtkcr6>70D1k{K%-(RhCL!_F!vOiTM{TFkD8wZ9X$S&ZO+==?k zROnx4sf^xI&zo3bWh(bC5;w`xoWP;q6!eTm$O(&E3SVur_w$y-LcvYk&(>$5!CiP+ zPr`x~zi0*jAW$PVG-eyE$-V3M4=s#iYVbT1LTwxJtnr5rq#y4+NPV4E?zXr8v~#o% zQ-?kaFxeOttIt*g7l^`hT;}crtLTBt4>TPC`oRuG93&as>41g15tFJ!oW#=A(1qVqN9%Z1I{fdqOd^0;3i}x1ZTS#A{g$r8d)Jx>ca*!aQR{f63Boa-%JDpOxOPIRR{To z{|!8NhYTY;n{@frR@+qgAA6&BX`9z!_?rio7r6|-7_?H%91{A~>*`I4Sb1Jg3a3K^ zh0))$Zsh1HXIm`jCfiMMRM|W9t8f4(Iprbwt)NgS!?n{#gD{g4fp$I>GHevr&EKCZ zl+)rthcblyeMytY=u`MLtv>9~K~=_6j!6UK6h^Dy62ktAN56~Z$K5ZbY(5lebJD>P zVL=h79FDzu`e~!n$}np&7dJNn4RfwHf_zBgOYU2d;GXf!w}`7_`WPBIG-#=vMI}Zp zF3jGog!^$lKI;Yyy?}D+GxG>4VhldDAxDGU_ln8X#AL3e&;QHejWH@EeYYtt0TR7h&R3&NqX>dlDq30;ttD zU(w3T5BOCVFP0}%S>zy#S11z~8pdaM{2-EfpDnmHmz!%+&}L1vn(ey<73m8d`Is?7 zpwku$vY0{#hQl+Qq_Z+iJ_}>{sf@iU^VZCCinjJ+e^m0{oq-T~LXR_nad93gvLy*8 zJo&$%no&9`z%Kg!g!P3gZi%E<1*BtTZ7-R_@gp&@1%Xdk0tX?X#UkD`|8yMvd*pXp zK*PkwVWCA#Jp_zRL@zDgeK)QG68B<_`n$DqY>f&Nij;&327bfzo*lm9+J`-^i)L{I@kEbZvcava4;0VNbr1 z{6lRy666qRDQ(`&61M{)Kkw3EsP}L!LOq=Aj-60{aXiolP%DdB_gQWqEi3JZQmbZb zlb>$z8yBuX*6vcQ1jX+S4&S}+IU@H&N5G9F;i#D5a30+M{7Ds-O zfX5fofo(@Rs`pk5g9ZaNfJcA#OR!Qr23cHKl)VN4P7FqrzaA04fT;BeUF zbl{e6`(Z3celwL@{?n%;?8BZ+nW5ixH>d!Qcy`2&+b`-b8QUtn9g6e(<)?`<;8S~g zZD^EeZ^n`=c)2`}@O^T2y)fcH`0V8Rb@=xW_uVZxjH;c#e;2))pA{-~N9*@_;b1ge zO$y5Wwgn9htqgs8<+B;=TvZkgvL%-LNCb)yF0*T5_??N022lQZ6o1LV|MUVvhJ4a= zzcfPbQg!@9`W3eF&%yN<3Rg4X7mpz#L}9v_H`?E@0)P zqM)K@+?wKnUsA3Rw!%RiYFF{}Tuf5_z5 z8N)XvS#Z=_IMa|P6Kr;SSjpr)1@@U{x3(2e)zTzxtBtxClMI(k?CJBusm(hs!}*ZO z=2G{Ox$wd%DCD^&E4nDFr0Riti;es&ItlEntXuStZi>9G-(**bVmHX|jhhOH;Gme!H$;fkD+v0$2Pm*xM%#`4D8@q<9#_)2FCVDl z3YV^LT>}sH$q0z(n_yx@JJ67%#o0RusR#`<|FY_x2-A@tWq!i!6!+h5h0)~2vB4CE z?FeE5Ncj+mp$Nx+N^xlhRJWE}Ld-KfStEO8BR3@pT&yT#R%oZZ#fsh|J+R?MeHG~G zM!Erc;!>fbHX5B#ANhk~^Zq_-cz6(UnC5VJKqi98dwGf0RFgFY_V73jEhbC*p8TF} zHq3nNciZ`dj@1s4h#rug6GoX3otdT4130sEe!AlRxtmR3S*gg6vF)F!Sn) z!@Fq?!$Sj7)+{fWF0?0E*#d&~X>EFLgk(>MmGUrZvj%wM1UCGcP2LrqgQ*IW^w;QG z9@*q)L7}rO=h;i_nt=1(>gD91dgB&!mw`d+ZYvQ2OVy|x(I(7-m(^L>)kVJA`)teO z1W&oAFE~H0S~j8=hwN!{PSf#m-KU$qUA0m+o^J2U^W&!xx55@6Y9|VwSBVCMCsBzU zpZ}aXT$D+Be{_zU17I zYl^qKD~R!&x)$Vhw3`Q~f*BpfEi0}Y3UFqm4c`$DNs8Yqi~R?8@Fg62XX__Hl!uDD z2Kq$eAJiXtGT0$JEFnbY$p0U*37!D)_6m8nnCab$F&`GqQ*|l5fVJStJn3yk!cHoY zx8Tx}zUI%2)vQ!Q9b@_un~6ArM?o{WRC9^>I61++S76?yTn}8pE7bOaknQM{ z;}HghsS`r5NzY+PP;DD#^`m=Bdq-X~_Q9Kh%|xysR6~U)j%){9*VW-78hT`yr>zSfDs%{xqCaeQ*Gv86(Z}@9KMNGMG}P>?Ma9KU{R|Dj zlx(dr0yo#<7b~LBzi%mU|6vkdUES^c41EnYBKJWtxx5f3)TMm}lanUX8R~DBqGA|! z`RT+kw=^X~G6z>Z3ZKfSj2`dPXQ-xWZs8FT?z1Wp345!B_w32rVb9Lt<+uzQvqHc1 z-hFY;sTPKZxgzc5C5ch(E+>Gy{_XB)(lQ)A2uN18A3JN4y}~QIkZ;*8qKyBCS_BJE zf1a!7wNM1X35<5|`S)P!QT^PUPP#1|jp8pB``qW-@*EAIY+=@-O{H;0o?(dkDRh}@ z2P>9#njQ}tQuCPusO%8beySeS4*o;HH^EK70X!1`|7ITIg{%;~XB%3*=m02i~fzYnMJh}i00O#DB>->9n;rVVQCZvc*;RS*RuJn9r2Cb@glnPatWp3_UsE zc?_@IJ9*X3fNhw#Za|DRT%2w?hElLnqSkmL0bx${Y9_R;AnMevl^%dk&|aPff@K3+sOpnJRuC zE$q1u}#LVF;)ppkRMi$j_rm)PNP>>O(Y0-9E#~N9Lp{TSiwB2Tz8K#dst0nd}Xd=nm1y~PB8pXyWcUG%gBzjM@d37bQOB&XTkWuyHmx#TdaGQ#esxyhSlwA38b+%)YlvT zOnfF4u?L?7GeL9puB$SM^ZGkT;01~t33gO!7pJwC?CcjO^}dM@YzPSUmcVF zGYiNhOfS?65xT29?G))Z^1Ar*oChCapdQqr5^u+Q6FJqBAWSyU_7LJRmvqXN;HJ_s zJ~lpwba>#28h$L-XCf!u9d7$a!UOvEAQKZ1*O!m}Ph21By`-VaIY9EIw~Ivl77K-( zAp|&#u)?tJlRh-Oj)o4wJ7O)lpkw$MJB${&Dj+Nr6k zKhCjv+!;-``@e2#{K%r!jLc>UK=@#PC;nWz0OUB3@ENrNG9Hiw1W}1}ePh;I-@mVw zjSY#4gHp}cE|*>wGp#i{RmH(|J?p&%iv35kGl+uie2;^P^0?{CR)VW@=a1m?-+te6 z5Imy_@}17$Q+~Ld7eGTp&($1a^>UvVv?1d%vZi}l@BKi&^$hqwNTl>yOcswk_@b$W z#qK(8;OW{dLNY54dQ3Jw-PDMza91d9iqO4$a&pp3tK-wt!|`0H_TetZr^1BU@^K}A zLw9|;34mx_48YCT1eSfn3AdN&q8&fK6~6m!zOS29O~Px=^vNFX!+Que>JmA8h`n56 zr<Ha(h@#Kpwkrtnn&96iWnMI#xJ0=b}U4lBTuo^c$uGy0IGy|aug0y@fk%QhPgy17BZap zQ1k{Kc2AdL$as=z((hCmc`lil^jPqs@c0PNvpGh`^IuRfq^{)GRmrb)&RXkm>`E@e zGH?)<0pEbPBXTcck5`H?qrW0P{?8j3;t3Bd`F@&qz^*0Df~a@64hOwAkYE=jtO#c& zmGJy)2Ag3wWFaeZ*dlFf%d`a@Bq)*li3Z6g(GG&RM2rqJQlSvJO3;FX%)$oO!{)+5 z3x!W*nPpwF4zV}V8m)J3Pkii6C(Y=v5uC~$=?G04(wNPbIlE*?CvFM2)4R+W5 zVRQ{v&{C0v5FiXe+n;07su$Tr^)@Y_&f54HhoAdl_wV-0vnM?AV9ptqxKx-x zCW|y;01439d0wODfgJS)q>PJ+i)RS(^YJcCuC1+|v9T(c#a?;Q37r!gdFWPL!}H6D z|1Asxp|#=kZ73N3Ehqk5k8WJ>d8;%WUXF#yqM>?UdP0~xh&N52h+blfz50`*217tqyYimKRfdArEcD6kR*u6;i z`~YO=-~Wy4b+x5NczC#Oqf-KKx_~nYB&)DyX;$E*5^&}%24RZx*_)#97WW*!$Lt{D zDgZDz#Ri8ron<%YJM`irgOavDND5Lti@c8E;&ng{@Fcv-z`y|Nk8ea0VeZh@Vr#y? zK3EuX=!uXAIj6t2N0TjI-5$>+=5|mnN#+d;3xD!ND1_0M47u`#O#>%mm~cQ23vu7- zDv0fLgGJ7$5SX}ahcX7~*ddVkYV*nZtQ-M-4RF8N>IRH4VWIP7ouLbzD!684v0-2yA)yY(_*fF3KKRr`jU1SU} z@X7FlXf9?lJr#MhM7nW<5x9+YwB5{W%vJ3W!WeAq zY-+0RD zr5rH!#PYF}u*k9u4VqlhF(jA46XFfwI!F>C7rK&^l5BE5eFeRW;&Mqy@8V@WQ*aMZ z*JMI&pfrOm=A)p{`&Cre>d$34adr}02#h4&@s0p6M46F+&!Q9X8yAbj2gPu?9S$ePH!nvzv|53({<05mp&IkO#ZLD9 ztph#epvEw;I%;w`)`Q|Fw0Au`EP}yAZ$=>6LBNQ|Nhc-A$j)Q|)D-5?+4#;xelTYj zyRjU4G*(ECh|Bq2v*Yl~(anhcq^~isRa>6-^|7F$kk~&qM8LZfBrc%&G)*VfmnNLH zg*S+QCnz;vCZ9%@iR|i)N%<~Q+!y}AMu>hRFssPLO?zo&S?vtc6OUPCKIwEnYciId z4+P(VI!Qq7So~qor{cb}#Wd#LNSLaDhkSdl?*jSyI1JPmd?%IR6!L+?oa0r_krLo5dsNDNuzW8n7otB2Fxs> zg{N_-qE?SXRLC&YAjJm`uTbZHTCa;gAs7EDz8_@SjlPBzpuPMB&oJhK3lCEW!*t93vd8^P{65 z_S_VrG-aNPU01x&^?thZ1(X6pzTQA}B_Sb!!=j@+U#*yR1H}D&_FG#ZlljTzStGC2 zY!Q%+JM2t&Opka&WpLdfz!DG>1AL!Guh`MZq@|UW0*Y_%<;}ST;#&~>3!suM_S?v< zhriNW9Cm&;SzZ@_fSxyFG?Z3+JUjp%2veLY;JmZBsRkterZM!4)h34?h_0!rH2{1J zI2F#DL-Q`@=2~;=z_|Ss)zxL;?DBH)$LEGG)~wPov{l8$`)7m|K)SZKu`!$Lh>o}h zsNU0+W+*4boOyBafi?{e+v@oS&ZvBVH3+zTJp%wfi1HajFwg3)c2uQM*##sQ0wvbR zI};B0orU7iOj;0N@W?sN=0CpL7@>smxc=S-AfKB9*RC@^Vly)IAI(%VC*1bxfP_va zSP%Fe2aBGc0FW%I+-|*prr3f`xebe~Yha)V#OX!7WdK%q z_W9HjjpcaGhy7U_PUEvQW#0ke>*1Dq`~A^oaW(pej)2Ht*G{592j-1V&XxmWk6JFb z8m#7qve7cu#8Fi}&qTNG`I^PP6TSXc;#DHxGEqi2o(t+0Ll7`UEfwBXM?^yMMBHmN zNU6QQe`i>@hed~z+`NPxc5SlKY`jRb$^kHOy}d<&cSGT~zJo(`Yb@tysG*FrT`fTT z3JW)c)PjDN7f{<5fzd$FWuR8Im|s~*a9*qMZO5bjP75L*u{V<=e~TT50(`mW^ulsX z4?k}7b6#Wr2|A!iAiP>B)MFnGtp8sG1}aB7E^RypIZdR1H1-XTJ(4%ITJSU25A=*d zOD&Qlt}$>*&mK2wY2ToSzRO$nrk+m6=Nk+e+6=V_7^AvxoplhzU=AtbTQg1SOQOBr z5xaiuqy|t$pnzM_+Oz~??(QB2aJ56HySfMi(v8E-qugX;8NCT;Qx63^m#MxoZ`F<% zf1LrVp+{cRkEk*Lyr+B@qRCRqe}99n(eQBD&pD2eXkO)yn~a(~*Jyz?7}=R9js+bTMwNa?4m3<46>EGBjK|dy zxXMFotmb$ferLO09)PZQ3GZa5Xy$Y%r9tn*hXk(I#woNnlD#`X{{_AdoVbUes52S9 zc3tiEba!9K;}AvRoaJ{sJm2Rg=n$pRsri@{85x<Z2j6iH$S+_5@CuSf;&111)vL&f zW9M{wK|1tKdeuN8Xg#YZtS4xMhtfYWF;TTp6N!3f8Zddme4wZrJnAyAow$OW009cH zo;zi|#10c^A1_#dvX6zIaGX!sMn%f>buQqg@T~EuSsp$<#sr0593T2?t!{@d4;RHX@mOAw0v>uDP*N`WVBq5V^U_;klO9Q!c%*bf zF0XV=O7qnIktrYcZHGmY(l; z{+R_VhCmZ-#-REI22%HQ&CJN^V2A|Y0XUe5`&_wQP0ghtH8r)iJWXhb$I00Y5X$;H zyDZ=|ZF4JAZwZ5P5BcNFkMH`xr|FLm|7K!(8gTEG*FYBg!`*c#Xtx7^sTS@jB`!5y zfGAt?<5l~&hE0pWh<)*%Pg((7x3xD~=3Sp;PB5M%aao}<>@RxOh~{8f#W8EadF)J; zqI^)JxM`M(YzF2mq^FYySsp&3G_0&gpr*(~wi5P01=f&QdLKD(py98mLy)e3%oZ51 zDosa=KKxvyXcz7A|4~9+wm!I;QC?Q-u>T4~=WQXsvzc>9DNo9br*?fw;zFs3-f z>seafUF>UNq5!x#Zpx;YP6_O zqo@>6L}7GDQ6!wWUgTz!SCivNMgVR6ZJ1~_iQe&=9?`q++J)o*u4?-qxGL!OQ%%hM zD1B{8HWQF##0Dfv)+Ez{ychtaqP13Cr4|o*=n>WI4dH;%s@dNfDc4Gh_Y`-%8PMRc zs|Y&!v}N?F`xQN-3gS0r-S2XaS7o9g&d1i)78O16=<*aj60sD7R)UA8SBK-y1lf~} z%rp98`zJwe=fro6&Ca;9U^U+B332{>FeXlM(Kf262p)|1AzzPHz@;n_;O=AE(kytoF<1c-l=mXO zAWqu#jp1fwP=ds6AEM$V*(f%{00t#mFA+G=R^C#D=Aw!U?2?#hMMaV3FU6Ww7a(dm zUnzHI_WSCN%4=?GO$1C$6DGjIqoAauJc4I-y|7e}69l?*Wv6j(Ag3<4c$dd8el^({9ZC=-97%r)v( z3y@fU0_@Hd&~2b+>!icNiB!_e8Wq`j^<#FV%yhJ!4_+Y!Ti5OOg0vAs5A-TwEObJ5 zH=l<$m}lRnv1tj5E+Y@n!3{Z8 z9`Nv{$hM21^44L30kx8A*04v|mI_FEOdm42i@RhllG z#l3p^aiQ`2uIsh#B6sfFlf zaAT3Epjse znSL-?C33&!0J{bt*FYx|5_`Myw4KbJf9N`;;Sx+$fPZxUYBm${joGu~Yz0KzpYhtR zjeyO9*bHE9H2H)=`TXuzu_!JszBxNktd?VduCK4nej778J4+;<{W|H_^tAd?`>N0H z`p=;|lZ8SaC$O?fP%QzM$LAo@*)6u93WSB&T^%Wc7!=@_H;|ez^zVz*?9N5`_Tv3m zS63GZAeE^~-@3<&;BQCVFZrl%)EF6q6qjkLqvB)dUELBU3T9`LFh z&=7!AB|2K>suoIz$Y}9Klm_yhRgyKza(f-O9df_QtXpML{0CJ=)A zrLgel?vxPdjP_=-v;Yd?s~>>fJ$43MxDvwj%4H%Y+Pt8FR{;p$JJ&V?U{nU4>L074e!K*E*b!+*xoK&-AfkhEgV6F8 zG_eHsYe5-1Hs>4}fo~G8q$U|-Ki)g?zy2nNQ36UV0fSDAFqPc5%$;RIO&%>S`}J8_ z9cB8yiCk8{0V^JO@Y4GL=@i^Hqm7bUy@9gB!)Yx}0G@M;_WrqQLAk|cb29Ib=PGIV z@rj9I)Hqh4Sc(UEA((~%2JG}?{2sOgRWa z4ERfkvH|QkSihhf+5@;AXf1f{jMexU)Jg^#>p14Bto)6Ru!)F}{jmyOhHNQe24IuH z^&KY=uvz?K>OW((-yGV1{*{GT7du&v2Npa}IZOso5D`T{sLa*Z{Bd`8cS;$Dg9);r z+4SbfuMqJH@DCAwdBn{^!*Hu#mtiH5fDtSj-IIdax?bSz~27k(Vr@bwCu>|l$tA|xafgl!fP5y54lYONrA!GVGQLc5)F zq0!lOW6yaV+8~)2q}ND{_Dpd{3-0F1SmU3KmWCgd3W{LeSE^lBi4XnM`WqdjJ2V0vn429S>WIEpfu=ifPOQ**`;2uyp+?Qh6qdN$Z{}Au+be zlZ}XBerA)8X2GcnTxcoO!Q5E1r3EB)MS}<=*!k54jq#1O-wBkP?wunM_rcyBhE1VS zT``XzWbE;|Ufh)}8~XV8#5Yn9a2U6P7YInr;#3hOpvls&kHLGmF_F`W9{Rr~6BYNqe;m#lpc9TR-8%vNu#wz5-y*fkFqw{-CKXz4)H`x_DSMBeDPYB%QZFFfIpzt=X1mn|K%A(5>d z^gV12&dJd>Bt?llp{$GHcRb)f1P>zqioWEO!92|A5395zVV)0W@M~+}YwlcDe6t0- zo5KhmLZ4?r(#)$!vSZH{NRfNx#IIjqO3YYRS;-l+YaVmCkb+ZY0t%-0HbvN2=bNFL zNj>R?Jr^Sr0EXw=5#2+}{#4e}*0vwaxu2q@JA7d$WU(G{1|w~oUstz>Pn_EdMk*1~MF$zXpef!!(tt6i$g< zprN4L9_Q+oN17WeqVpKC{)a*EEDqpRzWp|ocYS0K{HbaM3{gkygQ2P6*X~ifOhWLf zq&lYyu3|zm67}e}tL&nJ&Q?kiq%$9PS|MC8B#tEIwngj)$)WLV%e-nJZ0-lbc3rcz zhC#AjH(^KrqzVIr6JE|M@Z|g;UW@fM$hTK&~;mvo*?lCp?Sx*q3mz@#!A`W|l}?Y?`rROFj#Qp@Q90w9{T zmPkrU=BM}R{St;e0C;IUv;9ZIyr%J@^y%76#?3bedcyO5OuvwyeAQ_}W&T?{p8B#V<;e-Y9PcIqPydqCewVfpzCtcoqDXOsO=7n{4-E)u9VTx z(Wiuv?pNhoM5)0&!iP3aNA9__zhC9ik;7~EAg%@$bNruo>{q+PSxL_HI5;Ziz-l;f zogLZSjynvIxkaam&*_7~2w#=OBdaY^*qEr&$M|k=N_VnU*BXopvFVxu@pDC=M2xPX z18RB&*_Tr_T@QFcby|^ZH=$EqiNY1Wf@a9F$>N1a^L~98$+?)`(ld%kz5Tf=kliS3 zyB2S`ySBz-Hs%M}7#h~6U|-M)5hgMv|NLhbpy6jdRvS%{iRhY0^ylsJ zECpI;3@QEoU-$T*lF8{CVN}ZyBiXDk)w`g1OtxyqA%X(fbP9j`pQ+!chD52xVthhj zL|>uec*0WTD*OGdUx0Yci03`6lwLytM2uF0j_#M$>Mx?XY{8n2@m%muPcrz^>V>A zhJr=(mDp@D@2QTH%^l#!VGt8{(wL^%J){H{AfStZIdSfrq6f2( zAPeq?SpeWGpKzi-P8%LUB8WDRR!n9NN^x_t9Jy@PW+A!0-ch3DdyxJM

aF~{Qd@vU2I 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 ySXfwi%J=W-oq!Vsuuf0K|?#`V&_Puw1&hGS9 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 C#@Ltu literal 0 HcmV?d00001 diff --git a/public/app.js b/public/app.js index ea7b7889..fdca2f32 100644 --- a/public/app.js +++ b/public/app.js @@ -1635,6 +1635,7 @@ class App { } async loadUserData() { + const requestId = this._dataRequestId = (this._dataRequestId || 0) + 1; const username = document.getElementById('data-user-select')?.value; const statsContainer = document.getElementById('data-stats'); const contentContainer = document.getElementById('data-content'); @@ -1650,6 +1651,8 @@ class App { try { const data = await this.request(`/api/data?user=${encodeURIComponent(username)}`); + if (this._dataRequestId !== requestId || document.getElementById('data-user-select')?.value !== username) return; + if (this.currentUserData?.username !== username) this._dislikeFilters = {}, this._ratingFilters = {}; this.currentUserData = { username, data }; // 统计数据 @@ -1710,6 +1713,12 @@ class App {

`; + const dislikeCount = this.getDislikeEntries(data).length; + statsContainer.insertAdjacentHTML('beforeend', `

不喜欢

⊘
${dislikeCount}
`); + const ratingBadge = document.getElementById('tab-count-ratings'); + if (ratingBadge) ratingBadge.textContent = (data.ratingItems || []).length; + const dislikeBadge = document.getElementById('tab-count-dislikes'); + if (dislikeBadge) dislikeBadge.textContent = dislikeCount; // 更新 Tabs 徽章与显示状态 const tabsContainer = document.getElementById('data-tabs-container'); if (tabsContainer) { @@ -1737,6 +1746,9 @@ class App { }, 400); } catch (err) { + if (this._dataRequestId !== requestId) return; + statsContainer.classList.remove('content-loading'); + contentContainer.classList.remove('content-loading'); contentContainer.innerHTML = '

加载数据失败

'; } finally { applyMarqueeChecks(); @@ -1792,10 +1804,337 @@ class App { html += this.getArtistsSectionHtml(data.artists || [], tab === 'all'); } + if (tab === 'all' || tab === 'ratings') html += this.getRatingSectionHtml(data); + if (tab === 'all' || tab === 'dislikes') html += this.getDislikeSectionHtml(data); contentContainer.innerHTML = html; + this.initCustomSelects(); applyMarqueeChecks(); } + dislikeOriginLabel(channel) { + return ({ web: 'Web 添加', 'subsonic-rating': 'Subsonic 低分联动', 'web-rating-link': 'Web 低分联动', 'manual-rating-to-dislike': '手动评分联动', 'snapshot-restore': '评分恢复', unknown: '来源未记录' })[channel] || (channel ? `其他:${channel}` : '来源未记录'); + } + + adminPlatformOptions(items, selected, allLabel) { + const e = value => this.escapeHtml(String(value)); + const platforms = [...new Set(['wy', 'tx', 'kw', 'kg', 'mg', 'local', ...items.map(x => x.source || '*')])].filter(source => source !== 'bd'); + const label = code => code === 'local' ? '本地音乐' : code === '*' ? '未指定平台' : this.getSourceLabel(code); + return `` + platforms.map(code => ``).join(''); + } + + adminExtraFilters(section, filters) { + const handler = section === 'rating' ? 'filterRatingData' : 'filterDislikeData'; + const select = (key, label, options) => ``; + return `
+ ${select('cover','封面资料',[['','全部封面状态'],['yes','有封面'],['no','缺少封面']])} + ${select('period','记录时间',[['','不限时间'],['7','最近7天'],['30','最近30天'],['90','最近90天'],['unknown','未记录时间']])} + ${select('pageSize','每页条数',[['','默认条数'],['24','24条'],['48','48条'],['96','96条']])} + + +
`; + } + + adminMatchesExtra(filters, cover, time, text) { + if (filters.cover && (filters.cover === 'yes') !== !!cover) return false; + if (filters.period === 'unknown' ? !!time : filters.period && (!time || time < Date.now() - Number(filters.period) * 86400000)) return false; + const terms = String(filters.query || '').normalize('NFKC').trim().toLowerCase().split(/\s+/).filter(Boolean); + const haystack = String(text).normalize('NFKC').toLowerCase(); + return terms.every(term => haystack.includes(term)); + } + + adminPageSize(filters, fallback) { + const value = Number(filters.pageSize); + return [24,48,96].includes(value) ? value : fallback; + } + + exportAdminRecords(section) { + const data = this.currentUserData?.data || {}; + const rows = section === 'rating' ? this.getFilteredRatingRows(data.ratingItems || []) : this.getFilteredDislikeRows(this.getDislikeEntries(data)).map(({ x, r }) => ({ kind: x.kind, name: x.title, singer: x.singer, source: x.source, rule: x.rule, rating: r.rating, provenance: x.raw.provenance, reasons: x.raw.reasons })); + const url = URL.createObjectURL(new Blob([JSON.stringify({ user: this.currentUserData?.username, exportedAt: new Date().toISOString(), count: rows.length, records: rows }, null, 2)], { type: 'application/json' })); + const link = document.createElement('a'); link.href = url; link.download = section === 'rating' ? 'filtered-ratings.json' : 'filtered-dislikes.json'; link.click(); + setTimeout(() => URL.revokeObjectURL(url), 1000); + } + + resetAdminFilters(section) { + const rating = section === 'rating'; + if (rating) this._ratingFilters = {}; + else this._dislikeFilters = { view: this._dislikeFilters?.view }; + const node = document.querySelector(rating ? '.admin-ratings' : '.admin-dislikes:not(.admin-ratings)'); + if (node) node.outerHTML = rating ? this.getRatingSectionHtml(this.currentUserData?.data || {}) : this.getDislikeSectionHtml(this.currentUserData?.data || {}); + this.initCustomSelects(); + } + + getDislikeEntries(data) { + const entries = new Map(); + const add = (raw, kind, library = false) => { + const rule = String(raw.dislikeRule || ''); + const split = rule.lastIndexOf('@'); + const title = raw.name || raw.albumName || (kind === 'album' ? rule.slice(1, split < 0 ? undefined : split) : kind === 'artist' ? raw.singer || rule.slice(1) : rule.slice(0, split < 0 ? undefined : split)) || '未命名规则'; + const singer = raw.singer || raw.artistName || (split >= 0 ? rule.slice(split + 1) : ''); + const source = raw.source || ''; + const key = `${kind}|${source}|${rule || (kind === 'album' ? `!${title}@${singer}` : kind === 'artist' ? `@${title}` : `${title}@${singer}`)}`.normalize('NFKC').toLowerCase().replace(/\s*([()@])\s*/g, '$1'); + const image = raw.img || raw.pic || raw.picUrl || raw.cover || raw.meta?.picUrl || ''; + const cover = typeof image === 'string' && (/^https?:\/\//i.test(image) || /^\/(?!\/)/.test(image)) ? image : ''; + const item = { kind, title, singer, source, cover, rule, raw, library, channel: raw.provenance?.channel || 'unknown' }; + if (!entries.has(key)) entries.set(key, item); + else { const prior = entries.get(key); if (!prior.cover) prior.cover = cover; prior.libraryData = raw; } + }; + for (const row of data.dislikeList || []) { + const rule = String(row.dislikeRule || ''); + add(row, rule.startsWith('!') ? 'album' : rule.startsWith('@') || (!row.name && row.singer) ? 'artist' : 'song'); + } + for (const row of data.dislikeAlbums || []) add(row, 'album', true); + for (const row of data.dislikeArtists || []) add(row, 'artist', true); + return [...entries.values()]; + } + + getDislikeRating(x, data) { + const raw = x.raw; + const id = raw.id || raw.songmid || raw.meta?.songId || ''; + const keys = [id, `${x.source}_${id}`, x.kind === 'album' ? `alb_${x.source}_${raw.albumId || id}` : x.kind === 'artist' ? `art_${x.source}_${id}` : '']; + const key = keys.find(k => k && Object.hasOwn(data.userRatings || {}, k)); + return { id, key, rating: key ? Number(data.userRatings[key]) : null }; + } + + starsHtml(value, size = '') { + const v = Math.max(0, Math.min(5, Number(value) || 0)); + return `★★★★★`; + } + + getDislikeSectionHtml(data) { + const items = this.getDislikeEntries(data); + const e = value => this.escapeHtml(String(value ?? '')); + const f = this._dislikeFilters || {}; + const option = (value, text, key) => ``; + const channels = [...new Set(['web','web-rating-link','subsonic-rating','manual-rating-to-dislike','unknown', ...items.flatMap(x => [x.channel, ...(x.raw.reasons || []).map(r => r.channel)])])].sort(); + return `
+
⊘

不喜欢

歌曲、歌手与专辑规则 · Web 与 Subsonic 联动数据

${items.length} 条
+
${this.getDislikeStatsHtml(items)}
+
+ + + + + +
+
+ ${this.adminExtraFilters('dislike', f)} +

平台标注总条数;来源筛选包含同一条规则的全部添加原因。多个关键词需同时匹配。添加来源与音乐平台分别记录。缺少来源记录的条目显示“来源未记录”;展开详情可查看所有已保存字段。评分只表示关联记录,不代表整张专辑或歌手的歌曲都被评分。

+
${this.getDislikeResultsHtml(items)}
+
`; + } + + getDislikeStatsHtml(items) { + const data = this.currentUserData?.data || {}; + const f = this._dislikeFilters || {}; + items = this.getFilteredDislikeRows(items, { ...f, kind: '' }).map(row => row.x); + const count = k => items.filter(x => x.kind === k).length; + const rated = items.filter(x => this.getDislikeRating(x, data).rating != null).length; + const linked = items.filter(x => [x.raw.provenance, ...(x.raw.reasons || [])].some(reason => reason && /rating/.test(reason.channel))).length; + const chip = (kind, label, n, icon) => ``; + return `
${chip('', '全部', items.length, '⊘')}${chip('song', '歌曲', count('song'), '♪')}${chip('artist', '歌手', count('artist'), '♙')}${chip('album', '专辑', count('album'), '◎')}
★${rated}已评分
⇄${linked}评分联动
`; + } + + refreshDislikeStats() { + const node = document.getElementById('admin-dislike-stats'); + if (node) node.innerHTML = this.getDislikeStatsHtml(this.getDislikeEntries(this.currentUserData?.data || {})); + } + + refreshDislikeToggle() { + const f = this._dislikeFilters || {}; + document.querySelectorAll('.admin-view-toggle button').forEach((b, i) => b.classList.toggle('on', (i === 1) === (f.view !== 'grid'))); + } + + filterDislikeData(key, value) { + this._dislikeFilters = { ...(this._dislikeFilters || {}), [key]: value, page: 0 }; + const node = document.getElementById('admin-dislike-results'); + if (node) node.innerHTML = this.getDislikeResultsHtml(this.getDislikeEntries(this.currentUserData?.data || {})); + this.refreshDislikeStats(); + } + + dislikePage(delta) { + this._dislikeFilters = { ...(this._dislikeFilters || {}), page: Math.max(0, (this._dislikeFilters?.page || 0) + delta) }; + const node = document.getElementById('admin-dislike-results'); + if (node) { node.innerHTML = this.getDislikeResultsHtml(this.getDislikeEntries(this.currentUserData?.data || {})); node.scrollIntoView({ block: 'start', behavior: 'smooth' }); } + } + + getFilteredDislikeRows(items, f = this._dislikeFilters || {}) { + const data = this.currentUserData?.data || {}; + const withRating = items.map(x => ({ x, r: this.getDislikeRating(x, data) })); + const matchRating = r => !f.rating || (f.rating === 'rated' ? r.rating != null : f.rating === 'none' ? r.rating == null : f.rating === 'low' ? r.rating != null && r.rating <= 2 : f.rating === 'high' ? r.rating >= 4 : r.rating === Number(f.rating)); + return withRating.filter(({ x, r }) => (!f.kind || f.kind === x.kind) && (!f.channel || f.channel === x.channel || (x.raw.reasons || []).some(reason => reason.channel === f.channel)) && (!f.source || f.source === (x.source || '*')) && matchRating(r) && this.adminMatchesExtra(f, x.cover, x.raw.provenance?.at, JSON.stringify([x.title, x.singer, x.rule, x.source, x.raw.id, x.raw.songmid, x.raw.meta]))); + } + + getDislikeResultsHtml(items) { + const e = value => this.escapeHtml(String(value ?? '')); + const f = this._dislikeFilters || {}; + const data = this.currentUserData?.data || {}; + let selected = this.getFilteredDislikeRows(items, f); + if (f.sort === 'name') selected = [...selected].sort((a, b) => a.x.title.localeCompare(b.x.title, 'zh')); + else if (f.sort === 'rating') selected = [...selected].sort((a, b) => (b.r.rating ?? -1) - (a.r.rating ?? -1)); + else if (f.sort === 'time') selected = [...selected].sort((a, b) => (b.x.raw.provenance?.at || 0) - (a.x.raw.provenance?.at || 0)); + if (!selected.length) return '
⊘
暂无符合条件的不喜欢记录
'; + const PAGE = this.adminPageSize(f, 24), pages = Math.ceil(selected.length / PAGE); + const page = Math.min(f.page || 0, pages - 1); + this.resetAdminDetails(); + const cards = selected.slice(page * PAGE, page * PAGE + PAGE).map(({ x, r }) => { + const raw = x.raw, { id, key: ratingKey, rating } = r; + const fields = { '歌手': x.singer, '规则': x.rule, '音乐来源': x.source ? this.getSourceLabel(x.source) : '未指定(通用)', '对象 ID': id, '歌曲标识': raw.songmid, '专辑': raw.albumName || raw.meta?.albumName, '专辑 ID': raw.albumId || raw.meta?.albumId, '时长': raw.interval, '评分': rating == null ? '' : `${rating} 星`, '添加来源': this.dislikeOriginLabel(x.channel), '全部添加原因': (raw.reasons || [raw.provenance]).filter(Boolean).map(reason => this.dislikeOriginLabel(reason.channel) + (reason.ratingId ? `(${reason.ratingId})` : '')).join('、'), '添加时间': raw.provenance?.at ? new Date(raw.provenance.at).toLocaleString() : '', '补全来源': raw.enrichedBy ? this.dislikeOriginLabel(raw.enrichedBy.channel) : '', '补全时间': raw.enrichedBy?.at ? new Date(raw.enrichedBy.at).toLocaleString() : '', '音质': Array.isArray(raw.types) ? raw.types.map(q => `${q.type}${q.size ? ` (${q.size})` : ''}`).join('、') : '' }; + const image = x.cover ? `
${e(x.title)}封面` : ``; + const full = JSON.stringify({ ...raw, ...(x.libraryData ? { libraryData: x.libraryData } : {}), ...(ratingKey ? { linkedRating: { id: ratingKey, value: rating, origin: data.ratingOrigins?.[ratingKey] || null } } : {}) }, null, 2); + const when = raw.provenance?.at ? new Date(raw.provenance.at).toLocaleDateString() : ''; + const g = keys => keys.map(k => [k, fields[k]]); + const token = this.registerAdminDetail({ title: x.title, subtitle: [x.singer, raw.albumName || raw.meta?.albumName].filter(Boolean).join(' · '), cover: x.cover, icon: x.kind === 'song' ? '♪' : x.kind === 'album' ? '◎' : '♙', rating, raw: { ...raw, ...(x.libraryData ? { libraryData: x.libraryData } : {}), ...(ratingKey ? { linkedRating: { id: ratingKey, value: rating, origin: data.ratingOrigins?.[ratingKey] || null } } : {}) }, badges: [({ song: '歌曲', artist: '歌手', album: '专辑' })[x.kind], x.source ? this.getSourceLabel(x.source) : '通用规则', this.dislikeOriginLabel(x.channel)], sections: [{ title: '基本信息', fields: g(['歌手', '专辑', '时长', '音乐来源']) }, { title: '评分关联', fields: [['评分', fields['评分']], ['评分 ID', ratingKey || '']] }, { title: '添加记录', fields: g(['规则', '添加来源', '全部添加原因', '添加时间', '补全来源', '补全时间']) }, { title: '标识', fields: g(['对象 ID', '歌曲标识', '专辑 ID']) }, { title: '可用音质', fields: [['音质', Array.isArray(raw.types) ? raw.types.map(q => q.type + (q.size ? ' · ' + q.size : '')) : []]] }] }); + return `
${image}

${e(x.title)}

${e([x.singer || '未记录歌手', raw.albumName || raw.meta?.albumName].filter(Boolean).join(' · '))}

${e(({ song: '歌曲', artist: '歌手', album: '专辑' })[x.kind])}${e(this.dislikeOriginLabel(x.channel))}${e(x.source ? this.getSourceLabel(x.source) : '通用规则')}
${rating == null ? '未评分' : `${this.starsHtml(rating)}${e(rating)}`}
${e(when || '时间未记录')}
`; + }).join(''); + return `
共 ${selected.length} 条(总计 ${items.length} 条) · 第 ${page + 1} / ${pages} 页
${cards}
`; + } + + ratingOriginLabel(origin) { + if (!origin?.channel) return '来源未记录'; + return ({ web: 'Web 手动评分', subsonic: 'Subsonic 手动评分', 'web-dislike-link': '不喜欢自动补分', 'manual-dislike-to-rating': '后台补分', 'web-rating-link': 'Web 低分联动', 'subsonic-rating': 'Subsonic 低分联动', 'manual-rating-to-dislike': '后台低分补不喜欢', 'snapshot-restore': '评分恢复', unknown: '来源未记录' })[origin.channel] || '其他来源(未识别)'; + } + + async retryAdminRatingSync() { + if (this._ratingRetryBusy) return; + const user=this.currentUserData?.username;if(!user)return; + this._ratingRetryBusy=true; + try {const result=await this.request(`/api/data/rating-sync?user=${encodeURIComponent(user)}`,{method:'POST'});if(result.pending?.length)showInfo(`重试完成,仍有 ${result.pending.length} 项待处理`);else showSuccess('失败项已处理');if(this.currentUserData?.username===user)await this.loadUserData()} + catch(error){showError('重试失败:'+error.message)}finally{this._ratingRetryBusy=false} + } + + getRatingSectionHtml(data) { + const items = data.ratingItems || []; + const e = v => this.escapeHtml(String(v ?? '')); + const f = this._ratingFilters || {}; + const opt = (v, t, k) => ``; + const origins = ['web', 'subsonic', 'web-dislike-link', 'manual-dislike-to-rating']; + return `
+
★

评分

歌曲、专辑、歌手评分 · 含封面、平台与评分来源

${items.length} 条
+ ${(data.ratingSyncPending || []).length ? `
同步待处理 ${(data.ratingSyncPending || []).length} 项${data.ratingSyncPending.map(task => `

${e(task.id || '评分快照')}:${e(task.message)}

`).join('')}
` : ''} +
${this.getRatingStatsHtml(items)}
+
+ + + + + +
+ ${this.adminExtraFilters('rating', f)} +

平台标注该用户的总条数,0条也可筛选。多个关键词以空格分隔,需同时匹配;音乐平台与评分操作来源分别筛选。

+
${this.getRatingResultsHtml(items)}
+
`; + } + + getRatingStatsHtml(items) { + const f = this._ratingFilters || {}; + const total = items.length, dormant = items.filter(x => x.dormant).length; + const selected = this.getFilteredRatingRows(items).length; + items = this.getFilteredRatingRows(items, { ...f, kind: '', stars: '' }); + const n = k => items.filter(x => x.kind === k).length; + const avg = items.length ? (items.reduce((a, x) => a + x.rating, 0) / items.length).toFixed(2) : '–'; + const cell = (k, label, v) => ``; + const dist = [5, 4, 3, 2, 1].map(s => { const c = items.filter(x => x.rating === s).length; return ``; }).join(''); + return `
${cell('', '全部', items.length)}${cell('song', '歌曲', n('song'))}${cell('album', '专辑', n('album'))}${cell('artist', '歌手', n('artist'))}
${avg}平均分
评分分布 · 点击筛选 / 再次点击取消
${dist}
${avg}平均评分

当前匹配 ${selected} / ${total} 条

`; + } + + refreshRatingStats() { + const node = document.getElementById('admin-rating-stats'); + if (node) node.innerHTML = this.getRatingStatsHtml(this.currentUserData?.data?.ratingItems || []); + } + + filterRatingData(key, value) { + this._ratingFilters = { ...(this._ratingFilters || {}), [key]: value, page: 0 }; + const node = document.getElementById('admin-rating-results'); + if (node) node.innerHTML = this.getRatingResultsHtml(this.currentUserData?.data?.ratingItems || []); + this.refreshRatingStats(); + const stars = document.querySelector('.admin-ratings select[aria-label="星级"]'); + if (stars && key === 'stars') { stars.value = value; this.syncCustomSelects(); } + } + + ratingPage(delta) { + this._ratingFilters = { ...(this._ratingFilters || {}), page: Math.max(0, (this._ratingFilters?.page || 0) + delta) }; + const node = document.getElementById('admin-rating-results'); + if (node) { node.innerHTML = this.getRatingResultsHtml(this.currentUserData?.data?.ratingItems || []); node.scrollIntoView({ block: 'start' }); } + } + + getFilteredRatingRows(items, f = this._ratingFilters || {}) { + return items.filter(x => (!f.kind || x.kind === f.kind) && (!f.source || (x.source || '*') === f.source) && (!f.origin || (x.origin?.channel || '*') === f.origin) && (!f.stars || (f.stars === 'low' ? x.rating <= 2 : f.stars === 'high' ? x.rating >= 4 : x.rating === Number(f.stars))) && this.adminMatchesExtra(f, x.img, x.origin?.at, `${x.name} ${x.singer} ${x.albumName} ${x.id} ${x.effectiveId || ''} ${x.source || ''}`)); + } + + getRatingResultsHtml(items) { + const e = v => this.escapeHtml(String(v ?? '')); + const f = this._ratingFilters || {}; + let rows = this.getFilteredRatingRows(items, f); + rows = [...rows].sort((a, b) => f.sort === 'low' ? a.rating - b.rating : f.sort === 'time' ? (b.origin?.at || 0) - (a.origin?.at || 0) : f.sort === 'oldest' ? (a.origin?.at || 0) - (b.origin?.at || 0) : f.sort === 'singer' ? String(a.singer).localeCompare(String(b.singer), 'zh') : f.sort === 'source' ? String(a.source).localeCompare(String(b.source)) : f.sort === 'name' ? String(a.name).localeCompare(String(b.name), 'zh') : b.rating - a.rating); + if (!rows.length) return '
暂无符合条件的评分
'; + const PAGE = this.adminPageSize(f, 30), pages = Math.ceil(rows.length / PAGE), page = Math.min(f.page || 0, pages - 1); + const kindName = { song: '歌曲', album: '专辑', artist: '歌手' }; + this.resetAdminDetails(); + const body = rows.slice(page * PAGE, page * PAGE + PAGE).map(x => { + const cover = x.img ? `` : ''; + const sub = [x.singer, x.albumName].filter(Boolean).join(' · '); + const at = x.origin?.at ? new Date(x.origin.at).toLocaleString() : ''; + const token = this.registerAdminDetail({ title: x.name, subtitle: sub, cover: x.img, icon: x.kind === 'song' ? '♪' : x.kind === 'album' ? '◎' : '♙', rating: x.rating, raw: x, badges: [kindName[x.kind], x.source === 'local' ? '本地' : x.source ? this.getSourceLabel(x.source) : '未知平台'], sections: [{ title: '基本信息', fields: [['歌手', x.singer], ['专辑', x.albumName], ['时长', x.interval], ['音乐平台', x.source === 'local' ? '本地' : x.source ? this.getSourceLabel(x.source) : '']] }, { title: '评分记录', fields: [['评分来源', this.ratingOriginLabel(x.origin)], ['评分时间', at]] }, { title: '标识', fields: [['评分 ID', x.id], ['当前使用 ID', x.dormant ? x.effectiveId : '']] }] }); + return `
${cover}${x.kind === 'song' ? '♪' : x.kind === 'album' ? '◎' : '♙'}
${e(x.name)}
${e(sub || '—')}
${e(kindName[x.kind])}${e(x.source === 'local' ? '本地' : x.source ? this.getSourceLabel(x.source) : '未知平台')}${e(this.ratingOriginLabel(x.origin))}
${this.starsHtml(x.rating)}${e(at)}
`; + }).join(''); + return `
共 ${rows.length} 条(总计 ${items.length} 条) · 第 ${page + 1} / ${pages} 页
${body}
`; + } + + registerAdminDetail(model) { + this._adminDetails = this._adminDetails || new Map(); + const token = `d${this._adminSeq = (this._adminSeq || 0) + 1}`; + this._adminDetails.set(token, model); + return token; + } + + /** 解析/渲染后清空旧登记,避免翻页后令牌无限增长 */ + resetAdminDetails() { if ((this._adminDetails?.size || 0) > 5000) this._adminDetails = new Map(); } + + closeAdminDetail() { + const el = document.getElementById('admin-detail-modal'); + if (!el) return; + el.classList.add('closing'); + document.removeEventListener('keydown', this._adminDetailKey); + setTimeout(() => el.remove(), 160); + } + + openAdminDetail(token) { + const m = this._adminDetails?.get(token); + if (!m) return; + this.closeAdminDetail(); + document.getElementById('admin-detail-modal')?.remove(); + const e = v => this.escapeHtml(String(v ?? '')); + const cell = ([k, v]) => { + const copy = /ID|标识/.test(k) ? `` : ''; + const val = Array.isArray(v) ? `
${v.map(x => `${e(x)}`).join('')}
` : `${e(v)}`; + return `
${e(k)}
${val}${copy}
`; + }; + const sections = m.sections.map(s => ({ ...s, fields: s.fields.filter(([, v]) => v !== '' && v != null && !(Array.isArray(v) && !v.length)) })).filter(s => s.fields.length) + .map(s => `
${e(s.title)}
${s.fields.map(cell).join('')}
`).join(''); + const cover = m.cover ? `` : `
${m.icon || '♪'}
`; + const wrap = document.createElement('div'); + wrap.id = 'admin-detail-modal'; + wrap.className = 'adm-overlay'; + wrap.innerHTML = ``; + document.body.appendChild(wrap); + const close = () => this.closeAdminDetail(); + wrap.addEventListener('click', ev => { + if (ev.target === wrap || ev.target.closest('.adm-x')) return close(); + const c = ev.target.closest('.adm-copy'); + if (c) { navigator.clipboard?.writeText(c.dataset.copy); c.textContent = '已复制'; setTimeout(() => c.textContent = '复制', 1200); } + if (ev.target.closest('.adm-copy-json')) { navigator.clipboard?.writeText(JSON.stringify(m.raw, null, 2)); const b = ev.target.closest('.adm-copy-json'); b.textContent = '已复制'; setTimeout(() => b.textContent = '复制 JSON', 1200); } + }); + this._adminDetailKey = ev => { if (ev.key === 'Escape') close(); }; + document.addEventListener('keydown', this._adminDetailKey); + wrap.querySelector('.adm-panel').focus(); + } + getPlaylistsSectionHtml(userList, isAllTab) { const count = userList.length; let html = ` @@ -3367,9 +3706,6 @@ class App { if (form.elements['subsonic.linkRatingToDislike']) { form.elements['subsonic.linkRatingToDislike'].checked = config['subsonic.linkRatingToDislike'] === true; } - if (form.elements['subsonic.linkDislikeToRating']) { - form.elements['subsonic.linkDislikeToRating'].checked = config['subsonic.linkDislikeToRating'] === true; - } // 音质 / 源优选 if (form.elements['subsonic.quality.enabled']) { @@ -3438,7 +3774,6 @@ class App { 'subsonic.dislikeRequireSinger': formData.get('subsonic.dislikeRequireSinger') === 'on', 'subsonic.ratingPlaylists': formData.get('subsonic.ratingPlaylists') === 'on', 'subsonic.linkRatingToDislike': formData.get('subsonic.linkRatingToDislike') === 'on', - 'subsonic.linkDislikeToRating': formData.get('subsonic.linkDislikeToRating') === 'on', 'subsonic.quality.enabled': formData.get('subsonic.quality.enabled') === 'on', 'subsonic.quality.priority': (formData.get('subsonic.quality.priority') || '').trim() || 'flac,320k,128k', @@ -3469,10 +3804,12 @@ class App { body: JSON.stringify(config) }); this.loadedSubsonicConfig = Object.assign({}, this.loadedSubsonicConfig || {}, config); + this.updateLinkSyncUI(); if (res.warning) { showInfo('Subsonic 配置保存成功!\n\n⚠️ 警告:' + res.warning); } else { - showSuccess('Subsonic 配置保存成功!'); + const linkChanged = ['subsonic.dislikeRating', 'subsonic.linkRatingToDislike'].some(k => config[k] !== prevConfig[k]); + showSuccess('Subsonic 配置保存成功!' + (linkChanged ? '\n联动配置对后续操作生效,历史评分和不喜欢不会自动重算或删除。' : '')); } if (needRestart) { const ok = await showSelect( @@ -3507,7 +3844,7 @@ class App { if (this._linkSyncBound) return; const form = document.getElementById('subsonic-form'); if (!form) return; - ['subsonic.linkRatingToDislike', 'subsonic.linkDislikeToRating'].forEach(key => { + ['subsonic.linkRatingToDislike', 'subsonic.dislikeRating'].forEach(key => { const el = form.elements[key]; if (el) el.addEventListener('change', () => this.updateLinkSyncUI()); }); @@ -3518,11 +3855,22 @@ class App { const form = document.getElementById('subsonic-form'); [ ['subsonic.linkRatingToDislike', 'sync-rating-to-dislike-btn'], - ['subsonic.linkDislikeToRating', 'sync-dislike-to-rating-btn'], + ['subsonic.linkRatingToDislike', 'reconcile-rating-btn'], ].forEach(([key, btnId]) => { const btn = document.getElementById(btnId); - if (btn) btn.classList.toggle('hidden', !form?.elements[key]?.checked); + if (btn) { + btn.classList.remove('hidden'); + const saved = this.loadedSubsonicConfig || {}; + btn.disabled = !form?.elements[key]?.checked || saved[key] !== true || Number(saved['subsonic.dislikeRating'] ?? 1) <= 0; + btn.title = btn.disabled ? '请先开启并保存低分联动开关,且阈值大于 0' : btnId === 'reconcile-rating-btn' ? '先预览,再撤销失效评分原因;保留手动及其他有效原因' : '先预览,再补齐缺失的不喜欢规则'; + } }); + const manualButton = document.getElementById('sync-dislike-to-rating-btn'); + if (manualButton) { manualButton.classList.remove('hidden'); manualButton.disabled = this._linkSyncBusy === true; manualButton.title = '管理员预览并批量补1星,只补未评分歌曲;不依赖自动开关或阈值'; } + const saved = this.loadedSubsonicConfig || {}; + const threshold = Number(saved['subsonic.dislikeRating'] ?? 1); + const status = document.getElementById('subsonic-link-saved-status'); + if (status) status.textContent = '已保存:' + (threshold <= 0 ? '低分联动已暂停(阈值为 0);用户自动补分及后台补分不受影响' : `低分阈值 ${threshold} 星;低分补不喜欢${saved['subsonic.linkRatingToDislike'] ? '开启' : '关闭'};不喜欢自动补分由各用户独立设置`) + '。更改配置不会重算历史数据。'; } async loadLinkSyncUsers() { @@ -3550,17 +3898,17 @@ class App { } } - async syncLink(direction) { + async syncLink(direction, reconcile = false) { if (this._linkSyncBusy) return; const isRatingToDislike = direction === 'ratingToDislike'; - const key = isRatingToDislike ? 'subsonic.linkRatingToDislike' : 'subsonic.linkDislikeToRating'; - const label = isRatingToDislike ? '评星 → 不喜欢' : '不喜欢 → 评星'; - const btn = document.getElementById(isRatingToDislike ? 'sync-rating-to-dislike-btn' : 'sync-dislike-to-rating-btn'); + const key = 'subsonic.linkRatingToDislike'; + const label = reconcile ? '按当前阈值重算' : isRatingToDislike ? '低分补不喜欢' : '后台补分'; + const btn = document.getElementById(reconcile ? 'reconcile-rating-btn' : isRatingToDislike ? 'sync-rating-to-dislike-btn' : 'sync-dislike-to-rating-btn'); const form = document.getElementById('subsonic-form'); // 开关以服务端已保存的配置为准,避免「表单勾了但没保存」时后端拒绝 const checked = !!form?.elements[key]?.checked; const saved = (this.loadedSubsonicConfig || {})[key] === true; - if (!checked || !saved) { + if (isRatingToDislike && (!checked || !saved)) { showError(`请先开启「${label} 自动联动」并保存配置,再执行同步。`); return; } @@ -3569,8 +3917,13 @@ class App { showError('请先选择联动同步目标用户'); return; } + let preview; + try { + preview = await this.request('/api/subsonic/sync-link', { method: 'POST', body: JSON.stringify({ user, direction, preview: true, reconcile }) }); + } catch (err) { showError('同步预览失败: ' + err.message); return; } + const sample = (preview.candidates || []).slice(0, 20).map(x => `${x.name || x.id} [${x.source || '?'}]`).join('\n'); const confirmed = await showSelect('手动联动同步', - `将对用户 ${this.escapeHtml(user)} 执行「${label}」补数据:只补目标侧缺失的数据,不覆盖已有数据,也不会改动导入 / 回滚逻辑。\n\n确定继续吗?`, + `扫描范围包含用户歌单、本地曲目及在线缓存。待新增 ${preview.candidates?.length || 0} 项;已有评分 ${preview.existing?.length || 0} 项;重复关联 ${preview.duplicates?.length || 0} 项;解析失败 ${preview.failures?.length || 0} 项(最多显示20项):\n${this.escapeHtml(sample)}\n\n将对用户 ${this.escapeHtml(user)} 执行「${label}」补数据:${reconcile ? `将撤销 ${preview.removedReasons || 0} 个失效评分原因,移除 ${preview.removedRules || 0} 条无其他原因的规则;保留手动及来源不明规则,并补齐当前低分。` : '只补目标侧缺失的数据,不覆盖已有数据,也不会改动导入 / 回滚逻辑。'}\n\n确定继续吗?`, { confirmText: '开始同步', cancelText: '取消' }); if (!confirmed) return; @@ -3580,22 +3933,23 @@ class App { try { const res = await this.request('/api/subsonic/sync-link', { method: 'POST', - body: JSON.stringify({ user, direction }) + body: JSON.stringify({ user, direction, reconcile, preview: false }) }); - const text = `同步完成(${label} · 用户 ${user}):扫描 ${res.scanned} 条,新增 ${res.added} 条,已存在 ${res.skipped} 条` + + const text = `同步完成(${label} · 用户 ${user}):扫描 ${res.scanned} 条,新增 ${res.added} 条,补全 ${res.updated || 0} 条,已存在 ${res.skipped} 条` + (res.failed ? `,失败 ${res.failed} 条` : '') + - (res.batches > 1 ? `,分 ${res.batches} 批处理(全量)` : '') + '。'; + (res.batches > 1 ? `,分 ${res.batches} 批处理(全量)` : '') + (reconcile ? `,撤销原因 ${res.removedReasons || 0} 个、删除规则 ${res.removedRules || 0} 条` : '') + '。'; const box = document.getElementById('link-sync-result'); if (box) { box.textContent = text; box.classList.remove('hidden'); } - showSuccess(text); + if (res.warning) showInfo(text + '\n' + res.warning); else showSuccess(text); } catch (err) { showError('同步失败: ' + err.message); } finally { this._linkSyncBusy = false; - if (btn) { btn.disabled = false; btn.textContent = oldText || '同步'; } + if (btn) btn.textContent = oldText || '同步'; + this.updateLinkSyncUI(); } } @@ -3604,7 +3958,7 @@ class App { // 用服务端已保存的配置校验开关,只提供手动操作入口,绝不自动执行联动 const config = await this.request('/api/config'); const ratingToDislike = config['subsonic.linkRatingToDislike'] === true; - const dislikeToRating = config['subsonic.linkDislikeToRating'] === true; + const dislikeToRating = true; const threshold = Number(config['subsonic.dislikeRating'] ?? 1); if ((!ratingToDislike && !dislikeToRating) || !(threshold > 0)) return; const dirs = [ratingToDislike ? '评星 → 不喜欢' : '', dislikeToRating ? '不喜欢 → 评星' : ''] @@ -6735,7 +7089,7 @@ class App { return; } - if (!(await showSelect('回滚快照', '警告:此操作将把服务器数据回滚到选定的快照状态!\n\n1. 当前所有未保存的更改将丢失。\n2. 所有客户端的同步状态将被重置。\n3. 客户端连接后,请务必选择【远程覆盖本地】以获取回滚后的数据。\n\n确定要继续吗?', { danger: true }))) { + if (!(await showSelect('回滚快照', (kind === 'rating' ? '评分恢复范围:分数、来源与备份中的歌曲描述。保留当前收藏及本地文件关联;关联参照不会恢复旧关联。\n\n' : '') + '警告:此操作将把服务器数据回滚到选定的快照状态!\n\n1. 当前所有未保存的更改将丢失。\n2. 所有客户端的同步状态将被重置。\n3. 客户端连接后,请务必选择【远程覆盖本地】以获取回滚后的数据。\n\n确定要继续吗?', { danger: true }))) { return; } diff --git a/public/index.html b/public/index.html index a80381b1..7c12cb76 100644 --- a/public/index.html +++ b/public/index.html @@ -690,6 +690,14 @@

快速操作

收藏歌手 0 + +
@@ -1493,11 +1501,11 @@

Subsonic 协议配置 + OpenList + 播放缓存设置 ↗ +
@@ -1640,14 +1653,14 @@

Subsonic 协议配置

-
不喜欢 / 评分联动 (Subsonic)
+
评分与不喜欢(Subsonic)
- + - - - + + +
- 在列表中隐藏 dislike 歌曲 + data-help="在 Subsonic 搜索、普通歌单和专辑列表中隐藏命中项。关闭后重新显示,不删除规则,也不修改评分;评分歌单不受此过滤影响。">?

Subsonic 协议配置 + data-help="匹配时忽略 Live、Remix 等版本后缀,让基础歌名规则命中其他版本。仅改变过滤结果,不合并原始歌曲、不重写评分。">?

Subsonic 协议配置 + data-help="控制只有歌名、未记录歌手的通用规则:开启时不单独命中,关闭时按歌名命中。已有歌手的歌曲规则、专辑规则仍校验歌手。">?

Subsonic 协议配置 + data-help="Web 对歌曲、Subsonic 对歌曲、歌手或专辑提交低分时,解析后补对应不喜欢规则。仅影响之后的评分请求;已有低分需手动补数据。提高、清除评分或关闭开关均不删除规则。客户端是否能给歌手或专辑评分取决于客户端支持。">?

@@ -4173,23 +4206,27 @@

开始前:连接、启用和保存是三件事常规数据备份:本地 → OpenList

使用“备份范围”中 OpenList 列已保存的五类选择:歌曲与歌词、用户音源、歌单与不喜欢快照、用户数据、系统与账户。保存到 备份根路径/_data/相对路径,例如 - /local/_data/music/用户/歌曲.mp3。不会上传后删除本地;关闭范围不会清理已有云端副本,本地删除也不会自动传播到该数据目录。

+ /local/_data/music/用户/歌曲.mp3。不会上传后删除本地;关闭范围不会清理已有云端副本,本地删除也不会自动传播到该数据目录。 +

播放缓存:按用户独立处理

下方“OpenList 播放缓存”卡片单独选择用户和模式,云端位置为 备份根路径/用户名/cache/,例如 /local/admin/cache/。常规数据备份排除 - cache,不代表高级用户缓存规则不能上传缓存。两套范围与保存按钮互相独立。

+ cache,不代表高级用户缓存规则不能上传缓存。两套范围与保存按钮互相独立。 +

具体读取本地哪个目录?

常规“歌曲与歌词”读取实际数据目录的 music/,默认 data/music/,包含已有 LRC、封面与索引。排除数据目录外独立的根目录 music/、各级 - cache、外部自定义曲库、日志、runtime、临时文件和本地备份包。自定义 DATA_PATH 后以实际数据目录为准。

+ cache、外部自定义曲库、日志、runtime、临时文件和本地备份包。自定义 DATA_PATH 后以实际数据目录为准。 +

高级播放缓存跟随该用户当前缓存位置:data 对应 数据目录/cache/用户名/,root 对应 - 程序运行目录/cache/用户名/,不是同时扫描两边。用户未设置时使用全局位置;旧配置中有效的自定义 cacheDir 优先沿用。

+ 程序运行目录/cache/用户名/,不是同时扫描两边。用户未设置时使用全局位置;旧配置中有效的自定义 cacheDir 优先沿用。 +

四种缓存模式不是一次性操作

diff --git a/public/music/app.js b/public/music/app.js index fa6a058b..9ad3bf46 100644 --- a/public/music/app.js +++ b/public/music/app.js @@ -1434,6 +1434,7 @@ async function handleHeaderLogout(e) { } catch (err) { } const agreementAccepted = localStorage.getItem('lx_agreement_accepted'); localStorage.clear(); + window.dispatchEvent(new Event('ratingaccountchange')); sessionStorage.clear(); if (agreementAccepted) localStorage.setItem('lx_agreement_accepted', agreementAccepted); window.location.reload(); @@ -1528,6 +1529,7 @@ async function handleLogout() { const agreementAccepted = localStorage.getItem('lx_agreement_accepted'); localStorage.clear(); + window.dispatchEvent(new Event('ratingaccountchange')); sessionStorage.clear(); if (agreementAccepted) localStorage.setItem('lx_agreement_accepted', agreementAccepted); @@ -2237,7 +2239,7 @@ function renderQueue() {
${createMarqueeHtml(song.name, 'text-sm font-bold ' + (isActive ? 'text-emerald-500' : 't-text-main'))} -
+
${getSourceTag(song.source)} ${getQualityTags(song)} ${createMarqueeHtml(song.singer, 'text-[10px] t-text-muted flex-1')} @@ -2900,7 +2902,7 @@ function renderHotSearch(data) { if (!container || !data || !data.list || data.list.length === 0 || settings.hotSearchLimit === 0) { // 显示默认空白状态 container.innerHTML = ` -
+

输入关键词开始搜索音乐

@@ -2992,7 +2994,7 @@ function switchHotSearchTab(source) { const container = document.getElementById('search-results'); if (container) { container.innerHTML = ` -
+

正在加载热门搜索...

@@ -3034,7 +3036,7 @@ function showInitialSearchState() { // 显示加载状态 container.innerHTML = ` -
+

正在加载热门搜索...

@@ -3052,7 +3054,7 @@ function showInitialSearchState() { console.error('[HotSearch] 显示热搜失败:', err); // 失败时显示默认状态 container.innerHTML = ` -
+

输入关键词开始搜索音乐

@@ -3911,7 +3913,7 @@ function renderArtistSongsUI(list, page) {
${item.name}
-
+
${getSourceTag ? getSourceTag(item.source) : ''} ${getQualityTags ? getQualityTags(item) : ''} @@ -3936,6 +3938,7 @@ function renderArtistSongsUI(list, page) {
+ @@ -3982,6 +3985,7 @@ function renderArtistSongsUI(list, page) { // Init Marquee if needed (though we use truncate here) if (window.applyMarqueeChecks) applyMarqueeChecks(); if (typeof initArtistScrollListener === 'function') initArtistScrollListener(); + content.querySelectorAll('[data-rating-index]').forEach(button => window.RatingManager?.attach(button, list[Number(button.dataset.ratingIndex)])); window.ServerFileState?.paintBadges(content); } window.renderArtistSongsUI = renderArtistSongsUI; @@ -5206,7 +5210,11 @@ function renderResults(list) { window.viewingPlaylist = list; if (!list || list.length === 0) { - container.innerHTML = '
未找到相关结果
'; + const emptyDislike = window.currentViewingListId === 'dislike_songs' && !document.getElementById('gl-local-search-input')?.value?.trim() && !document.getElementById('search-input')?.value?.trim(); + if (emptyDislike) { + if (header) header.classList.add('hidden'); + container.innerHTML = '

还没有不喜欢任何歌曲

在歌曲操作菜单中点击“不喜欢”即可添加
'; + } else container.innerHTML = '
未找到相关结果
'; updatePaginationInfo(0, 0, 0, 1, 1); return; } @@ -5310,7 +5318,7 @@ function renderResults(list) {
${createMarqueeHtml(item.name)}
-
+
${getSourceTag(item.source)} ${getQualityTags(item)} @@ -5376,6 +5384,12 @@ function renderResults(list) { menu.addEventListener('click', event => event.stopPropagation()); menu.querySelector('[data-queue-next]').onclick = () => { enqueueSong(item, true); menu.open = false; }; menu.querySelector('[data-queue-add]').onclick = () => { enqueueSong(item); menu.open = false; }; + const rateButton = document.createElement('button'); + rateButton.type = 'button'; + rateButton.className = 'rating-menu-item'; + menu.querySelector('.queue-actions-menu').appendChild(rateButton); + window.RatingManager?.attach(rateButton, item); + window.RatingManager?.attachTag(row.querySelector('[data-rating-badges]'), item); const popup = menu.querySelector('.queue-actions-menu'); if (typeof popup.showPopover === 'function') { popup.setAttribute('popover', 'auto'); @@ -7964,6 +7978,7 @@ window.setImg = (id, src) => { }; function updatePlayerInfo(song, actualQuality) { + window.RatingManager?.current(song); // Bottom Player - 更新标题 const titleEl = document.getElementById('player-title'); if (titleEl) { @@ -12009,7 +12024,7 @@ function renderLibraryArtists(list, isDislike = false) { if (!list || list.length === 0) { container.innerHTML = ` -
+

${isDislike ? '还没有不喜欢任何歌手' : '还没有收藏任何歌手'}

在搜索结果中点击 ${isDislike ? '🚫 不喜欢歌手' : '♥ 收藏歌手'}

@@ -12090,7 +12105,7 @@ function renderLibraryAlbums(list, isDislike = false) { if (!list || list.length === 0) { container.innerHTML = ` -
+

${isDislike ? '还没有不喜欢任何专辑' : '还没有收藏任何专辑'}

在搜索结果中点击 ${isDislike ? '🚫 不喜欢专辑' : '♥ 收藏专辑'}

@@ -12704,6 +12719,7 @@ async function handleSyncLogout(skipConfirm = false) { // 7. 彻底清空 localStorage & sessionStorage const agreementAccepted = localStorage.getItem('lx_agreement_accepted'); localStorage.clear(); + window.dispatchEvent(new Event('ratingaccountchange')); sessionStorage.clear(); if (agreementAccepted) { localStorage.setItem('lx_agreement_accepted', agreementAccepted); @@ -12790,6 +12806,7 @@ async function handleLocalLogin() { } if (!tokenReady) throw new Error('登录已失效,请重新登录'); localStorage.setItem('lx_sync_user', user); + window.dispatchEvent(new Event('ratingaccountchange')); // [新增] 显示并加载 Token 管理面板 const tokenSection = document.getElementById('token-management-section'); @@ -12815,6 +12832,7 @@ async function handleLocalLogin() { // Save credentials to localStorage (Simple version) localStorage.setItem('lx_sync_mode', 'local'); // [Fix] Save mode localStorage.setItem('lx_sync_user', user); + window.dispatchEvent(new Event('ratingaccountchange')); if (pass) { localStorage.setItem('lx_sync_pass', pass); } @@ -13913,6 +13931,7 @@ function handleDislikeArtistsClick() { clearSearchDetailView(); exitListSecondaryModes(); window.currentViewingListId = 'dislike_artists'; + const pageTitle = document.getElementById('page-title'); if (pageTitle) pageTitle.textContent = '不喜欢歌手'; currentSearchScope = 'local_list'; window.refreshSearchStatusVisibility?.(); @@ -13954,6 +13973,7 @@ function handleDislikeAlbumsClick() { clearSearchDetailView(); exitListSecondaryModes(); window.currentViewingListId = 'dislike_albums'; + const pageTitle = document.getElementById('page-title'); if (pageTitle) pageTitle.textContent = '不喜欢专辑'; currentSearchScope = 'local_list'; window.refreshSearchStatusVisibility?.(); @@ -16087,6 +16107,7 @@ function cleanSongData(song) { if (song.url) cleanSong.url = song.url; if (song.folder) cleanSong.folder = song.folder; if (song.filename) cleanSong.filename = song.filename; + for (const key of ['_localFilename', '_localFolder', '_localLocation', '_localUsername', '_isCustomDir']) if (song[key] !== undefined) cleanSong[key] = song[key]; // Remove undefined keys const removeUndefined = (obj) => { @@ -18742,7 +18763,8 @@ window.CustomSelectManager = { if (opt.disabled) return; const li = document.createElement('li'); li.className = 'cs-option' + (opt.selected ? ' selected' : ''); - li.innerHTML = `${opt.text}`; + const optionLabel = document.createElement('span'); optionLabel.textContent = opt.text; + const check = document.createElement('i'); check.className = 'fas fa-check'; li.append(optionLabel, check); li.onclick = (e) => { e.stopPropagation(); @@ -18755,7 +18777,9 @@ window.CustomSelectManager = { }); dropdown.appendChild(optionsList); - document.body.appendChild(dropdown); + const dialogHost = select.closest('dialog[open]'); + (dialogHost || document.body).appendChild(dropdown); + dropdown._dialogHost = dialogHost; // 计算位置 this.reposition(trigger, dropdown); @@ -18771,17 +18795,23 @@ window.CustomSelectManager = { reposition(trigger, dropdown) { const rect = trigger.getBoundingClientRect(); dropdown.style.width = rect.width + 'px'; - dropdown.style.left = rect.left + 'px'; + const host = dropdown._dialogHost; + const hostRect = host?.getBoundingClientRect(); + dropdown.style.left = (host ? rect.left - hostRect.left + host.scrollLeft - host.clientLeft : rect.left + window.scrollX) + 'px'; // 检查空间,自动决定向上还是向下展开 - const spaceBelow = window.innerHeight - rect.bottom; + const spaceBelow = (hostRect ? Math.min(window.innerHeight, hostRect.bottom) : window.innerHeight) - rect.bottom; const dropdownHeight = dropdown.offsetHeight || 260; - if (spaceBelow < dropdownHeight && rect.top > dropdownHeight) { - dropdown.style.top = (rect.top + window.scrollY - dropdownHeight - 6) + 'px'; + const offsetTop = host ? -hostRect.top + host.scrollTop - host.clientTop : window.scrollY; + const spaceAbove = rect.top - (hostRect?.top || 0); + if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) { + dropdown.style.maxHeight = Math.max(80, Math.min(280, spaceAbove - 10)) + 'px'; + dropdown.style.top = (rect.top + offsetTop - Math.min(dropdownHeight, Math.max(80, spaceAbove - 10)) - 6) + 'px'; dropdown.classList.add('open-up'); } else { - dropdown.style.top = (rect.bottom + window.scrollY + 4) + 'px'; + dropdown.style.maxHeight = Math.max(80, Math.min(280, spaceBelow - 10)) + 'px'; + dropdown.style.top = (rect.bottom + offsetTop + 4) + 'px'; dropdown.classList.remove('open-up'); } }, diff --git a/public/music/css/rating.css b/public/music/css/rating.css new file mode 100644 index 00000000..55b2f6d3 --- /dev/null +++ b/public/music/css/rating.css @@ -0,0 +1,188 @@ +/* 评分 UI:动态星星选择器 + 我的评分面板。桌面居中弹窗,手机端底部抽屉。 */ +.rating-chip, .player-rating-button { width: fit-content; color: #d89b19; background: transparent; border: 0; font-size: 12px; padding: 2px 0; cursor: pointer; transition: transform .15s, color .15s; } +.rating-chip:hover { transform: none; } +.rating-chip.is-rated { font-weight: 600; text-shadow: 0 0 8px rgba(251,191,36,.35); } + +.web-rating-dialog { width: min(440px, calc(100vw - 28px)); max-height: 88vh; padding: 22px; border-radius: 22px; border: 1px solid #64748b55; background: var(--bg-panel, #1f2937); color: var(--text-main, #f1f5f9); box-shadow: 0 24px 60px rgba(0,0,0,.45); overflow: auto; margin: auto; } +.web-rating-dialog[open] { animation: rd-in .22s cubic-bezier(.2,.9,.3,1.2); } +.web-rating-dialog::backdrop { background: rgba(2,6,23,.55); backdrop-filter: blur(6px); } +.web-rating-dialog h3 { font-size: 18px; margin: 0; overflow-wrap: anywhere; } +.web-rating-dialog p { font-size: 13px; margin: 8px 0; } +.web-rating-dialog .rating-hint { opacity: .6; line-height: 1.6; font-size: 12px; } +.rd-grip { display: none; width: 40px; height: 4px; border-radius: 4px; background: #94a3b855; margin: -8px auto 14px; } +.rd-head { display: flex; gap: 14px; align-items: center; } +.rd-art { width: 64px; height: 64px; flex: 0 0 64px; border-radius: 14px; background: linear-gradient(135deg, #f59e0b55, #8b5cf655); display: grid; place-items: center; font-size: 26px; overflow: hidden; position: relative; } +.rd-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; } +.rd-meta { min-width: 0; } +.rd-singer { opacity: .65; margin: 4px 0 0 !important; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + +.rs-picker { display: flex; flex-direction: column; align-items: center; gap: 8px; margin: 22px 0 6px; } +.rs-picker.busy { opacity: .6; pointer-events: none; } +.rs-row { display: flex; gap: 6px; touch-action: none; user-select: none; } +.rs-star { font-size: 44px; line-height: 1; padding: 4px; background: transparent; border: 0; color: #64748b66; cursor: pointer; transition: transform .15s, color .15s, filter .15s; -webkit-tap-highlight-color: transparent; } +.rs-star.on { color: #fbbf24; filter: drop-shadow(0 0 10px rgba(251,191,36,.55)); transform: scale(1.08); } +.rs-star:hover { transform: scale(1.22); } +.rs-star:focus-visible { outline: 2px solid #fbbf24; outline-offset: 2px; border-radius: 10px; } +.rs-star.pop { animation: rs-pop .5s cubic-bezier(.2,1.4,.4,1); } +.rs-caption { font-size: 14px; font-weight: 600; color: #fbbf24; min-height: 20px; } +.rs-caption.dim { color: inherit; opacity: .55; font-weight: 400; } +.rs-clear { background: transparent; border: 0; color: inherit; opacity: .55; font-size: 12px; text-decoration: underline; cursor: pointer; padding: 4px 8px; } +.rs-clear:hover { opacity: 1; } +.rd-status { text-align: center; opacity: .7; min-height: 18px; } +.rating-close { width: 100%; margin-top: 12px; border: 1px solid #64748b66; background: transparent; color: inherit; border-radius: 12px; padding: 10px 12px; min-height: 44px; cursor: pointer; } +.rating-close:hover { background: #64748b22; } + +/* 我的评分面板 */ +.web-rating-dialog.is-collection { width: min(640px, calc(100vw - 28px)); } +.rc-head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; } +.rc-sub { opacity: .6; } +.rc-x { background: #64748b22; border: 0; color: inherit; width: 34px; height: 34px; border-radius: 50%; cursor: pointer; flex: 0 0 34px; } +.rc-summary { display: flex; gap: 18px; align-items: center; margin: 14px 0; padding: 14px; border-radius: 16px; background: #64748b1a; } +.rc-avg { display: flex; flex-direction: column; align-items: center; min-width: 84px; } +.rc-avg b { font-size: 34px; line-height: 1; color: #fbbf24; } +.rc-avg span { font-size: 11px; opacity: .6; margin-top: 4px; white-space: nowrap; } +.rc-bars { flex: 1; display: grid; gap: 4px; min-width: 0; } +.rc-bar { display: grid; grid-template-columns: 24px 1fr 28px; gap: 8px; align-items: center; font-size: 11px; } +.rc-bar em { font-style: normal; opacity: .7; } +.rc-bar span { height: 6px; border-radius: 6px; background: #64748b33; overflow: hidden; } +.rc-bar i { display: block; height: 100%; background: linear-gradient(90deg, #f59e0b, #fbbf24); border-radius: 6px; transition: width .4s; } +.rc-bar small { text-align: right; opacity: .6; } +.rc-tools { display: flex; gap: 8px; } +.rc-search, .rc-sort { background: transparent; color: inherit; border: 1px solid #64748b66; border-radius: 10px; padding: 9px 12px; min-width: 0; font-size: 13px; } +.rc-search { flex: 1; } +.rc-sort option { color: #111; } +.rc-chips { display: flex; gap: 6px; overflow-x: auto; padding: 10px 0; scrollbar-width: none; } +.rc-chips::-webkit-scrollbar { display: none; } +.rc-chip { flex: 0 0 auto; background: transparent; color: inherit; border: 1px solid #64748b55; border-radius: 999px; padding: 5px 12px; font-size: 12px; cursor: pointer; } +.rc-chip.on { background: #fbbf24; border-color: #fbbf24; color: #1f2937; font-weight: 600; } +.rc-list { max-height: 44vh; overflow: auto; } +.rc-row { display: flex; align-items: center; gap: 10px; padding: 10px 4px; border-bottom: 1px solid #64748b33; } +.rc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; } +.rc-info b { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.rc-info span { font-size: 12px; opacity: .6; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.rc-stars { display: flex; align-items: center; gap: 6px; background: transparent; border: 0; cursor: pointer; color: inherit; flex: 0 0 auto; padding: 6px; border-radius: 10px; } +.rc-stars:hover { background: #64748b22; } +.rc-star-text { --v: 0; font-size: 16px; letter-spacing: 1px; background: linear-gradient(90deg, #fbbf24 calc(var(--v) / 5 * 100%), #64748b55 0); -webkit-background-clip: text; background-clip: text; color: transparent; } +.rc-stars { --v: 0; } +.rc-stars .rc-star-text { --v: inherit; } +.rc-stars small { color: #fbbf24; font-weight: 700; } +.rc-empty { text-align: center; padding: 32px 8px; opacity: .6; font-size: 13px; } +.rc-more { width: 100%; margin-top: 8px; padding: 9px; border: 1px solid #64748b55; background: transparent; color: inherit; border-radius: 10px; cursor: pointer; } + +@keyframes rd-in { from { opacity: 0; transform: translateY(12px) scale(.96); } to { opacity: 1; transform: none; } } +@keyframes rs-pop { 0% { transform: scale(1); } 40% { transform: scale(1.6) rotate(-12deg); } 100% { transform: scale(1.08); } } +@media (prefers-reduced-motion: reduce) { .web-rating-dialog[open], .rs-star.pop { animation: none; } .rs-star, .rc-bar i { transition: none; } } + +/* 手机端:底部抽屉 */ +@media (max-width: 600px) { + .web-rating-dialog, .web-rating-dialog.is-collection { width: 100vw; max-width: 100vw; margin: auto 0 0; border-radius: 22px 22px 0 0; padding: 18px 18px calc(18px + env(safe-area-inset-bottom)); max-height: 92vh; } + .web-rating-dialog[open] { animation: rd-sheet .28s cubic-bezier(.2,.9,.3,1); } + .rd-grip { display: block; } + .rs-star { font-size: 48px; padding: 2px; } + .rs-row { gap: 4px; } + .rc-summary { flex-direction: column; align-items: stretch; gap: 10px; } + .rc-avg { flex-direction: row; gap: 10px; align-items: baseline; justify-content: center; } + .rc-list { max-height: 40vh; } +} +@keyframes rd-sheet { from { transform: translateY(100%); } to { transform: none; } } + +.web-rating-dialog.is-collection { width: min(720px, calc(100vw - 28px)); } +.rd-tags, .rc-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; } +.rd-tags span, .rc-tags span { font-size: 11px; padding: 1px 7px; border-radius: 5px; border: 1px solid #64748b66; opacity: .8; } +.rc-tags span.k { background: #64748b33; opacity: 1; } +.rc-kinds { display: flex; gap: 4px; border-bottom: 1px solid #64748b44; margin-bottom: 12px; overflow-x: auto; scrollbar-width: none; } +.rc-kind { background: transparent; border: 0; color: inherit; opacity: .6; padding: 8px 14px; font-size: 13px; cursor: pointer; border-bottom: 2px solid transparent; white-space: nowrap; } +.rc-kind.on { opacity: 1; border-bottom-color: #fbbf24; font-weight: 600; } +.rc-tools { flex-wrap: wrap; } +.rc-search { flex: 1 1 200px; } +.rc-cover { position: relative; width: 52px; height: 52px; flex: 0 0 52px; border-radius: 8px; background: #64748b30; display: grid; place-items: center; overflow: hidden; opacity: .95; } +.rc-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; } +.rc-row.kind-artist .rc-cover { border-radius: 50%; } +.rc-info { gap: 3px; } +.rc-stars:disabled { cursor: default; opacity: .9; } +.rc-stars:disabled:hover { background: transparent; } +@media (max-width: 600px) { + .rc-row { align-items: flex-start; flex-wrap: wrap; } + .rc-info { flex-basis: calc(100% - 70px); } + .rc-stars { margin-left: 62px; padding-top: 0; } + .rc-tools select { flex: 1 1 45%; } +} + +/* 我的评分:复用播放器下拉组件,保留模态弹窗的顶层菜单。 */ +.rc-head { display: grid; grid-template-columns: minmax(0,1fr) auto auto; align-items: start; } +.rc-export, .rc-reset { border: 1px solid var(--border-main, #64748b55); background: transparent; color: inherit; border-radius: 10px; padding: 9px 13px; font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; transition: background .15s ease; } +.rc-export:hover, .rc-reset:hover { background: #64748b20; } +.rc-tools { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr) auto; gap: 8px; } +.rc-tools .rc-search { grid-column: 1 / -1; width: 100%; min-width: 0; box-sizing: border-box; } +.rc-tools .cs-wrapper { min-width: 0; width: 100%; } +.rc-tools .cs-trigger { min-height: 40px; padding: 8px 12px; border-radius: 10px; box-sizing: border-box; font-size: 12px; } +.rc-tools .rc-reset { grid-column: 3; grid-row: 2 / span 2; align-self: stretch; } +.rc-tools .cs-wrapper:last-of-type { grid-column: 1 / span 2; } +.rc-source-help { margin: 12px 0 6px; font-size: 12px; color: var(--text-muted, #94a3b8); line-height: 1.7; } +.rc-source-help summary, .rc-record-detail summary { cursor: pointer; width: fit-content; } +.rc-source-help p { margin-top: 8px; } +.rc-result-status { font-size: 12px; color: var(--text-muted, #94a3b8); margin: 8px 0; } +.rc-record-detail { font-size: 11px; color: var(--text-muted, #94a3b8); margin-top: 5px; } +.rc-record-detail p { overflow-wrap: anywhere; white-space: normal; margin-top: 6px; } +button.rc-bar { width: 100%; border: 0; padding: 3px 0; color: inherit; background: transparent; cursor: pointer; text-align: left; font: inherit; } +button.rc-bar:hover { background: #64748b15; border-radius: 5px; } +.web-rating-dialog .cs-dropdown { max-width: calc(100% - 20px); } +.rc-head > div { min-width: 0; } +.rc-export:focus-visible, .rc-reset:focus-visible, button.rc-bar:focus-visible { outline: 2px solid #fbbf24; outline-offset: 3px; } +@media (max-width: 600px) { .rc-head { grid-template-columns: minmax(0,1fr) auto; } .rc-head .rc-export { grid-column: 1; grid-row: 2; justify-self: start; } .rc-head .rc-x { grid-column: 2; grid-row: 1; } .rc-tools { grid-template-columns: minmax(0,1fr) minmax(0,1fr); } .rc-tools .rc-reset { grid-column: 2; grid-row: auto; } .rc-tools .cs-wrapper:last-of-type { grid-column: auto; } } +@media (prefers-reduced-motion: reduce) { .rc-export, .rc-reset, .web-rating-dialog .cs-dropdown { transition: none; } } + +/* 当前用户评分偏好:不依赖动态 Tailwind 类,不影响其他设置卡片。 */ +.rating-preference-card { display: grid; grid-template-columns: minmax(0,1fr) auto; align-items: center; gap: 10px 20px; padding: 18px 20px; border: 1px solid var(--border-main, #64748b44); border-radius: 12px; background: var(--bg-panel, transparent); } +.rating-preference-heading { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 14px; font-weight: 600; color: var(--text-main, inherit); } +.rating-preference-heading .setting-tooltip-trigger { border: 0; padding: 0; background: transparent; font: inherit; flex-shrink: 0; } +.rating-preference-heading .setting-tooltip-content { font-weight: 400; } +.rating-preference-switch { display: inline-flex; position: relative; width: 44px; height: 24px; flex-shrink: 0; cursor: pointer; } +.rating-preference-switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; z-index: 1; cursor: pointer; } +.rating-preference-switch > span { width: 44px; height: 24px; border-radius: 999px; background: #64748b80; transition: background .18s ease; } +.rating-preference-switch > span::after { content: ''; position: absolute; left: 3px; top: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px #0002; transition: transform .18s ease; } +.rating-preference-switch input:checked + span { background: #10b981; } +.rating-preference-switch input:checked + span::after { transform: translateX(20px); } +.rating-preference-switch input:disabled { cursor: wait; } +.rating-preference-switch input:disabled + span { opacity: .5; } +.rating-preference-switch input:focus-visible + span { outline: 2px solid #10b981; outline-offset: 3px; } +.rating-preference-status { grid-column: 1 / -1; margin: 0; font-size: 12px; color: var(--text-muted, #94a3b8); } +.rating-preference-status[hidden] { display: none; } +@media (max-width:600px) { .rating-preference-card { padding: 16px; } } +@media (prefers-reduced-motion:reduce) { .rating-preference-switch > span, .rating-preference-switch > span::after { transition: none; } } + +/* 评分与平台、音质标签并列;不占未评分歌曲的空间。 */ +[data-rating-badges] { min-width: 0; } +.rating-chip.rating-score-tag { display: inline-flex; align-items: center; justify-content: center; gap: 3px; flex: 0 0 auto; padding: 2px 6px; min-height: 18px; border-radius: 6px; border: 1px solid #e6ab3b55; background: #e6ab3b15; color: #d99b20; font-size: 10px; line-height: 1.2; font-weight: 700; white-space: nowrap; letter-spacing: .02em; text-shadow: none; vertical-align: middle; } +.rating-score-tag[hidden] { display: none !important; } +.rating-score-tag:hover { background: #e6ab3b28; border-color: #e6ab3b90; } +.rating-chip { white-space: nowrap; flex-shrink: 0; } +.rating-preference-card { min-height: 72px; box-sizing: border-box; } +@media (max-width: 640px) { + .rating-chip:not(.rating-score-tag):not(#player-rating) { font-size: 0; min-width: 28px; min-height: 32px; display: inline-flex; align-items: center; justify-content: center; padding: 3px; line-height: 1; } + .rating-chip:not(.rating-score-tag):not(#player-rating)::before { content: '☆'; font-size: 17px; white-space: nowrap; } + .rating-chip.is-rated:not(.rating-score-tag):not(#player-rating)::before { content: '★'; } + .rating-chip.rating-score-tag { font-size: 9px; padding: 2px 5px; min-height: 17px; } + [data-rating-badges] { column-gap: 4px; } + .rating-preference-card { padding: 16px; min-height: 68px; } + .rating-preference-heading { font-size: 13px; } +} + +/* 所有桌面/手机操作区仅显示星形入口;分数标签尺寸与平台标签接近。 */ +.rating-chip:not(.rating-score-tag):not(#player-rating) { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; min-height: 28px; padding: 3px; font-size: 18px; line-height: 1; } +.rating-chip:hover, .rating-chip.rating-score-tag:hover { transform: none; } +.rating-chip.rating-score-tag { padding: 2px 7px; min-height: 20px; font-size: 11px; line-height: 1.2; border-radius: 6px; } +.queue-actions-menu .rating-chip { justify-content: flex-start; } +.dislike-empty-state { min-height: 280px; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 16px; padding: 32px 20px; text-align: center; color: var(--text-muted, #94a3b8); } +.dislike-empty-state > i { font-size: 56px; opacity: .22; } +.dislike-empty-state > p { margin: 0; } +.dislike-empty-state > small { font-size: 12px; line-height: 1.6; } +@media(max-width:640px) { + .rating-chip:not(.rating-score-tag):not(#player-rating) { font-size: 0; min-height: 32px; } + .rating-chip.rating-score-tag { min-height: 18px; padding: 2px 6px; font-size: 10px; } + .dislike-empty-state { min-height: 240px; } +} + +/* 菜单评分项保留动作名称与分数,手机端也不折叠为单图标。 */ +.rating-chip.rating-menu-item:not(.rating-score-tag):not(#player-rating) { width: 100%; justify-content: flex-start; padding: 10px 12px; font-size: 14px; line-height: 1.5; text-shadow: none; gap: 6px; } +.rating-chip.rating-menu-item::before { content: none !important; } diff --git a/public/music/index.html b/public/music/index.html index 9424d1b0..985550e8 100644 --- a/public/music/index.html +++ b/public/music/index.html @@ -43,7 +43,10 @@ + + @@ -119,6 +122,7 @@

LX MUSIC

class="fas fa-chevron-down text-xs transition-transform duration-200">
    +
  • @@ -3447,6 +3451,21 @@

    播放队列与列表

    +
    +
    + 不喜欢自动补分 + +
    + + +
    +
    @@ -4164,6 +4183,7 @@

    选择一首歌曲播放

    +
    @@ -6279,6 +6299,7 @@

    项目使用声明< + diff --git a/public/music/js/library/dislike_manager.js b/public/music/js/library/dislike_manager.js index 03699f24..80e73f5e 100644 --- a/public/music/js/library/dislike_manager.js +++ b/public/music/js/library/dislike_manager.js @@ -15,6 +15,7 @@ window.DislikeManager = (function () { const API_BASE = '/api/music/dislike'; const state = { + scoped: {}, initialized: false, loading: false, exact: new Set(), @@ -30,7 +31,7 @@ window.DislikeManager = (function () { }; /** 归一化:与服务端一致(@ → #、去空格、小写) */ - const normalize = (v) => String(v ?? '').replaceAll('@', '#').trim().toLowerCase(); + const normalize = (v) => String(v ?? '').replaceAll('@', '#').trim().toLowerCase().normalize('NFKC').replace(/\s*([()])\s*/g, '$1'); /** 拆分歌手:「A、B」「A,B」「A/B」「A feat.B」「A & B」 */ const splitSingers = (singer) => @@ -84,6 +85,7 @@ window.DislikeManager = (function () { } function applyData(data, options) { + state.scoped = data?.scoped || {}; state.exact = new Set(data?.exact || []); state.musicNames = new Set(data?.musicNames || []); state.singerNames = new Set(data?.singerNames || []); @@ -105,7 +107,7 @@ window.DislikeManager = (function () { state.loading = true; try { const r = await request(API_BASE); - if (r && r.success) applyData(r.data, r.options); + if (r && r.success) { applyData(r.data, r.options); if (r.warning) window.showInfo?.(r.warning); window.dispatchEvent(new Event('ratingdatachange')); } } catch (e) { console.error('[Dislike] load failed:', e); } finally { @@ -115,15 +117,19 @@ window.DislikeManager = (function () { } /** 判定一首歌是否命中不喜欢规则 */ - function isDisliked(song) { + function isDisliked(song, selected) { if (!song) return false; + const active = selected || state; + for (const [source, rules] of Object.entries(active.scoped || {})) { + if ((active.crossSource || song.source === source) && isDisliked(song, { ...active, scoped: {}, exact: new Set(rules.exact), musicNames: new Set(rules.musicNames), singerNames: new Set(rules.singerNames), albums: rules.albums })) return true; + } const name = normalize(song.name); const allSingers = splitSingers(song.singer); // primary 模式只看主唱(第一位歌手) - const singers = state.duetMode === 'primary' ? allSingers.slice(0, 1) : allSingers; + const singers = active.duetMode === 'primary' ? allSingers.slice(0, 1) : allSingers; // 候选歌名:原名 + 去后缀名(去重),提升 Live / Remix 版本召回 const candidateNames = Array.from( - new Set([name, state.normalizeName ? normalizeSongName(song.name) : ''].filter(Boolean)) + new Set([name, active.normalizeName ? normalizeSongName(song.name) : ''].filter(Boolean)) ); // 1. 专辑维度(专辑名 + 歌手 双重校验) @@ -131,15 +137,15 @@ window.DislikeManager = (function () { const albumName = getAlbumName(song); if (albumName) { const an = normalize(albumName); - for (const alb of state.albums) { + for (const alb of active.albums) { if (normalize(alb.albumName ?? '') !== an) continue; if (alb.singers && alb.singers.length) { if (!singers.length) { // 歌曲没有歌手信息:requireSinger 时无法确认,保守放过 - if (state.requireSinger) continue; + if (active.requireSinger) continue; } else { const albumSingers = alb.singers.map((s) => - state.normalizeName ? normalizeSongName(s) : normalize(s) + active.normalizeName ? normalizeSongName(s) : normalize(s) ); const hit = singers.some((x) => albumSingers.some((a) => x === a || x.includes(a) || a.includes(x)) @@ -153,12 +159,12 @@ window.DislikeManager = (function () { // 2. 歌手维度 if (singers.length) { - if (state.duetMode === 'all') { + if (active.duetMode === 'all') { // all:所有歌手都被屏蔽才算命中,避免牵连合作者 - if (singers.every((s) => state.singerNames.has(s))) return true; + if (singers.every((s) => active.singerNames.has(s))) return true; } else { for (const s of singers) { - if (state.singerNames.has(s)) return true; + if (active.singerNames.has(s)) return true; } } } @@ -167,13 +173,13 @@ window.DislikeManager = (function () { for (const n of candidateNames) { if (!n) continue; // 纯歌名规则:requireSinger 时不单独命中,避免同名歌被误杀 - if (state.musicNames.has(n) && !state.requireSinger) return true; + if (active.musicNames.has(n) && !active.requireSinger) return true; if (singers.length) { - if (state.duetMode === 'all') { - if (singers.every((s) => state.exact.has(`${n}@${s}`))) return true; + if (active.duetMode === 'all') { + if (singers.every((s) => active.exact.has(`${n}@${s}`))) return true; } else { for (const s of singers) { - if (state.exact.has(`${n}@${s}`)) return true; + if (active.exact.has(`${n}@${s}`)) return true; } } } @@ -184,7 +190,7 @@ window.DislikeManager = (function () { async function mutate(action, payload) { const r = await request(`${API_BASE}/${action}`, payload); - if (r && r.success) applyData(r.data, r.options); + if (r && r.success) { applyData(r.data, r.options); if (r.warning) window.showInfo?.(r.warning); window.dispatchEvent(new Event('ratingdatachange')); } return !!(r && r.success); } diff --git a/public/music/js/library/leaderboard_manager.js b/public/music/js/library/leaderboard_manager.js index dcb08a48..c658dd29 100644 --- a/public/music/js/library/leaderboard_manager.js +++ b/public/music/js/library/leaderboard_manager.js @@ -235,7 +235,7 @@ window.LeaderboardManager = (function () {
    ${window.createMarqueeHtml ? window.createMarqueeHtml(song.name) : `${song.name}`}
    -
    +
    ${window.getSourceTag ? window.getSourceTag(song.source || state.source) : ''} ${window.getQualityTags ? window.getQualityTags(song) : ''} @@ -277,6 +277,7 @@ window.LeaderboardManager = (function () { onclick="event.stopPropagation(); window.LeaderboardManager.addSongToPlaylist(${index})"> + +
    -
    +
    ${safeSinger} ${this.escapeHtml(qualityName || '标准')} ${item.bitrate ? `` : ''} @@ -1037,6 +1037,14 @@ window.CustomDirManager = { container.innerHTML = html; // 绑定封面加载失败兜底 + container.querySelectorAll('[data-lm-action="playlist"]').forEach(anchor => { + const item = this.displayData[Number(anchor.dataset.lmIndex)]; + if (!item) return; + const button = document.createElement('button'); button.type = 'button'; + button.className = 'text-xs text-amber-500 px-1 shrink-0'; + anchor.parentElement.insertBefore(button, anchor); + window.RatingManager?.attach(button, { ...item.songInfo, name: item.name || item.songInfo?.name, singer: item.singer || item.songInfo?.singer, isLocal: true, _localFilename: item.filename, _localFolder: true ? 'custom' : item.folder || 'cache', _localLocation: true ? undefined : document.getElementById('lm-location-select')?.value || 'root', _isCustomDir: true }); + }); container.querySelectorAll('.lm-cover-image').forEach(img => { img.addEventListener('error', () => { const index = parseInt(img.dataset.lmCoverIndex || '', 10); diff --git a/public/music/js/local/local_music.js b/public/music/js/local/local_music.js index d1259ac8..a2c50e63 100644 --- a/public/music/js/local/local_music.js +++ b/public/music/js/local/local_music.js @@ -1426,7 +1426,7 @@ window.LocalMusicManager = {
    -
    +
    ${safeSinger} ${this.escapeHtml(qualityName || '标准')} ${item.bitrate ? `` : ''} @@ -1539,6 +1539,14 @@ window.LocalMusicManager = { window.unobserveLazyImages(container); } container.innerHTML = html; + container.querySelectorAll('[data-lm-action="playlist"]').forEach(anchor => { + const item = this.displayData[Number(anchor.dataset.lmIndex)]; + if (!item) return; + const button = document.createElement('button'); button.type = 'button'; + button.className = 'text-xs text-amber-500 px-1 shrink-0'; + anchor.parentElement.insertBefore(button, anchor); + window.RatingManager?.attach(button, { ...item.songInfo, name: item.name || item.songInfo?.name, singer: item.singer || item.songInfo?.singer, isLocal: true, _localFilename: item.filename, _localFolder: false ? 'custom' : item.folder || 'cache', _localLocation: false ? undefined : document.getElementById('lm-location-select')?.value || 'root', _isCustomDir: false }); + }); container.querySelectorAll('.lm-cover-image').forEach(img => { img.addEventListener('error', () => { const index = parseInt(img.dataset.lmCoverIndex || '', 10); @@ -2567,12 +2575,14 @@ window.LocalMusicManager = { }, body: JSON.stringify({ filename: this.manualIndexTargetItem.filename, + folder: this.manualIndexTargetItem.folder, songInfo: onlineItem }) }); const result = await res.json(); if (result.success) { + window.dispatchEvent(new Event('ratingidentitychange')); if (typeof showInfo === 'function') showInfo('关联成功!文件名及标签已更新'); this.closeManualIndexModal(); if (isCustom && window.CustomDirManager) { diff --git a/public/music/js/ui/theme_manager.js b/public/music/js/ui/theme_manager.js index 2a7b1d2f..61fc4567 100644 --- a/public/music/js/ui/theme_manager.js +++ b/public/music/js/ui/theme_manager.js @@ -102,6 +102,7 @@ function updateAppearanceUI(activeMode) { } function switchSettingsTab(tabName) { + if (tabName === 'logic') window.RatingManager?.loadPreference(); const panels = ['system', 'display', 'logic', 'logs']; // Deactivate all first diff --git a/public/style.css b/public/style.css index 40346b33..b21ac0cf 100644 --- a/public/style.css +++ b/public/style.css @@ -9704,3 +9704,262 @@ button.olb-stat-card:focus-visible, .olb-filter-chip:focus-visible, .olb-active- #modal .olb-record-detail-table .olb-detail-key { width: 100px; } #modal .olb-record-detail-table td { padding: 10px 8px; } } + +/* 与 Subsonic 搜索说明一致的评分提示,正文适应窄屏。 */ +.subsonic-rating-note { + background: rgba(244, 63, 94, 0.06); + padding: 10px 12px; + border-radius: 6px; + line-height: 1.6; + overflow-wrap: anywhere; +} +.subsonic-rating-note p { margin: 5px 0; } +.subsonic-rating-note [role="status"] { display: block; margin-top: 6px; } + +/* 数据查看:不喜欢 / 评分。克制的扁平风格:细边框、小圆角、无渐变与悬浮位移。 */ +.admin-dislikes { margin-top: 28px; min-width: 0; } +.admin-dislike-icon, .admin-flat-icon { background: var(--bg-hover, rgba(128,128,128,.14)); color: var(--text-primary, inherit); border: 1px solid var(--border-color, rgba(128,128,128,.25)); } + +/* 统计条:一条带分隔线的整体,而不是一排彩色卡片 */ +.admin-dislike-stats, .admin-flat-stats { display: flex; flex-wrap: wrap; margin: 16px 0 12px; border: 1px solid var(--border-color, rgba(128,128,128,.22)); border-radius: 8px; overflow: hidden; } +.admin-flat-stats > *, .admin-dislike-stat { flex: 1 1 110px; display: flex; flex-direction: column; gap: 2px; align-items: flex-start; padding: 12px 16px; background: transparent; border: 0; border-right: 1px solid var(--border-color, rgba(128,128,128,.22)); color: inherit; font: inherit; text-align: left; cursor: pointer; min-width: 0; } +.admin-flat-stats > :last-child, .admin-dislike-stat:last-child { border-right: 0; } +.admin-flat-stats > .static, .admin-dislike-stat.static { cursor: default; } +.admin-flat-stats b, .admin-dislike-stat .s-num { font-size: 1.35rem; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.2; } +.admin-flat-stats span, .admin-dislike-stat .s-label { font-size: .72rem; color: var(--text-secondary); } +.admin-dislike-stat .s-icon { display: none; } +.admin-flat-stats > button:hover, .admin-dislike-stat:not(.static):hover { background: var(--bg-hover, rgba(128,128,128,.08)); } +.admin-flat-stats > button.on, .admin-dislike-stat.on { box-shadow: inset 0 -2px 0 var(--accent-primary, #6366f1); background: var(--bg-hover, rgba(128,128,128,.08)); } + +.admin-dist { display: grid; gap: 4px; margin: 0 0 14px; max-width: 420px; } +.admin-dist-row { display: grid; grid-template-columns: 26px 1fr 34px; gap: 8px; align-items: center; font-size: .72rem; color: var(--text-secondary); } +.admin-dist-row i { height: 4px; background: rgba(128,128,128,.2); border-radius: 2px; overflow: hidden; } +.admin-dist-row u { display: block; height: 100%; background: #d4a017; text-decoration: none; } +.admin-dist-row em { font-style: normal; text-align: right; font-variant-numeric: tabular-nums; } + +.admin-dislike-toolbar { display: grid; grid-template-columns: minmax(200px, 2.2fr) repeat(4, minmax(110px, 1fr)) auto; gap: 8px; margin: 8px 0 10px; align-items: center; } +.admin-ratings .admin-dislike-toolbar { grid-template-columns: minmax(200px, 2.2fr) repeat(4, minmax(110px, 1fr)); } +.admin-dislike-toolbar > * { min-width: 0; } +.admin-dislike-toolbar select, .admin-dislike-search input { width: 100%; } +.admin-dislike-search { position: relative; } +.admin-dislike-search > span { display: none; } +.admin-view-toggle { display: inline-flex; border-radius: 6px; overflow: hidden; border: 1px solid var(--border-color, rgba(128,128,128,.25)); } +.admin-view-toggle button { background: transparent; border: 0; color: inherit; padding: 8px 12px; cursor: pointer; } +.admin-view-toggle button.on { background: var(--bg-hover, rgba(128,128,128,.18)); } + +/* 行式列表(默认) */ +.admin-rows, .admin-dislike-grid.is-list { display: flex; flex-direction: column; border: 1px solid var(--border-color, rgba(128,128,128,.22)); border-radius: 8px; overflow: hidden; } +.admin-row { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto auto; gap: 14px; align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--border-color, rgba(128,128,128,.16)); } +.admin-row:last-child { border-bottom: 0; } +.admin-row:hover { background: var(--bg-hover, rgba(128,128,128,.06)); } +.admin-row-cover { position: relative; width: 44px; height: 44px; border-radius: 4px; background: rgba(128,128,128,.14); display: grid; place-items: center; color: var(--text-secondary); overflow: hidden; } +.admin-row-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; } +.admin-row.kind-artist .admin-row-cover { border-radius: 50%; } +.admin-row-title { font-weight: 600; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.admin-row-sub { font-size: .76rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; } +.admin-row-meta { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; } +.admin-row-meta span { font-size: .7rem; color: var(--text-secondary); border: 1px solid var(--border-color, rgba(128,128,128,.25)); border-radius: 4px; padding: 1px 6px; white-space: nowrap; } +.admin-row-meta span:first-child { color: inherit; } +.admin-row-score { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; min-width: 120px; } +.admin-row-score small { font-size: .68rem; color: var(--text-secondary); } + +/* 不喜欢:卡片视图保持克制 */ +.admin-dislike-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 12px; } +.admin-dislike-grid.is-list { gap: 0; } +.admin-dislike-card { display: flex; align-items: flex-start; gap: 14px; min-width: 0; padding: 14px; border: 1px solid var(--border-color, rgba(128,128,128,.22)); border-radius: 8px; background: transparent; } +.is-list .admin-dislike-card { border: 0; border-bottom: 1px solid var(--border-color, rgba(128,128,128,.16)); border-radius: 0; padding: 10px 14px; align-items: center; } +.is-list .admin-dislike-card:last-child { border-bottom: 0; } +.is-list .admin-dislike-cover { width: 44px; height: 44px; flex-basis: 44px; font-size: 18px; } +.admin-dislike-cover { width: 76px; height: 76px; flex: 0 0 76px; overflow: hidden; border-radius: 4px; background: rgba(128,128,128,.14); display: grid; place-items: center; color: var(--text-secondary); font-size: 26px; } +.admin-dislike-card.kind-artist .admin-dislike-cover { border-radius: 50%; } +.admin-dislike-cover a, .admin-dislike-cover img { display: block; width: 100%; height: 100%; object-fit: cover; } +.admin-dislike-main { flex: 1; min-width: 0; overflow-wrap: anywhere; } +.admin-dislike-main h4 { margin: 6px 0 2px; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } +.admin-dislike-main p { color: var(--text-secondary); margin: 0 0 4px; font-size: .78rem; } +.admin-dislike-badges { display: flex; flex-wrap: wrap; gap: 5px; } +.admin-dislike-badges span { font-size: .7rem; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--border-color, rgba(128,128,128,.25)); color: var(--text-secondary); } +.admin-dislike-badges span.k { color: inherit; } +.admin-dislike-rating { display: flex; align-items: center; gap: 6px; font-size: .78rem; margin-bottom: 2px; } +.admin-dislike-rating .muted { color: var(--text-secondary); opacity: .7; } +.admin-dislike-rating b { color: #d4a017; font-weight: 600; } +.admin-stars { --v: 0; display: inline-block; font-size: 14px; letter-spacing: 2px; line-height: 1; background: linear-gradient(90deg, #d4a017 calc(var(--v) / 5 * 100%), rgba(128,128,128,.3) 0); -webkit-background-clip: text; background-clip: text; color: transparent; } +.admin-dislike-main summary { cursor: pointer; color: var(--text-secondary); font-size: .78rem; padding: 6px 0; } +.admin-dislike-main dl { margin: 8px 0; font-size: .78rem; } +.admin-dislike-main dl > div { display: grid; grid-template-columns: 72px minmax(0,1fr); gap: 8px; padding: 5px 0; border-bottom: 1px solid rgba(128,128,128,.12); } +.admin-dislike-main dt { color: var(--text-secondary); } +.admin-dislike-main dd { margin: 0; } +.admin-dislike-main pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 360px; overflow: auto; padding: 12px; background: rgba(128,128,128,.08); border-radius: 6px; font-size: .72rem; } +.admin-dislike-summary { font-size: .78rem; color: var(--text-secondary); margin: 12px 0 8px; } +.admin-dislike-empty { padding: 40px 12px; text-align: center; color: var(--text-secondary); border: 1px dashed var(--border-color, rgba(128,128,128,.3)); border-radius: 8px; } +.admin-dislike-empty .big { font-size: 28px; opacity: .4; } +.admin-dislike-pages { display: flex; justify-content: center; gap: 10px; margin: 16px 0; } + +@media (max-width: 1100px) { .admin-dislike-toolbar, .admin-ratings .admin-dislike-toolbar { grid-template-columns: repeat(2, minmax(0,1fr)); } .admin-dislike-search { grid-column: 1/-1; } } +@media (max-width: 720px) { + .admin-row { grid-template-columns: 44px minmax(0, 1fr); row-gap: 6px; } + .admin-row-meta { grid-column: 2; justify-content: flex-start; } + .admin-row-score { grid-column: 2; flex-direction: row; align-items: center; justify-content: space-between; min-width: 0; } + .admin-flat-stats > *, .admin-dislike-stat { flex-basis: 33%; border-bottom: 1px solid var(--border-color, rgba(128,128,128,.22)); } + .admin-dislike-grid { grid-template-columns: minmax(0,1fr); } + .admin-dislike-card { padding: 12px; gap: 10px; } + .admin-dislike-cover { width: 56px; height: 56px; flex-basis: 56px; } +} + + +/* 用户音乐数据看板:复用主题变量和 lx-select,限定在数据查看区。 */ +.admin-dislikes { position: relative; margin-block: 26px; animation: admin-panel-in .28s ease-out; } +.admin-dislikes:has(.lx-select.is-open) { z-index: 30; } +.admin-dislikes .data-section-header { margin-bottom: 20px; } +.admin-dislikes .data-tab-count { border-radius: 999px; padding: 5px 12px; background: color-mix(in srgb, var(--accent-primary, #6484ff) 10%, transparent); border: 1px solid color-mix(in srgb, var(--accent-primary, #6484ff) 22%, transparent); } +.admin-flat-stats, .admin-dislike-stats { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; border: 0; background: transparent; overflow: visible; margin-bottom: 18px; } +.admin-dislike-stats { grid-template-columns: repeat(6, minmax(0, 1fr)); } +.admin-flat-stats > *, .admin-dislike-stat { position: relative; min-width: 0; padding: 18px; border: 1px solid var(--border-color, rgba(128,128,128,.2)); border-radius: 14px; text-align: left; background: color-mix(in srgb, var(--bg-card, #20263d) 92%, transparent); transition: border-color .18s ease, background .18s ease, transform .18s ease; } +.admin-flat-stats > button:hover, .admin-dislike-stat:not(.static):hover { transform: translateY(-2px); border-color: var(--accent-primary, #6484ff); } +.admin-flat-stats > .on, .admin-dislike-stat.on { background: color-mix(in srgb, var(--accent-primary, #6484ff) 12%, var(--bg-card, #20263d)); border-color: var(--accent-primary, #6484ff); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-primary, #6484ff) 14%, transparent); } +.admin-flat-stats b, .admin-dislike-stat .s-num { display: block; font-size: clamp(1.25rem, 2vw, 1.8rem); line-height: 1.2; font-variant-numeric: tabular-nums; letter-spacing: -.04em; } +.admin-flat-stats > * > span, .admin-dislike-stat .s-label { display: block; color: var(--text-secondary); margin-top: 8px; font-size: .76rem; } +.admin-dislike-stat .s-icon { position: absolute; top: 16px; right: 16px; color: var(--accent-primary, #6484ff); opacity: .7; } +.admin-rating-insights { display: grid; grid-template-columns: minmax(0, 1fr) minmax(200px, .65fr); gap: 24px; padding: 22px; margin-bottom: 18px; border: 1px solid var(--border-color, rgba(128,128,128,.2)); border-radius: 16px; background: color-mix(in srgb, var(--bg-card, #20263d) 72%, transparent); } +.admin-eyebrow { display: block; color: var(--text-secondary); font-size: .75rem; letter-spacing: .06em; margin-bottom: 14px; } +.admin-dist { max-width: none; margin: 0; } +button.admin-dist-row { width: 100%; border: 1px solid transparent; border-radius: 7px; padding: 6px 8px; background: transparent; text-align: left; cursor: pointer; font: inherit; font-size: .76rem; transition: background .18s ease; } +button.admin-dist-row:hover, button.admin-dist-row.on { background: color-mix(in srgb, var(--accent-primary, #6484ff) 10%, transparent); } +button.admin-dist-row.on { border-color: color-mix(in srgb, var(--accent-primary, #6484ff) 35%, transparent); } +.admin-dist-row i { height: 6px; } +.admin-dist-row u { border-radius: 6px; transition: width .35s ease; background: #e7b74e; } +.admin-insight-score { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; border-left: 1px solid var(--border-color, rgba(128,128,128,.2)); } +.admin-score-ring { width: 100px; height: 100px; border-radius: 50%; background: conic-gradient(#e7b74e calc(var(--score) * 20%), rgba(128,128,128,.15) 0); display: flex; flex-direction: column; justify-content: center; align-items: center; position: relative; isolation: isolate; } +.admin-score-ring::before { content: ''; position: absolute; inset: 7px; border-radius: inherit; background: var(--bg-card, #20263d); z-index: -1; } +.admin-score-ring b { font-size: 1.6rem; font-variant-numeric: tabular-nums; } +.admin-score-ring span, .admin-insight-score small { font-size: .7rem; color: var(--text-secondary); } +.admin-insight-score p { margin: 12px 0 5px; font-size: .8rem; } +.admin-dislike-toolbar, .admin-ratings .admin-dislike-toolbar { grid-template-columns: minmax(200px, 1.7fr) repeat(5, minmax(110px, 1fr)); padding: 14px; border: 1px solid var(--border-color, rgba(128,128,128,.2)); border-radius: 14px; background: color-mix(in srgb, var(--bg-card, #20263d) 65%, transparent); } +.admin-extra-filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin: 12px 0; } +.admin-filter-field { display: flex; flex-direction: column; gap: 7px; min-width: 145px; flex: 1 1 145px; max-width: 240px; } +.admin-filter-field > span { color: var(--text-secondary); font-size: .73rem; } +.admin-extra-filters .lx-select { width: 100%; } +.admin-filter-reset { margin-left: auto; min-height: 44px; } +.admin-dislikes .lx-select-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.admin-rows { border-radius: 14px; } +.admin-row { padding: 16px; transition: background .16s ease; animation: admin-panel-in .22s ease-out; } +.admin-row-main { min-width: 0; } +.admin-row-cover { width: 48px; height: 48px; border-radius: 10px; } +.admin-row-cover img { transition: transform .22s ease; } +.admin-row:hover .admin-row-cover img { transform: scale(1.06); } +.admin-row-meta span { border-radius: 6px; padding: 3px 7px; font-size: .68rem; background: rgba(128,128,128,.04); } +.admin-rating-detail { margin-top: 7px; color: var(--text-secondary); font-size: .72rem; } +.admin-rating-detail summary { width: fit-content; cursor: pointer; color: var(--accent-primary, #8ca8ff); } +.admin-rating-detail p { overflow-wrap: anywhere; } +.admin-rating-detail pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 260px; overflow: auto; padding: 12px; border-radius: 8px; background: rgba(128,128,128,.08); } +.admin-dislike-card { transition: border-color .18s ease, background .18s ease, transform .18s ease; animation: admin-panel-in .22s ease-out; } +.admin-dislike-grid:not(.is-list) .admin-dislike-card:hover { transform: translateY(-3px); } +.admin-dislikes button:focus-visible, .admin-rating-detail summary:focus-visible { outline: 2px solid var(--accent-primary, #6484ff); outline-offset: 3px; } +@keyframes admin-panel-in { from { opacity: .4; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } } +@media (max-width: 1400px) { .admin-dislike-toolbar, .admin-ratings .admin-dislike-toolbar { grid-template-columns: repeat(3, minmax(0, 1fr)); } .admin-dislike-search { grid-column: span 2; } } +@media (max-width: 900px) { .admin-flat-stats, .admin-dislike-stats { grid-template-columns: repeat(3, minmax(0,1fr)); } .admin-rating-insights { gap: 16px; padding: 16px; } .admin-flat-stats > *, .admin-dislike-stat { padding: 14px; } } +@media (max-width: 600px) { .admin-dislike-toolbar, .admin-ratings .admin-dislike-toolbar { grid-template-columns: repeat(2,minmax(0,1fr)); padding: 10px; } .admin-dislike-search { grid-column: 1 / -1; } .admin-flat-stats, .admin-dislike-stats { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 8px; } .admin-rating-insights { grid-template-columns: 1fr; } .admin-insight-score { border-left: 0; border-top: 1px solid var(--border-color, rgba(128,128,128,.2)); padding-top: 16px; } .admin-filter-field { max-width: none; } .admin-filter-reset { margin-left: 0; } } +@media (prefers-reduced-motion: reduce) { .admin-dislikes, .admin-dislikes *, .admin-dislikes *::before { animation: none !important; transition: none !important; scroll-behavior: auto !important; } } + +.admin-dislikes .admin-dislike-stat .s-icon { display: block; } +.admin-dislikes .admin-flat-stats > :last-child, .admin-dislikes .admin-dislike-stat:last-child { border-right: 1px solid var(--border-color, rgba(128,128,128,.2)); } +@media (min-width: 721px) { .admin-row { grid-template-columns: 48px minmax(0,1fr) auto auto; } } + +.admin-row-cover > a { position: absolute; inset: 0; z-index: 1; } +.adm-open { margin-top: 6px; padding: 4px 10px; font-size: .74rem; border: 1px solid var(--border-color, rgba(128,128,128,.3)); border-radius: 6px; background: transparent; color: var(--text-secondary); cursor: pointer; } +.adm-open:hover { color: inherit; background: var(--bg-hover, rgba(128,128,128,.12)); } +.admin-row-main { display: flex; flex-direction: column; align-items: flex-start; } + +.adm-overlay { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; padding: 20px; background: rgba(2,6,23,.6); backdrop-filter: blur(6px); animation: adm-fade .16s ease-out; } +.adm-overlay.closing { opacity: 0; transition: opacity .16s; } +.adm-panel { width: min(640px, 100%); max-height: min(86vh, 760px); display: flex; flex-direction: column; background: var(--bg-card, #181c33); color: var(--text-primary, #e5e7eb); border: 1px solid var(--border-color, rgba(128,128,128,.28)); border-radius: 14px; box-shadow: 0 24px 64px rgba(0,0,0,.5); outline: 0; overflow: hidden; animation: adm-pop .2s cubic-bezier(.2,.9,.3,1.1); } +.adm-grip { display: none; } +.adm-head { display: flex; gap: 16px; align-items: flex-start; padding: 20px 20px 16px; border-bottom: 1px solid var(--border-color, rgba(128,128,128,.2)); position: relative; } +.adm-cover { flex: 0 0 96px; width: 96px; height: 96px; border-radius: 8px; overflow: hidden; background: rgba(128,128,128,.16); display: grid; place-items: center; font-size: 34px; color: var(--text-secondary); } +.adm-cover img { width: 100%; height: 100%; object-fit: cover; display: block; } +.adm-title { min-width: 0; flex: 1; padding-right: 36px; } +.adm-title h3 { margin: 8px 0 2px; font-size: 1.15rem; line-height: 1.3; overflow-wrap: anywhere; } +.adm-title p { margin: 0 0 8px; font-size: .82rem; color: var(--text-secondary); overflow-wrap: anywhere; } +.adm-tags { display: flex; flex-wrap: wrap; gap: 5px; } +.adm-tags span { font-size: .7rem; padding: 1px 7px; border-radius: 4px; border: 1px solid var(--border-color, rgba(128,128,128,.3)); color: var(--text-secondary); } +.adm-tags span.k { color: inherit; background: rgba(128,128,128,.14); } +.adm-score { display: flex; align-items: center; gap: 8px; } +.adm-score.muted { color: var(--text-secondary); font-size: .8rem; } +.adm-score b { color: #d4a017; } +.admin-stars.lg { font-size: 20px; } +.adm-x { position: absolute; top: 14px; right: 14px; width: 30px; height: 30px; border-radius: 6px; border: 0; background: transparent; color: var(--text-secondary); cursor: pointer; } +.adm-x:hover { background: var(--bg-hover, rgba(128,128,128,.16)); color: inherit; } +.adm-body { overflow: auto; padding: 4px 20px 20px; } +.adm-section { padding-top: 16px; } +.adm-section h5 { margin: 0 0 8px; font-size: .7rem; letter-spacing: .08em; color: var(--text-secondary); font-weight: 600; } +.adm-section dl { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; } +.adm-field { padding: 8px 0; border-bottom: 1px solid var(--border-color, rgba(128,128,128,.14)); min-width: 0; } +.adm-field dt { font-size: .7rem; color: var(--text-secondary); margin-bottom: 2px; } +.adm-field dd { margin: 0; display: flex; align-items: center; gap: 8px; font-size: .86rem; min-width: 0; } +.adm-val { overflow-wrap: anywhere; min-width: 0; } +.adm-val.mono { font-family: ui-monospace, Consolas, monospace; font-size: .78rem; } +.adm-copy { flex: none; font-size: .68rem; padding: 1px 7px; border-radius: 4px; border: 1px solid var(--border-color, rgba(128,128,128,.3)); background: transparent; color: var(--text-secondary); cursor: pointer; } +.adm-copy:hover { color: inherit; } +.adm-chips { display: flex; flex-wrap: wrap; gap: 5px; } +.adm-chips span { font-size: .74rem; padding: 2px 8px; border-radius: 4px; background: rgba(128,128,128,.14); } +.adm-field:has(.adm-chips) { grid-column: 1 / -1; } +.adm-raw { margin-top: 18px; } +.adm-raw summary { cursor: pointer; font-size: .78rem; color: var(--text-secondary); } +.adm-raw-tools { margin: 8px 0; } +.adm-raw pre { max-height: 240px; overflow: auto; margin: 0; padding: 12px; border-radius: 6px; background: rgba(128,128,128,.1); font-size: .72rem; white-space: pre-wrap; overflow-wrap: anywhere; } +@keyframes adm-fade { from { opacity: 0; } } +@keyframes adm-pop { from { opacity: 0; transform: translateY(10px) scale(.97); } } +@keyframes adm-sheet { from { transform: translateY(100%); } } +@media (max-width: 600px) { + .adm-overlay { align-items: end; padding: 0; } + .adm-panel { width: 100%; max-height: 90vh; border-radius: 16px 16px 0 0; animation: adm-sheet .26s cubic-bezier(.2,.9,.3,1); } + .adm-grip { display: block; width: 36px; height: 4px; border-radius: 4px; background: rgba(128,128,128,.4); margin: 8px auto 0; } + .adm-head { padding: 12px 16px; gap: 12px; } + .adm-cover { flex-basis: 72px; width: 72px; height: 72px; } + .adm-body { padding: 0 16px calc(16px + env(safe-area-inset-bottom)); } + .adm-section dl { grid-template-columns: minmax(0, 1fr); } +} +@media (prefers-reduced-motion: reduce) { .adm-overlay, .adm-panel { animation: none; } } + +/* Subsonic 播放缓存:独立布局,避免说明挤占配置项。 */ +.subsonic-cache-settings { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 18px 28px; align-items: center; } +.subsonic-cache-settings .config-toggle-row { min-width: 0; min-height: 48px; gap: 16px; margin: 0; } +.subsonic-cache-settings .config-toggle-info { min-width: 0; } +.subsonic-cache-settings .toggle-switch { flex-shrink: 0; } +.subsonic-cache-settings .config-field { min-width: 0; margin: 0; } +.subsonic-cache-help-row { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-top: 14px; border-top: 1px solid var(--border-color, #64748b33); font-size: .8rem; color: var(--text-secondary); } +.subsonic-cache-help-row > span { display: inline-flex; align-items: center; gap: 6px; } +.subsonic-cache-help-row a { color: var(--accent-primary, #8ca8ff); text-decoration: none; } +.subsonic-cache-help-row a:hover { text-decoration: underline; } +@media(max-width:720px) { .subsonic-cache-settings { grid-template-columns: minmax(0,1fr); gap: 14px; } } + +/* User data: consistent dislike rows and compact cards. */ +.admin-dislike-score { min-width: 104px; text-align: right; } +.admin-dislike-score .admin-dislike-rating { justify-content: flex-end; gap: 8px; } +.admin-dislike-score small { color: var(--text-secondary); font-size: .72rem; } +.admin-dislike-grid.is-list .admin-dislike-card { display: grid; grid-template-columns: 56px minmax(180px, 1fr) minmax(160px, auto) 116px; gap: 18px; padding: 18px 20px; } +.admin-dislike-grid.is-list .admin-dislike-cover { width: 56px; height: 56px; } +.admin-dislike-grid.is-list .admin-dislike-badges { justify-content: flex-end; max-width: 360px; } +.admin-dislike-main h4 { margin: 0 0 5px; } +.admin-dislike-main .adm-open { margin-top: 6px; } +.admin-dislike-grid:not(.is-list) .admin-dislike-card { display: grid; grid-template-columns: 64px minmax(0, 1fr); align-items: start; } +.admin-dislike-grid:not(.is-list) .admin-dislike-cover { width: 64px; height: 64px; } +.admin-dislike-grid:not(.is-list) .admin-dislike-badges { grid-column: 1 / -1; } +.admin-dislike-grid:not(.is-list) .admin-dislike-score { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; text-align: left; } +.admin-rating-status-help { margin-left: 6px; border: 0; padding: 0; font: inherit; font-size: .75rem; vertical-align: middle; } +@media (max-width: 1100px) { + .admin-dislike-grid.is-list .admin-dislike-card { grid-template-columns: 48px minmax(0, 1fr) 104px; gap: 12px; } + .admin-dislike-grid.is-list .admin-dislike-cover { width: 48px; height: 48px; } + .admin-dislike-grid.is-list .admin-dislike-badges { grid-column: 2; grid-row: 2; justify-content: flex-start; } + .admin-dislike-grid.is-list .admin-dislike-score { grid-column: 3; grid-row: 1 / 3; } +} +@media (max-width: 540px) { + .admin-dislike-grid.is-list .admin-dislike-card { padding: 14px 12px; grid-template-columns: 44px minmax(0, 1fr); } + .admin-dislike-grid.is-list .admin-dislike-cover { width: 44px; height: 44px; } + .admin-dislike-grid.is-list .admin-dislike-score { grid-column: 2; grid-row: 3; display: flex; align-items: center; justify-content: space-between; gap: 8px; text-align: left; } + .admin-dislike-grid.is-list .admin-dislike-badges { grid-column: 2; } +} + +.admin-dislikes > .data-section-header > .data-tab-count { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; min-width: 48px; height: auto; line-height: 1.5; white-space: nowrap; background-image: none; overflow: visible; } +.admin-dislikes > .data-section-header > .data-tab-count::before, .admin-dislikes > .data-section-header > .data-tab-count::after { content: none; } + +.admin-section-count { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; min-width: 48px; padding: 5px 12px; border: 1px solid rgba(100,132,255,.25); border-radius: 999px; background: rgba(100,132,255,.08); color: var(--text-secondary); font-size: .75rem; font-weight: 600; line-height: 1.5; white-space: nowrap; } diff --git a/scripts/sdk-interface-audit.mjs b/scripts/sdk-interface-audit.mjs deleted file mode 100644 index 3894814a..00000000 --- a/scripts/sdk-interface-audit.mjs +++ /dev/null @@ -1,99 +0,0 @@ -// Live, read-only SDK audit. Run before and after a migration with the same cases. -import { build } from 'esbuild' -import fs from 'node:fs/promises' -import path from 'node:path' -import { pathToFileURL } from 'node:url' -import { execFileSync } from 'node:child_process' - -const phase = process.argv[2] || 'after' -if (!['before', 'after'].includes(phase)) throw new Error('Expected phase: before or after') -const dir = path.resolve('reports/sdk-interface-audit') -const buildDir = path.resolve('cache/sdk-interface-audit') -await fs.mkdir(dir, { recursive: true }) -await fs.mkdir(buildDir, { recursive: true }) -const baselineRef = process.env.SDK_AUDIT_BASE_REF || execFileSync('git', ['-c', 'safe.directory=E:/Antigravity/lxserver', 'rev-parse', 'HEAD'], { encoding: 'utf8' }).trim() -const root = path.resolve('src/modules/utils/musicSdk').replaceAll('\\', '/') -const names = ['tx/musicSearch', 'tx/musicInfo', 'tx/singer', 'tx/songList', 'tx/lyric', 'kg/musicSearch', 'kg/songList', 'kg/leaderboard', 'kw/musicSearch', 'kw/songList', 'kw/lyric', 'wy/musicSearch', 'wy/songList', 'wy/singer', 'wy/lyric', 'mg/musicSearch', 'mg/pic', 'mg/lyric'] -await build({ - stdin: { contents: names.map((n, i) => `import m${i} from ${JSON.stringify(root + '/' + n + '.js')};`).join('\n') + '\nexport default {' + names.map((n, i) => `${JSON.stringify(n)}:m${i}`).join(',') + '}', resolveDir: process.cwd(), loader: 'js' }, - outfile: path.join(buildDir, phase + '.cjs'), bundle: true, platform: 'node', format: 'cjs', packages: 'external', - plugins: [{ name: 'audit-request-observer', setup(b) { - if (phase === 'before') b.onLoad({ filter: /[\\/]musicSdk[\\/].*\.[jt]s$/ }, ({ path: p }) => { - const relative = path.relative(process.cwd(), p).replaceAll('\\', '/') - return { contents: execFileSync('git', ['-c', 'safe.directory=E:/Antigravity/lxserver', 'show', baselineRef + ':' + relative], { encoding: 'utf8' }), loader: p.endsWith('.ts') ? 'ts' : 'js', resolveDir: path.dirname(p) } - }) - b.onLoad({ filter: /[\\/]utils[\\/]request\.js$/ }, async ({ path: p }) => { - let contents = await fs.readFile(p, 'utf8') - contents = contents.replace('export const httpFetch =', 'const originalHttpFetch =') - contents += `\nexport const httpFetch = (url, options = {}) => { - const record = { url: String(url).split('?')[0], method: options.method || 'GET' }; - globalThis.__auditRequests?.push(record); - const req = originalHttpFetch(url, { ...options, timeout: 6000 }); - globalThis.__auditActive?.add(req); - req.promise = req.promise.then(resp => { record.status = resp.statusCode; record.code = resp.body?.code ?? resp.body?.errcode ?? resp.body?.error_code; - record.modules = Object.fromEntries(Object.entries(resp.body || {}).filter(([k,v]) => v && typeof v === 'object' && 'code' in v).map(([k,v]) => [k, {code:v.code, keys:Object.keys(v.data || {})}])); - if (resp.body?.resource) record.resource = { count:resp.body.resource.length, keys:Object.keys(resp.body.resource[0] || {}) }; - return resp; }) - .catch(err => { record.error = err.message; throw err; }).finally(() => globalThis.__auditActive?.delete(req)); - return req; - };` - return { contents, loader: 'js', resolveDir: path.dirname(p) } - }) - } }], -}) -globalThis.lx = { config: {} } -globalThis.__auditRequests = [] -globalThis.__auditActive = new Set() -process.on('unhandledRejection', error => console.error('SDK unhandled rejection:', error?.message || error)) -const sdk = (await import(pathToFileURL(path.join(buildDir, phase + '.cjs')).href)).default.default -const results = [] -const samples = {} -const unwrap = value => value?.promise || value -async function check(name, call, validate) { - const start = Date.now(), offset = globalThis.__auditRequests.length - let timer - try { - const value = await Promise.race([Promise.resolve().then(call).then(unwrap), new Promise((_, reject) => { timer = setTimeout(() => reject(new Error('audit deadline (20s)')), 20000) })]) - const summary = validate(value) - results.push({ name, ok: true, ms: Date.now() - start, summary }) - } catch (error) { results.push({ name, ok: false, ms: Date.now() - start, error: error.message }) } - finally { clearTimeout(timer); for (const r of globalThis.__auditActive) r.cancelHttp?.(); globalThis.__auditActive.clear() } - results.at(-1).requests = globalThis.__auditRequests.slice(offset) - console.log(JSON.stringify(results.at(-1))) - await fs.writeFile(path.join(dir, phase + '.json'), JSON.stringify({ phase, baselineRef, time: new Date().toISOString(), results }, null, 2)) -} -function list(v) { if (!Array.isArray(v?.list) || !v.list.length) throw new Error('missing/non-empty list'); return { count: v.list.length, total: v.total, first: v.list[0].name || v.list[0].info?.name } } -function info(v) { if (!v?.info?.name) throw new Error('missing info.name'); return { name: v.info.name } } -function lyric(v) { if (!v?.lyric || !/\[\d+:\d+/.test(v.lyric)) throw new Error('missing timed lyric'); return { length: v.lyric.length, word: !!v.lxlyric, translation: !!v.tlyric } } -for (const source of ['tx', 'kg', 'kw', 'wy', 'mg']) { - await check(source + '.search', async () => { - const v = await sdk[source + '/musicSearch'].search('周杰伦', 1, 10) - samples[source] = v.list?.[0] - return v - }, list) -} -// Fixed detail fixtures keep before/after comparisons independent of search rankings. -const txSample = { songmid: '0027oMO61wWi55', songId: 718475 } -const mgSample = { songmid: '1140505222', copyrightId: '60054704965' } -await check('tx.musicInfo', () => sdk['tx/musicInfo'](txSample.songmid), v => { if (!v?.songmid) throw new Error('missing songmid'); return { name: v.name } }) -for (const method of ['getInfo', 'getAlbumList', 'getSongList']) await check('tx.singer.' + method, () => sdk['tx/singer'][method]('0025NhlN2yWrP4', 1, 5), method === 'getInfo' ? info : list) -await check('tx.playlist.hot', () => sdk['tx/songList'].getList(3, null, 1), v => { samples.txList = v.list?.[0]; return list(v) }) -await check('tx.playlist.default', () => sdk['tx/songList'].getList('hot', null, 1), list) -await check('tx.playlist.recommend', () => sdk['tx/songList'].getList(-1, null, 1), list) -await check('tx.playlist.tag', () => sdk['tx/songList'].getList(3, '165', 1), list) -await check('tx.playlist.detail', () => sdk['tx/songList'].getListDetail('9013043487'), list) -await check('tx.lyric', () => sdk['tx/lyric'].getLyric(txSample), lyric) -await check('kw.lyric', () => sdk['kw/lyric'].getLyric({ songmid: '118990' }), lyric) -await check('kw.playlist', () => sdk['kw/songList'].getList('hot', null, 1), list) -await check('wy.tags', () => sdk['wy/songList'].getTag(), v => { if (!Array.isArray(v) || !v.length) throw new Error('missing tags'); return { count: v.length } }) -for (const method of ['getInfo', 'getAlbumList', 'getSongList']) await check('wy.singer.' + method, () => sdk['wy/singer'][method]('6452', 1, 5), method === 'getInfo' ? info : list) -await check('wy.lyric', () => sdk['wy/lyric']('186016'), lyric) -await check('mg.pic', () => sdk['mg/pic'].getPic(mgSample), v => { if (typeof v !== 'string' || !/^https?:/.test(v)) throw new Error('expected image URL, got ' + typeof v); return { url: v } }) -await check('mg.lyric', () => sdk['mg/lyric'].getLyric(mgSample), lyric) -await check('kg.playlist', () => sdk['kg/songList'].getList('5', null, 1), v => { samples.kgList = v.list?.[0]; return list(v) }) -await check('kg.playlist.detail', () => sdk['kg/songList'].getListDetail('id_1067062', 1), list) -// Real shared chain/code values must be supplied; invented codes are not success tests. -if (process.env.KG_SHARE_LINK) await check('kg.playlist.share', () => sdk['kg/songList'].getListDetail(process.env.KG_SHARE_LINK, 1), list) -if (process.env.KG_SHARE_CODE) await check('kg.playlist.code', () => sdk['kg/songList'].getListDetail(process.env.KG_SHARE_CODE, 1), list) -console.log(`Completed ${results.length} cases: ${results.filter(r => r.ok).length} passed. Report: ${dir}/${phase}.json`) -process.exitCode = results.some(r => !r.ok) ? 1 : 0 diff --git a/src/defaultConfig.ts b/src/defaultConfig.ts index 77037961..bb5fcd84 100644 --- a/src/defaultConfig.ts +++ b/src/defaultConfig.ts @@ -108,9 +108,8 @@ const config: LX.Config = { 'subsonic.sharedListMode': 'leaderboard', // 共享歌单内容模式: leaderboard | playlist | both 'subsonic.sharedListSort': 'hot', // 共享歌单排序: hot | new 'subsonic.dislikeRating': 1, // 评分联动 dislike 阈值: 0 < rating <= 该值 视为不喜欢(写回原生 dislike 规则); 设为 0 关闭联动 - 'subsonic.ratingPlaylists': true, // 是否向 Subsonic 客户端暴露 1~5 星评星歌单(虚拟只读, 不落盘); 开启时 1 星歌单承载「我不喜欢」并强制双向联动 + 'subsonic.ratingPlaylists': true, // 是否向 Subsonic 客户端暴露 1~5 星评星歌单(虚拟只读, 不落盘); 仅控制歌单显示,不改变联动开关 'subsonic.linkRatingToDislike': false, // 解耦开关(正向): 评星 -> 不喜欢 是否自动联动; false=不联动(仅记录评分) - 'subsonic.linkDislikeToRating': false, // 解耦开关(反向): 不喜欢 -> 评星 是否自动联动; false=不联动(仅记录不喜欢) 'subsonic.hideDisliked': true, // 是否在 Subsonic 列表中隐藏 dislike 命中的歌曲(关闭则只评分不剔除) 'subsonic.dislikeCrossSource': false, // dislike 是否跨平台同名命中(各平台 ID 不互通, 开启会误伤同名歌手/专辑) 'subsonic.dislikeNoRecommend': true, // 推荐类接口(每日推荐/随机/相似)是否排除 dislike 歌曲(与 hideDisliked 独立) diff --git a/src/modules/dislike/dislikeDataManage.ts b/src/modules/dislike/dislikeDataManage.ts index 84669200..1f5e74e3 100644 --- a/src/modules/dislike/dislikeDataManage.ts +++ b/src/modules/dislike/dislikeDataManage.ts @@ -1,8 +1,9 @@ +import { registerDislikeMigration } from '../../server/rating/ratingMigration' import fs from 'node:fs' import path from 'node:path' import { SPLIT_CHAR } from '@/constants' import { type SnapshotDataManage } from './snapshotDataManage' -import { filterRules, encodeAlbumRule } from './utils' +import { encodeAlbumRule, canonicalDislikeRule, scopedDislikeRule } from './utils' export class DislikeDataManage { snapshotDataManage: SnapshotDataManage @@ -10,6 +11,7 @@ export class DislikeDataManage { constructor(snapshotDataManage: SnapshotDataManage) { this.snapshotDataManage = snapshotDataManage + if (snapshotDataManage.dislikeDir) registerDislikeMigration(path.dirname(snapshotDataManage.dislikeDir), this) try { const latest = this.snapshotDataManage.snapshotInfo?.latest @@ -72,7 +74,7 @@ export class DislikeDataManage { // Returns all active rule strings separated by newline (used by dislikeCache for parsing) getDislikeRulesString = (): string => { return this.dislikeRules.dislikeList - .map(s => this.buildDislikeRule(s)) + .map(s => scopedDislikeRule(this.buildDislikeRule(s), (s as any).source)) .filter(Boolean) .join('\n') } @@ -84,44 +86,76 @@ export class DislikeDataManage { } addDislikeInfo = async(infos: LX.Dislike.DislikeSongInfo[]) => { - // Check for duplicates - const currentRules = new Set(this.dislikeRules.dislikeList.map(s => this.buildDislikeRule(s))) - for (const info of infos) { - const rule = this.buildDislikeRule(info) - if (!rule) continue - if (!currentRules.has(rule)) { - info.dislikeRule = rule + const key = (item: any) => scopedDislikeRule(this.buildDislikeRule(item), item.source) + const current = new Map(this.dislikeRules.dislikeList.map(item => [key(item), item])) + for (const raw of infos) { + const info: any = { ...raw, dislikeRule: canonicalDislikeRule(this.buildDislikeRule(raw)) } + if (!info.dislikeRule) continue + info.provenance = info.provenance || { channel: 'unknown', at: Date.now() } + info.reasons = info.reasons || [info.provenance] + const existing: any = current.get(key(info)) + if (existing) { + // 只有身份不冲突时补字段;同名不同ID不能互相污染。 + const identity = (x: any) => String(x.songmid || x.id || '').replace(new RegExp('^' + (x.source || '') + '_'), '') + const reasons = existing.reasons || [existing.provenance || { channel: 'unknown', at: Date.now() }] + for (const reason of info.reasons) if (!reasons.some((x: any) => x.channel === reason.channel && x.ratingId === reason.ratingId)) reasons.push(reason) + existing.reasons = reasons + if (identity(existing) && identity(info) && identity(existing) !== identity(info)) continue + const fill = (target: any, incoming: any) => { + for (const [field, value] of Object.entries(incoming)) { + if (['dislikeRule', 'provenance', 'reasons', '__proto__', 'constructor', 'prototype'].includes(field) || value == null || value === '') continue + const old = target[field] + if (old == null || old === '' || (Array.isArray(old) && !old.length)) target[field] = value + else if (typeof old === 'object' && !Array.isArray(old) && typeof value === 'object' && !Array.isArray(value)) fill(old, value) + } + } + const before = JSON.stringify(existing) + fill(existing, info) + if (JSON.stringify(existing) !== before) existing.enrichedBy = info.provenance + } else { this.dislikeRules.dislikeList.push(info) - currentRules.add(rule) + current.set(key(info), info) } } return this.dislikeRules } + /** 同步读取当前规则并裁剪原因,避免预览期间新增的手动原因被旧副本覆盖。 */ + reconcileRatingReasons = (validIds: Set, preview = true) => { + const removed: any[] = [] + const next: LX.Dislike.DislikeSongInfo[] = [] + for (const item of this.dislikeRules.dislikeList) { + const reasons = item.reasons || [item.provenance || { channel: 'unknown', at: 0 }] + const remaining = reasons.filter(reason => { + const keep = !reason.ratingId || validIds.has(reason.ratingId) + if (!keep) removed.push({ rule: item.dislikeRule, source: item.source, ratingId: reason.ratingId }) + return keep + }) + if (remaining.length) next.push({ ...item, reasons: remaining, provenance: remaining[0] }) + } + const result = { removedReasons: removed.length, removedRules: this.dislikeRules.dislikeList.length - next.length, removals: removed } + if (!preview) this.dislikeRules = { dislikeList: next } + return result + } + + removeDislikeInfo = async(rule: string, source?: string) => { + const wanted = scopedDislikeRule(rule, source) + this.dislikeRules.dislikeList = this.dislikeRules.dislikeList.filter(item => scopedDislikeRule(this.buildDislikeRule(item), (item as any).source) !== wanted) + } + addDislikeAlbums = async(infos: LX.Dislike.DislikeAlbumInfo[]) => { if (!infos || infos.length === 0) return this.dislikeRules - const currentRules = new Set(this.dislikeRules.dislikeList.map(s => this.buildDislikeRule(s))) - const lines = infos.map(info => encodeAlbumRule(info.albumName, info.singer)) - - for (let i = 0; i < lines.length; i++) { - const rule = lines[i] - if (!currentRules.has(rule)) { - this.dislikeRules.dislikeList.push({ - name: '', - singer: '', - dislikeRule: rule - }) - currentRules.add(rule) - } - } + await this.addDislikeInfo(infos.map(info => ({ name: '', singer: '', + dislikeRule: encodeAlbumRule(info.albumName, info.singer), source: info.source, + provenance: info.provenance, reasons: info.reasons }))) return this.dislikeRules } overwirteDislikeInfo = async(rulesString: string) => { - const validRules = new Set(filterRules(rulesString)) + const validRules = new Set(rulesString.split('\n').map(r => r.trim()).filter(Boolean)) const existingMap = new Map() for (const item of this.dislikeRules.dislikeList) { - const r = this.buildDislikeRule(item) + const r = scopedDislikeRule(this.buildDislikeRule(item), (item as any).source) if (r && validRules.has(r)) { existingMap.set(r, item) } @@ -134,7 +168,8 @@ export class DislikeDataManage { newDislikeList.push({ name: '', singer: '', - dislikeRule: r, + dislikeRule: r.includes('::') ? r.split('::').slice(1).join('::') : r, + source: r.split('::')[0] === '*' ? undefined : r.split('::')[0], }) } } diff --git a/src/modules/dislike/match.ts b/src/modules/dislike/match.ts index ddf0bc76..5b558194 100644 --- a/src/modules/dislike/match.ts +++ b/src/modules/dislike/match.ts @@ -1,5 +1,5 @@ import { SPLIT_CHAR } from '@/constants' -import { parseAlbumRule } from './utils' +import { canonicalDislikeRule, parseAlbumRule } from './utils' import { normalizeText, normalizeSongName } from '@/server/utils/songVersion' /** @@ -20,6 +20,7 @@ export const splitSingers = (singer: unknown): string[] => export interface DislikeRuleSet { /** 精确规则:歌名@歌手 */ + scoped?: Map exact: Set /** 纯歌名规则 */ musicNames: Set @@ -43,7 +44,23 @@ export function parseDislikeRules(rules: string): DislikeRuleSet { } for (const raw of String(rules || '').split('\n')) { - const line = raw.trim() + let line = raw.trim() + const scope = line.indexOf('::') + if (scope >= 0) { + const source = line.slice(0, scope) + const body = line.slice(scope + 2) + if (source !== '*') { + set.scoped ||= new Map() + const prior = set.scoped.get(source) + const parsed = parseDislikeRules(body) + if (prior) { + for (const key of ['exact', 'musicNames', 'singerNames'] as const) for (const value of parsed[key]) prior[key].add(value) + for (const [name, singers] of parsed.albums) { const target = prior.albums.get(name) || new Set(); for (const singer of singers) target.add(singer); prior.albums.set(name, target) } + } else set.scoped.set(source, parsed) + continue + } + line = body + } if (!line) continue // 专辑维度(!<专辑名>@<歌手>,按歌手多条,聚合到专辑名 -> 歌手集合) @@ -60,7 +77,7 @@ export function parseDislikeRules(rules: string): DislikeRuleSet { // 歌曲 / 歌手维度 const [name, singer] = line.split(SPLIT_CHAR.DISLIKE_NAME) - const n = normalizeText(name) + const n = canonicalDislikeRule(normalizeText(name)) const s = normalizeText(singer) // 额外登记「去后缀」版本,让「晴天 (Live)」也能命中「晴天」规则(反之亦然)。 // 开关关闭时匹配端不会用归一化名,这些额外 key 自然不会被命中。 @@ -145,19 +162,24 @@ export function isDisliked( set: DislikeRuleSet, options: DislikeMatchOptions = {}, ): boolean { + if (set.scoped) { + for (const [source, rules] of set.scoped) { + if ((options.crossSource || source === input.source) && isDisliked(input, rules, options)) return true + } + } const crossSource = options.crossSource === true const duetMode = options.duetMode || 'any' const normalizeName = options.normalizeName !== false const requireSinger = options.requireSinger !== false - const name = normalizeText(input.name) + const name = canonicalDislikeRule(normalizeText(input.name)) const allSingers = splitSingers(input.singer) // primary 模式只看主唱(第一位歌手) const singers = duetMode === 'primary' ? allSingers.slice(0, 1) : allSingers const source = normalizeText(input.source) // 候选歌名:原名 + 去后缀名(去重),提升对 Live / Remix 等版本的召回 const candidateNames = Array.from(new Set( - [name, normalizeName ? normalizeSongName(input.name) : ''].filter(Boolean) + [name, normalizeName ? canonicalDislikeRule(normalizeSongName(input.name)) : ''].filter(Boolean) )) // 1. 专辑维度(专辑名 + 歌手集合,复用 duetMode 决定多歌手判定方式) @@ -221,3 +243,11 @@ export function filterDisliked( if (!items || items.length === 0) return items return items.filter(item => !isDisliked(toInput(item), set, options)) } + +export function scopeDislikeRules(set: DislikeRuleSet, source?: string): DislikeRuleSet { + if (!source) return set + set.scoped ||= new Map() + let rules = set.scoped.get(source) + if (!rules) { rules = parseDislikeRules(''); set.scoped.set(source, rules) } + return rules +} diff --git a/src/modules/dislike/utils.ts b/src/modules/dislike/utils.ts index 25644344..5406a487 100644 --- a/src/modules/dislike/utils.ts +++ b/src/modules/dislike/utils.ts @@ -70,3 +70,10 @@ export const filterRules = (rules: string) => { } return new Set(list) } + +/** 固定格式去重键;保留 Live 等版本语义,只消除大小写和括号邻接空格。 */ +export const canonicalDislikeRule = (rule: string): string => + rule.normalize('NFKC').trim().toLowerCase().replace(/\s*([()@])\s*/g, '$1') + +export const scopedDislikeRule = (rule: string, source?: string): string => + `${source || '*'}::${canonicalDislikeRule(rule)}` diff --git a/src/server/integrations/subsonic.ts b/src/server/integrations/subsonic.ts index d112a1c0..0b8ff59a 100644 --- a/src/server/integrations/subsonic.ts +++ b/src/server/integrations/subsonic.ts @@ -1,3 +1,5 @@ +import { withRatingIdentityLock } from '../rating/ratingIdentityLock' +import { writeRating, writeRatingUnlocked, recordRatingBackfillFailure, flushRatingSnapshot, readRatings, resolveStoredRatingId } from '../rating/ratingService' import { lookupLocalLyrics } from '@/server/music/localLyrics' import http from 'http' import { Readable } from 'stream' @@ -5,7 +7,7 @@ import { pipeline } from 'stream/promises' import crypto from 'crypto' import { URL } from 'url' import { getUserSpace, getUserDirname, getUserConfig } from '@/user' -import { createRatingSnapshot } from '../ratingSnapshot' +import { createRatingSnapshot, withMetaLock } from '../rating/ratingSnapshot' import { callUserApiGetMusicUrl } from '@/server/sources/userApi' import { downloadAndCache, checkCache, serveCacheFile, getFileName } from '@/server/music/fileCache' import { resolveOpenlistCacheEntry } from '@/server/openlist/openlistBackup' @@ -24,7 +26,7 @@ import { proxyCoverImage } from '@/server/media/coverProxy' import { subsonicLog } from '@/utils/log4js' import { fetchGenres, fetchRadios, fetchPlaylistsByGenre, fetchRadioSongs, fetchPlaylistSongs, fetchSongsByGenre } from '@/server/utils/discovery' import { listRadioStations, getRadioStation, addRadioStation, updateRadioStation, removeRadioStation } from '@/server/music/radioStations' -import { getLocalTracks, findLocalTrack, localMusic, localSong, localAlbums, localArtists, localFile, localCover, localLyrics, serveLocalTrack, isLocalSong, isLocalEntity, getLocalScanStatus, readLocalState, editLocalState, mergeLocalPlaylist } from '@/server/music/subsonicLocal' +import { getLocalTracks, localRatingId, findLocalTrack, localMusic, localSong, localAlbums, localArtists, localFile, localCover, localLyrics, serveLocalTrack, isLocalSong, isLocalEntity, getLocalScanStatus, readLocalState, editLocalState, mergeLocalPlaylist } from '@/server/music/subsonicLocal' import { getCustomMusicDir } from '@/server/music/customMusicManager' import { checkLyricCache } from '@/server/music/fileCache' import { parseLyrics } from '@/utils/lrcTool' @@ -144,6 +146,12 @@ export interface LinkSyncSummary { threshold: number /** 实际处理的批次数(0 表示无待处理条目) */ batches: number + candidates?: Array<{ id: string, name?: string, source?: string }> + updated?: number + warning?: string + existing?: any[] + duplicates?: any[] + failures?: any[] } const countDislikeRules = (rules: string): number => @@ -459,6 +467,7 @@ export interface SubsonicMeta { starredAlbums: string[] starredArtists: string[] starredArtistNames: string[] + ratingOrigins?: Record ratings: Record } @@ -471,22 +480,9 @@ export function getSubsonicMetaFilePath(username: string): string { } export function readSubsonicMeta(username: string): SubsonicMeta { - try { - const filePath = getSubsonicMetaFilePath(username) - if (fs.existsSync(filePath)) { - const data = JSON.parse(fs.readFileSync(filePath, 'utf8')) - return { - starredAlbums: Array.isArray(data.starredAlbums) ? data.starredAlbums : [], - starredArtists: Array.isArray(data.starredArtists) ? data.starredArtists : [], - // 兼容旧版元数据:starredArtistNames 可能为 undefined - starredArtistNames: Array.isArray(data.starredArtistNames) ? data.starredArtistNames : [], - ratings: data.ratings && typeof data.ratings === 'object' ? data.ratings : {}, - } - } - } catch (e) { - subsonicLog.error('[Subsonic] Failed to read subsonic-meta.json:', e) - } - return { starredAlbums: [], starredArtists: [], starredArtistNames: [], ratings: {} } + const data = readRatings(username) + return { ...data, starredAlbums: Array.isArray(data.starredAlbums) ? data.starredAlbums : [], starredArtists: Array.isArray(data.starredArtists) ? data.starredArtists : [], starredArtistNames: Array.isArray(data.starredArtistNames) ? data.starredArtistNames : [] } + } export function writeSubsonicMeta(username: string, meta: SubsonicMeta) { @@ -494,9 +490,11 @@ export function writeSubsonicMeta(username: string, meta: SubsonicMeta) { const filePath = getSubsonicMetaFilePath(username) const dirPath = path.dirname(filePath) if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }) - fs.writeFileSync(filePath, JSON.stringify(meta), 'utf8') + fs.writeFileSync(filePath + '.meta.tmp', JSON.stringify(meta), 'utf8') + fs.renameSync(filePath + '.meta.tmp', filePath) } catch (e) { subsonicLog.error('[Subsonic] Failed to write subsonic-meta.json:', e) + throw e } } @@ -734,53 +732,18 @@ export function syncNativeLibraryToSubsonic( * 后写入者会整体覆盖前者的修改,导致用户刚设置的星标或评分丢失。 * 这里按 username 串成 Promise 链,保证同一用户的读-改-写严格顺序执行。 */ -const metaLocks = new Map>() - -/** - * 同一用户 subsonic-meta.json 的「读-改-写」串行化锁。 - * 避免 handleSetRating / handleStar / syncDislikeToRating 并发写同一文件互相覆盖。 - */ -function withMetaLock(username: string, task: () => Promise): Promise { - const prev = metaLocks.get(username) ?? Promise.resolve() - const run = (): Promise => task() - // 前一个任务无论成功还是失败都要继续,避免一次异常卡死整条队列 - const next = prev.then(run, run) - const tail = next.then(() => undefined, () => undefined) - metaLocks.set(username, tail) - tail.then(() => { - if (metaLocks.get(username) === tail) metaLocks.delete(username) - }) - return next -} - /** * 双向联动:网页端「不喜欢」(dislike) <-> Subsonic 评分(rating)。 * 网页给某首歌点「不喜欢」时,回写该用户 subsonic-meta.json 的 ratings 映射, * 使 Subsonic 客户端能看到这颗低星(与正向联动 handleSetRating 共用同一份存储): - * rating > 0 -> ratings[id] = rating(低星,落入 dislike 区间) - * rating <= 0 -> 删除 ratings[id](恢复未评) + * rating > 0 -> 仅在没有评分时补充低星 + * rating <= 0 -> 不更改评分,保留用户手工数据 * id 即 Subsonic 歌曲 id(source_songId)。模块级函数,供 server.ts 的 /api/music/dislike 直接调用。 */ -export async function syncDislikeToRating(username: string, id: string, rating: number): Promise { - if (!id) return - try { - await withMetaLock(username, async () => { - const meta = readSubsonicMeta(username) - const r = Math.max(0, Math.min(5, Math.floor(rating))) - if (r <= 0) { - if (meta.ratings[id] === undefined) return - delete meta.ratings[id] - } else { - meta.ratings[id] = r - } - writeSubsonicMeta(username, meta) - subsonicLog.debug(`[Subsonic] dislike<->rating 同步: ${id} -> ${r} (user=${username})`) - }) - } catch (e) { - subsonicLog.error('[Subsonic] dislike<->rating 同步失败:', e) - } - // 评分写入后生成/复用一份「我的评分」快照,使当前评分可被下载备份 - void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 评分快照生成失败:', e)) +export async function syncDislikeToRating(username: string, id: string, rating: number, song?: any): Promise { + if (!id || rating <= 0) return + const saved = await writeRating(username, id, rating, 'web-dislike-link', song, { onlyMissing: true }) + if (saved.snapshotWarning) throw new Error(saved.snapshotWarning) } /** @@ -1542,7 +1505,7 @@ class SubsonicHandler { if (isLocalSong(id) && ['stream', 'download', 'getCoverArt', 'getLyrics', 'getLyricsBySongId', 'getSong'].includes(method)) { const track = await findLocalTrack(user, id) if (!track || !localFile(track)) return error('Local song not found in selected storage') - if (method === 'getSong') return send({ song: { ...localSong(track, user), userRating: readSubsonicMeta(user).ratings[id] || 0 } }) + if (method === 'getSong') return send({ song: { ...localSong(track, user), userRating: readSubsonicMeta(user).ratings[localRatingId(track)] || 0 } }) if (method === 'getCoverArt') { const cover = localCover(track) if (cover) { res.setHeader('Content-Type', cover.mime); res.end(cover.data) } @@ -1747,7 +1710,7 @@ class SubsonicHandler { */ private musicToSongFlat(music: LX.Music.MusicInfo, parentId: string, artistIdOverride?: string, username?: string) { const meta = (music as any).meta || {} - if (meta.localTrack && username) return { ...localSong(meta.localTrack, username), parent: parentId, userRating: this.userRatingsCache.get(username)?.[music.id] || 0 } + if (meta.localTrack && username) return { ...localSong(meta.localTrack, username), parent: parentId, userRating: this.userRatingsCache.get(username)?.[localRatingId(meta.localTrack)] || 0 } const id = music.id const singer = music.singer || 'Unknown Artist' @@ -2054,23 +2017,44 @@ class SubsonicHandler { this.loadOnlineSongCache() for (const [id, m] of this.onlineSongCache) if (!all.has(id)) all.set(id, m) // 补充未收藏的本地歌曲:cacheOnlineSong 会跳过本地歌曲,仅靠歌单会漏掉已评分的 NAS 曲目; - // 在线缓存超出上限被淘汰的已评分歌曲暂无法覆盖(可接受)。 + // 缓存淘汰的已评分歌曲会在下方尝试按 ID 重新解析。 for (const t of await getLocalTracks(username)) if (!all.has(t.id)) all.set(t.id, localMusic(t)) - const assigned = new Set() + // Web独立评分资料可用于展示未加入歌单、也未进入在线缓存的歌曲。 + try { + const file = path.join(global.lx.userPath, getUserDirname(username), 'rating', 'songs.json') + const catalog = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : {} + for (const [id, stored] of Object.entries(catalog)) { + if (all.has(id) || id.startsWith('local_')) continue + const item = stored as any + all.set(id, { ...item, meta: { songId: id.slice(String(item.source).length + 1), albumName: item.albumName } }) + } + } catch { /* 资料缺失时继续现有解析路径 */ } + for (const [id, music] of all) { - const star = ratings[id] + const star = ratings[(music.meta as any)?.localTrack ? localRatingId((music.meta as any).localTrack) : id] // ratings 来自可手工编辑的 subsonic-meta.json;只接受 1~5 的整数, // 否则 groups.get(1.5) 为 undefined,push 会让整个 getPlaylists 请求 500。 if (typeof star === 'number' && Number.isInteger(star) && star >= 1 && star <= 5) { groups.get(star)!.push(music) - assigned.add(id) } } + // 缓存淘汰后重新解析已评分歌曲;解析失败保留原评分,后续可重试。 + for (const [id, star] of Object.entries(ratings)) { + if (all.has(id) || /^(alb_|art_|artist_)/.test(id) || !Number.isInteger(star) || star < 1 || star > 5) continue + try { + const hit = await withTimeout(this.resolveSongMeta(username, id), LINK_SYNC_ITEM_TIMEOUT_MS) + if (hit?.music) { + all.set(id, hit.music) + groups.get(star)!.push(hit.music) + } + } catch (e) { subsonicLog.warn(`[Subsonic] 无法解析已评分歌曲 ${id}`, e) } + } + // 1 星歌单 = 1 星歌曲 ∪ dislike 规则命中的歌曲 if (global.lx.config['subsonic.ratingPlaylists'] !== false) { - const candidates = [...all.values()].filter(m => !assigned.has(m.id) || ratings[m.id] === 1) + const candidates = [...all.values()] const kept = await this.filterDislikedSongs(username, candidates) const keptIds = new Set(kept.map(m => m.id)) const oneStar = groups.get(1)! @@ -2215,10 +2199,11 @@ class SubsonicHandler { if (!(star >= 1 && star <= 5)) return this.sendError(res, 70, 'Rating playlist not found', format) const groups = await this.getRatingPlaylistSongs(username) const musics = groups.get(star) || [] - // 强制标注该星级,让客户端把这批歌识别为对应评分(1 星歌单里的 dislike 歌曲可能没有 rating 记录) + const actualRatings = (await this.getUserSubsonicMeta(username)).ratings + // 优先展示真实评分,没有评分的屏蔽项以 1 星展示。 const entry = musics.map((m: LX.Music.MusicInfo) => ({ ...this.musicToSongFlat(m, id, undefined, username), - userRating: star, + userRating: actualRatings[(m.meta as any)?.localTrack ? localRatingId((m.meta as any).localTrack) : m.id] || star, })) const name = star === 1 ? '★☆☆☆☆ 1星 · 我不喜欢' @@ -2227,7 +2212,7 @@ class SubsonicHandler { playlist: { id, name, - comment: star === 1 ? '该歌单关联「我不喜欢」:打 1 星即加入,提高或清除评分即移除' : '', + comment: star === 1 ? '包含 1 星及不喜欢命中歌曲;保留真实评分,联动仅补充数据' : '', owner: username, public: false, songCount: musics.length, @@ -3206,10 +3191,11 @@ class SubsonicHandler { if (global.lx.config['subsonic.hideDisliked'] && !ratingStar) { musics = await this.filterDislikedSongs(username, musics) } - // 评星歌单强制标注星级,让客户端把 dislike 命中的歌曲也识别为对应评分 + const actualRatings = ratingStar ? (await this.getUserSubsonicMeta(username)).ratings : {} + // 保留真实评分,没有评分的屏蔽项以 1 星展示。 const toSong = (m: LX.Music.MusicInfo) => { const flat = this.musicToSongFlat(m, id, undefined, username) - return ratingStar ? { ...flat, userRating: ratingStar } : flat + return ratingStar ? { ...flat, userRating: actualRatings[(m.meta as any)?.localTrack ? localRatingId((m.meta as any).localTrack) : m.id] || ratingStar } : flat } if (format === 'json') { @@ -5187,6 +5173,7 @@ class SubsonicHandler { const merge = (base: string[], add: Set, del: Set): string[] => Array.from(new Set([...(base || []).filter((x: string) => !del.has(x)), ...add])) await this.saveUserSubsonicMeta(username, { + ...fresh, starredAlbums: merge(fresh.starredAlbums, addedAlbums, removedAlbums), starredArtists: merge(fresh.starredArtists, addedArtists, removedArtists), starredArtistNames: merge(fresh.starredArtistNames, addedArtistNames, removedArtistNames), @@ -5252,15 +5239,15 @@ class SubsonicHandler { return valid.length } catch (e) { subsonicLog.error('[Subsonic] 写入 dislike 规则失败:', e) - return 0 + throw e } } /** 写入专辑维度的 dislike 规则(!<专辑名>@<歌手>,按歌手拆多条) */ - private async addDislikeAlbum(username: string, album: { albumName: string, singers: string[] }): Promise { + private async addDislikeAlbum(username: string, album: { albumName: string, singers: string[], source?: string }, ratingId?: string, channel = 'subsonic-rating'): Promise { try { const userSpace = getUserSpace(username) as any - const infos = (album.singers || []).map(singer => ({ albumName: album.albumName, singer })) + const infos = (album.singers || []).map(singer => ({ albumName: album.albumName, singer, source: album.source, provenance: { channel, at: Date.now(), ratingId } })) if (infos.length === 0) return 0 await userSpace.dislikeManage.dislikeDataManage.addDislikeAlbums(infos) await userSpace.dislikeManage.createSnapshot() @@ -5268,7 +5255,7 @@ class SubsonicHandler { return infos.length } catch (e) { subsonicLog.error('[Subsonic] 写入专辑 dislike 失败:', e) - return 0 + throw e } } @@ -5339,7 +5326,7 @@ class SubsonicHandler { */ private async resolveDislikeTarget(username: string, id: string): Promise<{ infos: Array<{ name: string, singer: string }> - album?: { albumName: string, singers: string[] } + album?: { albumName: string, singers: string[], source?: string } singer?: { name: string, source: string, singerId: string } keys: Set }> { @@ -5359,7 +5346,7 @@ class SubsonicHandler { } const identity = await this.resolveSingerIdentity(username, name, preset) - const infos = identity.name ? [{ name: '', singer: identity.name }] : [] + const infos = identity.name ? [{ name: '', singer: identity.name, source: identity.source, provenance: { channel: 'subsonic-rating', at: Date.now() } }] : [] return { infos, singer: identity, @@ -5390,7 +5377,7 @@ class SubsonicHandler { if (!albumName) return { infos: [], keys: new Set() } const singers = [...singerSet] const keys = new Set(singers.map(s => encodeAlbumRule(albumName, s))) - const album = { albumName, singers } + const album = { albumName, singers, source } return { infos: [], album, keys } } @@ -5404,16 +5391,14 @@ class SubsonicHandler { singer: hit.music.singer || '', source: hit.music.source, interval: hit.music.interval, + provenance: { channel: 'subsonic-rating', at: Date.now() }, pic: (hit.music as any).img || (hit.music as any).meta?.picUrl || undefined, }] : [] let singerIdentity: { name: string, source: string, singerId: string } | undefined if (hit?.music) { const rawSingerId = (hit.music as any).singerId - singerIdentity = await this.resolveSingerIdentity( - username, - (hit.music.singer || '').split('、')[0] || '', - rawSingerId ? { source: hit.music.source, id: String(rawSingerId) } : undefined, - ) + // 歌曲规则已有歌曲身份,不为附带歌手资料在线回源,避免补同步被无关超时丢弃。 + singerIdentity = { name: (hit.music.singer || '').split('、')[0] || '', source: hit.music.source, singerId: String(rawSingerId || '') } } return { infos, @@ -5434,7 +5419,7 @@ class SubsonicHandler { return filterDisliked(musics, ruleSet, (m) => ({ name: m.name, singer: m.singer, - source: m.source, + source: (m.meta as any)?.localTrack?.platformId?.split('_')[0] || m.source, albumId: (m as any).meta?.albumId ?? (m as any).albumId ?? (m as any).album?.id, albumName: (m as any).meta?.albumName, }), { crossSource, duetMode, normalizeName, requireSinger }) @@ -5454,7 +5439,7 @@ class SubsonicHandler { * 语义等价于重放一次 setRating 的正向联动,但只补不删;与快照导入/回滚完全解耦, * 仅由管理员在 Subsonic 配置页点击「同步」时触发。 */ - async syncRatingsToDislike(username: string): Promise { + async syncRatingsToDislike(username: string, preview = false): Promise { const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) const summary: LinkSyncSummary = { direction: 'ratingToDislike', user: username, @@ -5466,7 +5451,10 @@ class SubsonicHandler { const ratings = meta.ratings || {} const lowRatedIds = Object.keys(ratings).filter(id => typeof ratings[id] === 'number' && ratings[id] > 0 && ratings[id] <= threshold) + for (let i = lowRatedIds.length - 1; i >= 0; i--) { if (await resolveStoredRatingId(username, lowRatedIds[i]) !== lowRatedIds[i]) lowRatedIds.splice(i, 1) } summary.scanned = lowRatedIds.length + summary.candidates = lowRatedIds.map(id => ({ id, source: id.replace(/^(alb_|art_)/, '').split('_')[0] })) + if (preview) return summary if (lowRatedIds.length === 0) return summary const userSpace = getUserSpace(username) as any @@ -5476,32 +5464,33 @@ class SubsonicHandler { const batch = lowRatedIds.slice(start, start + LINK_SYNC_BATCH_SIZE) summary.batches++ const infos: any[] = [] - const albumSingers = new Map>() + const albumInfos: any[] = [] // 单条解析可能在线回源,逐条设超时;失败只记数,不中断后续批次 for (const id of batch) { try { const target = await withTimeout(this.resolveDislikeTarget(username, id), LINK_SYNC_ITEM_TIMEOUT_MS) - for (const info of target.infos) infos.push(info) + if (!target.infos.length && (!target.album || !target.album.singers.length)) { summary.failed++; continue } + for (const info of target.infos) infos.push({ ...info, provenance: { channel: 'manual-rating-to-dislike', at: Date.now(), ratingId: id } }) if (target.album) { - const singers = albumSingers.get(target.album.albumName) ?? new Set() - for (const s of target.album.singers) singers.add(s) - albumSingers.set(target.album.albumName, singers) + for (const singer of target.album.singers) albumInfos.push({ albumName: target.album.albumName, source: target.album.source, singer, provenance: { channel: 'manual-rating-to-dislike', at: Date.now(), ratingId: id } }) } } catch (e) { summary.failed++ subsonicLog.warn(`[Subsonic] 联动同步:解析评分歌曲 ${id} 失败`, e) } } - if (infos.length === 0 && albumSingers.size === 0) continue + if (infos.length === 0 && albumInfos.length === 0) continue - const albumInfos = Array.from(albumSingers).flatMap(([albumName, singers]) => - Array.from(singers).map(singer => ({ albumName, singer }))) try { // addDislikeInfo / addDislikeAlbums 自带按规则行去重,只补不删 const before = userSpace.dislikeManage.dislikeDataManage.getDislikeRulesString() as string + const beforeData = JSON.stringify(userSpace.dislikeManage.dislikeDataManage.dislikeRules) await userSpace.dislikeManage.dislikeDataManage.addDislikeInfo(infos) if (albumInfos.length > 0) await userSpace.dislikeManage.dislikeDataManage.addDislikeAlbums(albumInfos) const after = userSpace.dislikeManage.dislikeDataManage.getDislikeRulesString() as string + const beforeItems = new Map((JSON.parse(beforeData || '{}').dislikeList || []).map((x: any) => [`${x.source || '*'}::${x.dislikeRule}`, JSON.stringify(x)])) + const changedExisting = (userSpace.dislikeManage.dislikeDataManage.dislikeRules?.dislikeList || []).filter((x: any) => { const previous = beforeItems.get(`${x.source || '*'}::${x.dislikeRule}`); return previous && previous !== JSON.stringify(x) }).length + summary.updated = (summary.updated || 0) + changedExisting const added = Math.max(0, countDislikeRules(after) - countDislikeRules(before)) summary.added += added summary.skipped += Math.max(0, infos.length + albumInfos.length - added) @@ -5513,7 +5502,7 @@ class SubsonicHandler { } } finally { // 全部分批结束后统一落盘 + 失效缓存,只生成一份快照,避免按批堆积 - if (summary.added > 0) { + if (summary.added > 0 || summary.updated) { await userSpace.dislikeManage.createSnapshot() invalidateDislikeCache(username) } @@ -5525,13 +5514,15 @@ class SubsonicHandler { * 手动补数据(不喜欢 → 评星):对当前 dislike 规则命中的歌曲补写低星评分。 * 语义等价于重放一次网页端「不喜欢」的反向联动(1 星),只补不覆盖已有评分。 */ - async syncDislikesToRating(username: string): Promise { + async syncDislikesToRating(username: string, preview = false): Promise { + return withRatingIdentityLock(username, () => this.syncDislikesToRatingUnlocked(username, preview)) + } + private async syncDislikesToRatingUnlocked(username: string, preview = false): Promise { const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) const summary: LinkSyncSummary = { direction: 'dislikeToRating', user: username, scanned: 0, added: 0, skipped: 0, failed: 0, threshold, batches: 0, } - if (threshold <= 0) return summary // 与评星歌单同源:用户歌单 + 已缓存的在线歌曲,纯内存规则匹配,不在线回源 const listData = await this.getSubsonicListData(username) @@ -5552,84 +5543,98 @@ class SubsonicHandler { const kept = await this.filterDislikedSongs(username, candidates) const keptIds = new Set(kept.map(m => m.id)) - const hitIds = candidates.filter(m => !keptIds.has(m.id)).map(m => m.id) - - // 与 /api/music/dislike/add 的自动联动保持一致:不喜欢回写 1 星 - await withMetaLock(username, async () => { - const meta = readSubsonicMeta(username) - for (const id of hitIds) { - if (meta.ratings[id] > 0) { summary.skipped++; continue } - meta.ratings[id] = 1 - summary.added++ - } - if (summary.added > 0) { - writeSubsonicMeta(username, meta) - this.userRatingsCache.set(username, meta.ratings || {}) - void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 联动同步评分快照生成失败:', e)) - } - }) + const hits = candidates.filter(m => !keptIds.has(m.id)) + const meta = readSubsonicMeta(username) + const unique = new Map() + summary.existing = []; summary.duplicates = []; summary.failures = [] + for (const music of hits) { + try { + const id = await resolveStoredRatingId(username, music.id) + const row = { id, name: music.name, source: id.startsWith('local_') ? 'local' : id.split('_')[0] } + if (unique.has(id)) { summary.duplicates.push(row); continue } + unique.set(id, music) + if (meta.ratings[id] > 0) summary.existing.push(row) + } catch { summary.failures.push({ id: music.id, name: music.name, stage: 'identity' }); summary.failed++ } + } + summary.candidates = [...unique].filter(([id]) => !meta.ratings[id]).map(([id, music]) => ({ id, name: music.name, source: id.startsWith('local_') ? 'local' : id.split('_')[0] })) + summary.skipped = summary.existing.length + summary.duplicates.length + if (preview) return summary + for (const candidate of summary.candidates) { + try { + const saved = await writeRatingUnlocked(username, candidate.id, 1, 'manual-dislike-to-rating', unique.get(candidate.id), { onlyMissing: true, deferSnapshot: true }) + if (saved.unchanged) summary.skipped++; else summary.added++ + if (saved.snapshotWarning) summary.warning = saved.snapshotWarning + this.userRatingsCache.set(username, saved.meta.ratings) + } catch { recordRatingBackfillFailure(username,candidate.id,'manual-dislike-to-rating'); summary.failed++; summary.failures.push({ ...candidate, stage: 'write' }) } + } + if (summary.added) summary.warning = await flushRatingSnapshot(username) || summary.warning + return summary } /** * 处理 Subsonic setRating:写回评分,并按配置把低分(<=阈值)联动为「不喜欢」。 */ + async reconcileRatingDislikes(username: string, preview = true) { + return withRatingIdentityLock(username, () => this.reconcileRatingDislikesUnlocked(username, preview)) + } + private async reconcileRatingDislikesUnlocked(username: string, preview = true) { + const dm = (getUserSpace(username) as any).dislikeManage + const ratings = readSubsonicMeta(username).ratings + const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) + const valid = new Set() + for (const [id, value] of Object.entries(ratings) as [string, number][]) { + if (value > 0 && value <= threshold && await resolveStoredRatingId(username, id).catch(() => id) === id) valid.add(id) + } + const candidates = await this.syncRatingsToDislike(username, true) + if (preview) return { ...candidates, ...dm.dislikeDataManage.reconcileRatingReasons(valid, true) } + await dm.createSnapshot() // 先保留可回滚的当前规则 + const removed = dm.dislikeDataManage.reconcileRatingReasons(valid, false) + await dm.createSnapshot() + invalidateDislikeCache(username) + const added = await this.syncRatingsToDislike(username, false) + return { ...added, ...removed } + } + + async applyRatingLink(username: string, id: string, rating: number, song?: any, channel = 'web-rating-link') { + const threshold = global.lx.config['subsonic.dislikeRating'] ?? 1 + if (!global.lx.config['subsonic.linkRatingToDislike'] || threshold <= 0 || rating <= 0 || rating > threshold) return + const target = await this.resolveDislikeTarget(username, id) + if (!target.infos.length && !target.album && song && !song.isLocal && !song._localFilename && !id.startsWith('local_')) { + if (!song.name || !song.singer) throw new Error('缺少歌曲资料') + const info = { id, name: song.name, singer: song.singer, source: song.source, interval: song.interval, provenance: { channel, at: Date.now(), ratingId: id } } + await this.addDislikeRules(username, [info]) + return + } + if (!target.infos.length && !target.album) throw new Error('无法解析不喜欢目标') + await this.addDislikeRules(username, target.infos.map(x => ({ ...x, provenance: { channel, at: Date.now(), ratingId: id } }))) + if (target.album) await this.addDislikeAlbum(username, target.album, id, channel) + } + + async getRatingMetadata(username: string, id: string): Promise { + if (/^(alb_|art_|artist_|lalb_|lart_)/.test(id)) { + const target = await withTimeout(this.resolveDislikeTarget(username,id),LINK_SYNC_ITEM_TIMEOUT_MS) + return target.album ? {name:target.album.albumName,singer:target.album.singers.join('、'),source:target.album.source} : target.infos[0] ? {name:target.infos[0].singer,source:(target.infos[0] as any).source} : undefined + } + return (await withTimeout(this.resolveSongMeta(username,id),LINK_SYNC_ITEM_TIMEOUT_MS))?.music + } + private async handleSetRating(res: http.ServerResponse, username: string, params: URLSearchParams, format: string) { const id = params.get('id') if (!id) return this.sendError(res, 10, 'Required parameter is missing: id', format) - const rating = parseInt(params.get('rating') || '0', 10) - if (isNaN(rating) || rating < 0 || rating > 5) { + const rating = Number(params.get('rating') || '0') + if (!Number.isInteger(rating) || rating < 0 || rating > 5) { return this.sendError(res, 0, 'Rating must be between 0 and 5', format) } - // 读-改-写整体串行化,避免与并发的 star / dislike 联动互相覆盖 - await withMetaLock(username, async () => { - const meta = await this.getUserSubsonicMeta(username) - if (rating === 0) { - delete meta.ratings[id] - } else { - meta.ratings[id] = rating - } - await this.saveUserSubsonicMeta(username, meta) - // [修复] 立即刷新内存评星缓存,保证本次请求之后的歌曲序列化能带上最新 userRating - this.userRatingsCache.set(username, meta.ratings || {}) - }) - subsonicLog.debug(`[Subsonic] setRating ${id} -> ${rating} (user=${username})`) - // 评分写入后生成/复用一份「我的评分」快照,使当前评分可被下载备份 - void createRatingSnapshot(username).catch(e => subsonicLog.warn('[Subsonic] 评分快照生成失败:', e)) - - // [dislike 联动] 0 < rating <= dislikeRating 视为「不喜欢」,写回 lx-music 原生 dislike 规则; - // 提高评分或清除评分则移除此前写入的规则。需 linkRatingToDislike 开启才联动,否则仅记录评分。 - const threshold = global.lx.config['subsonic.dislikeRating'] ?? 1 - // 评星歌单开启时,1 星歌单承载「我不喜欢」,正向联动必须生效: - // 客户端给歌曲打 1 星 -> 写入 dislike 规则;提高评分或清除 -> 移除规则。 - const linkToDislike = global.lx.config['subsonic.linkRatingToDislike'] || this.isRatingPlaylistEnabled() - if (linkToDislike && threshold > 0) { - try { - const target = await this.resolveDislikeTarget(username, id) - // [调试] 打印解析到的维度与身份信息,便于确认各入口能拿到什么 - if (global.lx.config['subsonic.enableDebug']) { - subsonicLog.debug(`[Subsonic] dislike 解析 id=${id}`, JSON.stringify({ - dimension: target.album ? 'album' : (id.startsWith('art_') || id.startsWith('artist_') ? 'singer' : 'song'), - song: target.infos, - singer: target.singer || null, - album: target.album || null, - keys: Array.from(target.keys), - })) - } - if (rating > 0 && rating <= threshold) { - let added = await this.addDislikeRules(username, target.infos) - if (target.album) added += await this.addDislikeAlbum(username, target.album) - subsonicLog.debug(`[Subsonic] setRating 联动 dislike:写入 ${added} 条规则 (id=${id}, user=${username})`) - } else { - const removed = await this.removeDislikeRules(username, target.keys) - if (removed > 0) { - subsonicLog.debug(`[Subsonic] setRating 联动 dislike:移除 ${removed} 条规则 (id=${id}, user=${username})`) - } - } - } catch (e) { - subsonicLog.error('[Subsonic] setRating 联动 dislike 失败:', e) - } + const resolved = rating > 0 ? await this.getRatingMetadata(username,id).catch(() => undefined) : undefined + const saved = await writeRating(username, id, rating, 'subsonic', resolved) + this.userRatingsCache.set(username, saved.meta.ratings) + try { await this.applyRatingLink(username, saved.id, rating, undefined, 'subsonic-rating') } + catch (e) { + subsonicLog.error('[Subsonic] setRating 联动 dislike 失败:', e) + return this.sendError(res, 0, '评分已保存,但不喜欢同步失败;请重试或手动补同步', format) } + if (saved.snapshotWarning) return this.sendError(res, 0, saved.snapshotWarning, format) return this.sendResponse(res, {}, format) } @@ -5794,13 +5799,25 @@ class SubsonicHandler { return this.renderRandomSongs(res, picked, format, rootKey, username) } + private async filterRecommendationEntries(username: string, entries: { music: LX.Music.MusicInfo, listId: string }[]) { + if (!global.lx.config['subsonic.dislikeNoRecommend']) return entries + const visible = await this.filterDislikedEntries(username, entries) + const meta = await this.getUserSubsonicMeta(username) + const threshold = Number(global.lx.config['subsonic.dislikeRating'] ?? 1) + return visible.filter(({ music }) => { + const track = (music.meta as any)?.localTrack + const rating = meta.ratings[track ? localRatingId(track) : music.id] || 0 + return !(threshold > 0 && rating > 0 && rating <= threshold) + }) + } + private async renderRandomSongs(res: http.ServerResponse, picked: { music: LX.Music.MusicInfo, listId: string }[], format: string, rootKey: string = 'randomSongs', username?: string) { // [dislike] 随机歌曲 / 流派歌曲 / 每日推荐等入口共用此渲染。 // 这里受 dislikeNoRecommend 控制(与列表剔除 hideDisliked 相互独立): // 即使不隐藏歌曲,也可以让它们不再出现在推荐里。 let list = picked if (username && global.lx.config['subsonic.dislikeNoRecommend']) { - list = await this.filterDislikedEntries(username, picked) + list = await this.filterRecommendationEntries(username, picked) } if (format === 'json') { @@ -5833,16 +5850,9 @@ class SubsonicHandler { ) { const size = Math.min(parseInt(params.get('size') || '20'), 100) try { - // 取当天全部候选(最多 100),再按「不喜欢」阈值排除:评分落在 (0, threshold] 视为不喜欢。 - // 阈值取自 subsonic.dislikeRating(可配置),避免此处硬编码导致管理员改阈值后语义不一致。 const all = await fetchRecommendedSongs(100) - const meta = await this.getUserSubsonicMeta(username) - const threshold = global.lx.config['subsonic.dislikeRating'] ?? 1 - const songs = all.filter((s: any) => { - const r = meta.ratings[s.id] || 0 - return !(threshold > 0 && r > 0 && r <= threshold) - }).slice(0, size) - const picked = songs.map((s: any) => ({ music: s, listId: 'recommended' })) + const candidates = all.map((music: any) => ({ music, listId: 'recommended' })) + const picked = (await this.filterRecommendationEntries(username, candidates)).slice(0, size) return this.renderRandomSongs(res, picked, format, 'recommendedSongs', username) } catch (e) { subsonicLog.error('[Subsonic] getRecommendedSongs 出错:', e) @@ -5915,7 +5925,7 @@ class SubsonicHandler { // [dislike] 相似歌曲属于推荐性质,受 dislikeNoRecommend 控制 if (global.lx.config['subsonic.dislikeNoRecommend']) { - picked = await this.filterDislikedEntries(username, picked) + picked = await this.filterRecommendationEntries(username, picked) } return picked } @@ -7717,7 +7727,7 @@ class SubsonicHandler { // [dislike] 热门歌曲同样过滤 if (global.lx.config['subsonic.hideDisliked']) { - picked = await this.filterDislikedEntries(username, picked) + picked = await this.filterRecommendationEntries(username, picked) } // [修复] 尊重客户端的 count:SDK 分支此前会把抓到的全部返回(最多 500 首) picked = picked.slice(0, count) @@ -8056,10 +8066,10 @@ export function invalidateSubsonicPlaylistCache(): void { export const subsonicHandler = new SubsonicHandler() /** 管理端「联动数据同步」按钮入口:仅手动触发,不参与快照导入/回滚链路 */ -export function syncRatingsToDislike(username: string): Promise { - return subsonicHandler.syncRatingsToDislike(username) +export function syncRatingsToDislike(username: string, preview = false): Promise { + return subsonicHandler.syncRatingsToDislike(username, preview) } -export function syncDislikesToRating(username: string): Promise { - return subsonicHandler.syncDislikesToRating(username) +export function syncDislikesToRating(username: string, preview = false): Promise { + return subsonicHandler.syncDislikesToRating(username, preview) } diff --git a/src/server/music/customMusicManager.ts b/src/server/music/customMusicManager.ts index d098dbfa..30080a13 100644 --- a/src/server/music/customMusicManager.ts +++ b/src/server/music/customMusicManager.ts @@ -1,3 +1,4 @@ +import { withRatingIdentityLock } from '../rating/ratingIdentityLock' import fs from 'fs' import path from 'path' import http from 'http' @@ -572,7 +573,8 @@ export const removeCustomFile = (filename: string, username: string): boolean => } // 手动关联自定义目录歌曲(更新 ID3 标签及 custom_index.json) -export const linkCustomSong = async (filename: string, songInfo: any, username: string) => { +export const linkCustomSong = (filename: string, songInfo: any, username: string) => withRatingIdentityLock(username, () => linkCustomSongUnlocked(filename, songInfo, username)) +const linkCustomSongUnlocked = async (filename: string, songInfo: any, username: string) => { const customDir = getCustomMusicDir(username) if (!customDir) throw new Error('用户未启用或未配置自定义目录') @@ -623,6 +625,8 @@ export const linkCustomSong = async (filename: string, songInfo: any, username: customIndexManager.set(username, filename, updatedItem) customIndexManager.save(username) + require('./subsonicLocal').invalidateLocalCatalog(username) + await require('./subsonicLocal').getLocalTracks(username) return { success: true, message: '关联成功', data: updatedItem } } diff --git a/src/server/music/fileCache.ts b/src/server/music/fileCache.ts index 39cfb30d..a6d5f2bd 100644 --- a/src/server/music/fileCache.ts +++ b/src/server/music/fileCache.ts @@ -1,3 +1,4 @@ +import { withRatingIdentityLock } from '../rating/ratingIdentityLock' import { beginCloudBackup } from '@/utils/backupPolicy' import { resolveContainedPath } from '../auth/security' import { serveFile } from '../http/serveFile' @@ -1367,7 +1368,8 @@ export const batchUpdateMetadata = async (filenames: string[], username: string /** * Link an unindexed local file to a specific online song identity */ -export const linkLocalFile = async (oldFilename: string, songInfo: any, username: string | undefined, targetFolder?: string) => { +export const linkLocalFile = (oldFilename: string, songInfo: any, username: string | undefined, targetFolder?: string) => withRatingIdentityLock(username || '_open', () => linkLocalFileUnlocked(oldFilename, songInfo, username, targetFolder)) +const linkLocalFileUnlocked = async (oldFilename: string, songInfo: any, username: string | undefined, targetFolder?: string) => { const normalizedUsername = (username && username !== '_open' && username !== 'default') ? username : '_open' // Find the item in all possible folders @@ -1435,8 +1437,11 @@ export const linkLocalFile = async (oldFilename: string, songInfo: any, username indexManager.update(normalizedUsername, item, folder) // 3. Post-link processing: Update ID3 tags and cover + require('./subsonicLocal').updateLocalTrackLink(normalizedUsername, dir, oldFilename, newFilename, newId) await batchUpdateMetadata([newFilename], normalizedUsername) + require('./subsonicLocal').invalidateLocalCatalog(normalizedUsername) + await require('./subsonicLocal').getLocalTracks(normalizedUsername) return { success: true, filename: newFilename, diff --git a/src/server/music/subsonicLocal.ts b/src/server/music/subsonicLocal.ts index 0ab41c30..d63a5e2c 100644 --- a/src/server/music/subsonicLocal.ts +++ b/src/server/music/subsonicLocal.ts @@ -41,6 +41,7 @@ interface Registry { tracks: Record } export interface LocalPlaylist { name: string; ids: string[]; created: string; changed: string; standalone: boolean } interface UserState { playlists: Record; starred: Record } const locks = new Map>() +const catalogRevisions = new Map() const catalogs = new Map() const scans = new Map() const pending = new Map>() @@ -91,11 +92,11 @@ const duration = (value: unknown) => { } /** Main roots follow persistent user settings; browsing overrides never affect this catalog. */ -export function getLocalTracks(user: string, force = false): Promise { +export function getLocalTracks(user: string, force = false, browseLocation?: string): Promise { return withCacheBrowseLocation('/rest/', () => { - const location = getUserCacheLocation(user) + const location = browseLocation || getUserCacheLocation(user) const custom = getCustomMusicDir(user) - const key = JSON.stringify([location, custom, getCacheDir(user, false, location), getCacheDir(user, true, location)]) + const key = JSON.stringify([catalogRevisions.get(user) || 0, location, custom, getCacheDir(user, false, location), getCacheDir(user, true, location)]) const cached = catalogs.get(user) if (!force && cached?.key === key && Date.now() - cached.at < 30_000) return Promise.resolve(cached.tracks) const pendingKey = `${user}:${key}` @@ -122,7 +123,8 @@ export function getLocalTracks(user: string, force = false): Promise !seen.has(id))] } + +/** 关联后评分以在线身份为准;未关联时保留本地身份。 */ +export const localRatingId = (track: Pick): string => track.platformId || track.id +export function invalidateLocalCatalog(user: string): void { catalogs.delete(user); catalogRevisions.set(user, (catalogRevisions.get(user) || 0) + 1) } + +/** 缓存关联可能改名;保留原本地ID和旧定位别名,读取评分时仍以最新在线ID为准。 */ +export function updateLocalTrackLink(user: string, root: string, oldFilename: string, filename: string, platformId: string): void { + const file = userFile(user, 'subsonic-local-registry.json') + const registry = read(file, { tracks: {} }) + const actualRoot = fs.realpathSync(root) + const oldPath = path.resolve(actualRoot, oldFilename) + const newPath = localFile({ root, filename }) + if (!newPath || !oldPath.startsWith(actualRoot + path.sep)) throw new Error('Invalid local rating relocation') + const previous = registry.tracks[oldPath] + if (previous) { + const track = { ...previous, root: actualRoot, filename, platformId } + for (const [key, item] of Object.entries(registry.tracks)) if (item.id === track.id) registry.tracks[key] = track + registry.tracks[newPath] = track + write(file, registry) + } + invalidateLocalCatalog(user) +} diff --git a/src/server/rating/README.md b/src/server/rating/README.md new file mode 100644 index 00000000..2f8b25b7 --- /dev/null +++ b/src/server/rating/README.md @@ -0,0 +1,16 @@ +# 评分模块 + +Web 与 Subsonic 共用这组服务。运行数据仍保存于用户目录,源码归类不改变数据位置。 + +| 文件 | 职责 | +| --- | --- | +| ratingService.ts | 评分读写、歌曲身份解析、描述资料、失败任务重试 | +| ratingIdentityLock.ts | 按用户串行化本地关联与评分写入 | +| ratingMigration.ts | 本地转在线的身份合并、不喜欢原因迁移及事务日志恢复 | +| ratingPreferences.ts | 用户独立的不喜欢自动补分偏好 | +| ratingSnapshot.ts | 评分导入、导出、快照与恢复、元数据锁 | +| ratingValidation.ts | 存储结构与评分历史校验 | + +锁顺序为身份锁 → 元数据锁;持有身份锁的调用方使用 writeRatingUnlocked,避免重复取得同一锁。 +迁移提交同步完成,不跨 await。事务失败会回滚;未完成日志在评分访问或不喜欢管理器初始化时恢复。 +不支持多个服务进程同时写入同一用户数据目录。 diff --git a/src/server/rating/ratingIdentityLock.ts b/src/server/rating/ratingIdentityLock.ts new file mode 100644 index 00000000..b18b2b9d --- /dev/null +++ b/src/server/rating/ratingIdentityLock.ts @@ -0,0 +1,10 @@ +/** 串行化同一用户的关联变更与评分写入;独立于元数据锁,固定先身份锁后元数据锁。 */ +const pending = new Map>() +export function withRatingIdentityLock(user: string, task: () => Promise): Promise { + const previous = pending.get(user) || Promise.resolve() + const result = previous.then(task, task) + const tail = result.then(() => undefined, () => undefined) + pending.set(user, tail) + void tail.then(() => { if (pending.get(user) === tail) pending.delete(user) }) + return result +} diff --git a/src/server/rating/ratingMigration.ts b/src/server/rating/ratingMigration.ts new file mode 100644 index 00000000..cea2c66c --- /dev/null +++ b/src/server/rating/ratingMigration.ts @@ -0,0 +1,92 @@ +import fs from 'node:fs' +import path from 'node:path' +import { createHash } from 'node:crypto' + +const live = new Map>() +export function registerDislikeMigration(dir: string, manager: any) { live.set(path.resolve(dir), new WeakRef(manager)); recoverRatingTransaction(dir) } +const replace = (file: string, value: string | null) => { + if (value === null) { if (fs.existsSync(file)) fs.unlinkSync(file); return } + fs.mkdirSync(path.dirname(file), { recursive: true }) + fs.writeFileSync(file + '.transaction.tmp', value, { encoding: 'utf8', flush: true }) + fs.renameSync(file + '.transaction.tmp', file) +} +/** A durable redo journal finishes interrupted commits before another rating read. */ +export function recoverRatingTransaction(dir: string) { + const journal = path.join(dir, 'rating', 'transaction.json') + if (!fs.existsSync(journal)) return + const entries = JSON.parse(fs.readFileSync(journal, 'utf8')) + if (!Array.isArray(entries)) throw new Error('Invalid rating transaction') + for (const entry of entries) { + if (!entry || typeof entry.file !== 'string' || typeof entry.after !== 'string') throw new Error('Invalid rating transaction') + const target = path.resolve(dir, entry.file) + const relative = path.relative(dir, target).replaceAll('\\', '/') + if (!target.startsWith(path.resolve(dir) + path.sep) || !/^(subsonic-meta\.json|rating\/songs\.json|dislike\/snapshotInfo\.json|dislike\/snapshot\/snapshot_[a-f0-9]{32})$/.test(relative)) throw new Error('Invalid rating transaction path') + } + for (const entry of entries) replace(path.resolve(dir, entry.file), entry.after) + fs.unlinkSync(journal) + if (entries.some(entry => entry.file.replaceAll('\\', '/') === 'dislike/snapshotInfo.json')) refreshLive(dir) +} +function refreshLive(dir: string) { + const manager = live.get(path.resolve(dir))?.deref() + if (!manager) return + const info = path.join(dir, 'dislike', 'snapshotInfo.json') + if (!fs.existsSync(info)) return + manager.snapshotDataManage.snapshotInfo = JSON.parse(fs.readFileSync(info, 'utf8')) + const latest = manager.snapshotDataManage.snapshotInfo.latest + if (latest) manager.dislikeRules = JSON.parse(fs.readFileSync(path.join(dir, 'dislike', 'snapshot', 'snapshot_' + latest), 'utf8')) +} +export function commitRatingFiles(dir: string, changes: Map) { + recoverRatingTransaction(dir) + const entries = [...changes].map(([file, after]) => ({ file: path.relative(dir, file), after, before: fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null })) + if (!entries.length) return + const journal = path.join(dir, 'rating', 'transaction.json') + replace(journal, JSON.stringify(entries)) + try { + for (const entry of entries) replace(path.join(dir, entry.file), entry.after) + } catch (error) { + // Keep the journal if rollback itself fails; the next read completes the commit. + for (const entry of entries) replace(path.join(dir, entry.file), entry.before) + fs.unlinkSync(journal) + throw error + } + fs.unlinkSync(journal) + if (entries.some(entry => entry.file.replaceAll('\\', '/') === 'dislike/snapshotInfo.json')) refreshLive(dir) +} +/** Pure identity normalization, shared by reads, linking and snapshot restore. */ +export function planRatingMigration(dir: string, data: any, catalog: any, tracks?: any[]) { + data.ratings ||= {} + const registry = path.join(dir, 'subsonic-local-registry.json') + const linked: any[] = tracks || (fs.existsSync(registry) ? Object.values(JSON.parse(fs.readFileSync(registry, 'utf8')).tracks || {}) : []) + const aliases = new Map() + for (const t of linked) if (t.id?.startsWith('local_') && /^(wy|tx|kw|kg|mg|bd)_/.test(t.platformId || '')) aliases.set(t.id, t.platformId) + for (const [old, target] of aliases) { + if (!data.ratings[target] && data.ratings[old]) { + data.ratings[target] = data.ratings[old] + if (data.ratingOrigins?.[old]) { data.ratingOrigins ||= {}; data.ratingOrigins[target] = data.ratingOrigins[old] } + if (data.ratingHistory?.[old]) { data.ratingHistory ||= {}; data.ratingHistory[target] = data.ratingHistory[old] } + catalog[target] = { ...(catalog[old] || {}), ...(catalog[target] || {}), id: target, source: target.split('_')[0] } + } + delete data.ratings[old] + if (data.ratingOrigins) delete data.ratingOrigins[old] + if (data.ratingHistory) delete data.ratingHistory[old] + delete catalog[old] + } + const changes = new Map() + const manager = live.get(path.resolve(dir))?.deref() + const infoFile = path.join(dir, 'dislike', 'snapshotInfo.json') + const info = manager?.snapshotDataManage.snapshotInfo || (fs.existsSync(infoFile) ? JSON.parse(fs.readFileSync(infoFile, 'utf8')) : null) + if (info?.latest) { + const source = manager?.dislikeRules || JSON.parse(fs.readFileSync(path.join(dir, 'dislike', 'snapshot', 'snapshot_' + info.latest), 'utf8')) + const rules = JSON.parse(JSON.stringify(source)) + let changed = false + for (const item of rules.dislikeList || []) for (const reason of [item.provenance, item.enrichedBy, ...(item.reasons || [])]) { + if (reason && aliases.has(reason.ratingId)) { reason.ratingId = aliases.get(reason.ratingId); changed = true } + } + if (changed) { + const content = JSON.stringify(rules), id = createHash('md5').update(content).digest('hex') + changes.set(path.join(dir, 'dislike', 'snapshot', 'snapshot_' + id), content) + changes.set(infoFile, JSON.stringify({ ...info, latest: id, time: Date.now(), list: [...new Set([info.latest, ...(info.list || [])])].filter(x => x !== id && !(info.imported || []).includes(x)) })) + } + } + return changes +} diff --git a/src/server/rating/ratingPreferences.ts b/src/server/rating/ratingPreferences.ts new file mode 100644 index 00000000..181ac94d --- /dev/null +++ b/src/server/rating/ratingPreferences.ts @@ -0,0 +1,19 @@ +import fs from 'node:fs' +import path from 'node:path' +import { getUserDirname } from '@/user' +export interface RatingPreferences { dislikeAutoRating: boolean } +const preferenceFile = (user: string) => path.join(global.lx.userPath, getUserDirname(user), 'rating', 'preferences.json') +export function readRatingPreferences(user: string): RatingPreferences { + const file = preferenceFile(user) + if (!fs.existsSync(file)) return { dislikeAutoRating: false } + try { const data = JSON.parse(fs.readFileSync(file, 'utf8')); return { dislikeAutoRating: data.dislikeAutoRating === true } } + catch { console.warn('[评分设置] 用户设置无法读取,自动补分暂按关闭处理:', user); return { dislikeAutoRating: false } } +} +export function saveRatingPreferences(user: string, value: unknown): RatingPreferences { + if (typeof value !== 'boolean') throw new Error('dislikeAutoRating must be boolean') + const data = { dislikeAutoRating: value } + const file = preferenceFile(user) + fs.mkdirSync(path.dirname(file), { recursive: true }) + fs.writeFileSync(file + '.tmp', JSON.stringify(data), 'utf8'); fs.renameSync(file + '.tmp', file) + return data +} diff --git a/src/server/rating/ratingService.ts b/src/server/rating/ratingService.ts new file mode 100644 index 00000000..a3ec8dba --- /dev/null +++ b/src/server/rating/ratingService.ts @@ -0,0 +1,262 @@ +import { commitRatingFiles, recoverRatingTransaction, planRatingMigration } from './ratingMigration' +import { normalizeRatingHistory, validateRatingStorage } from './ratingValidation' +import { createHash } from 'node:crypto' +import { withRatingIdentityLock } from './ratingIdentityLock' +import fs from 'node:fs' +import path from 'node:path' +import { getUserDirname } from '@/user' +import { createRatingSnapshot, withMetaLock } from './ratingSnapshot' +import { getLocalTracks, localFile, localRatingId } from '../music/subsonicLocal' +import { getCacheDir } from '../music/fileCache' +import { getCustomMusicDir } from '../music/customMusicManager' + +const metaFile = (user: string) => path.join(global.lx.userPath, getUserDirname(user), 'subsonic-meta.json') +export const readRatings = (user: string): any => { + const file = metaFile(user) + recoverRatingTransaction(path.dirname(file)) + if (!fs.existsSync(file)) return { starredAlbums: [], starredArtists: [], starredArtistNames: [], ratings: {} } + const data = validateRatingStorage(JSON.parse(fs.readFileSync(file, 'utf8'))) + if (data.ratingHistory) data.ratingHistory = normalizeRatingHistory(data.ratingHistory) + migrateLinkedRatings(user, data) + return { ...data, ratings: data.ratings || {} } +} +/** 同步读改写不跨 await,关联扫描与评分写入共享同一进程的串行临界段。 */ +export function migrateLinkedRatings(user: string, supplied?: any, tracks?: any[]) { + const file = metaFile(user) + recoverRatingTransaction(path.dirname(file)) + if (!fs.existsSync(file)) return + const data = supplied || validateRatingStorage(JSON.parse(fs.readFileSync(file, 'utf8'))) + const dir = path.dirname(file) + const registryFile = path.join(dir, 'subsonic-local-registry.json') + const linked: any[] = tracks || (fs.existsSync(registryFile) ? Object.values(JSON.parse(fs.readFileSync(registryFile, 'utf8')).tracks || {}) : []) + const catalogFile = path.join(dir, 'rating', 'songs.json') + const catalog = fs.existsSync(catalogFile) ? JSON.parse(fs.readFileSync(catalogFile, 'utf8')) : {} + const before = JSON.stringify(data), beforeCatalog = JSON.stringify(catalog) + const changes = planRatingMigration(dir, data, catalog, linked) + if (JSON.stringify(catalog) !== beforeCatalog) changes.set(catalogFile, JSON.stringify(catalog)) + if (JSON.stringify(data) !== before) changes.set(file, JSON.stringify(data)) + commitRatingFiles(dir, changes) +} +/** 未关联使用本地ID,关联后读写在线ID;本地评分迁移到在线ID,在线已有评分优先。 */ +export async function resolveRatingId(user: string, song: any): Promise { + if (!song || typeof song !== 'object') throw new Error('Missing song') + if (song.isLocal || song._localFilename) { + if (song._localUsername && song._localUsername !== user) throw new Error('不能为其他用户的本地文件评分') + const filename = song._localFilename || song.filename + if (typeof filename !== 'string') throw new Error('Missing local filename') + const folder = song._isCustomDir ? 'custom' : song._localFolder || song.folder + if (!['music', 'cache', 'custom'].includes(folder)) throw new Error('Invalid local folder') + const location = song._localLocation + if (location && !['root', 'data'].includes(location)) throw new Error('Invalid storage location') + const root = folder === 'custom' ? getCustomMusicDir(user) : getCacheDir(user, folder === 'music', location) + if (!root) throw new Error('Local storage unavailable') + const file = localFile({ root, filename }) + const tracks = await getLocalTracks(user, false, folder === 'custom' ? undefined : location) + let track = file ? tracks.find(t => localFile(t) === file) : undefined + if (!file) { + // 仅接受由本地文件注册表记录的改名别名,不按歌名或在线ID猜测文件。 + const actualRoot = fs.realpathSync(root) + const key = path.resolve(actualRoot, filename) + if (!key.startsWith(actualRoot + path.sep)) throw new Error('Invalid local path') + const registryFile = path.join(path.dirname(metaFile(user)), 'subsonic-local-registry.json') + const registry = fs.existsSync(registryFile) ? JSON.parse(fs.readFileSync(registryFile, 'utf8')) : { tracks: {} } + const prior = registry.tracks?.[key] + if (prior) track = tracks.find(t => t.id === prior.id && localFile(t)) + } + if (!track) throw new Error('该文件不在当前用户本地曲库中,请刷新本地列表') + return localRatingId(track) + } + const source = String(song.source || '') + let id = String(source === 'tx' ? song.songmid || song.meta?.songId || song.id || '' : song.meta?.songId || song.songmid || song.id || '') + if (id.startsWith('local_')) { + return resolveStoredRatingId(user, id) + } + if (!['wy','tx','kw','kg','mg','bd'].includes(source) || !id || id.length > 256 || /[\s\\/]/.test(id)) throw new Error('Invalid song identity') + if (!id.startsWith(source + '_')) id = source + '_' + id + return id +} +export async function resolveStoredRatingId(user: string, id: string): Promise { + if (!id.startsWith('local_')) return id + const track = (await getLocalTracks(user)).find(t => t.id === id) + if (track) return localRatingId(track) + if (Object.hasOwn(readRatings(user).ratings, id)) return id + throw new Error('Unknown local song') +} + +export interface RatingWriteOptions { onlyMissing?: boolean, deferSnapshot?: boolean, repairOnly?: boolean } +export function writeRating(user: string, id: string, rating: number, channel: string, song?: any, options: RatingWriteOptions = {}) { + return withRatingIdentityLock(user, async () => { + try {return await writeRatingUnlocked(user, id, rating, channel, song, options)} + catch(error){if(options.onlyMissing)recordRatingBackfillFailure(user,id,channel);throw error} + }) +} +/** 调用方已经持有身份锁时使用;读改写仍统一经过元数据锁。 */ +export async function writeRatingUnlocked(user: string, id: string, rating: number, channel: string, song?: any, options: RatingWriteOptions = {}) { + if (!Number.isInteger(rating) || rating < 0 || rating > 5) throw new Error('Rating must be an integer between 0 and 5') + if (typeof id !== 'string' || !id || id.length > 512 || ['__proto__', 'constructor', 'prototype'].includes(id)) throw new Error('Invalid rating ID') + const localInput = id.startsWith('local_') || String(song?.id || '').startsWith('local_') || song?.isLocal || song?._localFilename + id = song && (song.isLocal || song._localFilename) ? await resolveRatingId(user, song) : await resolveStoredRatingId(user, id) + if (song && !id.startsWith('local_') && localInput) { + const linked = (await getLocalTracks(user)).find(track => track.platformId === id) + // 使用服务端关联资料,避免关联前的列表条目覆盖在线歌曲资料。 + song = linked ? { name: linked.title, singer: linked.artist, albumName: linked.album, interval: linked.duration } : undefined + } + const meta = await withMetaLock(user, async () => { + const data = readRatings(user) + data.ratingOrigins ||= {} + if (options.repairOnly) rating = data.ratings[id] || 0 + const changed = !(options.onlyMissing && data.ratings[id] > 0) && (data.ratings[id] || 0) !== rating + if (!changed) data._ratingUnchanged = true + if (changed) { + const event = { from: data.ratings[id] || 0, to: rating, channel, at: Date.now() } + data.ratingHistory ||= {} + data.ratingHistory[id] = [...(data.ratingHistory[id] || []), event].slice(-30) + if (rating === 0) { delete data.ratings[id]; delete data.ratingOrigins[id] } + else { data.ratings[id] = rating; data.ratingOrigins[id] = { channel, at: Date.now() } } + fs.mkdirSync(path.dirname(metaFile(user)), { recursive: true }) + const temporary = metaFile(user) + '.rating.tmp' + fs.writeFileSync(temporary, JSON.stringify(data), 'utf8'); fs.renameSync(temporary, metaFile(user)) + } + if (!song && rating > 0) song = knownRatingSong(user, id) + if (!song && rating > 0) setRatingTask(user, 'metadata:' + id, {id,kind:'metadata',message:'歌曲资料尚未解析',at:Date.now()}) + if (song && rating > 0) { + try { + // 独立评分资料目录,不写歌单;拒绝持久化带鉴权参数的播放/封面URL。 + const file = path.join(path.dirname(metaFile(user)), 'rating', 'songs.json') + fs.mkdirSync(path.dirname(file), { recursive: true }) + const catalog = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : {} + const incoming: any = { id, name: String(song.name || '').slice(0,500), singer: String(song.singer || '').slice(0,500), source: id.startsWith('local_') ? 'local' : id.replace(/^(alb_|art_|artist_)/, '').split('_')[0], albumName: String(song.meta?.albumName || song.albumName || '').slice(0,500), interval: song.interval, img: safeCover(song.img || song.meta?.picUrl || song.picUrl), albumId: String(song.meta?.albumId || song.albumId || '').slice(0,200) } + const previous = catalog[id] || {} + catalog[id] = { ...previous, ...Object.fromEntries(Object.entries(incoming).filter(([,value]) => value !== undefined && value !== null && value !== '')) } + const temp = file + '.tmp' + const next = JSON.stringify(catalog) + if (fs.existsSync(file) && fs.readFileSync(file, 'utf8') !== next || !fs.existsSync(file)) { + fs.writeFileSync(temp, next, 'utf8'); fs.renameSync(temp, file); data._ratingCatalogChanged = true + } + setRatingTask(user, 'catalog:' + id, null) + setRatingTask(user, 'metadata:' + id, null) + } catch { data._ratingCatalogWarning = true; setRatingTask(user, 'catalog:' + id, { id, kind: 'catalog', message: '歌曲资料保存失败', song: ratingDescriptor(id, song), at: Date.now() }) } + } + return data + }) + let snapshotWarning: string | undefined = meta._ratingCatalogWarning ? '评分已保存,但评分歌曲资料保存失败' : undefined + delete meta._ratingCatalogWarning + const unchanged = !!meta._ratingUnchanged; delete meta._ratingUnchanged + const catalogChanged = !!meta._ratingCatalogChanged; delete meta._ratingCatalogChanged + if (!options.deferSnapshot && (!unchanged || catalogChanged || readRatingTasks(user).some((task: any) => task.kind === 'snapshot'))) { + const result = await flushRatingSnapshot(user); snapshotWarning = result || snapshotWarning + } + if (options.onlyMissing) setRatingTask(user, 'backfill:' + id, null) + return { id, meta, snapshotWarning, unchanged } +} + +/** 仅保留不带查询串/凭据的公开封面地址,避免持久化鉴权参数。 */ +export const safeCover = (value: any): string => { + if (typeof value !== 'string' || value.length > 500 || !/^https?:\/\//i.test(value)) return '' + try { const url = new URL(value); return /[?#]/.test(value) || url.username || url.password ? '' : value } catch { return '' } +} + +export type RatingKind = 'song' | 'album' | 'artist' +export const ratingKind = (id: string): RatingKind => /^(alb_|lalb_)/.test(id) ? 'album' : /^(art_|artist_|lart_)/.test(id) ? 'artist' : 'song' + +/** 汇总该用户的全部评分(歌曲/专辑/歌手),补齐封面、平台、来源与时间。 */ +export function listRatingItems(user: string): any[] { + const meta = readRatings(user) + const dir = path.join(global.lx.userPath, getUserDirname(user)) + const readJson = (file: string, fallback: any) => { try { return JSON.parse(fs.readFileSync(file, 'utf8')) } catch { return fallback } } + const catalog = readJson(path.join(dir, 'rating', 'songs.json'), {}) + const online = readJson(path.join(global.lx.dataPath, 'runtime', 'subsonic-online-cache.json'), []) + const localRegistry = readJson(path.join(dir, 'subsonic-local-registry.json'), { tracks: {} }) + const onlineMap = new Map((Array.isArray(online) ? online : []).map((x: any) => [x.id, x])) + const localMap = new Map(Object.values(localRegistry.tracks || {}).map((x: any) => [x.id, x])) + const library = new Map() + for (const [file, prefix] of [['library/albums.json', 'alb'], ['library/artists.json', 'art'], ['dislike/library/albums.json', 'alb'], ['dislike/library/artists.json', 'art']]) { + const rows = readJson(path.join(dir, file), []) + if (Array.isArray(rows)) for (const row of rows) if (row?.id && !library.has(`${prefix}_${row.source}_${row.id}`)) library.set(`${prefix}_${row.source}_${row.id}`, row) + } + return Object.entries(meta.ratings as Record).map(([id, rating]) => { + const kind = ratingKind(id) + const origin = meta.ratingOrigins?.[id] || null + const history = meta.ratingHistory?.[id] || [] + if (kind !== 'song') { + const row = { ...(catalog[id] || {}), ...(library.get(id) || {}) } + return { id, rating, kind, history, name: row.name || id, singer: row.artistName || '', source: row.source || id.split('_')[1] || '', albumName: '', img: safeCover(row.picUrl || row.meta?.picUrl), origin } + } + const local: any = localMap.get(id) + const effectiveId = local?.platformId || id + const item: any = { ...(local || {}), ...(onlineMap.get(id) || {}), ...(catalog[id] || {}) } + const source = id.startsWith('local_') ? 'local' : item.source || id.split('_')[0] + return { id, rating, kind, history, effectiveId, name: item.name || item.title || id, singer: item.singer || item.artist || '', source, albumName: item.albumName || item.album || item.meta?.albumName || '', interval: item.interval || item.duration, img: safeCover(item.img || item.pic || item.picUrl || item.meta?.picUrl), origin } + }) +} + +/** 解析接口返回明确归属;本地历史只作说明,不作为在线评分回退值。 */ +export async function ratingIdentityDetails(user: string, song: any, details = false) { + const id = await resolveRatingId(user, song) + const local = song.isLocal || song._localFilename || String(song.id || '').startsWith('local_') + const identity = local ? (id.startsWith('local_') ? 'local' : 'linked-online') : 'online' + if (!details) return { id, identity } + const tracks = await getLocalTracks(user) + const related = tracks.filter(t => localRatingId(t) === id) + const rows = listRatingItems(user) + return { id, identity, + target: rows.find(x => x.id === id) || { id }, + linkedCopies: related.length } +} + +function ratingDescriptor(id: string, song: any) { + return {id,source:id.replace(/^(alb_|art_|artist_)/,'').split('_')[0],name:String(song?.name||song?.title||'').slice(0,500),singer:String(song?.singer||song?.artist||'').slice(0,500),albumName:String(song?.albumName||song?.meta?.albumName||song?.album||'').slice(0,500),albumId:String(song?.albumId||song?.meta?.albumId||'').slice(0,200),img:safeCover(song?.img||song?.meta?.picUrl),interval: typeof song?.interval === 'string' || typeof song?.interval === 'number' ? song.interval : undefined} +} +function knownRatingSong(user: string, id: string): any { + const files = [path.join(path.dirname(metaFile(user)),'rating','songs.json'),path.join(global.lx.dataPath,'runtime','subsonic-online-cache.json'),path.join(path.dirname(metaFile(user)),'subsonic-local-registry.json')] + for (const file of files) { + if (!fs.existsSync(file)) continue + try { + const data=JSON.parse(fs.readFileSync(file,'utf8'));const rows=Array.isArray(data)?data:Object.values(data.tracks||data) + const song:any=rows.find((row:any)=>row.id===id||row.platformId===id) + if(song)return ratingDescriptor(id,song) + } catch { /* 缓存损坏不阻止分数写入;主评分文件严格校验。 */ } + } +} +const taskFile=(user:string)=>path.join(path.dirname(metaFile(user)),'rating','sync-status.json') +export function readRatingTasks(user:string):any[] { + const file=taskFile(user);if(!fs.existsSync(file))return [] + try { + const tasks=JSON.parse(fs.readFileSync(file,'utf8')) + if(!Array.isArray(tasks)||tasks.some(t=>!t||typeof t.key!=='string'||!['catalog','metadata','snapshot','backfill'].includes(t.kind)))throw Error('invalid status') + return tasks + } catch {return [{key:'status-error',kind:'status',message:'同步状态文件损坏,原文件已保留;请人工检查',at:0}]} +} + +function setRatingTask(user:string,key:string,task:any) { + try {const file=taskFile(user);const current=readRatingTasks(user);if(current.some(row=>row.kind==='status'))throw Error('damaged status');const rows=current.filter(row=>row.key!==key);if(task)rows.push({...task,key});fs.mkdirSync(path.dirname(file),{recursive:true});const next=JSON.stringify(rows);if(!fs.existsSync(file)||fs.readFileSync(file,'utf8')!==next){fs.writeFileSync(file+'.tmp',next,'utf8');fs.renameSync(file+'.tmp',file)}} + catch { /* 状态文件失败不掩盖评分主操作的结果。 */ } +} +export async function flushRatingSnapshot(user:string):Promise { + try {await createRatingSnapshot(user);setRatingTask(user,'snapshot',null)} + catch {setRatingTask(user,'snapshot',{kind:'snapshot',message:'评分快照生成失败',at:Date.now()});return '评分已保存,但评分快照生成失败,可重试失败项'} +} +export async function retryRatingTasks(user:string) { + const tasks=readRatingTasks(user) + for(const task of tasks){ + if(task.kind==='status')throw Error('同步状态文件损坏,已保留原文件,请人工检查后重试') + if(task.kind==='backfill') { + try {await writeRating(user,task.id,1,task.channel,undefined,{onlyMissing:true})}catch{} + } else if ((task.kind==='catalog'||task.kind==='metadata') && task.id) { + if (!(readRatings(user).ratings[task.id]>0)) {setRatingTask(user,task.key,null);continue} + const song = task.kind==='catalog' ? task.song : await require('../integrations/subsonic').subsonicHandler.getRatingMetadata(user,task.id).catch(()=>undefined) + if(song)await writeRating(user,task.id,readRatings(user).ratings[task.id]||0,'repair',song,{repairOnly:true}) + } else if(task.kind==='snapshot') await flushRatingSnapshot(user) + } + + return {pending:readRatingTasks(user),version:ratingVersion(user)} +} +export function ratingVersion(user:string):string { + const dir=path.dirname(metaFile(user));const files=['subsonic-meta.json','subsonic-local-registry.json','rating/songs.json','rating/sync-status.json'] + return createHash('sha256').update(files.map(name=>{try{const stat=fs.statSync(path.join(dir,name),{bigint:true});return `${name}:${stat.mtimeNs}:${stat.size}`}catch{return name+':missing'}}).join('|')).digest('hex').slice(0,24) +} + +export function recordRatingBackfillFailure(user:string,id:string,channel:string) { + if (!['web-dislike-link','manual-dislike-to-rating'].includes(channel) || typeof id!=='string' || !id || id.length>512 || ['__proto__','constructor','prototype'].includes(id)) return + setRatingTask(user,'backfill:'+id,{id,kind:'backfill',channel,message:'补分写入失败',at:Date.now()}) +} diff --git a/src/server/ratingSnapshot.ts b/src/server/rating/ratingSnapshot.ts similarity index 53% rename from src/server/ratingSnapshot.ts rename to src/server/rating/ratingSnapshot.ts index f0939dc3..a082e5ce 100644 --- a/src/server/ratingSnapshot.ts +++ b/src/server/rating/ratingSnapshot.ts @@ -1,3 +1,6 @@ +import { commitRatingFiles, recoverRatingTransaction, planRatingMigration } from './ratingMigration' +import { normalizeRatingHistory, validateRatingStorage } from './ratingValidation' +import { withRatingIdentityLock } from './ratingIdentityLock' import fs from 'node:fs' import path from 'node:path' import { createHash } from 'node:crypto' @@ -13,7 +16,11 @@ export interface RatingMeta { starredAlbums: string[] starredArtists: string[] starredArtistNames: string[] + ratingOrigins?: Record ratings: Record + ratingHistory?: Record + ratingCatalog?: Record + localLinks?: { id: string, filename: string, platformId?: string }[] } export interface RatingSnapshotItem { @@ -27,6 +34,25 @@ interface RatingSnapshotInfo { imported: string[] } +const metaLocks = new Map>() + +/** + * 同一用户 subsonic-meta.json 的「读-改-写」串行化锁。 + * 避免 handleSetRating / handleStar / syncDislikeToRating 并发写同一文件互相覆盖。 + */ +export function withMetaLock(username: string, task: () => Promise): Promise { + const prev = metaLocks.get(username) ?? Promise.resolve() + const run = (): Promise => task() + // 前一个任务无论成功还是失败都要继续,避免一次异常卡死整条队列 + const next = prev.then(run, run) + const tail = next.then(() => undefined, () => undefined) + metaLocks.set(username, tail) + tail.then(() => { + if (metaLocks.get(username) === tail) metaLocks.delete(username) + }) + return next +} + const emptyMeta = (): RatingMeta => ({ starredAlbums: [], starredArtists: [], starredArtistNames: [], ratings: {} }) const userDir = (username: string) => path.join(global.lx.userPath, getUserDirname(username)) @@ -51,26 +77,73 @@ const snapshotPath = (username: string, id: string) => { return path.join(snapshotDir(username), `snapshot_${id}`) } +export function sanitizeRatingCatalog(value: any): Record { + const catalog: Record = Object.create(null) + if (!value || typeof value !== 'object' || Array.isArray(value)) return catalog + for (const [id, raw] of Object.entries(value)) { + if (!raw || typeof raw !== 'object' || ['__proto__', 'constructor', 'prototype'].includes(id)) continue + const row: any = { id } + for (const key of ['name', 'singer', 'source', 'albumName', 'albumId', 'interval']) { + const field = (raw as any)[key] + if (typeof field === 'string' || typeof field === 'number') row[key] = String(field).slice(0, 500) + } + try { const url = new URL((raw as any).img); if (/^https?:$/.test(url.protocol) && !url.username && !url.password && !url.search && !url.hash) row.img = url.href } catch {} + catalog[id] = row + } + return catalog +} + +/** 完整导出评分、描述及关联参照;不包含音频,不猜测或覆盖当前文件关联。 */ +export function exportRatingBackup(username: string): RatingMeta & { type: string, restorePolicy: string } { + recoverRatingTransaction(userDir(username)) + const meta = readMeta(username) + let catalog = {} + let tracks: any[] = [] + const catalogFile = path.join(ratingDir(username), 'songs.json') + if (fs.existsSync(catalogFile)) catalog = JSON.parse(fs.readFileSync(catalogFile, 'utf8')) + const registryFile = path.join(userDir(username), 'subsonic-local-registry.json') + if (fs.existsSync(registryFile)) tracks = Object.values(JSON.parse(fs.readFileSync(registryFile, 'utf8')).tracks || {}) + return { ...meta, type: 'lxRating_v1', restorePolicy: 'ratings-and-descriptions-current-links', ratingCatalog: sanitizeRatingCatalog(catalog), + localLinks: [...new Map(tracks.map(t => [t.id, { id: t.id, filename: t.filename, platformId: t.platformId }])).values()] } +} + const normalizeMeta = (data: any): RatingMeta => ({ + ...(data?.ratingHistory ? { ratingHistory: normalizeRatingHistory(data.ratingHistory) } : {}), + ...(data?.ratingCatalog ? { ratingCatalog: sanitizeRatingCatalog(data.ratingCatalog) } : {}), + ...(Array.isArray(data?.localLinks) ? { localLinks: data.localLinks.filter((x: any) => x && typeof x.id === 'string' && typeof x.filename === 'string').map((x: any) => ({ id: x.id, filename: x.filename, platformId: x.platformId })) } : {}), + ...(data?.ratingOrigins ? { ratingOrigins: data.ratingOrigins } : {}), starredAlbums: Array.isArray(data?.starredAlbums) ? data.starredAlbums : [], starredArtists: Array.isArray(data?.starredArtists) ? data.starredArtists : [], starredArtistNames: Array.isArray(data?.starredArtistNames) ? data.starredArtistNames : [], - ratings: data?.ratings && typeof data.ratings === 'object' && !Array.isArray(data.ratings) ? data.ratings : {}, + ratings: Object.fromEntries(Object.entries(data?.ratings && typeof data.ratings === 'object' && !Array.isArray(data.ratings) ? data.ratings : {}).filter(([id, value]) => !['__proto__', 'constructor', 'prototype'].includes(id) && Number.isInteger(value) && Number(value) >= 1 && Number(value) <= 5).map(([id, value]) => [id, Number(value)])), }) /** 供 HTTP 导入入口复用:外部备份(含 lxRating_v1 标记)统一归一化为评分元数据后再落盘 */ export const normalizeRatingMeta = normalizeMeta const readMeta = (username: string): RatingMeta => { + recoverRatingTransaction(userDir(username)) + const file = metaPath(username) + if (!fs.existsSync(file)) return emptyMeta() try { - if (fs.existsSync(metaPath(username))) return normalizeMeta(JSON.parse(fs.readFileSync(metaPath(username), 'utf8'))) - } catch { /* 损坏时按空评分处理 */ } - return emptyMeta() + const data = validateRatingStorage(JSON.parse(fs.readFileSync(file, 'utf8'))) + const catalogFile = path.join(ratingDir(username), 'songs.json') + const catalog = fs.existsSync(catalogFile) ? JSON.parse(fs.readFileSync(catalogFile, 'utf8')) : {} + const before = JSON.stringify(data), beforeCatalog = JSON.stringify(catalog) + const changes = planRatingMigration(userDir(username), data, catalog) + if (JSON.stringify(data) !== before) changes.set(file, JSON.stringify(data)) + if (JSON.stringify(catalog) !== beforeCatalog) changes.set(catalogFile, JSON.stringify(catalog)) + commitRatingFiles(userDir(username), changes) + return normalizeMeta(data) + } + catch { throw new Error('评分文件损坏,已停止操作并保留原文件,请从备份恢复') } } const writeMeta = (username: string, meta: RatingMeta) => { fs.mkdirSync(path.dirname(metaPath(username)), { recursive: true }) - fs.writeFileSync(metaPath(username), JSON.stringify(meta), 'utf8') + const file = metaPath(username) + fs.writeFileSync(file + '.restore.tmp', JSON.stringify(meta), 'utf8') + fs.renameSync(file + '.restore.tmp', file) } const readInfo = (username: string): RatingSnapshotInfo => { @@ -113,7 +186,7 @@ const cleanupAutoSnapshots = (username: string) => { /** 按当前评分内容生成(或复用)一份系统快照,返回快照 id */ export const createRatingSnapshot = async (username: string): Promise => { - const meta = readMeta(username) + const meta = exportRatingBackup(username) const id = md5(JSON.stringify(meta)) ensureDirs(username) const file = snapshotPath(username, id) @@ -175,7 +248,26 @@ export const readRatingSnapshot = async (username: string, id: string): Promise< export const restoreRatingSnapshot = async (username: string, id: string): Promise => { const meta = await readRatingSnapshot(username, id) if (!meta) throw new Error('Rating snapshot not found') - writeMeta(username, meta) + // 与 Subsonic 的评分/收藏写入共用锁,旧快照的收藏字段不参与恢复。 + await withRatingIdentityLock(username, () => withMetaLock(username, async () => { + recoverRatingTransaction(userDir(username)) + const current = readMeta(username) + const dir = userDir(username) + recoverRatingTransaction(dir) + const catalogFile = path.join(ratingDir(username), 'songs.json') + const catalog = meta.ratingCatalog ? sanitizeRatingCatalog(meta.ratingCatalog) : (fs.existsSync(catalogFile) ? JSON.parse(fs.readFileSync(catalogFile, 'utf8')) : {}) + const history = { ...(current.ratingHistory || meta.ratingHistory || {}) } + for (const key of new Set([...Object.keys(current.ratings), ...Object.keys(meta.ratings)])) { + const from = current.ratings[key] || 0, to = meta.ratings[key] || 0 + if (from !== to) history[key] = [...(history[key] || []), { from, to, channel: 'snapshot-restore', at: Date.now(), snapshotId: id }].slice(-30) + } + const restored = { ...current, ratings: { ...meta.ratings }, ratingOrigins: { ...(meta.ratingOrigins || {}) }, ratingHistory: history } + const changes = planRatingMigration(dir, restored, catalog) + changes.set(catalogFile, JSON.stringify(catalog)) + changes.set(metaPath(username), JSON.stringify(restored)) + commitRatingFiles(dir, changes) + + })) } export const deleteRatingSnapshot = async (username: string, id: string): Promise => { diff --git a/src/server/rating/ratingValidation.ts b/src/server/rating/ratingValidation.ts new file mode 100644 index 00000000..a6b981bd --- /dev/null +++ b/src/server/rating/ratingValidation.ts @@ -0,0 +1,16 @@ +const record = (value: any) => value && typeof value === 'object' && !Array.isArray(value) +const safeId = (id: string) => !!id && id.length <= 512 && !['__proto__','constructor','prototype'].includes(id) +export function normalizeRatingHistory(value: any): Record { + const result: Record = Object.create(null) + if (!record(value)) return result + for (const [id, events] of Object.entries(value)) { + if (!safeId(id) || !Array.isArray(events)) continue + result[id] = events.filter(e => record(e) && Number.isInteger(e.from) && e.from >= 0 && e.from <= 5 && Number.isInteger(e.to) && e.to >= 0 && e.to <= 5 && typeof e.at === 'number' && Number.isFinite(e.at) && e.at > 0 && typeof e.channel === 'string' && e.channel.length <= 100).slice(-30).map(e => ({ from:e.from,to:e.to,at:e.at,channel:e.channel,...(typeof e.snapshotId === 'string' && e.snapshotId.length<=200 ? {snapshotId:e.snapshotId}: {}) })) + } + return result +} +export function validateRatingStorage(data: any) { + if (!record(data) || (data.ratings !== undefined && !record(data.ratings))) throw new Error('评分文件结构损坏,请从备份恢复;原文件未修改') + if (data.ratings && Object.entries(data.ratings).some(([id,value]) => !safeId(id) || !Number.isInteger(value) || Number(value)<1 || Number(value)>5)) throw new Error('评分文件包含无效分值,已停止操作并保留原文件') + return data +} diff --git a/src/server/server.ts b/src/server/server.ts index 83e74e84..a17e3ee3 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,3 +1,5 @@ +import { readRatingPreferences, saveRatingPreferences } from './rating/ratingPreferences' +import { ratingVersion, readRatingTasks, retryRatingTasks, ratingIdentityDetails, listRatingItems, readRatings, resolveRatingId, resolveStoredRatingId, writeRating } from './rating/ratingService' import { getOpenlistRuntimeStatus } from './openlist/openlistBackup' import * as webdavRestoreTasks from './backup/webdavRestoreTasks' import { lookupLocalLyrics } from './music/localLyrics' @@ -19,12 +21,12 @@ import { SYNC_CLOSE_CODE, } from '@/constants' import { getUserSpace, releaseUserSpace, getUserName, getServerId, getUserDirname, getUserConfig, migrateUserData, renameUserSpace, finishRenameUserSpace, updateAllUserSnapshotDirs } from '@/user' -import { parseDislikeRules, splitSingers } from '@/modules/dislike/match' +import { scopeDislikeRules, parseDislikeRules, splitSingers } from '@/modules/dislike/match' import { encodeAlbumRule } from '@/modules/dislike/utils' import { normalizeText } from '@/server/utils/songVersion' import { invalidateDislikeCache } from '@/server/utils/dislikeCache' -import { invalidateSubsonicPlaylistCache, syncRatingsToDislike, syncDislikesToRating } from '@/server/integrations/subsonic' -import { createRatingSnapshot, saveRatingImport, listRatingSnapshots, readRatingSnapshot, restoreRatingSnapshot, deleteRatingSnapshot, normalizeRatingMeta, isValidSnapshotId } from './ratingSnapshot' +import { invalidateSubsonicPlaylistCache, syncRatingsToDislike, syncDislikesToRating, readSubsonicMeta } from '@/server/integrations/subsonic' +import { exportRatingBackup, createRatingSnapshot, saveRatingImport, listRatingSnapshots, readRatingSnapshot, restoreRatingSnapshot, deleteRatingSnapshot, normalizeRatingMeta, isValidSnapshotId } from './rating/ratingSnapshot' import { createMsg2call } from 'message2call' import { handleFileManager } from './integrations/fileManager' import formidable from 'formidable' @@ -176,12 +178,13 @@ const serializeDislikeRules = (rules: string, username?: string) => { const albumsArr = JSON.parse(fs.readFileSync(albumsFile, 'utf8')) if (Array.isArray(albumsArr)) { for (const x of albumsArr) { + const scoped = scopeDislikeRules(parsed, x.source) const albumName = normalizeText(String(x.name || '')) if (!albumName) continue - let sSet = parsed.albums.get(albumName) + let sSet = scoped.albums.get(albumName) if (!sSet) { sSet = new Set() - parsed.albums.set(albumName, sSet) + scoped.albums.set(albumName, sSet) } const singers = splitSingers(x.artistName) for (const s of singers) sSet.add(s) @@ -194,8 +197,9 @@ const serializeDislikeRules = (rules: string, username?: string) => { const artistsArr = JSON.parse(fs.readFileSync(artistsFile, 'utf8')) if (Array.isArray(artistsArr)) { for (const x of artistsArr) { + const scoped = scopeDislikeRules(parsed, x.source) const singerName = normalizeText(String(x.name || '')) - if (singerName) parsed.singerNames.add(singerName) + if (singerName) scoped.singerNames.add(singerName) } } } @@ -204,6 +208,7 @@ const serializeDislikeRules = (rules: string, username?: string) => { } } return { + scoped: parsed.scoped ? Object.fromEntries([...parsed.scoped].map(([source, rules]) => [source, { exact: [...rules.exact], musicNames: [...rules.musicNames], singerNames: [...rules.singerNames], albums: [...rules.albums].map(([albumName, singers]) => ({ albumName, singers: [...singers] })) }])) : {}, exact: Array.from(parsed.exact), musicNames: Array.from(parsed.musicNames), singerNames: Array.from(parsed.singerNames), @@ -1973,11 +1978,16 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi console.error(err) } + const dislikeList = (await userSpace.dislikeManage.getDislikeRules()).dislikeList + await require('./music/subsonicLocal').getLocalTracks(verifiedUser) + const ratingMeta = readSubsonicMeta(verifiedUser) + const ratingItems = listRatingItems(verifiedUser) + const activeRatings = Object.fromEntries(ratingItems.filter(x => !x.dormant).map(x => [x.id, x.rating])) res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache, no-store, must-revalidate' }) - res.end(JSON.stringify({ ...data, albums, artists, dislikeAlbums, dislikeArtists })) + res.end(JSON.stringify({ ...data, albums, artists, dislikeAlbums, dislikeArtists, dislikeList, userRatings: activeRatings, storedRatings: ratingMeta.ratings, ratingOrigins: ratingMeta.ratingOrigins || {}, ratingItems, ratingSyncPending: readRatingTasks(verifiedUser) })) }).catch(err => { res.writeHead(500) res.end(err.message) @@ -2462,18 +2472,18 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi return } try { - const { user, direction } = JSON.parse(await readBody(req)) + const { user, direction, preview, reconcile } = JSON.parse(await readBody(req)) if (!user || typeof user !== 'string') throw new Error('Missing user') if (direction !== 'ratingToDislike' && direction !== 'dislikeToRating') throw new Error('Invalid direction') const enabled = direction === 'ratingToDislike' ? global.lx.config['subsonic.linkRatingToDislike'] - : global.lx.config['subsonic.linkDislikeToRating'] + : true if (!enabled) throw new Error('联动开关未开启,请先在配置中开启并保存') const known = user === '_open' || global.lx.config.users.some((u: any) => u.name === user) if (!known) throw new Error('用户不存在') const result = direction === 'ratingToDislike' - ? await syncRatingsToDislike(user) - : await syncDislikesToRating(user) + ? (reconcile === true ? await require('./integrations/subsonic').subsonicHandler.reconcileRatingDislikes(user, preview !== false) : await syncRatingsToDislike(user, preview === true)) + : await syncDislikesToRating(user, preview === true) res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify(result)) } catch (err: any) { @@ -5538,14 +5548,14 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi void readBody(req).then(async body => { try { - const { filename, songInfo } = JSON.parse(body) + const { filename, songInfo, folder } = JSON.parse(body) if (!filename || !songInfo) { res.writeHead(400) res.end('Missing params') return } - const result = await fileCache.linkLocalFile(filename, songInfo, verified) + const result = await fileCache.linkLocalFile(filename, songInfo, verified, folder === 'music' || folder === 'cache' ? folder : undefined) res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify(result)) } catch (e: any) { @@ -7152,6 +7162,68 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi // GET /api/music/dislike 返回已解析的规则集(歌曲 / 歌手 / 专辑) // POST /api/music/dislike/add body: { type, name?, singer?, source?, albumId? } // POST /api/music/dislike/remove body: 同上 + if (pathname === '/api/data/rating-sync' && (req.method === 'GET' || req.method === 'POST')) { + res.setHeader('Content-Type','application/json'); res.setHeader('Cache-Control','no-store') + if (req.headers['x-frontend-auth'] !== global.lx.config['admin.password']) {res.writeHead(401);res.end(JSON.stringify({error:'Unauthorized'}));return} + try { + const user = new URL(req.url || '/', 'http://localhost').searchParams.get('user') || '' + if (user !== '_open' && !global.lx.config.users.some(u=>u.name===user)) throw Error('用户不存在') + const result = req.method === 'POST' ? await retryRatingTasks(user) : {pending:readRatingTasks(user),version:ratingVersion(user)} + res.end(JSON.stringify(result)) + } catch(e:any){res.writeHead(400);res.end(JSON.stringify({error:e.message}))} + return + } + + if (pathname === '/api/music/rating-preferences' && (req.method === 'GET' || req.method === 'POST')) { + const user = verifyUserAuth(req) + res.setHeader('Content-Type', 'application/json'); res.setHeader('Cache-Control', 'no-store') + if (!user) { res.writeHead(401); res.end(JSON.stringify({ error: '请先登录本地账号' })); return } + try { + const preference = req.method === 'GET' ? readRatingPreferences(user) : saveRatingPreferences(user, JSON.parse(await readBody(req)).dislikeAutoRating) + res.end(JSON.stringify(preference)) + } catch (e: any) { res.writeHead(400); res.end(JSON.stringify({ error: e.message })) } + return + } + + if (pathname === '/api/music/ratings' && (req.method === 'GET' || req.method === 'POST')) { + const user = verifyUserAuth(req) + if (!user) { res.writeHead(401); res.end(JSON.stringify({ error: '请先登录本地账号' })); return } + try { + res.setHeader('Content-Type', 'application/json') + res.setHeader('Cache-Control', 'no-store') + if (req.method === 'GET') { + const meta = readRatings(user) + for (const id of Object.keys(meta.ratings)) { if (id.startsWith('local_') && await resolveStoredRatingId(user, id) !== id) { delete meta.ratings[id]; if (meta.ratingOrigins) delete meta.ratingOrigins[id] } } + const songs = listRatingItems(user).filter(item => Object.hasOwn(meta.ratings, item.id)) + res.end(JSON.stringify({ version: ratingVersion(user), pending: readRatingTasks(user), ratings: meta.ratings, origins: meta.ratingOrigins || {}, songs })); return + } + const body = JSON.parse(await readBody(req)) + if (body.operation === 'version') { res.end(JSON.stringify({ version: ratingVersion(user) })); return } + if (body.operation === 'retryFailed') { res.end(JSON.stringify(await retryRatingTasks(user))); return } + if (body.operation === 'exportBackup') { res.end(JSON.stringify(exportRatingBackup(user))); return } + if (body.operation === 'resolve') { + if (!Array.isArray(body.songs) || body.songs.length > 100) throw new Error('Too many songs') + const meta = readRatings(user) + const entries = await Promise.all(body.songs.map(async (song: any) => { + try { const identity = await ratingIdentityDetails(user, song, body.includeDetails === true); return { ...identity, rating: meta.ratings[identity.id] || 0 } } + catch (e: any) { return { id: null, rating: 0, error: e.message } } + })) + res.end(JSON.stringify({ entries, version: ratingVersion(user) })); return + } + const rating = body.rating + if (!Number.isInteger(rating) || rating < 0 || rating > 5) throw new Error('评分必须为0至5的整数') + const requestedId = await resolveRatingId(user, body.song) + const saved = await writeRating(user, requestedId, rating, 'web', body.song) + const id = saved.id + let linkWarning + try { await require('./integrations/subsonic').subsonicHandler.applyRatingLink(user, id, rating, body.song) } + catch { linkWarning = '评分已保存,但不喜欢联动失败,可重试或手动补齐' } + invalidateSubsonicPlaylistCache() + res.end(JSON.stringify({ id, rating, warning: linkWarning || saved.snapshotWarning })) + } catch (err: any) { res.writeHead(400); res.end(JSON.stringify({ error: err.message })) } + return + } + if (pathname === '/api/music/dislike' && req.method === 'GET') { const verified = verifyUserAuth(req) if (!verified) { @@ -7183,8 +7255,15 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi } try { const isAdd = pathname === '/api/music/dislike/add' - const payload = JSON.parse(body || '{}') + let payload = JSON.parse(body || '{}') const type = String(payload.type || 'song') + if (type === 'song' && (payload.isLocal || payload._localFilename)) { + const effectiveId = await resolveRatingId(verified, payload) + const local = require('./music/subsonicLocal') + const tracks = await local.getLocalTracks(verified, false, payload._localLocation) + const track = tracks.find((item: any) => local.localRatingId(item) === effectiveId) + payload = { ...payload, id: effectiveId, source: effectiveId.startsWith('local_') ? 'local' : effectiveId.split('_')[0], name: track?.title || payload.name, singer: track?.artist || payload.singer } + } const name = String(payload.name || '') const singer = String(payload.singer || '') const source = String(payload.source || '') @@ -7205,7 +7284,7 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi return } const singers = splitSingers(singer) - if (isAdd) await dm.dislikeDataManage.addDislikeAlbums(singers.map(s => ({ albumName, singer: s }))) + if (isAdd) await dm.dislikeDataManage.addDislikeAlbums(singers.map(s => ({ albumName, singer: s, source, provenance: { channel: 'web', at: Date.now() } }))) else for (const s of singers) { removeKeys.add(encodeAlbumRule(normalizeText(albumName), s)) removeKeys.add(normalizeText(encodeAlbumRule(albumName, s))) @@ -7216,7 +7295,7 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi res.end(JSON.stringify({ success: false, message: 'Missing singer' })) return } - if (isAdd) await dm.dislikeDataManage.addDislikeInfo([{ name: '', singer, dislikeRule: '' }]) + if (isAdd) await dm.dislikeDataManage.addDislikeInfo([{ name: '', singer, source, dislikeRule: '', provenance: { channel: 'web', at: Date.now() } }]) else removeKeys.add(`@${normalizeText(singer)}`) } else { if (!name) { @@ -7227,6 +7306,8 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi if (isAdd) { const { type, ...songData } = payload songData.dislikeRule = '' + songData.provenance = { channel: 'web', at: Date.now() } + songData.reasons = [songData.provenance] await dm.dislikeDataManage.addDislikeInfo([songData]) } else { if (singer) { @@ -7238,29 +7319,25 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi } } - const dislikeRatingThreshold = global.lx.config['subsonic.dislikeRating'] ?? 1 - if (global.lx.config['subsonic.linkDislikeToRating'] && dislikeRatingThreshold > 0 && id && source) { - const subId = id.startsWith(`${source}_`) ? id : `${source}_${id}` + let ratingWarning: string | undefined + let ratingResult: string | undefined + const dislikeAutoRating = readRatingPreferences(verified).dislikeAutoRating + if (type === 'song' && dislikeAutoRating && id && source) { try { + const subId = await resolveRatingId(verified, payload) + const hadRating = readRatings(verified).ratings[subId] > 0 const { syncDislikeToRating } = require('./integrations/subsonic') - await syncDislikeToRating(verified, subId, isAdd ? 1 : 0) + await syncDislikeToRating(verified, subId, isAdd ? 1 : 0, payload) + ratingResult = !isAdd ? 'unchanged' : hadRating ? 'existing' : 'supplemented' } catch (e) { console.error('[黑名单 API] 评分回写失败:', e) + ratingWarning = '不喜欢操作已保存,但补分或评分快照未完成,可重试或在后台补分' + ratingResult = 'failed' } } if (!isAdd && removeKeys.size > 0) { - const rulesString = dm.dislikeDataManage.getDislikeRulesString() - const lines = rulesString.split('\n').filter((l: string) => l.trim()) - const remain = lines.filter((l: string) => { - const trimmed = l.trim().toLowerCase() - if (removeKeys.has(trimmed)) return false - // Also check without spaces or with alias - return true - }) - if (remain.length !== lines.length) { - await dm.dislikeDataManage.overwirteDislikeInfo(remain.join('\n')) - } + for (const rule of removeKeys) await dm.dislikeDataManage.removeDislikeInfo(rule, source || undefined) } await dm.createSnapshot() @@ -7270,7 +7347,7 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi const data: any = serializeDislikeRules(finalRulesString, verified) data.dislikeList = dm.dislikeDataManage.dislikeRules.dislikeList || [] res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' }) - res.end(JSON.stringify({ success: true, data, options: dislikeMatchOptions() })) + res.end(JSON.stringify({ success: true, data, options: dislikeMatchOptions(), warning: ratingWarning, ratingResult })) } catch (err: any) { console.error('[黑名单 API] 处理异常:', err?.message) res.writeHead(500, { 'Content-Type': 'application/json' }) @@ -7443,8 +7520,8 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi 'subsonic.sharedListMode': global.lx.config['subsonic.sharedListMode'] ?? 'leaderboard', 'subsonic.sharedListSort': global.lx.config['subsonic.sharedListSort'] ?? 'hot', 'subsonic.dislikeRating': global.lx.config['subsonic.dislikeRating'] ?? 1, + 'subsonic.ratingPlaylists': global.lx.config['subsonic.ratingPlaylists'] ?? true, 'subsonic.linkRatingToDislike': global.lx.config['subsonic.linkRatingToDislike'] ?? false, - 'subsonic.linkDislikeToRating': global.lx.config['subsonic.linkDislikeToRating'] ?? false, 'subsonic.hideDisliked': global.lx.config['subsonic.hideDisliked'] ?? true, 'subsonic.dislikeCrossSource': global.lx.config['subsonic.dislikeCrossSource'] ?? false, 'subsonic.dislikeNoRecommend': global.lx.config['subsonic.dislikeNoRecommend'] ?? true, @@ -7742,6 +7819,7 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi if (['hot', 'new'].includes(st)) global.lx.config['subsonic.sharedListSort'] = st as any } if (newConfig['subsonic.dislikeRating'] !== undefined) global.lx.config['subsonic.dislikeRating'] = Number(newConfig['subsonic.dislikeRating']) + if (typeof newConfig['subsonic.ratingPlaylists'] === 'boolean') global.lx.config['subsonic.ratingPlaylists'] = newConfig['subsonic.ratingPlaylists'] if (newConfig['subsonic.hideDisliked'] !== undefined) global.lx.config['subsonic.hideDisliked'] = !!newConfig['subsonic.hideDisliked'] if (newConfig['subsonic.dislikeCrossSource'] !== undefined) global.lx.config['subsonic.dislikeCrossSource'] = !!newConfig['subsonic.dislikeCrossSource'] if (newConfig['subsonic.dislikeNoRecommend'] !== undefined) global.lx.config['subsonic.dislikeNoRecommend'] = !!newConfig['subsonic.dislikeNoRecommend'] @@ -7752,7 +7830,6 @@ const handleStartServer = async (port = 9527, ip = '0.0.0.0') => await new Promi if (newConfig['subsonic.dislikeNormalizeName'] !== undefined) global.lx.config['subsonic.dislikeNormalizeName'] = !!newConfig['subsonic.dislikeNormalizeName'] if (newConfig['subsonic.dislikeRequireSinger'] !== undefined) global.lx.config['subsonic.dislikeRequireSinger'] = !!newConfig['subsonic.dislikeRequireSinger'] if (newConfig['subsonic.linkRatingToDislike'] !== undefined) global.lx.config['subsonic.linkRatingToDislike'] = !!newConfig['subsonic.linkRatingToDislike'] - if (newConfig['subsonic.linkDislikeToRating'] !== undefined) global.lx.config['subsonic.linkDislikeToRating'] = !!newConfig['subsonic.linkDislikeToRating'] if (newConfig['subsonic.recommendPoolSize'] !== undefined) global.lx.config['subsonic.recommendPoolSize'] = Number(newConfig['subsonic.recommendPoolSize']) if (newConfig['subsonic.lyricTranslation'] !== undefined) global.lx.config['subsonic.lyricTranslation'] = newConfig['subsonic.lyricTranslation'] if (newConfig['subsonic.cacheOnPlay'] !== undefined) global.lx.config['subsonic.cacheOnPlay'] = newConfig['subsonic.cacheOnPlay'] diff --git a/src/server/utils/dislikeCache.ts b/src/server/utils/dislikeCache.ts index c04bda39..3a9dcc27 100644 --- a/src/server/utils/dislikeCache.ts +++ b/src/server/utils/dislikeCache.ts @@ -1,5 +1,5 @@ import type { DislikeRuleSet } from '@/modules/dislike/match' -import { parseDislikeRules } from '@/modules/dislike/match' +import { scopeDislikeRules, parseDislikeRules } from '@/modules/dislike/match' /** * dislike 规则集解析缓存。 @@ -52,12 +52,13 @@ export async function getCachedDislikeRuleSet( if (Array.isArray(albumsArr)) { const { normalizeText, splitSingers } = require('@/modules/dislike/match') for (const x of albumsArr) { + const scoped = scopeDislikeRules(set, x.source) const albumName = normalizeText(String(x.name || '')) if (!albumName) continue - let sSet = set.albums.get(albumName) + let sSet = scoped.albums.get(albumName) if (!sSet) { sSet = new Set() - set.albums.set(albumName, sSet) + scoped.albums.set(albumName, sSet) } const singers = splitSingers(x.artistName) for (const s of singers) sSet.add(s) @@ -70,8 +71,9 @@ export async function getCachedDislikeRuleSet( if (Array.isArray(artistsArr)) { const { normalizeText } = require('@/modules/dislike/match') for (const x of artistsArr) { + const scoped = scopeDislikeRules(set, x.source) const singerName = normalizeText(String(x.name || '')) - if (singerName) set.singerNames.add(singerName) + if (singerName) scoped.singerNames.add(singerName) } } } diff --git a/src/types/config.d.ts b/src/types/config.d.ts index beac82f2..84e32526 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -394,18 +394,13 @@ declare namespace LX { */ 'subsonic.linkRatingToDislike'?: boolean - /** - * 解耦开关(反向): 不喜欢 -> 评星 是否自动联动 (默认 false) - * true 时, 网页端 / Subsonic 给某歌点「不喜欢」会回写该用户 subsonic-meta.json 的 ratings 映射(低星), - * 使 Subsonic 客户端能看到这颗星; false 时, 「不喜欢」仅写入原生 dislike 规则, 不回写评星, 与评星解耦。 - */ - 'subsonic.linkDislikeToRating'?: boolean + /** * 是否向 Subsonic 客户端暴露 1~5 星评星歌单 (默认 true) * 虚拟只读歌单(不落盘、不影响 LX 客户端「我的歌单」):id 为 rating_1 ~ rating_5。 - * rating_1 承载「我不喜欢」:除 1 星歌曲外并入 dislike 规则命中的歌曲,并强制显示 1 星; - * 开启时「1 星 <-> 不喜欢」双向联动强制生效(不受上面两个解耦开关影响), + * rating_1 承载「我不喜欢」:除 1 星歌曲外并入 dislike 规则命中的歌曲,无真实评分时显示 1 星; + * 仅控制显示;自动联动分别受对应开关控制,仅补充缺失数据, * 便于只能用评星操作的 Subsonic 客户端通过 1 星查找并处理不喜欢。 */ 'subsonic.ratingPlaylists'?: boolean diff --git a/src/types/dislike_list.d.ts b/src/types/dislike_list.d.ts index ca700104..06908a90 100644 --- a/src/types/dislike_list.d.ts +++ b/src/types/dislike_list.d.ts @@ -28,11 +28,17 @@ declare namespace LX { * 规则串中以 !<专辑名>@<歌手> 形式存储,按歌手拆成多条。 */ interface DislikeAlbumInfo { + source?: string + provenance?: { channel: string, at: number, ratingId?: string } + reasons?: { channel: string, at: number, ratingId?: string }[] albumName: string singer: string } interface DislikeSongInfo { + provenance?: { channel: string, at: number, ratingId?: string } + reasons?: { channel: string, at: number, ratingId?: string }[] + enrichedBy?: { channel: string, at: number } id?: string name: string singer: string diff --git a/src/utils/backupPolicy.ts b/src/utils/backupPolicy.ts index 1c92f67c..8a877606 100644 --- a/src/utils/backupPolicy.ts +++ b/src/utils/backupPolicy.ts @@ -29,7 +29,7 @@ export interface BackupContext { export const BACKUP_TYPE_INFO = [ { id: 'music', label: '歌曲与歌词', description: '当前数据目录的 music/(默认 data/music)内的歌曲、已有歌词、封面和音乐索引;不含各级 cache、数据目录外独立 music 或外部曲库。' }, { id: 'userFiles', label: '用户音源文件', description: 'users/source 内的音源脚本、顺序和状态文件,以及上传的用户文件。' }, - { id: 'snapshots', label: '歌单与不喜欢快照', description: '快照正文、snapshotInfo.json;包含没有扩展名的快照及已配置的外部歌单快照目录。' }, + { id: 'snapshots', label: '歌单、不喜欢与评分快照', description: '快照正文、snapshotInfo.json;包含没有扩展名的快照及已配置的外部歌单快照目录。' }, { id: 'userData', label: '用户数据', description: '用户设置、播放记录、收藏与其他 JSON 数据;不包含音源文件和快照。' }, { id: 'system', label: '系统与账户', description: 'config.js、users.json、serverInfo.json 等系统 JSON;包含账号和连接凭据。' }, ] as const @@ -55,7 +55,7 @@ export function backupType(relative: string): BackupType | null { if (/^users\/[^/]+\/music\//i.test(rel)) return null if (/\.(tmp|oltmp|part|log|lock|db|sqlite)(-(wal|shm))?$/i.test(rel) || /(^|\/)temp-|(^|\/)lx-sync-backup-/.test(lower)) return null if (lower.startsWith('music/')) return 'music' - if (lower.startsWith('_snapshots/') || /^users\/[^/]+\/(list|dislike)\/snapshot(\/|info\.json$)/i.test(rel)) return 'snapshots' + if (lower.startsWith('_snapshots/') || /^users\/[^/]+\/(list|dislike|rating)\/snapshot(\/|info\.json$)/i.test(rel)) return 'snapshots' if (/^(users\/source|source|uploads)\//i.test(rel)) return 'userFiles' if (/^users\/[^/]+\//i.test(rel)) return 'userData' if (lower === 'config.js' || (!rel.includes('/') && lower.endsWith('.json'))) return 'system' diff --git a/test/admin-dislike-view.test.cjs b/test/admin-dislike-view.test.cjs new file mode 100644 index 00000000..5fe0a2fe --- /dev/null +++ b/test/admin-dislike-view.test.cjs @@ -0,0 +1,61 @@ +const test = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const vm = require('node:vm'); +const source = fs.readFileSync('public/app.js','utf8'); +function harness(data) { + const start=source.indexOf(' dislikeOriginLabel('),end=source.indexOf(' getPlaylistsSectionHtml(',start); + assert.ok(start>=0&&end>start); + const context=vm.createContext({}); + vm.runInContext(`class Harness { escapeHtml(s) { return String(s).replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('"','"').replaceAll("'",''') } getSourceLabel(s) { return s } ${source.slice(start,end)} }; globalThis.instance=new Harness()`,context); + const app=context.instance;app.currentUserData={username:'test',data};return app; +} +const fixture={dislikeList:[{name:'',singer:'artist',source:'tx',id:'tx_1',songmid:'1',img:'javascript:alert(1)',dislikeRule:'track@artist',provenance:{channel:'web',at:1}},{name:'',singer:'',source:'wy',dislikeRule:'!album@artist',provenance:{channel:'subsonic-rating',at:2}}],dislikeArtists:[{name:'Artist',source:'tx',picUrl:'https://example.com/cover.jpg'}],userRatings:{tx_1:5},ratingOrigins:{tx_1:{channel:'subsonic',at:3}}}; +test('管理查看合并三类记录,准确区分添加来源与平台,保留原始字段',()=>{ + const app=harness(fixture);const rows=app.getDislikeEntries(fixture); + assert.deepEqual(Array.from(rows,x=>x.kind),['song','album','artist']);assert.equal(rows[0].cover,'');assert.equal(rows[1].title,'album');assert.equal(rows[2].channel,'unknown'); + const html=app.getDislikeSectionHtml(fixture);assert.match(html,/Web 添加/);assert.match(html,/Subsonic 低分联动/);assert.match(html,/来源未记录/);assert.match(html,/查看详情/);assert.ok([...app._adminDetails.values()].every(m=>m.raw&&m.sections.length));assert.ok(!html.includes('
    '));assert.match(html,/aria-label="5 星"/);assert.ok(!html.includes('',value:'tx',selected:true}],closest:()=>host};const wrapper=make();const trigger={getBoundingClientRect:()=>({left:120,top:150,bottom:190,width:140})};context.window.CustomSelectManager.open(select,wrapper,trigger);return{body,manager:context.window.CustomSelectManager,select};
    +}
    +test('统一下拉菜单挂载到所属dialog,坐标换算为弹窗内且文本不注入HTML',()=>{
    + const host={children:[],appendChild(x){this.children.push(x)},getBoundingClientRect:()=>({left:100,top:50,bottom:650}),scrollLeft:0,scrollTop:10,clientLeft:1,clientTop:1};const{body}=setup(host);assert.equal(body.children.length,0);assert.equal(host.children.length,1);const dropdown=host.children[0];assert.equal(dropdown.style.left,'19px');assert.equal(dropdown.style.top,'153px');assert.equal(dropdown.children[0].children[0].children[0].textContent,'');
    +});
    +test('非模态页面下拉菜单继续挂载body,不改变普通页面坐标',()=>{const{body}=setup(null);assert.equal(body.children.length,1);assert.equal(body.children[0].style.left,'120px');assert.equal(body.children[0].style.top,'194px')});
    +test('我的评分显式初始化统一组件、映射手动补分,并在关闭时清理菜单',()=>{const text=fs.readFileSync('public/music/js/library/rating_manager.js','utf8');assert.match(text,/CustomSelectManager\?\.init\(select\)/);assert.match(text,/'manual-dislike-to-rating': '后台补分'/);assert.match(text,/collectionDialog.addEventListener\('close'.*CustomSelectManager\?\.closeAll/);assert.match(text,/评分来源是什么意思/);assert.match(text,/terms.every/)});
    diff --git a/test/rating-feature-coverage.test.ts b/test/rating-feature-coverage.test.ts
    new file mode 100644
    index 00000000..6b0195ce
    --- /dev/null
    +++ b/test/rating-feature-coverage.test.ts
    @@ -0,0 +1,181 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import vm from 'node:vm'
    +import { transformSync } from 'esbuild'
    +import { DislikeDataManage } from '../src/modules/dislike/dislikeDataManage'
    +import { parseDislikeRules, filterDisliked } from '../src/modules/dislike/match'
    +
    +const source = fs.readFileSync('src/server/integrations/subsonic.ts', 'utf8').replace(/\r/g, '')
    +function between(from: string, to: string) {
    +  const a = source.indexOf(from), b = source.indexOf(to, a + from.length)
    +  assert.ok(a >= 0 && b > a, from)
    +  return source.slice(a, b)
    +}
    +function dataManage() {
    +  return new DislikeDataManage({ snapshotInfo: {}, getSnapshotInfo: async () => ({ latest: null }) } as any)
    +}
    +function harness() {
    +  const dm = dataManage()
    +  const state = { snapshots: 0, ratings: {} as Record, invalidations: 0, aliases: {} as Record }
    +  const methods = between('    private async resolveDislikeTarget(', '    /** 按 dislike 规则过滤歌曲列表') +
    +    between('    async syncRatingsToDislike(', '    /**\n     * 手动补数据(不喜欢') +
    +    between('    async syncDislikesToRating(', '    /**\n     * 处理 Subsonic setRating')
    +  const context = vm.createContext({
    +    resolveStoredRatingId: async (_u: string, id: string) => state.aliases[id] || id,
    +    localRatingId: (track: any) => track.platformId || track.id,
    +    state, global: { lx: { config: { 'subsonic.dislikeRating': 1 } } },
    +    getUserSpace: () => ({ dislikeManage: { dislikeDataManage: dm, createSnapshot: async () => { state.snapshots++ } } }),
    +    withTimeout: (p: any) => p, LINK_SYNC_ITEM_TIMEOUT_MS: 8000, LINK_SYNC_BATCH_SIZE: 20,
    +    countDislikeRules: (r: string) => r.split('\n').filter(Boolean).length,
    +    invalidateDislikeCache: () => { state.invalidations++ },
    +    writeRatingUnlocked:async (_u:string,id:string,rating:number)=>{const unchanged=state.ratings[id]>0;if(!unchanged)state.ratings[id]=rating;return {id,meta:{ratings:state.ratings},unchanged}},
    +    recordRatingBackfillFailure:()=>{},
    +    flushRatingSnapshot:async()=> (state as any).snapshotFailure ? '快照失败' : undefined,
    +    readSubsonicMeta: () => ({ ratings: state.ratings }),
    +    writeSubsonicMeta: (_u: string, meta: any) => { state.ratings = meta.ratings },
    +    withRatingIdentityLock: async (_u: string, fn: () => any) => fn(),
    +    withMetaLock: async (_u: string, f: () => any) => f(), createRatingSnapshot: async () => {},
    +    getLocalTracks: async () => [], localMusic: (x: any) => x,
    +    splitSingers: (s: string) => s.split('、'), normalizeText: (s: string) => s,
    +    encodeAlbumRule: (a: string, s: string) => `!${a}@${s}`,
    +    musicSdk: { wy: { extendDetail: { getAlbumSongs: async () => ({ name: 'album', list: [{ singer: 'artist' }] }) } } },
    +    subsonicLog: { warn() {}, error() {} },
    +  })
    +  vm.runInContext(transformSync(`class Harness {
    +    onlineSongCache = new Map(); userRatingsCache = new Map(); songs = new Map();
    +    loadOnlineSongCache() {}
    +    async getSubsonicListData() { return { loveList: [], defaultList: [...this.songs.values()], userList: [] } }
    +    async filterDislikedSongs(_u, songs) { return songs.filter(s => s.name !== 'blocked') }
    +    async resolveSongMeta(_u, id) { if (id === 'fail') throw Error('offline'); const music = this.songs.get(id); return music ? { music } : null }
    +    async resolveSingerIdentity(_u, name, preset) { return { name, source: preset?.source || '', singerId: preset?.id || '' } }
    +    async resolveArtistKey() { return { name: 'artist' } }
    +    dislikeRuleKey(name, singer) { return name + '@' + singer }
    +    ${methods}
    +  }; globalThis.instance = new Harness()`, { loader: 'ts', format: 'cjs' }).code, context)
    +  return { instance: (context as any).instance, dm, state }
    +}
    +const song = (id: string) => ({ id, name: 'track-' + id, singer: 'artist', source: 'wy', songmid: id, img: 'cover', interval: '03:00', types: [{ type: '128k' }], _types: { '128k': {} } })
    +
    +test('Subsonic 歌曲转换保留 Web 所需的已知资料字段', async () => {
    +  const { instance, dm } = harness()
    +  instance.songs.set('wy_1', song('wy_1'))
    +  const target = await instance.resolveDislikeTarget('alice', 'wy_1')
    +  await dm.addDislikeInfo(target.infos)
    +  const item = dm.dislikeRules.dislikeList[0] as any
    +  for (const key of ['id', 'source', 'songmid', 'name', 'singer', 'img', 'interval', 'types', '_types']) assert.deepEqual(item[key], (song('wy_1') as any)[key])
    +  assert.equal(item.dislikeRule, 'track-wy_1@artist')
    +})
    +
    +test('已知限制:残缺字段不会凭空补齐,同规则不同来源不会合并资料', async () => {
    +  const { instance, dm } = harness()
    +  instance.songs.set('wy_1', { id: 'wy_1', name: 'track', singer: 'artist' })
    +  const target = await instance.resolveDislikeTarget('alice', 'wy_1')
    +  assert.equal(target.infos[0].img, undefined)
    +  await dm.addDislikeInfo([{ name: 'track', singer: 'artist', dislikeRule: '' }])
    +  await dm.addDislikeInfo([{ ...song('wy_1'), name: 'track', dislikeRule: '' }] as any)
    +  assert.equal(dm.dislikeRules.dislikeList.length, 2)
    +  assert.equal((dm.dislikeRules.dislikeList[0] as any).img, undefined)
    +})
    +
    +test('歌手转换为名称规则,专辑转换为专辑规则,不展开歌曲', async () => {
    +  const { instance } = harness()
    +  const artist = await instance.resolveDislikeTarget('alice', 'art_tx_123')
    +  assert.equal(artist.infos[0].name, '')
    +  assert.equal(artist.infos[0].singer, 'artist')
    +  const album = await instance.resolveDislikeTarget('alice', 'alb_wy_123')
    +  assert.equal(album.infos.length, 0)
    +  assert.equal(album.album.albumName, 'album')
    +  assert.deepEqual(Array.from(album.album.singers), ['artist'])
    +})
    +
    +test('手动正向同步全量分批、幂等、跳过高分、失败继续并生成一次快照', async () => {
    +  const { instance, state, dm } = harness()
    +  for (let n = 0; n < 43; n++) { const id = 'wy_' + n; instance.songs.set(id, song(id)); state.ratings[id] = 1 }
    +  state.ratings.fail = 1; state.ratings.high = 5
    +  const first = await instance.syncRatingsToDislike('alice')
    +  assert.equal(first.scanned, 44); assert.equal(first.batches, 3); assert.equal(first.failed, 1)
    +  assert.equal(first.added, 43); assert.equal(state.snapshots, 1); assert.equal(state.invalidations, 1)
    +  const second = await instance.syncRatingsToDislike('alice')
    +  assert.equal(second.added, 0); assert.equal(dm.dislikeRules.dislikeList.length, 43)
    +})
    +
    +test('手动反向同步只补命中且缺失的评分,保留已有高分', async () => {
    +  const { instance, state } = harness()
    +  instance.songs.set('a', { ...song('a'), name: 'blocked' })
    +  instance.songs.set('b', { ...song('b'), name: 'blocked' })
    +  instance.songs.set('c', song('c')); state.ratings.a = 5
    +  const result = await instance.syncDislikesToRating('alice')
    +  assert.equal(result.added, 1); assert.equal(result.skipped, 1)
    +  assert.deepEqual(state.ratings, { a: 5, b: 1 })
    +})
    +
    +for (const [name, rules, candidate, options, expected] of [
    +  ['版本归一化开', 'track@artist', { name: 'track (Live)', singer: 'artist' }, { normalizeName: true }, 0],
    +  ['版本归一化关', 'track@artist', { name: 'track (Live)', singer: 'artist' }, { normalizeName: false }, 1],
    +  ['纯歌名要求歌手', 'track', { name: 'track', singer: 'artist' }, { requireSinger: true }, 1],
    +  ['纯歌名不要求歌手', 'track', { name: 'track', singer: 'artist' }, { requireSinger: false }, 0],
    +  ['合唱任一歌手', '@artist', { name: 'track', singer: 'other、artist' }, { duetMode: 'any' }, 0],
    +  ['合唱全部歌手', '@artist', { name: 'track', singer: 'other、artist' }, { duetMode: 'all' }, 1],
    +  ['合唱仅主唱', '@artist', { name: 'track', singer: 'other、artist' }, { duetMode: 'primary' }, 1],
    +] as const) {
    +  test(`规则选项:${name}`, () => {
    +    const result = filterDisliked([candidate], parseDislikeRules(rules), (x: any) => x, options as any)
    +    assert.equal(result.length, expected)
    +  })
    +}
    +
    +test('推荐过滤独立于普通列表隐藏开关', async () => {
    +  const method = between('    private async filterRecommendationEntries(', '    private async handleGetSimilarSongs')
    +  for (const hide of [false, true]) for (const exclude of [false, true]) {
    +    const context = vm.createContext({ global: { lx: { config: { 'subsonic.hideDisliked': hide, 'subsonic.dislikeNoRecommend': exclude } } } })
    +    vm.runInContext(transformSync(`class Harness {
    +      async getUserSubsonicMeta(){return {ratings:{}}}
    +      async filterDislikedEntries(_u, list) { return list.filter(x => x.music.id !== 'blocked') }
    +      musicToSongFlat(m) { return m }
    +      sendResponse(_res, data) { return data }
    +      ${method}
    +    }; globalThis.instance = new Harness()`, { loader: 'ts', format: 'cjs' }).code, context)
    +    const result = await (context as any).instance.renderRandomSongs({}, [{ music: { id: 'blocked' }, listId: 'default' }], 'json', 'randomSongs', 'alice')
    +    assert.equal(result.randomSongs.song.length, exclude ? 0 : 1)
    +  }
    +})
    +
    +test('已知限制:同名歌曲规则不带来源,跨来源开关不能隔离歌曲规则', () => {
    +  const rules = parseDislikeRules('track@artist')
    +  for (const crossSource of [false, true]) {
    +    const result = filterDisliked([{ name: 'track', singer: 'artist', source: 'tx' }], rules, x => x, { crossSource })
    +    assert.equal(result.length, 0)
    +  }
    +})
    +
    +test('手动正向同步把空解析计入失败,预览不写规则', async () => {
    +  const { instance, state, dm } = harness()
    +  state.ratings.missing = 1
    +  const preview = await instance.syncRatingsToDislike('alice', true)
    +  assert.equal(preview.candidates.length, 1)
    +  assert.equal(dm.dislikeRules.dislikeList.length, 0)
    +  assert.equal(state.snapshots, 0)
    +  const actual = await instance.syncRatingsToDislike('alice')
    +  assert.equal(actual.failed, 1)
    +  assert.equal(actual.added, 0)
    +})
    +
    +test('手动正向补齐已有记录也必须保存快照并报告updated', async () => {
    +  const { instance, state, dm } = harness()
    +  const music = song('wy_1')
    +  await dm.addDislikeInfo([{ name: music.name, singer: music.singer, source: music.source, id: music.id }])
    +  instance.songs.set('wy_1', music); state.ratings.wy_1 = 1
    +  const actual = await instance.syncRatingsToDislike('alice')
    +  assert.equal(actual.added, 0)
    +  assert.equal(actual.updated, 1)
    +  assert.equal(state.snapshots, 1)
    +  assert.equal((dm.dislikeRules.dislikeList[0] as any).img, 'cover')
    +})
    +
    +
    +test('后台补分预览区分已有分、重复关联和真正待新增,快照失败返回警告',async()=>{
    + const {instance,state}=harness();instance.songs.set('a',{...song('a'),name:'blocked'});instance.songs.set('b',{...song('b'),name:'blocked'});instance.songs.set('c',{...song('c'),name:'blocked'});state.aliases.b='a';state.ratings.a=5;
    + const preview=await instance.syncDislikesToRating('alice',true);assert.equal(preview.candidates.length,1);assert.equal(preview.existing.length,1);assert.equal(preview.duplicates.length,1);assert.equal(state.ratings.c,undefined)
    + ;(state as any).snapshotFailure=true;const result=await instance.syncDislikesToRating('alice');assert.equal(result.added,1);assert.equal(result.warning,'快照失败');assert.equal(state.ratings.a,5)
    +})
    diff --git a/test/rating-link-policy.test.ts b/test/rating-link-policy.test.ts
    new file mode 100644
    index 00000000..145b5b80
    --- /dev/null
    +++ b/test/rating-link-policy.test.ts
    @@ -0,0 +1,121 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import vm from 'node:vm'
    +import { transformSync } from 'esbuild'
    +
    +const source = fs.readFileSync('src/server/integrations/subsonic.ts', 'utf8')
    +const start = source.indexOf('    private async handleSetRating(')
    +const end = source.indexOf('    private async handleGetStarred(', start)
    +const reverseStart = source.indexOf('export async function syncDislikeToRating(')
    +const reverseEnd = source.indexOf('/**', reverseStart)
    +function build(config: Record = {}) {
    +  const state = { ratings: {} as Record, adds: 0, removes: 0, snapshots: 0, fail: false }
    +  const context = vm.createContext({
    +    global: { lx: { config } }, state,
    +    withTimeout: (promise:any) => promise, LINK_SYNC_ITEM_TIMEOUT_MS:8000,
    +    resolveStoredRatingId: async (_u: string, id: string) => id,
    +    withRatingIdentityLock: async (_u: string, fn: () => any) => fn(),
    +    withMetaLock: async (_u: string, fn: () => any) => fn(),
    +    createRatingSnapshot: async () => { state.snapshots++ },
    +    writeRating: async (_u: string, id: string, rating: number, channel:string, _song:any, options:any={}) => { if (state.fail && channel==='web-dislike-link') throw Error('disk failure');if(options.onlyMissing&&state.ratings[id]>0)return {id,meta:{ratings:state.ratings},unchanged:true};if (rating) state.ratings[id] = rating; else delete state.ratings[id]; state.snapshots++; return { id, meta: { ratings: state.ratings } } },
    +    readSubsonicMeta: () => ({ ratings: state.ratings }),
    +    writeSubsonicMeta: (_u: string, meta: any) => { if (state.fail) throw Error('disk failure'); state.ratings = meta.ratings },
    +    subsonicLog: { debug() {}, warn() {}, error() {} },
    +  })
    +  vm.runInContext(transformSync(`
    +class Harness {
    +  userRatingsCache = new Map()
    +  async getUserSubsonicMeta() { return { ratings: state.ratings } }
    +  async saveUserSubsonicMeta(_u, meta) { state.ratings = meta.ratings }
    +  async resolveSongMeta() {return null}
    +  async getRatingMetadata() {return null}
    +  async resolveDislikeTarget() { if (state.fail) throw Error('offline'); return { infos: [{ name: 'song' }], keys: new Set(['song']) } }
    +  async addDislikeRules() { state.adds++; return 1 }
    +  async removeDislikeRules() { state.removes++; return 1 }
    +  sendResponse() { return { ok: true } }
    +  sendError(_r, _code, message) { return { ok: false, message } }
    +${source.slice(source.indexOf('    async applyRatingLink('), start)}
    +${source.slice(start, end)}
    +}
    +${source.slice(reverseStart, reverseEnd).replace('export async', 'async')}
    +globalThis.instance = new Harness()
    +globalThis.reverse = syncDislikeToRating
    +`, { loader: 'ts', format: 'cjs' }).code, context)
    +  return { state, instance: (context as any).instance, reverse: (context as any).reverse }
    +}
    +
    +test('评分歌单开启也不能绕过关闭的正向联动', async () => {
    +  const { state, instance } = build({ 'subsonic.ratingPlaylists': true, 'subsonic.linkRatingToDislike': false })
    +  await instance.handleSetRating({}, 'alice', new URLSearchParams({ id: 'wy_1', rating: '1' }), 'json')
    +  assert.equal(state.ratings.wy_1, 1)
    +  assert.equal(state.snapshots, 1)
    +  assert.equal(state.adds, 0)
    +})
    +
    +test('联动仅补充低分规则,提高或清除评分不删除手工规则', async () => {
    +  const { state, instance } = build({ 'subsonic.linkRatingToDislike': true })
    +  for (const rating of ['1', '5', '0']) await instance.handleSetRating({}, 'alice', new URLSearchParams({ id: 'wy_1', rating }), 'json')
    +  assert.equal(state.adds, 1)
    +  assert.equal(state.removes, 0)
    +  assert.equal(state.ratings.wy_1, undefined)
    +})
    +
    +test('联动解析失败返回部分成功提示,评分保留供重试', async () => {
    +  const { state, instance } = build({ 'subsonic.linkRatingToDislike': true })
    +  state.fail = true
    +  const result = await instance.handleSetRating({}, 'alice', new URLSearchParams({ id: 'wy_1', rating: '1' }), 'json')
    +  assert.equal(result.ok, false)
    +  assert.match(result.message, /评分已保存/)
    +  assert.equal(state.ratings.wy_1, 1)
    +})
    +
    +test('反向联动保留高分,取消不喜欢保留评分,仅缺失评分补 1 星', async () => {
    +  const { state, reverse } = build()
    +  state.ratings.wy_1 = 5
    +  await reverse('alice', 'wy_1', 1)
    +  await reverse('alice', 'wy_1', 0)
    +  assert.equal(state.ratings.wy_1, 5)
    +  await reverse('alice', 'wy_2', 1)
    +  assert.equal(state.ratings.wy_2, 1)
    +})
    +
    +for (const threshold of [0, 1, 2]) {
    +  for (const enabled of [false, true]) {
    +    for (const visible of [false, true]) {
    +      test(`开关矩阵:阈值 ${threshold} 联动 ${enabled} 评分歌单 ${visible}`, async () => {
    +        const { state, instance } = build({ 'subsonic.dislikeRating': threshold, 'subsonic.linkRatingToDislike': enabled, 'subsonic.ratingPlaylists': visible })
    +        await instance.handleSetRating({}, 'alice', new URLSearchParams({ id: 'wy_1', rating: '2' }), 'json')
    +        assert.equal(state.ratings.wy_1, 2)
    +        assert.equal(state.adds, enabled && threshold >= 2 ? 1 : 0)
    +        assert.equal(state.snapshots, 1)
    +      })
    +    }
    +  }
    +}
    +
    +test('Web歌手/专辑不喜欢不能被误写成歌曲评分', async () => {
    +  const server = fs.readFileSync('src/server/server.ts', 'utf8')
    +  const start = server.indexOf('            const dislikeAutoRating =')
    +  const end = server.indexOf('            if (!isAdd && removeKeys.size', start)
    +  assert.ok(start >= 0 && end > start)
    +  for (const type of ['song', 'singer', 'album']) {
    +    const calls: any[] = []
    +    const context = vm.createContext({
    +      readRatingPreferences: () => ({ dislikeAutoRating: true }),
    +      readRatings: () => ({ ratings: {} }),
    +      type, id: 'real-id', source: 'tx', verified: 'test', isAdd: true,
    +      global: { lx: { config: { 'subsonic.linkDislikeToRating': true, 'subsonic.dislikeRating': 1 } } },
    +      payload: { id: 'real-id', source: 'tx' }, resolveRatingId: async () => 'tx_real-id',
    +      require: () => ({ syncDislikeToRating: async (...args: any[]) => calls.push(args) }), console,
    +    })
    +    await vm.runInContext(transformSync(`(async () => { ${server.slice(start, end)} })()`, { loader: 'ts', format: 'cjs' }).code, context)
    +    assert.equal(calls.length, type === 'song' ? 1 : 0)
    +    if (type === 'song') assert.deepEqual(calls[0].slice(0,3), ['test', 'tx_real-id', 1])
    +  }
    +})
    +
    +
    +test('自动补分写盘失败向调用方抛出,不伪报成功',async()=>{
    + const {state,reverse}=build();state.fail=true;await assert.rejects(()=>reverse('alice','wy_1',1),/disk failure/)
    +})
    diff --git a/test/rating-migration.test.ts b/test/rating-migration.test.ts
    new file mode 100644
    index 00000000..c59203ac
    --- /dev/null
    +++ b/test/rating-migration.test.ts
    @@ -0,0 +1,54 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import os from 'node:os'
    +import path from 'node:path'
    +import { commitRatingFiles, recoverRatingTransaction, planRatingMigration, registerDislikeMigration } from '../src/server/rating/ratingMigration'
    +const fixture = (fn: (dir: string) => void) => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lx-rating-transaction-')); try { fn(dir) } finally { fs.rmSync(dir, { recursive: true, force: true }) } }
    +test('跨文件提交第二次写入失败完整回滚,删除事务日志',()=>fixture(dir=>{
    + const a=path.join(dir,'rating/songs.json'),b=path.join(dir,'subsonic-meta.json');fs.mkdirSync(path.dirname(a),{recursive:true});fs.writeFileSync(a,'old catalog');fs.writeFileSync(b,'old ratings')
    + const rename=fs.renameSync;let failed=false
    + try { fs.renameSync=((from:any,to:any)=>{if(to===b&&!failed){failed=true;throw Error('disk failure')}return rename(from,to)}) as any
    + assert.throws(()=>commitRatingFiles(dir,new Map([[a,'new catalog'],[b,'new ratings']])),/disk failure/)
    + }finally{fs.renameSync=rename}
    + assert.equal(fs.readFileSync(a,'utf8'),'old catalog');assert.equal(fs.readFileSync(b,'utf8'),'old ratings');assert.ok(!fs.existsSync(path.join(dir,'rating/transaction.json')))
    +}))
    +test('中断后由日志完成所有文件提交,重复恢复幂等,拒绝越界日志',()=>fixture(dir=>{
    + fs.mkdirSync(path.join(dir,'rating'));fs.writeFileSync(path.join(dir,'rating/transaction.json'),JSON.stringify([{file:'rating/songs.json',after:'catalog'},{file:'subsonic-meta.json',after:'ratings'}]))
    + recoverRatingTransaction(dir);recoverRatingTransaction(dir);assert.equal(fs.readFileSync(path.join(dir,'subsonic-meta.json'),'utf8'),'ratings')
    + fs.writeFileSync(path.join(dir,'rating/transaction.json'),JSON.stringify([{file:'../escape',after:'bad'}]));assert.throws(()=>recoverRatingTransaction(dir),/Invalid/)
    +}))
    +test('迁移全部原因ID,保留手动原因和旧快照,并同步运行时规则及快照索引',()=>fixture(dir=>{
    + const dislike=path.join(dir,'dislike');fs.mkdirSync(path.join(dislike,'snapshot'),{recursive:true})
    + const rules={dislikeList:[{name:'歌',provenance:{channel:'web-rating-link',ratingId:'local_a'},reasons:[{channel:'web-rating-link',ratingId:'local_a'},{channel:'web'}]}]}
    + const info={latest:'old',list:[],imported:[],clients:{}}
    + fs.writeFileSync(path.join(dislike,'snapshot/snapshot_old'),JSON.stringify(rules));fs.writeFileSync(path.join(dislike,'snapshotInfo.json'),JSON.stringify(info))
    + const manager={dislikeRules:rules,snapshotDataManage:{snapshotInfo:info}};registerDislikeMigration(dir,manager)
    + const data={ratings:{local_a:1},ratingOrigins:{local_a:{channel:'web',at:1}}},catalog={local_a:{name:'歌'}}
    + const changes=planRatingMigration(dir,data,catalog,[{id:'local_a',platformId:'wy_a'}]);changes.set(path.join(dir,'subsonic-meta.json'),JSON.stringify(data));commitRatingFiles(dir,changes)
    + assert.equal(manager.dislikeRules.dislikeList[0].provenance.ratingId,'wy_a');assert.equal(manager.dislikeRules.dislikeList[0].reasons[0].ratingId,'wy_a');assert.equal(manager.dislikeRules.dislikeList[0].reasons[1].channel,'web');assert.notEqual(manager.snapshotDataManage.snapshotInfo.latest,'old');assert.ok(fs.existsSync(path.join(dislike,'snapshot/snapshot_old')))
    + assert.equal(planRatingMigration(dir,data,catalog,[{id:'local_a',platformId:'wy_a'}]).size,0)
    +}))
    +
    +test('只有收藏没有ratings也能整理关联,不生成虚假分数',()=>fixture(dir=>{
    + const data:any={starredArtists:['keep']},catalog={}
    + const changes=planRatingMigration(dir,data,catalog,[{id:'local_a',platformId:'wy_a'}])
    + assert.deepEqual(data.ratings,{});assert.deepEqual(data.starredArtists,['keep']);assert.equal(changes.size,0)
    +}))
    +test('仅提交评分文件不能覆盖尚未保存的运行时不喜欢',()=>fixture(dir=>{
    + const dislike=path.join(dir,'dislike');fs.mkdirSync(path.join(dislike,'snapshot'),{recursive:true})
    + const info={latest:'old',list:[],imported:[],clients:{}}
    + fs.writeFileSync(path.join(dislike,'snapshotInfo.json'),JSON.stringify(info));fs.writeFileSync(path.join(dislike,'snapshot/snapshot_old'),JSON.stringify({dislikeList:[]}))
    + const manager={snapshotDataManage:{snapshotInfo:info},dislikeRules:{dislikeList:[{name:'尚未保存'}]}}
    + registerDislikeMigration(dir,manager)
    + commitRatingFiles(dir,new Map([[path.join(dir,'subsonic-meta.json'),JSON.stringify({ratings:{wy_a:3}})]]))
    + assert.equal(manager.dislikeRules.dislikeList[0].name,'尚未保存')
    +}))
    +test('初始化不喜欢管理器时先完成遗留事务,不必访问评分接口',()=>fixture(dir=>{
    + fs.mkdirSync(path.join(dir,'rating'));fs.mkdirSync(path.join(dir,'dislike/snapshot'),{recursive:true})
    + const id='a'.repeat(32),info={latest:id,list:[],clients:{},imported:[]}
    + fs.writeFileSync(path.join(dir,'rating/transaction.json'),JSON.stringify([{file:'dislike/snapshot/snapshot_'+id,after:JSON.stringify({dislikeList:[{name:'已恢复'}]})},{file:'dislike/snapshotInfo.json',after:JSON.stringify(info)}]))
    + const manager={snapshotDataManage:{snapshotInfo:{}},dislikeRules:{dislikeList:[] as any[]}}
    + registerDislikeMigration(dir,manager)
    + assert.equal(manager.dislikeRules.dislikeList[0].name,'已恢复');assert.ok(!fs.existsSync(path.join(dir,'rating/transaction.json')))
    +}))
    diff --git a/test/rating-preferences.test.ts b/test/rating-preferences.test.ts
    new file mode 100644
    index 00000000..eae38db4
    --- /dev/null
    +++ b/test/rating-preferences.test.ts
    @@ -0,0 +1,25 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import os from 'node:os'
    +import path from 'node:path'
    +import vm from 'node:vm'
    +import { createRequire } from 'node:module'
    +import { transformSync } from 'esbuild'
    +const actualRequire=createRequire(import.meta.url)
    +test('自动补分偏好默认关闭、按用户落盘隔离、布尔校验且关闭保留其他用户',()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-preferences-'))
    + try{
    +  const mod={exports:{} as any}
    +  const require=(id:string)=>id==='@/user'?{getUserDirname:(user:string)=>user}:actualRequire(id)
    +  vm.runInNewContext(transformSync(fs.readFileSync('src/server/rating/ratingPreferences.ts','utf8'),{loader:'ts',format:'cjs'}).code,{module:mod,exports:mod.exports,require,global:{lx:{userPath:root}},console:{warn(){}}})
    +  const api=mod.exports
    +  assert.equal(api.readRatingPreferences('a').dislikeAutoRating,false)
    +  api.saveRatingPreferences('a',true);assert.equal(api.readRatingPreferences('a').dislikeAutoRating,true);assert.equal(api.readRatingPreferences('b').dislikeAutoRating,false)
    +  for(const value of [1,'true',null,{},undefined])assert.throws(()=>api.saveRatingPreferences('a',value))
    +  assert.equal(api.readRatingPreferences('a').dislikeAutoRating,true)
    +  api.saveRatingPreferences('b',true);api.saveRatingPreferences('a',false);assert.equal(api.readRatingPreferences('a').dislikeAutoRating,false);assert.equal(api.readRatingPreferences('b').dislikeAutoRating,true)
    +  const file=path.join(root,'a/rating/preferences.json');assert.equal(JSON.parse(fs.readFileSync(file,'utf8')).dislikeAutoRating,false);assert.equal(fs.existsSync(file+'.tmp'),false)
    +  fs.writeFileSync(file,'broken');assert.equal(api.readRatingPreferences('a').dislikeAutoRating,false)
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    diff --git a/test/rating-recommendation-switch.test.ts b/test/rating-recommendation-switch.test.ts
    new file mode 100644
    index 00000000..02091555
    --- /dev/null
    +++ b/test/rating-recommendation-switch.test.ts
    @@ -0,0 +1,16 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import vm from 'node:vm'
    +import { transformSync } from 'esbuild'
    +const source=fs.readFileSync('src/server/integrations/subsonic.ts','utf8')
    +const start=source.indexOf('    private async handleGetRecommendedSongs(')
    +const end=source.indexOf('    private async ',start+20)
    +const filterStart=source.indexOf('    private async filterRecommendationEntries(')
    +const filterEnd=source.indexOf('    private async renderRandomSongs(',filterStart)
    +for(const enabled of [false,true]) test(`每日推荐低分排除遵守开关 ${enabled}`,async()=>{
    + const context:any={global:{lx:{config:{'subsonic.dislikeNoRecommend':enabled,'subsonic.dislikeRating':1}}},localRatingId:(t:any)=>t.platformId||t.id,fetchRecommendedSongs:async()=>[{id:'wy_1'},{id:'wy_2'}],subsonicLog:{error(){}}}
    + vm.runInNewContext(transformSync(`class Harness { async filterDislikedEntries(_u,entries){return entries} async getUserSubsonicMeta(){ return {ratings:{wy_1:1,wy_2:5}} } renderRandomSongs(_res,rows){return rows} ${source.slice(filterStart,filterEnd)} ${source.slice(start,end)} }; globalThis.instance=new Harness()`,{loader:'ts',format:'cjs'}).code,context)
    + const rows=await context.instance.handleGetRecommendedSongs({},'a',new URLSearchParams(),'json')
    + assert.equal(rows.length,enabled?1:2)
    +})
    diff --git a/test/rating-snapshot.test.ts b/test/rating-snapshot.test.ts
    index d568a8b4..e99ab34e 100644
    --- a/test/rating-snapshot.test.ts
    +++ b/test/rating-snapshot.test.ts
    @@ -12,11 +12,14 @@ const nodeRequire = createRequire(import.meta.url)
     type Api = Record
     
     const load = (userPath: string, maxSnapshotNum = 3): Api => {
    -  const source = fs.readFileSync(path.resolve('src/server/ratingSnapshot.ts'), 'utf8')
    +  const source = fs.readFileSync(path.resolve('src/server/rating/ratingSnapshot.ts'), 'utf8')
       const code = transformSync(source, { loader: 'ts', format: 'cjs', target: 'node20' }).code
       const mod = { exports: {} as Api }
       const require = (id: string): any => {
    -    if (id === '@/user') return { getUserDirname: (u: string) => u }
    +    if (id === './ratingMigration' || id === '../../server/rating/ratingMigration') return nodeRequire(path.resolve('src/server/rating/ratingMigration.ts'))
    +    if (id === './ratingIdentityLock') return nodeRequire(path.resolve('src/server/rating/ratingIdentityLock.ts'))
    +    if (id === './ratingValidation') return nodeRequire(path.resolve('src/server/rating/ratingValidation.ts'))
    +  if (id === '@/user') return { getUserDirname: (u: string) => u }
         if (id === '@/user/data') return { getUserConfig: () => ({ maxSnapshotNum }) }
         return nodeRequire(id)
       }
    @@ -28,8 +31,9 @@ const load = (userPath: string, maxSnapshotNum = 3): Api => {
         console,
         process,
         Buffer,
    +    URL,
         __dirname: path.resolve('src/server'),
    -    __filename: path.resolve('src/server/ratingSnapshot.ts'),
    +    __filename: path.resolve('src/server/rating/ratingSnapshot.ts'),
       })
       vm.runInContext(code, context)
       return mod.exports
    @@ -53,6 +57,24 @@ const writeMeta = (userDir: string, ratings: Record) =>
       fs.writeFileSync(metaFile(userDir), JSON.stringify({ ratings, starredAlbums: [], starredArtists: [], starredArtistNames: [] }), 'utf8')
     const plain = (value: T): T => JSON.parse(JSON.stringify(value))
     
    +test('恢复评分快照保留当前收藏,并与并发写入串行', async () => {
    +  await withUser(3, async (api, userDir) => {
    +    writeMeta(userDir, { old: 1 })
    +    const id = await api.createRatingSnapshot('alice')
    +    const pending = api.withMetaLock('alice', async () => {
    +      await new Promise(resolve => setTimeout(resolve, 10))
    +      fs.writeFileSync(metaFile(userDir), JSON.stringify({ ratings: { newer: 5 }, starredAlbums: ['album'], starredArtists: ['artist'], starredArtistNames: ['name'] }))
    +    })
    +    await Promise.all([pending, api.restoreRatingSnapshot('alice', id)])
    +    const restored = JSON.parse(fs.readFileSync(metaFile(userDir), 'utf8'))
    +    assert.equal(restored.ratingHistory.old.at(-1).channel, 'snapshot-restore')
    +    delete restored.ratingHistory
    +    assert.deepEqual(restored, {
    +      ratings: { old: 1 }, ratingOrigins: {}, starredAlbums: ['album'], starredArtists: ['artist'], starredArtistNames: ['name'],
    +    })
    +  })
    +})
    +
     test('S4 快照 id:路径穿越与非法字符全部拒绝', async () => {
       await withUser(3, (api) => {
         for (const id of ['abc', '2026-11-08', 'a'.repeat(32), '用户备份']) {
    @@ -115,12 +137,11 @@ test('S9 索引兼容:旧版 snapshotInfo 无 imported 字段时降级为空
       })
     })
     
    -test('S9 meta 损坏降级为空评分;读写与删除、回滚幂等', async () => {
    +test('S9 meta 损坏阻止导出并保留原文件;读写与删除、回滚幂等', async () => {
       await withUser(3, async (api, userDir) => {
         fs.writeFileSync(metaFile(userDir), '{ broken', 'utf8')
    -    const id = await api.createRatingSnapshot('alice')
    -    const meta = plain(await api.readRatingSnapshot('alice', id))
    -    assert.deepEqual(meta.ratings, {})
    +    await assert.rejects(()=>api.createRatingSnapshot('alice'),/损坏/)
    +    assert.equal(fs.readFileSync(metaFile(userDir),'utf8'),'{ broken')
         assert.equal(await api.readRatingSnapshot('alice', 'missing'), null)
         assert.equal(await api.readRatingSnapshot('alice', '../evil'), null)
         assert.equal(await api.deleteRatingSnapshot('alice', 'missing'), false)
    @@ -139,3 +160,54 @@ test('S9 meta 损坏降级为空评分;读写与删除、回滚幂等', async
         await assert.rejects(() => api.saveRatingImport('alice', '../evil', {}, 0), /Invalid snapshot id/)
       })
     })
    +
    +
    +test('完整评分导出含描述及关联参照,回滚恢复描述而不覆盖收藏或文件关联',async()=>{
    + await withUser(3,async(api,dir)=>{
    +  writeMeta(dir,{wy_1:4});fs.mkdirSync(path.join(dir,'rating'),{recursive:true})
    +  fs.writeFileSync(path.join(dir,'rating/songs.json'),JSON.stringify({wy_1:{name:'晴天',img:'https://example.com/a.jpg'}}))
    +  const registry=JSON.stringify({tracks:{a:{id:'local_a',filename:'a.wav',platformId:'wy_1'}}})
    +  fs.writeFileSync(path.join(dir,'subsonic-local-registry.json'),registry)
    +  const exported=api.exportRatingBackup('alice');assert.equal(exported.ratingCatalog.wy_1.name,'晴天');assert.equal(exported.localLinks[0].platformId,'wy_1')
    +  const id=await api.createRatingSnapshot('alice')
    +  fs.writeFileSync(path.join(dir,'rating/songs.json'),'{}');writeMeta(dir,{wy_1:1})
    +  await api.restoreRatingSnapshot('alice',id)
    +  assert.equal(JSON.parse(fs.readFileSync(path.join(dir,'rating/songs.json'),'utf8')).wy_1.name,'晴天')
    +  assert.equal(fs.readFileSync(path.join(dir,'subsonic-local-registry.json'),'utf8'),registry)
    +  assert.deepEqual(plain(api.normalizeRatingMeta({ratings:{a:6,b:'3',c:0,d:2}}).ratings),{d:2})
    + })
    +})
    +
    +
    +test('恢复第二个文件失败时回滚歌曲描述与评分,不留下半恢复状态',async()=>{
    + await withUser(3,async(api,dir)=>{
    +  writeMeta(dir,{wy_1:1});fs.mkdirSync(path.join(dir,'rating'),{recursive:true});const catalog=path.join(dir,'rating/songs.json');fs.writeFileSync(catalog,JSON.stringify({wy_1:{name:'旧描述'}}));const id=await api.createRatingSnapshot('alice')
    +  writeMeta(dir,{wy_1:5});fs.writeFileSync(catalog,JSON.stringify({wy_1:{name:'当前描述'}}));const before=fs.readFileSync(metaFile(dir),'utf8')
    +  const rename=fs.renameSync;let failed=false
    +  try {
    +   fs.renameSync=((from:any,to:any)=>{if(!failed&&String(to)===metaFile(dir)&&String(from).endsWith('.transaction.tmp')){failed=true;throw Error('模拟写入失败')}return rename(from,to)}) as any
    +   await assert.rejects(()=>api.restoreRatingSnapshot('alice',id),/模拟写入失败/)
    +  }finally{fs.renameSync=rename}
    +  assert.equal(fs.readFileSync(metaFile(dir),'utf8'),before);assert.equal(JSON.parse(fs.readFileSync(catalog,'utf8')).wy_1.name,'当前描述')
    + })
    +})
    +
    +
    +test('评分历史导入只保留有效事件并限制30条,异常结构不会进入展示数据',async()=>{
    + await withUser(3,async(api)=>{
    +  const bad=api.normalizeRatingMeta({ratings:{wy_1:4},ratingHistory:{wy_1:{broken:true},wy_2:[null,{},'bad',{from:0,to:9,at:1,channel:'web'}],wy_3:Array.from({length:50},(_,n)=>({from:0,to:4,at:n+1,channel:'web',url:'secret'}))}})
    +  assert.equal(bad.ratingHistory.wy_1,undefined);assert.equal(bad.ratingHistory.wy_2.length,0);assert.equal(bad.ratingHistory.wy_3.length,30);assert.equal(bad.ratingHistory.wy_3[0].url,undefined)
    + })
    +})
    +
    +test('恢复旧本地快照返回前完成身份迁移',async()=>{
    + await withUser(3,async(api,dir)=>{
    +  writeMeta(dir,{local_old:2});const id=await api.createRatingSnapshot('alice')
    +  fs.writeFileSync(path.join(dir,'subsonic-local-registry.json'),JSON.stringify({tracks:{file:{id:'local_old',platformId:'wy_online'}}}))
    +  writeMeta(dir,{wy_online:5})
    +  await api.restoreRatingSnapshot('alice',id)
    +  const data=JSON.parse(fs.readFileSync(metaFile(dir),'utf8'))
    +  assert.equal(data.ratings.local_old,undefined);assert.equal(data.ratings.wy_online,2)
    +  assert.ok(!fs.existsSync(path.join(dir,'rating/transaction.json')))
    + })
    +})
    diff --git a/test/snapshot-rating-wiring.test.ts b/test/snapshot-rating-wiring.test.ts
    index e2bcfb66..1a4c068d 100644
    --- a/test/snapshot-rating-wiring.test.ts
    +++ b/test/snapshot-rating-wiring.test.ts
    @@ -95,7 +95,7 @@ test('S19 playList_v2 转换:非该格式返回 null,残缺 data 不抛异
     })
     
     const syncLinkBody = slice(
    -  '          const { user, direction } = JSON.parse(await readBody(req))',
    +  '          const { user, direction, preview, reconcile } = JSON.parse(await readBody(req))',
       '        } catch (err: any) {',
     )
     
    diff --git a/test/subsonic-rating-playlists.test.ts b/test/subsonic-rating-playlists.test.ts
    index d864a2c4..ef34968d 100644
    --- a/test/subsonic-rating-playlists.test.ts
    +++ b/test/subsonic-rating-playlists.test.ts
    @@ -34,6 +34,10 @@ const build = (ratingPlaylists: boolean | undefined = undefined) => {
         global: { lx: { config } },
         getLocalTracks: async () => [],
         localMusic: (x: any) => x,
    +    localRatingId: (track: any) => track.platformId || track.id,
    +    withTimeout: (p: any) => p,
    +    LINK_SYNC_ITEM_TIMEOUT_MS: 8000,
    +    subsonicLog: { warn() {} },
         console,
       })
       vm.runInContext(transformSync(harness, { loader: 'ts', format: 'cjs', target: 'node20' }).code, context)
    @@ -55,6 +59,26 @@ test('S5 ratings 值域:非整数 / 越界 / 字符串评分不得让 getPlayl
       for (const star of [1, 2, 4, 5]) assert.equal(groups.get(star).length, 0)
     })
     
    +test('高评分屏蔽歌曲同时进入原星级与不喜欢合集', async () => {
    +  const { instance } = build(true)
    +  instance.meta = { ratings: { a: 5 } }
    +  instance.listData = { loveList: [], defaultList: [song('a')], userList: [] }
    +  instance.disliked = new Set(['a'])
    +  const groups = await instance.getRatingPlaylistSongs('alice')
    +  assert.equal(groups.get(1)[0].id, 'a')
    +  assert.equal(groups.get(5)[0].id, 'a')
    +})
    +
    +test('缓存淘汰后解析已评分歌曲,排除专辑和歌手', async () => {
    +  const { instance } = build(true)
    +  instance.meta = { ratings: { lost: 5, alb_wy_1: 5, art_tx_2: 4 } }
    +  const calls: string[] = []
    +  instance.resolveSongMeta = async (_user: string, id: string) => { calls.push(id); return { music: song(id) } }
    +  const groups = await instance.getRatingPlaylistSongs('alice')
    +  assert.equal(groups.get(5)[0].id, 'lost')
    +  assert.deepEqual(calls, ['lost'])
    +})
    +
     test('S8 开关:默认开启,显式 false 关闭', () => {
       assert.equal(build().instance.isRatingPlaylistEnabled(), true)
       assert.equal(build(true).instance.isRatingPlaylistEnabled(), true)
    @@ -83,7 +107,7 @@ test('S8 只读语义与配置契约:虚拟歌单不得被写入或删除', ()
       assert.match(source, /评星歌单为只读播放列表,请通过给歌曲评星来修改/)
       assert.match(source, /评星歌单为只读播放列表,不支持删除/)
       assert.match(source, /Rating playlists are disabled/)
    -  assert.match(source, /linkToDislike = .*\|\| this\.isRatingPlaylistEnabled\(\)/)
    +  assert.match(source, /if \(!global\.lx\.config\['subsonic\.linkRatingToDislike'\]/)
       const defaults = fs.readFileSync(path.resolve('src/defaultConfig.ts'), 'utf8')
       assert.match(defaults, /'subsonic\.ratingPlaylists': true/)
     })
    diff --git a/test/web-rating-controls.test.cjs b/test/web-rating-controls.test.cjs
    new file mode 100644
    index 00000000..49a36f29
    --- /dev/null
    +++ b/test/web-rating-controls.test.cjs
    @@ -0,0 +1,34 @@
    +const test=require('node:test');const assert=require('node:assert/strict');const fs=require('node:fs');const vm=require('node:vm');
    +function setup(fetch){const storage=new Map([['lx_sync_user','a'],['lx_user_token','token-a']]);const window={addEventListener(){}};const context={window,localStorage:{getItem:k=>storage.get(k)||null},document:{addEventListener(){},hidden:false},setInterval(){},queueMicrotask(){},fetch,ensureUserAuthToken:async()=>true,getUserAuthHeaders:()=>({'x-user-token':storage.get('lx_user_token')})};vm.runInNewContext(fs.readFileSync('public/music/js/library/rating_manager.js','utf8'),context);return{manager:window.RatingManager,storage,context}}
    +const button=()=>({isConnected:true,textContent:'',setAttribute(){}});
    +test('评分按100首分批查询,不上传播放URL或鉴权封面',async()=>{const bodies=[];const{manager}=setup(async(_u,options)=>{const body=JSON.parse(options.body);bodies.push(body);return{ok:true,json:async()=>({entries:body.songs.map(s=>({id:s.id,rating:4}))})}});const buttons=[];for(let n=0;n<101;n++){const b=button();buttons.push(b);manager.attach(b,{id:'wy_'+n,source:'wy',url:'secret',pic:'token-cover'})}await manager.refresh();assert.equal(bodies.length,2);assert.equal(bodies[0].songs.length,100);assert.ok(!JSON.stringify(bodies).includes('secret'));assert.ok(!JSON.stringify(bodies).includes('token-cover'));assert.ok(buttons.every(x=>x.textContent==='★'))});
    +test('账号切换与播放器换歌后,旧请求不能刷新新控件',async()=>{let release;const{manager,storage}=setup(()=>new Promise(r=>{release=r}));const b=button();manager.attach(b,{id:'wy_old',source:'wy'});const pending=manager.refresh();await new Promise(r=>setImmediate(r));manager.attach(b,{id:'wy_new',source:'wy'});release({ok:true,json:async()=>({entries:[{id:'wy_old',rating:5}]})});await pending;assert.equal(b.textContent,'☆');const pending2=manager.refresh();await new Promise(r=>setImmediate(r));storage.set('lx_sync_user','b');storage.set('lx_user_token','token-b');release({ok:true,json:async()=>({entries:[{id:'wy_new',rating:5}]})});await pending2;assert.equal(b.textContent,'☆')});
    +
    +
    +test('同账号重叠刷新只采用最后请求,旧响应不能覆盖新评分',async()=>{
    + const waiting=[];const {manager}=setup(()=>new Promise(resolve=>waiting.push(resolve)));const b=button();manager.attach(b,{id:'wy_1',source:'wy'});
    + const old=manager.refresh();await new Promise(r=>setImmediate(r));const latest=manager.refresh();await new Promise(r=>setImmediate(r));
    + waiting[1]({ok:true,json:async()=>({entries:[{id:'wy_1',rating:5}]})});await latest;
    + waiting[0]({ok:true,json:async()=>({entries:[{id:'wy_1',rating:1}]})});await old;assert.equal(b.textContent,'★');
    +});
    +
    +
    +test('分数tag仅在已评分时显示,清分和退出账号立即隐藏',async()=>{
    + let rating=4;const {manager,storage}=setup(async()=>({ok:true,json:async()=>({entries:[{id:'wy_1',rating}]})}));const tag=button();manager.attach(tag,{id:'wy_1',source:'wy'},true);assert.equal(tag.hidden,true);await manager.refresh();assert.equal(tag.hidden,false);assert.equal(tag.textContent,'★ 4');rating=0;await manager.refresh();assert.equal(tag.hidden,true);rating=5;await manager.refresh();assert.equal(tag.hidden,false);storage.delete('lx_sync_user');await manager.refresh();assert.equal(tag.hidden,true);
    +});
    +
    +
    +test('歌单操作区接入评分,合集刷新重新读服务端并保留滚动',()=>{
    + const list=fs.readFileSync('public/music/js/library/songlist_manager.js','utf8');assert.match(list,/data-songlist-rating/);assert.match(list,/RatingManager\?\.attach\(button, entry.item\)/);
    + const rating=fs.readFileSync('public/music/js/library/rating_manager.js','utf8');assert.match(rating,/data = latest; render\(\); list.scrollTop = scroll/);assert.match(rating,/collectionDialog\?\.open.*collectionReload/);
    +});
    +
    +
    +test('同账号认证更新Token后用户偏好仍能回显并解除禁用',async()=>{
    + const {manager,storage,context}=setup(async()=>({ok:true,json:async()=>({dislikeAutoRating:true})}));const toggle={disabled:false,checked:false};const status={};context.document.getElementById=id=>id==='setting-dislike-auto-rating'?toggle:status;context.ensureUserAuthToken=async()=>{storage.set('lx_user_token','renewed-token')};await manager.loadPreference();assert.equal(toggle.checked,true);assert.equal(toggle.disabled,false);
    +});
    +
    +
    +test('版本不变仅查询版本,版本变化再批量刷新分数',async()=>{
    + let version='v1',resolved=0,polled=0;const {manager}=setup(async(_u,opt)=>{const body=JSON.parse(opt.body);if(body.operation==='version'){polled++;return{ok:true,json:async()=>({version})}}resolved++;return{ok:true,json:async()=>({version,entries:[{id:'wy_1',rating:4}]})}});manager.attach(button(),{id:'wy_1',source:'wy'});await manager.refresh();await manager.refresh();assert.equal(resolved,1);assert.equal(polled,1);version='v2';await manager.refresh();assert.equal(resolved,2)
    +});
    diff --git a/test/web-rating-service.test.ts b/test/web-rating-service.test.ts
    new file mode 100644
    index 00000000..e87341ff
    --- /dev/null
    +++ b/test/web-rating-service.test.ts
    @@ -0,0 +1,172 @@
    +import test from 'node:test'
    +import assert from 'node:assert/strict'
    +import fs from 'node:fs'
    +import os from 'node:os'
    +import path from 'node:path'
    +import vm from 'node:vm'
    +import { createRequire } from 'node:module'
    +import { transformSync } from 'esbuild'
    +const actualRequire = createRequire(import.meta.url)
    +function load(root: string, snapshot:()=>Promise = async()=>{}) {
    + const tracks:any[]=[]
    + const locks=new Map>()
    + const mod={exports:{} as any}
    + const require=(id:string):any=>{
    +    if (id === './ratingMigration' || id === '../../server/rating/ratingMigration') return actualRequire(path.resolve('src/server/rating/ratingMigration.ts'))
    +  if(id==='./ratingIdentityLock')return actualRequire(path.resolve('src/server/rating/ratingIdentityLock.ts'))
    +  if (id === './ratingValidation') return actualRequire(path.resolve('src/server/rating/ratingValidation.ts'))
    +  if(id==='@/user')return {getUserDirname:(user:string)=>user}
    +  if(id==='./ratingSnapshot')return {withMetaLock:(user:string,fn:any)=>{const p=(locks.get(user)||Promise.resolve()).then(fn);locks.set(user,p.catch(()=>{}));return p},createRatingSnapshot:snapshot}
    +  if(id==='../music/subsonicLocal')return {localRatingId:(track:any)=>track.platformId||track.id,getLocalTracks:async()=>tracks,localFile:(track:any)=>{const resolved=path.resolve(track.root,track.filename);return resolved.startsWith(path.resolve(track.root)+path.sep)&&fs.existsSync(resolved)?resolved:null}}
    +  if(id==='../music/fileCache')return {getCacheDir:(user:string)=>path.join(root,user,'audio')}
    +  if(id==='../music/customMusicManager')return {getCustomMusicDir:(user:string)=>path.join(root,user,'audio')}
    +  return actualRequire(id)
    + }
    + vm.runInNewContext(transformSync(fs.readFileSync('src/server/rating/ratingService.ts','utf8'),{loader:'ts',format:'cjs'}).code,{module:mod,exports:mod.exports,require,URL,global:{lx:{userPath:root,dataPath:root}}})
    + return {api:mod.exports,tracks}
    +}
    +test('Web评分服务并发写入不丢数据、隔离用户、保留收藏且不改歌单',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-web-rating-unit-'))
    + try{
    +  const {api}=load(root);fs.mkdirSync(path.join(root,'a'),{recursive:true});const file=path.join(root,'a','subsonic-meta.json');fs.writeFileSync(file,JSON.stringify({starredArtists:['artist'],ratings:{}}));const list=path.join(root,'a','list.json');fs.writeFileSync(list,'playlist-marker')
    +  await Promise.all(Array.from({length:20},(_,n)=>api.writeRating('a','wy_'+n,5,'web',{name:'歌'+n,singer:'人',source:'wy',url:'secret-url'})))
    +  const data=api.readRatings('a');assert.equal(Object.keys(data.ratings).length,20);assert.equal(data.starredArtists[0],'artist');assert.equal(data.ratingOrigins.wy_0.channel,'web');assert.equal(fs.readFileSync(list,'utf8'),'playlist-marker');assert.equal(Object.keys(api.readRatings('b').ratings).length,0)
    +  assert.ok(!fs.readFileSync(path.join(root,'a','rating','songs.json'),'utf8').includes('secret-url'))
    +  for(const r of [-1,6,1.5,'5'])await assert.rejects(()=>api.writeRating('a','wy_bad',r,'web'))
    +  await api.writeRating('a','wy_0',0,'web');assert.equal(api.readRatings('a').ratings.wy_0,undefined);assert.equal(api.readRatings('a').ratingOrigins.wy_0,undefined)
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +test('本地未关联按本地ID,关联及重新关联后按对应在线ID,拒绝越权',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-web-rating-local-'))
    + try{
    +  const {api,tracks}=load(root);const audio=path.join(root,'a','audio');fs.mkdirSync(audio,{recursive:true});fs.writeFileSync(path.join(audio,'song.wav'),'audio');tracks.push({id:'local_stable',root:audio,filename:'song.wav',platformId:undefined})
    +  const song={isLocal:true,_localFilename:'song.wav',_localFolder:'custom',_localUsername:'a',source:'tx',songmid:'old'}
    +  assert.equal(await api.resolveRatingId('a',song),'local_stable');tracks[0].platformId='wy_new';assert.equal(await api.resolveRatingId('a',{...song,source:'wy',songmid:'new'}),'wy_new')
    +  await api.writeRating('a','local_stable',2,'web')
    +  assert.equal(api.readRatings('a').ratings.wy_new,2)
    +  tracks[0].platformId='tx_other'
    +  assert.equal(await api.resolveStoredRatingId('a','local_stable'),'tx_other')
    +  assert.equal(api.readRatings('a').ratings.tx_other,undefined)
    +  await api.writeRating('a','local_stable',4,'subsonic')
    +  assert.equal(api.readRatings('a').ratings.tx_other,4)
    +  assert.equal(api.readRatings('a').ratings.wy_new,2)
    +  await assert.rejects(()=>api.resolveRatingId('b',song));await assert.rejects(()=>api.resolveRatingId('a',{...song,_localFilename:'../subsonic-meta.json'}))
    +  assert.equal(await api.resolveRatingId('a',{source:'tx',songmid:'abc',songId:123}),'tx_abc')
    +  assert.equal(await api.resolveRatingId('a',{source:'wy',id:'wy_123'}),'wy_123')
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +
    +test('资料合并保留封面和专辑ID,拒绝凭据及查询参数封面', async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-merge-'))
    + try {
    +  const {api}=load(root)
    +  await api.writeRating('a','wy_1',4,'web',{name:'原歌名',source:'wy',albumId:'album',img:'https://example.com/cover.jpg'})
    +  await api.writeRating('a','wy_1',3,'web',{name:'',source:'wy'})
    +  const row=JSON.parse(fs.readFileSync(path.join(root,'a/rating/songs.json'),'utf8')).wy_1
    +  assert.equal(row.name,'原歌名');assert.equal(row.albumId,'album');assert.equal(row.img,'https://example.com/cover.jpg')
    +  assert.equal(api.safeCover('https://user:secret@example.com/a'),'');assert.equal(api.safeCover('https://example.com/a?token=secret'),'')
    + } finally { fs.rmSync(root,{recursive:true,force:true}) }
    +})
    +
    +test('排队评分在取得身份锁后重新解析关联,并清除旧本地评分',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-identity-'))
    + try {
    +  const {api,tracks}=load(root);const audio=path.join(root,'a/audio');fs.mkdirSync(audio,{recursive:true});fs.writeFileSync(path.join(audio,'a.wav'),'audio')
    +  const track={id:'local_a',root:audio,filename:'a.wav',platformId:undefined as string|undefined};tracks.push(track)
    +  await api.writeRating('a','local_a',5,'web')
    +  const lock=actualRequire(path.resolve('src/server/rating/ratingIdentityLock.ts')).withRatingIdentityLock
    +  let release!:()=>void
    +  const association=lock('a',async()=>{await new Promise(r=>{release=r});track.platformId='wy_linked'})
    +  await Promise.resolve()
    +  const write=api.writeRating('a','local_a',2,'web')
    +  release();await association;await write
    +  assert.equal(api.readRatings('a').ratings.wy_linked,2)
    +  fs.writeFileSync(path.join(root,'a/subsonic-local-registry.json'),JSON.stringify({tracks:{a:track}}))
    +  assert.ok(!api.listRatingItems('a').some((x:any)=>x.id==='local_a'));assert.equal(api.readRatings('a').ratings.wy_linked,2)
    + } finally {fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +
    +test('重复同分不改来源或时间,清分记录历史;旧本地ID资料不覆盖关联在线描述',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-idempotence-'))
    + try {
    +  const {api,tracks}=load(root)
    +  await api.writeRating('a','wy_1',4,'web',{name:'在线曲名',source:'wy'})
    +  const first=api.readRatings('a');const duplicate=await api.writeRating('a','wy_1',4,'subsonic')
    +  assert.equal(duplicate.unchanged,true);assert.deepEqual(JSON.parse(JSON.stringify(api.readRatings('a').ratingOrigins)),JSON.parse(JSON.stringify(first.ratingOrigins)))
    +  assert.equal(api.readRatings('a').ratingHistory.wy_1.length,1)
    +  tracks.push({id:'local_old',platformId:'wy_1',title:'在线曲名',artist:'歌手',album:'专辑'})
    +  await api.writeRating('a','local_old',2,'web',{id:'local_old',source:'local',name:'旧本地曲名'})
    +  const catalog=JSON.parse(fs.readFileSync(path.join(root,'a/rating/songs.json'),'utf8'));assert.equal(catalog.wy_1.name,'在线曲名')
    +  await api.writeRating('a','wy_1',0,'web');const events=api.readRatings('a').ratingHistory.wy_1
    +  assert.equal(events.length,3);assert.equal(events[2].from,2);assert.equal(events[2].to,0)
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +
    +test('同分补齐描述不改评分来源,资料失败可单独重试,版本能感知变化',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-repair-'))
    + try {
    +  const {api}=load(root);await api.writeRating('a','wy_1',4,'subsonic')
    +  const before=api.readRatings('a');const version=api.ratingVersion('a')
    +  await api.writeRating('a','wy_1',4,'web',{name:'补齐曲名',source:'wy'})
    +  assert.equal(api.readRatings('a').ratingOrigins.wy_1.channel,'subsonic');assert.equal(api.readRatings('a').ratingHistory.wy_1.length,1)
    +  assert.equal(JSON.parse(fs.readFileSync(path.join(root,'a/rating/songs.json'),'utf8')).wy_1.name,'补齐曲名');assert.notEqual(api.ratingVersion('a'),version)
    +  const rename=fs.renameSync;let failed=false
    +  try{fs.renameSync=((from:any,to:any)=>{if(!failed&&String(to).endsWith('songs.json')){failed=true;throw Error('disk')}return rename(from,to)}) as any
    +   const saved=await api.writeRating('a','wy_1',4,'web',{name:'可重试曲名',source:'wy'});assert.ok(saved.snapshotWarning)
    +  }finally{fs.renameSync=rename}
    +  assert.ok(api.readRatingTasks('a').some((t:any)=>t.kind==='catalog'))
    +  await api.retryRatingTasks('a');assert.equal(api.readRatingTasks('a').length,0)
    +  assert.equal(JSON.parse(fs.readFileSync(path.join(root,'a/rating/songs.json'),'utf8')).wy_1.name,'可重试曲名');assert.equal(api.readRatings('a').ratingOrigins.wy_1.at,before.ratingOrigins.wy_1.at)
    +  const stable=api.ratingVersion('a');await api.writeRating('a','wy_1',4,'web',{name:'可重试曲名',source:'wy'});assert.equal(api.ratingVersion('a'),stable)
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +test('快照失败记录状态并可重试,修复资料不能覆写较新的评分',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-snapshot-retry-'))
    + try{
    +  let fail=true;const {api}=load(root,async()=>{if(fail)throw Error('snapshot disk')})
    +  const result=await api.writeRating('a','wy_1',2,'web',{name:'歌曲',source:'wy'});assert.ok(result.snapshotWarning);assert.ok(api.readRatingTasks('a').some((x:any)=>x.kind==='snapshot'))
    +  fail=false;await api.retryRatingTasks('a');assert.equal(api.readRatingTasks('a').length,0)
    +  await api.writeRating('a','wy_1',5,'subsonic');await api.writeRating('a','wy_1',1,'repair',{name:'歌曲',source:'wy'},{repairOnly:true});assert.equal(api.readRatings('a').ratings.wy_1,5);assert.equal(api.readRatings('a').ratingOrigins.wy_1.channel,'subsonic')
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +
    +test('同步状态损坏不清空文件,主评分损坏拒绝写入与覆盖',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-storage-errors-'))
    + try{
    +  const {api}=load(root);await api.writeRating('a','wy_1',4,'web',{name:'歌曲',source:'wy'});const status=path.join(root,'a/rating/sync-status.json');fs.writeFileSync(status,'broken')
    +  assert.equal(api.readRatingTasks('a')[0].kind,'status');await assert.rejects(()=>api.retryRatingTasks('a'),/损坏/);assert.equal(fs.readFileSync(status,'utf8'),'broken')
    +  const meta=path.join(root,'a/subsonic-meta.json');fs.writeFileSync(meta,'broken');await assert.rejects(()=>api.writeRating('a','wy_1',5,'web'));assert.equal(fs.readFileSync(meta,'utf8'),'broken')
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +
    +test('补分主文件写入失败登记重试任务,只重试未评分项且保留较新评分',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-backfill-retry-'))
    + try {
    +  const {api}=load(root);const rename=fs.renameSync;let fail=true
    +  try{fs.renameSync=((from:any,to:any)=>{if(fail&&String(to).endsWith('subsonic-meta.json'))throw Error('meta disk');return rename(from,to)}) as any
    +   await assert.rejects(()=>api.writeRating('a','wy_1',1,'web-dislike-link',{name:'曲',source:'wy'},{onlyMissing:true}),/meta disk/)
    +  }finally{fs.renameSync=rename;fail=false}
    +  assert.ok(api.readRatingTasks('a').some((x:any)=>x.kind==='backfill'))
    +  await api.writeRating('a','wy_1',5,'web',{name:'曲',source:'wy'});await api.retryRatingTasks('a');assert.equal(api.readRatings('a').ratings.wy_1,5);assert.equal(api.readRatingTasks('a').length,0)
    + }finally{fs.rmSync(root,{recursive:true,force:true})}
    +})
    +
    +test('关联迁移保留来源与历史,在线评分优先且删除本地所有当前记录',async()=>{
    + const root=fs.mkdtempSync(path.join(os.tmpdir(),'lx-rating-migrate-'))
    + try {
    +  const {api}=load(root);const dir=path.join(root,'a');fs.mkdirSync(path.join(dir,'rating'),{recursive:true})
    +  const file=path.join(dir,'subsonic-meta.json')
    +  fs.writeFileSync(file,JSON.stringify({ratings:{local_a:5,local_b:2,wy_b:4},ratingOrigins:{local_a:{channel:'web',at:1},local_b:{channel:'web',at:2},wy_b:{channel:'subsonic',at:3}},ratingHistory:{local_a:[{from:0,to:5,channel:'web',at:1}],local_b:[]},starredArtists:['keep']}))
    +  fs.writeFileSync(path.join(dir,'rating/songs.json'),JSON.stringify({local_a:{name:'原歌名'},local_b:{name:'删除'}}))
    +  fs.writeFileSync(path.join(dir,'subsonic-local-registry.json'),JSON.stringify({tracks:{a:{id:'local_a',platformId:'wy_a'},b:{id:'local_b',platformId:'wy_b'}}}))
    +  const data=api.readRatings('a');assert.deepEqual(JSON.parse(JSON.stringify(data.ratings)),{wy_a:5,wy_b:4});assert.equal(data.ratingOrigins.wy_a.at,1);assert.equal(data.ratingOrigins.wy_b.channel,'subsonic');assert.equal(data.ratingHistory.wy_a.length,1);assert.equal(data.ratingHistory.local_a,undefined);assert.equal(data.starredArtists[0],'keep')
    +  const catalog=JSON.parse(fs.readFileSync(path.join(dir,'rating/songs.json'),'utf8'));assert.equal(catalog.local_a,undefined);assert.equal(catalog.local_b,undefined);assert.equal(catalog.wy_a.name,'原歌名')
    +  const before=fs.readFileSync(file,'utf8');api.readRatings('a');assert.equal(fs.readFileSync(file,'utf8'),before)
    + } finally {fs.rmSync(root,{recursive:true,force:true})}
    +})