ENECHANGE Developer Blog

ENECHANGE開発者ブログ

Team Blog HubのAtomフィード配信はじめました

CTO室の岩本 (@iwamot) です。同僚エンジニアの情報発信を活性化するのが、ぼくのミッションのひとつです。

ENECHANGEでは、Team Blog Hubを使って、所属エンジニアのブログ記事や発表スライドを集約・公開しています。経緯は「Team Blog Hub を用いた ENECHANGE エンジニア記事まとめサイトの公開」に書きました。

そして先日から、集約結果のAtomフィード配信も始めています。Team Blog Hubにはフィード配信機能がないため、forkしたソースコードに手を入れた形です。

今回の記事では、具体的にどう実装したかをご紹介します。

実装内容

結論から書くと、src/builder/posts.tsを下記のように編集しました。yarn build の際に、静的なpublic/atom.xmlを出力します。

$ git diff cf65d3be29336b2a789a58b501c01dd5116bb7b6 src/builder/posts.ts
diff --git a/src/builder/posts.ts b/src/builder/posts.ts
index 21721c1..87b0eda 100644
--- a/src/builder/posts.ts
+++ b/src/builder/posts.ts
@@ -1,6 +1,8 @@
+import { Feed } from "feed";
 import fs from "fs-extra";
 import Parser from "rss-parser";
 import { members } from "../../members";
+import { config } from "../../site.config";
 import { PostItem, Member } from "../types";
 export default {};

@@ -8,6 +10,7 @@ type FeedItem = {
   title: string;
   link: string;
   contentSnippet?: string;
+  content?: string;
   isoDate?: string;
   dateMiliSeconds: number;
 };
@@ -21,10 +24,11 @@ async function fetchFeedItems(url: string) {

   // return item which has title and link
   return feed.items
-    .map(({ title, contentSnippet, link, isoDate }) => {
+    .map(({ title, contentSnippet, content, link, isoDate }) => {
       return {
         title,
         contentSnippet: contentSnippet?.replace(/\n/g, ""),
+        content: content,
         link,
         isoDate,
         dateMiliSeconds: isoDate ? new Date(isoDate).getTime() : 0,
@@ -77,6 +81,37 @@ async function getMemberFeedItems(member: Member): Promise<PostItem[]> {
     if (items) allPostItems = [...allPostItems, ...items];
   }
   allPostItems.sort((a, b) => b.dateMiliSeconds - a.dateMiliSeconds);
+
+  const feed = new Feed({
+    title: config.siteMeta.title,
+    description: config.siteMeta.description,
+    id: config.siteRoot + "/",
+    link: config.siteRoot + "/",
+    feed: config.siteRoot + "/atom.xml",
+    copyright: "© " + config.siteMeta.teamName,
+  });
+  allPostItems.slice(0, 15).forEach((post) => {
+    feed.addItem({
+      title: post.title,
+      id: post.link,
+      link: post.link,
+      content: post.content,
+      author: [
+        {
+          name: post.authorName,
+          link:
+            config.siteRoot + "/members/" + encodeURIComponent(post.authorId),
+        },
+      ],
+      date: new Date(post.dateMiliSeconds),
+    });
+  });
+  fs.ensureDirSync("public");
+  fs.writeFileSync("public/atom.xml", feed.atom1());
+
   fs.ensureDirSync(".contents");
-  fs.writeJsonSync(".contents/posts.json", allPostItems);
+  fs.writeJsonSync(".contents/posts.json", allPostItems.map((post) => {
+    delete post.content;
+    return post;
+  }));
 })();

Atomフィードの構築にはfeedパッケージを使っています。yarn add --dev feed で別途インストールしました。

また、フィードのエントリには、rss-parserのパース結果の content を含めるようにしました。contentSnippet だと、READMEの例のように情報量が少なくなってしまうためです。

content: '<a href="http://example.com">this is a link</a> &amp; <b>this is bold text</b>'
contentSnippet: 'this is a link & this is bold text'

まとめ

以上、Team Blog Hubでの集約フィード配信例をご紹介しました。あくまで一例ですが、参考になれば幸いです。