diff --git a/README.md b/README.md index 6a9d1ae..543ff89 100644 --- a/README.md +++ b/README.md @@ -457,7 +457,8 @@ _Are you aware of any other fixer that isn't included here? Feel free to open an - [EmbedEZ • bilibliez.com](https://embedez.com) - [fxBilibili • fxbilibili.seria.moe](https://github.com/seriaati/fxBilibili) - [BiliFix • vxbilibili.com](https://vxbilibili.com/) *Used by FixTweetBot* - - Other official public instances/redirects: `vxb23.tv` + - Rewrites `bilibili.com` to `vxbilibili.com` and `b23.tv` to `vxb23.tv`, preserving subdomains + - Supports BiliFix translation languages through the website settings - Threads Threads - [FixThreads • official instance deprecated](https://github.com/milanmdev/fixthreads) - Other unofficial public instances/redirects: `fixthreads.seria.moe` *Used by FixTweetBot*, `drhong.ddns.net:9813` (http only) diff --git a/database/migrations/2026_09_10_010000_add_bilifix_translation.py b/database/migrations/2026_09_10_010000_add_bilifix_translation.py new file mode 100644 index 0000000..0dc5fc7 --- /dev/null +++ b/database/migrations/2026_09_10_010000_add_bilifix_translation.py @@ -0,0 +1,13 @@ +"""AddBilifixTranslation Migration.""" + +from masoniteorm.migrations import Migration + + +class AddBilifixTranslation(Migration): + def up(self): + with self.schema.table('guilds') as table: + table.boolean('bilibili_tr').default(False).after('bilibili') + + def down(self): + with self.schema.table('guilds') as table: + table.drop_column('bilibili_tr') diff --git a/src/settings.py b/src/settings.py index 0305f54..7ca72a1 100644 --- a/src/settings.py +++ b/src/settings.py @@ -15,6 +15,7 @@ from database.models.CustomWebsite import CustomWebsite from src.utils import * +from src.websites import normalize_bilifix_language __all__ = ('SettingsView',) @@ -290,12 +291,14 @@ def __init__(self, setting: BaseSetting, **kwargs): async def on_submit(self, interaction: discore.Interaction): lang = str(self.children[0]) - if len(lang) != 2: + normalizer = getattr(self.setting, 'normalize_translation_language', None) + normalized = normalizer(lang) if normalizer else (lang if len(lang) == 2 else None) + if normalized is None: # noinspection PyUnresolvedReferences await interaction.response.send_message( t('settings.lang_modal.error', invalid_lang=lang, lang_iso=self.interaction_lang), ephemeral=True, delete_after=10) return - self.setting.ctx.guild.update({'lang': lang}) + self.setting.ctx.guild.update({'lang': normalized}) await self.setting.view.refresh(interaction) @@ -1415,6 +1418,23 @@ class BilibiliSetting(WebsiteBaseSetting): name = 'BiliBili' emoji = discore.config.emoji.bilibili proxies = {"BiliFix": "https://www.vxbilibili.com/"} + is_translation = True + + def normalize_translation_language(self, language: str) -> str | None: + return normalize_bilifix_language(language) + + async def translation_action(self, view: SettingsView, interaction: discore.Interaction, _) -> None: + self.translation = not self.translation + language = normalize_bilifix_language(self.ctx.guild.lang) + if language is None: + # noinspection PyUnresolvedReferences + locale = interaction.locale.value.lower() + language = normalize_bilifix_language(locale) \ + or normalize_bilifix_language(locale.split('-')[0]) \ + or 'en' + self.lang = language + self.ctx.guild.update({'bilibili_tr': self.translation, 'lang': self.lang}) + await view.refresh(interaction) class IFunnySetting(EmbedEZBaseSetting): diff --git a/src/websites.py b/src/websites.py index f710ee6..c966c5e 100644 --- a/src/websites.py +++ b/src/websites.py @@ -9,10 +9,31 @@ from database.models.Guild import * from src import utils -__all__ = ('WebsiteLink', 'websites') +__all__ = ('WebsiteLink', 'normalize_bilifix_language', 'websites') _logger = logging.getLogger(__name__) +_bilifix_languages = { + 'en', 'zh-tw', 'zh-cn', 'ja', 'ko', 'es', 'pt', 'fr', + 'de', 'it', 'ru', 'vi', 'id', 'th', 'ms', 'tl', +} +_bilifix_language_aliases = { + 'jp': 'ja', 'kr': 'ko', 'eng': 'en', 'cn': 'zh-cn', + 'chs': 'zh-cn', 'zh-hans': 'zh-cn', 'tw': 'zh-tw', + 'cht': 'zh-tw', 'zh-hant': 'zh-tw', 'may': 'ms', + 'my': 'ms', 'vn': 'vi', 'ph': 'tl', 'fil': 'tl', +} + + +def normalize_bilifix_language(language: str | None) -> str | None: + """Return a language code accepted by BiliFix.""" + + if not language: + return None + language = language.strip().lower() + language = _bilifix_language_aliases.get(language, language) + return language if language in _bilifix_languages else None + def call_if_valid(func: Callable) -> Callable: """ @@ -675,26 +696,35 @@ class BiliBiliLink(GenericWebsiteLink): hypertext_label = 'BiliBili' fix_domain = "vxbilibili.com" fixer_name = "BiliFix" + is_translation = True routes = generate_routes( - ["bilibili.com", "b23.tv", "b22.top"], + ["bilibili.com", "b23.tv"], { - "/video/:id": None, + "/video/:id": ['p'], "/:id": None, "/bangumi/play/:id": None, "/bangumi/media/:id": None, "/bangumi/v2/media-index": ["media_id"], + "/cheese/play/:id": None, "/opus/:id": None, "/dynamic/:id": None, + "/read/:id": None, "/space/:id": None, "/detail/:id": None, + "/detail.html": ["itemsId"], "/m/detail/:id": None, + "/manga/detail/:id": None, }) async def get_fixed_url(self) -> tuple[str | None, str | None]: subdomain = "" - if self.match['subdomain'] and self.match['subdomain'] not in ('www', 'm'): + if self.match['subdomain']: subdomain = self.match['subdomain'] + '.' - fixed_url = self.get_patched_url("vx" + self.match['domain'], subdomain) + target_domain = "vx" + self.match['domain'] + fixed_url = self.get_patched_url(target_domain, subdomain) + if self.guild['bilibili_tr'] and (language := normalize_bilifix_language(self.guild.lang)): + target_host = subdomain + target_domain + fixed_url = fixed_url.replace(target_host, f'{target_host}/{language}', 1) return fixed_url, self.fixer_name