Skip to content
This repository was archived by the owner on Jul 17, 2026. It is now read-only.

feat(歌词): 新增屏蔽词还原功能 - #927

Merged
apoint123 merged 2 commits into
devfrom
dev-f
Feb 22, 2026
Merged

apoint123 merged 2 commits into
devfrom
dev-f

Conversation

@kazukokawagawa

Copy link
Copy Markdown
Collaborator

添加设置选项以还原歌词中的屏蔽词(如 f**k 还原为 fuck)。新增迁移函数、设置状态、UI 开关及歌词处理逻辑。

添加设置选项以还原歌词中的屏蔽词(如 f**k 还原为 fuck)。新增迁移函数、设置状态、UI 开关及歌词处理逻辑。
@kazukokawagawa kazukokawagawa self-assigned this Feb 22, 2026
Copilot AI review requested due to automatic review settings February 22, 2026 04:47
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @kazukokawagawa, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求引入了一个新功能,允许用户选择还原歌词中被屏蔽的词汇。通过在设置中提供一个用户界面开关,用户可以控制是否将“f**k”等审查过的词语恢复为原始形式。这一改进增强了用户对歌词显示内容的控制,并确保了设置状态的正确持久化和迁移。

Highlights

  • 新增歌词屏蔽词还原功能: 引入了一个新功能,允许用户将歌词中的屏蔽词(如 "f**k")还原为原始词汇。
  • 添加用户界面开关: 在设置中增加了一个名为 "Fuck *** Mode" 的开关,用户可以手动启用或禁用此功能。
  • 实现歌词处理逻辑: 创建了一个新的工具文件 lyricProfanity.ts,其中包含用于识别和替换各种屏蔽词的正则表达式。
  • 更新设置存储和迁移: 在 SettingState 中添加了 uncensorMaskedProfanity 属性,并更新了设置迁移版本至 11,以确保新设置的兼容性。
Changelog
  • src/components/Setting/config/play.ts
    • 添加了新的设置选项 "uncensorMaskedProfanity" 及其 UI 开关。
  • src/core/player/LyricManager.ts
    • 导入了 applyProfanityUncensor 函数。
    • 在歌词处理流程中应用了屏蔽词还原逻辑。
  • src/stores/migrations/settingMigrations.ts
    • 将设置 Schema 版本更新至 11。
    • 添加了版本 11 的迁移函数,为 uncensorMaskedProfanity 设置默认值 false。
  • src/stores/setting.ts
    • 在 SettingState 接口中添加了 uncensorMaskedProfanity 属性。
    • 在 useSettingStore 的默认状态中初始化 uncensorMaskedProfanity 为 false。
  • src/utils/lyric/lyricProfanity.ts
    • 新增文件,实现了 replaceMaskedProfanity 函数,用于替换多种屏蔽词。
    • 实现了 applyProfanityUncensor 函数,根据用户设置对歌词数据进行处理。
Activity
  • 此拉取请求目前没有外部活动(例如评论或审查)。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces a feature to uncensor masked profanity in lyrics. While the implementation is functional, there are several performance and correctness issues. Specifically, the use of multiple sequential regex replacements is inefficient, and the current patterns risk false positives. Additionally, the processing pipeline leads to redundant deep cloning of lyric data, and a utility function accesses global state directly, which impacts testability and modularity.

Comment thread src/utils/lyric/lyricProfanity.ts
Comment thread src/utils/lyric/lyricProfanity.ts Outdated
Comment thread src/utils/lyric/lyricProfanity.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a feature to restore censored profanity in song lyrics (e.g., "f**k" → "fuck"). The implementation follows established patterns in the codebase for lyric transformation features, including a new utility module, setting state management, migration function, and UI configuration.

Changes:

  • Added lyricProfanity.ts utility module with regex-based replacement logic for common profanity censorship patterns
  • Integrated profanity uncensor processing into the lyric pipeline in LyricManager.ts
  • Added uncensorMaskedProfanity setting with migration from schema version 10 to 11

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/utils/lyric/lyricProfanity.ts New utility module implementing regex-based profanity uncensoring for masked words in lyrics
src/stores/setting.ts Added uncensorMaskedProfanity boolean property to settings state with default value false
src/stores/migrations/settingMigrations.ts Incremented schema version to 11 and added migration function to initialize the new setting
src/core/player/LyricManager.ts Integrated applyProfanityUncensor into lyric processing pipeline after bracket replacement
src/components/Setting/config/play.ts Added "Fuck *** Mode" UI toggle with description for the profanity uncensor feature
Comment thread src/stores/setting.ts
Comment on lines +15 to +19
.replace(/\*{4}ing/gi, "fucking")
.replace(/b\*{3}h/gi, "bitch")
.replace(/d\*{2}k/gi, "dick")
.replace(/d\*{2}n/gi, "damn")
.replace(/\*{4}er/gi, "fucker")

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generic patterns "****ing" and "****er" could potentially match censored words other than the intended profanity. While the likelihood of false positives is low in practice (since music services typically only censor profanity), consider adding a comment explaining the assumption that these patterns primarily match "fucking" and "fucker" respectively, to help future maintainers understand the design decision.

Copilot uses AI. Check for mistakes.
Comment thread src/utils/lyric/lyricProfanity.ts
Comment on lines +6 to +23
const replaceMaskedProfanity = (text: string) => {
if (!text) return text;
return text
.replace(/f\*{2}k/gi, "fuck")
.replace(/s\*{2}t/gi, "shit")
.replace(/c\*{2}t/gi, "cunt")
.replace(/c\*{2}k/gi, "cock")
.replace(/co\*{2}/gi, "cock")
.replace(/s\*{2}ker/gi, "sucker")
.replace(/\*{4}ing/gi, "fucking")
.replace(/b\*{3}h/gi, "bitch")
.replace(/d\*{2}k/gi, "dick")
.replace(/d\*{2}n/gi, "damn")
.replace(/\*{4}er/gi, "fucker")
.replace(/as\*{2}le/gi, "asshole")
.replace(/w\*{3}e/gi, "whore")
.replace(/n\*{3}a/gi, "nigga");
};

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc comment for the replaceMaskedProfanity function. Following the codebase convention seen in lyricFormat.ts, internal helper functions should have JSDoc comments explaining their purpose, parameters, and return values. This improves code maintainability and developer understanding.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +34
const processLine = (line: LyricLine) => {
if (line.words) {
line.words.forEach((w) => {
w.word = replaceMaskedProfanity(w.word);
if (w.romanWord) w.romanWord = replaceMaskedProfanity(w.romanWord);
});
}
if (line.translatedLyric) line.translatedLyric = replaceMaskedProfanity(line.translatedLyric);
if (line.romanLyric) line.romanLyric = replaceMaskedProfanity(line.romanLyric);
};

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc comment for the processLine function. Following the codebase convention seen in lyricFormat.ts (lines 169-175), helper functions should have JSDoc comments explaining their purpose and parameters.

Copilot uses AI. Check for mistakes.
Comment thread src/utils/lyric/lyricProfanity.ts Outdated
Comment on lines +36 to +44
export const applyProfanityUncensor = (lyricData: SongLyric): SongLyric => {
const settingStore = useSettingStore();
if (!settingStore.uncensorMaskedProfanity) return lyricData;

const newLyricData = cloneDeep(lyricData);
newLyricData.lrcData?.forEach(processLine);
newLyricData.yrcData?.forEach(processLine);
return newLyricData;
};

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc comment for the applyProfanityUncensor function. Following the codebase convention seen in lyricFormat.ts (lines 42-46), exported functions should have JSDoc comments explaining their purpose, parameters, and return values.

Copilot uses AI. Check for mistakes.
修复 applyProfanityUncensor 函数中未正确传递去码设置的问题,将设置判断逻辑从函数内部移至调用处,确保歌词去码功能能根据用户设置正确生效。
@apoint123
apoint123 merged commit e6353e8 into dev Feb 22, 2026
4 checks passed
@apoint123
apoint123 deleted the dev-f branch February 22, 2026 08:50
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

3 participants