Files
Auto_Bangumi/docs/ja/dev/plugins/events.md
Estrella Pan 045bdbd407 fix(4.0): 已打 ab:renamed 的种子在本进程未发布过时补发 torrent.organized
标签在发布之前打上,之后的轮次不再检查该种子:订阅者处理中被取消
(重启、插件重载)的事件永远不会再投递,硬链接漏掉这一集。现在每个
进程按当前文件名为已打标签的种子补发一次,丢失的事件在下次启动时
重新投递,投递恢复为至少一次;没有事件总线时不查询文件。
test_renamed_tag_skips_before_file_and_offset_queries 改为在已发布的
稳态下断言。文档与 TorrentOrganized 说明同步更新。
2026-10-08 16:42:42 +02:00

6.5 KiB
Raw Permalink Blame History

イベント

イベントは凍結された dataclass です。クラス変数 kind がイベント名です。ホストとプラグインは 1 つのイベントバスを共有します。

from ab_sdk import subscribe
from ab_sdk.events import RssFailureEvent

@subscribe("rss_failure")
async def on_rss_failure(self, event: RssFailureEvent):
    self.ctx.log.warning("購読 %s が失敗しました:%s", event.rss_name, event.error)
  • 購読者は専用のキューで、発行順に非同期で実行されます。失敗やタイムアウトは発行側に影響せず、プラグインのブレーカーに数えられます。既定のタイムアウトは 30 秒です。大きなファイルのコピーのような長い処理には @subscribe(kind, timeout=600) を使います。
  • "*" は全イベントを購読します。
  • 発行は self.ctx.bus.publish(event) で行います。プラグインのイベントの kind は <プラグイン id>. で始める必要があります。ホストのイベントとの衝突を防ぐためです。
  • フロントエンドコンポーネントは host.events.on(kind, callback) で同じバスを購読します。コールバックはイベントのフィールドを受け取ります(フロントエンドスロット を参照)。

システムイベント

AB が通知センターに送るイベントは、すべて ab_sdk.events.SystemEvent のサブクラスです。severity、payload()、describe()(既定の中国語タイトルと本文)、i18n()(フロントエンドの i18n キーと引数)を持ちます。AB はまず通知センターに書き込み、次にイベントバスへ発行し、最後に外部チャンネルへプッシュします。「通知」スイッチが影響するのは外部へのプッシュだけです。プラグインは常にイベントを受け取ります。

kind イベントクラス 発行のタイミング
rss_failure RssFailureEvent RSS 購読が正常から接続異常に変わったとき
download_failure DownloadFailureEvent リトライ後もトレントの追加に失敗したとき
offset_review OffsetReviewEvent 作品のシーズン / 話数オフセットの確認が必要なとき
downloader_unavailable DownloaderUnavailableEvent ダウンローダーに接続できない、認証情報が違う、IP が遮断された。各インスタンスが利用可能から利用不可に変わるたびに 1 回
update_available UpdateAvailableEvent 新しいバージョンを検出したとき
update_applied / update_failed UpdateAppliedEvent オンライン更新が成功 / 失敗したとき
llm_auth_failure LLMAuthFailureEvent サブスクリプション型 LLM プロバイダーの認証情報が無効になったとき
llm_plugin_install_failed LLMPluginInstallFailedEvent LLM プラグインのインストールに失敗したとき
rename_conflict RenameConflictEvent メディアファイルのリネームで保存先が競合したとき
rename_skipped RenameSkippedEvent リネーム方式がファイル名を決められず、元の名前のままにしたとき
plugin.loaded PluginLoaded プラグインの読み込みに成功したとき
plugin.disabled PluginDisabled プラグインの読み込みに失敗した、またはブレーカーが作動したとき

システムイベントの kind は 3.x の値のままです(通知センターはこれで保存と翻訳を行います)。そのため . のプレフィックスはありません。

整理イベント

kind イベントクラス フィールド 発行のタイミング
file.renamed FileRenamed bangumi_id、old_path、new_path、file_kind、downloader_id ファイルが実際にリネームされたとき(バージョン置換後のリネームを含む)
torrent.organized TorrentOrganized torrent_hash、bangumi_id、files(OrganizedFile(path, kind) のタプル)、downloader_id トレントの整理が完了したとき。リネーム方式が none でも発行され、files は元のパスです。選択したリネーム方式が未登録(プラグインが無効、または遮断済み)の間は発行されません
  • パスはダウンローダーから見た絶対パスで、/ で連結されます(Windows ダウンローダーの \ も / に統一されます)。AB とダウンローダーで見えるディレクトリが異なる場合(別々のコンテナで動作している場合など)は、購読者側でパスを変換する必要があります。
  • bangumi_id はトレントの ab:<id> タグに由来します。古いトレントでは None の場合があります。downloader_id はトレントがあるダウンローダーインスタンスの id です。インスタンスごとにパスの見え方が異なることがあります。
  • torrent.organized の配信は少なくとも 1 回(at-least-once)です。ダウンローダーにある整理済みのトレントは、「リネーム済み」タグがあっても、AB を再起動するたびにもう一度発行されます。購読者は冪等にしてください。
  • この 2 つのイベントはイベントバスにだけ発行されます。通知センターには入りません。

独自イベント

通常のイベントは Event を継承して定義します。通知できるイベントは SystemEvent を継承します。発行すると、ホストのイベントと同じ経路をたどります。通知センターへの書き込み(フロントエンドに翻訳がなければ describe() のタイトルと本文を表示)、イベントバスへの発行、外部チャンネルへのプッシュです。dedup_key() が同じイベントは、通知センターで 1 件にまとめられます。

from dataclasses import dataclass
from typing import ClassVar
from ab_sdk.events import SystemEvent

@dataclass(frozen=True, slots=True)
class SyncFailed(SystemEvent):
    kind: ClassVar[str] = "my-plugin.sync_failed"
    severity: ClassVar[str] = "warning"
    reason: str

    def describe(self) -> tuple[str, str]:
        return ("同期に失敗しました", self.reason)

組み込みの hardlink の hardlink.failed も、この方法で発行しています。