Closed4

Bluesky Feed & TT-RSS Plugin 修正作業

ぽぽこんぽぽこん

概要

RSSHub の Bluesky Feed機能でのテンプレートエラーと、TT-RSS の Mercury/Readability プラグインでの引数エラーの修正作業。

RSSHUBのBlueskyFeedでリンクの中身もフィードに含めたかった。(しずインフィード)

ぽぽこんぽぽこん

1. Bluesky Feed テンプレートエラー修正

問題

TemplateError: Cannot read properties of undefined (reading 'handle')
Route: /bsky/profile/:handle/feed/:space/:routeParams?

テンプレート内で embed.record.author.handleundefined になる問題が発生。

解決策

A. テンプレートファイル修正 (post.art)

ファイルパス: ./docker/app/ttrss/post.art/app/dist/templates/post-7b0043bb.art

修正内容:

{{ if text }}
    {{@ text }}<br>
{{ /if }}

{{ if embed }}
    {{ if embed.$type === 'app.bsky.embed.images#view' }}
        {{ each embed.images i }}
            <img src="{{ i.fullsize }}" alt="{{ i.alt }}"><br>
        {{ /each }}
    {{ else if embed.$type === 'app.bsky.embed.video#view' }}
        <video 
            controls
            poster="{{ embed.thumbnail }}"
            style="max-width: 100%; height: auto;"
            preload="metadata">
            <source src="{{ embed.playlist }}" type="application/x-mpegURL">
            Your browser does not support HTML5 video playback.
        </video><br>
    {{ else if embed.$type === 'app.bsky.embed.external#view' }}
        <a href="{{ embed.external.uri }}"><b>{{ embed.external.title }}</b><br>
            {{ embed.external.description }}
        </a>
    {{ else if embed.$type === 'app.bsky.embed.record#view' || embed.$type === 'app.bsky.embed.recordWithMedia#view' }}
        {{ if embed.record }}
            <p>引用ポスト:</p>
            {{ if embed.record.author }}
                <a href="https://bsky.app/profile/{{ embed.record.author.handle }}/post/{{ embed.record.uri.split('app.bsky.feed.post/')[1] }}">
                    <b>{{ embed.record.author.displayName || embed.record.author.handle }}</b><br>
                    {{ if embed.record.value }}
                        {{ embed.record.value.text.split('\n')[0] }}
                    {{ /if }}
                </a>
            {{ else }}
                <p>作成者情報が利用できません</p>
            {{ /if }}
        {{ /if }}
    {{ /if }}
{{ /if }}

主な変更点:

  • embed.record.author の存在チェックを追加
  • 存在しない場合のフォールバック表示を実装
  • embed.record.value の安全なアクセスを追加

B. JavaScript ファイル修正 (feeds.js)

ファイルパス: ./docker/app/ttrss/feeds.js/app/dist/feeds-CBPLXXDU.js

修正内容:

async function handler(ctx) {
    const handle = ctx.req.param('handle');
    const space = ctx.req.param('space');
    const DID = await resolveHandle(handle, cache.tryGet);
    const uri = `at://${DID}/app.bsky.feed.generator/${space}`;
    const profile = await getFeedGenerator(uri, cache.tryGet);
    const feeds = await getFeed(uri, cache.tryGet);
    
    const items = feeds.feed.map(({ post }) => {
        // 安全なデータクリーンアップ
        const safeEmbed = post.embed ? {
            ...post.embed,
            // recordタイプの場合、authorが存在しない場合はrecord自体をnullに
            record: (post.embed.record && post.embed.record.author) ? {
                ...post.embed.record,
                author: {
                    handle: post.embed.record.author.handle || 'unknown',
                    displayName: post.embed.record.author.displayName || post.embed.record.author.handle || 'Unknown Author'
                },
                value: post.embed.record.value || { text: '' },
                uri: post.embed.record.uri || ''
            } : null
        } : null;

        return {
            title: post.record?.text?.split('\n')[0] || 'Untitled Post',
            description: art(path.join(__dirname, 'templates/post-7b0043bb.art'), {
                text: post.record?.text?.replaceAll('\n', '<br>') || '',
                embed: safeEmbed,
            }),
            author: post.author?.displayName || post.author?.handle || 'Unknown Author',
            pubDate: parseDate(post.record?.createdAt),
            link: generateLinkFunction(), // sizu.me対応のリンク生成
            upvotes: post.likeCount || 0,
            comments: post.replyCount || 0,
        };
    });

    return {
        title: `${profile.view?.displayName || 'Unknown'} — Bluesky`,
        description: profile.view?.description?.replaceAll('\n', ' ') || '',
        link: `https://bsky.app/profile/${handle}/feed/${space}`,
        image: profile.view?.avatar,
        icon: profile.view?.avatar,
        logo: profile.view?.avatar,
        item: items,
        allowEmpty: true,
    };
}

主な変更点:

  • safeEmbed オブジェクトによる安全なデータ構造の作成
  • embed.record.author が存在しない場合は recordnull に設定
  • オプショナルチェイニング(?.)による安全なプロパティアクセス
  • テンプレートエンジン(art)の正しい使用

C. Docker マウント設定

docker-compose.yml:

volumes:
  - ./docker/app/ttrss/post.art:/app/dist/templates/post-7b0043bb.art:ro  # Post template
  - ./docker/app/ttrss/feeds.js:/app/dist/feeds-CBPLXXDU.js:ro            # Feeds handler

確認コマンド:

# マウント確認
docker exec -it <container> cat /app/dist/templates/post-7b0043bb.art
docker exec -it <container> cat /app/dist/feeds-CBPLXXDU.js
ぽぽこんぽぽこん

2. TT-RSS プラグイン引数エラー修正

問題

ArgumentCountError: Too few arguments to function Feeds::_get_title(), 
1 passed and at least 2 expected

プラグインが Feeds::_get_title() を旧仕様(引数1個)で呼び出していたが、新仕様では最低2個の引数が必要。

調査結果

関数シグネチャ確認:

grep -n "_get_title" /var/www/classes/Feeds.php

結果:

static function _get_title(int|string $id, int $owner_uid, bool $cat = false): string {

必要な引数:

  1. $id - フィードID
  2. $owner_uid - ユーザーID
  3. $cat - カテゴリフラグ(オプション)

修正対象プラグイン

A. af_readability プラグイン

エラー箇所確認:

grep -n "_get_title" /var/www/plugins.local/af_readability/init.php
# 116: <?= Feeds::_get_title($f) . " " . (in_array($f, $append_feeds) ? __("(append)") : "") ?>

修正コマンド:

sed -i '116s/Feeds::_get_title($f)/Feeds::_get_title($f, $_SESSION['\''uid'\''])/g' /var/www/plugins.local/af_readability/init.php

修正結果:

<?= Feeds::_get_title($f, $_SESSION['uid']) . " " . (in_array($f, $append_feeds) ? __("(append)") : "") ?>

B. mercury_fulltext プラグイン

エラー箇所確認:

grep -n "_get_title" /var/www/plugins.local/mercury_fulltext/init.php
# 122: Feeds::_get_title($f) . "</a></li>";

修正コマンド:

sed -i '122s/Feeds::_get_title($f)/Feeds::_get_title($f, $_SESSION['\''uid'\''])/g' /var/www/plugins.local/mercury_fulltext/init.php

修正結果:

Feeds::_get_title($f, $_SESSION['uid']) . "</a></li>";

修正確認

確認コマンド:

grep -n "_get_title" /var/www/plugins.local/af_readability/init.php
grep -n "_get_title" /var/www/plugins.local/mercury_fulltext/init.php

期待される結果:

/var/www/plugins.local/af_readability/init.php:116: <?= Feeds::_get_title($f, $_SESSION['uid']) . " " . (in_array($f, $append_feeds) ? __("(append)") : "") ?>
/var/www/plugins.local/mercury_fulltext/init.php:122: Feeds::_get_title($f, $_SESSION['uid']) . "</a></li>";

3. 作業後の確認事項

TT-RSS再起動

docker restart <ttrss-container-name>

動作確認

  1. Bluesky Feed:

    • http://localhost:1200/bsky/profile/username.bsky.social/feed/feedid でエラーが出ないこと
    • 引用ポストが正しく表示されること
  2. TT-RSS プラグイン:

    • エラーログに ArgumentCountError が出ないこと
    • プラグイン設定画面が正常に表示されること
    • Readability、Mercury Fulltext機能が正常動作すること

バックアップ作成

# 将来の作業のために修正版をバックアップ
cp /var/www/plugins.local/af_readability/init.php /backup/af_readability_init_fixed.php
cp /var/www/plugins.local/mercury_fulltext/init.php /backup/mercury_fulltext_init_fixed.php
cp ./docker/app/ttrss/post.art /backup/post_fixed.art
cp ./docker/app/ttrss/feeds.js /backup/feeds_fixed.js
ぽぽこんぽぽこん

4. 学んだポイント

テンプレートエラー対策

  • データの事前クリーンアップ: テンプレートに渡す前にデータ構造を安全にする
  • 条件分岐の活用: テンプレート内で適切な存在チェックを行う
  • フォールバック設計: データが不完全な場合の代替表示を準備

プラグイン互換性

  • API変更への対応: フレームワーク更新時は関数シグネチャの変更に注意
  • 段階的修正: エラーログから具体的な箇所を特定して最小限の修正を行う
  • バージョン管理: 修正前のバックアップを必ず作成

Docker運用

  • ファイルマウント: 開発用ファイルを適切にマウントして反映確認
  • コンテナ内確認: マウントが正しく行われているかの検証手順

緊急時対応

  • プラグインエラー時は一時無効化可能
  • テンプレートエラー時はマウント解除で元に戻る
  • 全修正内容はこのドキュメントで再現可能
このスクラップは18日前にクローズされました