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.handle
が undefined
になる問題が発生。
解決策
post.art
)
A. テンプレートファイル修正 (ファイルパス: ./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
の安全なアクセスを追加
feeds.js
)
B. JavaScript ファイル修正 (ファイルパス: ./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
が存在しない場合はrecord
をnull
に設定 - オプショナルチェイニング(
?.
)による安全なプロパティアクセス - テンプレートエンジン(
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 {
必要な引数:
-
$id
- フィードID -
$owner_uid
- ユーザーID -
$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>
動作確認
-
Bluesky Feed:
-
http://localhost:1200/bsky/profile/username.bsky.social/feed/feedid
でエラーが出ないこと - 引用ポストが正しく表示されること
-
-
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日前にクローズされました