2
4

Qiitaのトレンドに載ったらうれしいですよね。

今回は、Qiitaが提供しているRSSを使って自身の記事がトレンド入りしたらSlackで教えてくれる機能を実装してみました。

はじめに (すみません、実はシリーズです。)

以前、QiitaのRSSをDrupalでAPI化する実装をしてみました。
せっかく実装したAPIですので、今回さらに活躍させてみようと思います。

※ 「せっかく公式がRSSを提供しているのに、なんでAPI化するの?」っていう疑問あると思います。どれかの記事で触れてるので文句・不満がある人は読んでください。

トレンド / Feed (Qiita公式)

どうやら、個人記事RSS/トレンド記事RSS どちらもXMLの構造に大きなフォーマットの違いがないようです。(APIをそのまま使えるからありがたい 🤲)
以下のURLが提供しているFeedです。(リーダー登録してもいいかもですね。)
https://qiita.com/popular-items/feed

実装しましょ

手順はこちらです。

  1. API実装
  2. Slack通知関数の実装
  3. Cron の設定

そんな難しくないです。1つずつやっていきましょ。

今回はDrupalで実装しましたが、どの言語/どのフレームワークでも、ある程度は対応できる仕様だと思います。
ご自身のお得意なものを使ってください。

001. API実装

API実装(XMLパース)については、過去記事で紹介しています。
ほぼ変更ありませんので細かいところはそちらを参照ください。

ただ、1点だけ過去記事と違う所 があります。

個人記事 / RSSにはなかった Author を今回使用します。
記事の投稿者が誰かわからないAPIは嫌ですよね。

QiitaController::parseXml()を編集してください。過去記事もみてね 🤲
/**
 * Parses XML data and generates list item markup for each feed item.
 *
 * @param \SimpleXMLElement $xml
 *   The XML data.
 * @param string $url
 *   Rss url.
 *
 * @return array
 *   The array for the list items.
 */
private function parseXml(\SimpleXMLElement $xml, string $url): array {
  $articles = [];
  foreach ($xml->entry as $o) {
    // Get feed item.
    $title = (string) $o->title;
    $link = (string) $o->url;
    $author = (string) $o->author->name;
    $published = (string) $o->published;
    if (!isset($title) || !isset($link) || !isset($published)) {
      continue;
    }
    $published = new \Datetime($published);

    if (!$author) {
      // 個人RSSの場合.
      $articles[] = [
        'title' => $title,
        'link' => $link,
        'published' => $published->format('c'),
      ];
    }
    else {
      // トレンドRSSの場合Authorを考慮する.
      $articles[] = [
        'author' => $author,
        'link' => $link,
        'published' => $published->format('c'),
        'title' => $title,
      ];
    }
  }
  return [
    'title' => (string) $xml->title,
    'link' => $url,
    'data' => $articles,
  ];
}

以前の実装したメソッドをゴリ押しで対応させました。(雑だけど許して)

API化についてはこちらの記事で紹介しています。

APIにアクセスして、JSONデータが返ってくれば👌です。
これでAPIの実装は完了です。

/api/qiita/{id}{id}にユーザー名をセットする想定です。
例えば、/api/qiita/umekikazuyaにアクセスする感じ。

今回のFeedのURLはhttps://qiita.com/popular-items/feed です。
{ホスト名}/api/qiita/popular-itemsでアクセスする感じですね。

※ 以前の記事では、アカウント単位で 8時間 キャッシュさせる機構についても紹介しています。そちらもぜひ。

002. Slack通知関数の実装

次は、Slack通知関数の実装を行います。

イメージはこんな感じ。

  1. APIからJSONデータを取得する
  2. JSONデータに自身のアカウントが存在するかチェック
  3. Slackのフォーマットに変換
/script/batch/trend-notice-slack.php
$client = new Client();
try {
  $url = '{$ホスト名}';
  $endpoint = '/api/qiita/feed/popular-items';
  $http_request = $client->get($url . $endpoint);
  $raw_data = $http_request->getBody()->getContents();
  if (!$raw_data) {
    throw new \Exception();
  }
}
catch (\Exception $e) {
  echo 'APIの取得に失敗.';
  return;
}

// 取得JSONデータを配列に変換.
$data = json_decode($raw_data, TRUE);

// 自分のアカウントでデータを絞り込み.
$filtered_data = array_filter($data['data'], function ($item) {
  // 自身のアカウント名.
  return $item['author'] === 'umekikazuya';
});

// Slackに送信するメッセージの構築.
$blocks = [];
foreach ($filtered_data as $item) {
  $blocks[] = [
    "type" => "section",
    "text" => [
      "type" => "mrkdwn",
      "text" => "<{$item['link']}|{$item['title']}> - {$item['published']}",
    ],
  ];
}
$slack_message = [
  "blocks" => $blocks,
];

// 環境変数.
$token = getenv('slack_token');
$channel_id = getenv('slack_channel_id');

// Slackに送信.
$client = new Client();
$client->post('https://slack.com/api/chat.postMessage', [
  'headers' => [
    'Authorization' => "Bearer {$token}",
    'Content-Type' => 'application/json',
  ],
  'json' => [
    'channel' => $channel_id,
    'blocks' => $slack_message['blocks'],
  ],
]);
echo "Slackに送信しました。";
// ※ 記事内では細かい例外処理は省略しています。.

003. Cron の設定

その前に...。

先程のPHP関数を実行するBashを実装しました。

/script/qiita-trend-notice-slack.bash
$DRUSH_PATH php:script $PATH/script/batch/trend-notice-slack.php

※ Drushは、Drupalと親和性の高いCLIツールです。

では ShellをCronで実行しましょう。

1. Crontab を開く
crontab -e
2. Cron の設定

最近人気の記事を毎日5時/17時に更新

とありますが、ちょっと時間のズレがある気かもしれないので 更新の1時間後に Cron を設定しましょう。

0 6,18 * * * bash {PATH}/script/batch/trend-notice-slack.bash

Cron設定は以上です。

執筆

記事を書きましょう。

待機

トレンド入りするかどうかは保証できません。

まとめ

それぞれの機能の単体テストはしましたので動作は問題ないかと。
ただ、トレンド入りしてないので通しで動くかはわかりません。現在待機中です。(記事の質悪いのかな 😥)

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4