MATLAB タグ付きの新着投稿をお知らせする Twitter bot (Powered by ThingSpeak)

# やったこと

MATLAB の新着記事無いかな～と Qiita をチェックする回数を減らすために、MATLAB タグのついた記事を自動でお知らせする bot を作ったのでコード公開します。

アカウントはこちら -> [@Qiita_MATLAB](https://twitter.com/qiita_matlab)

:::note warn
2023/08/15 追記
ThingSpeak からの Tweet が現在機能していないので今は GitHub Actions と Twitter API v2 を使っています。[GitHub:minoue-xx/Qiita-what-was-posted-on-this-day](https://github.com/minoue-xx/Qiita-what-was-posted-on-this-day)
:::

![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/b0aed513-5f93-ef37-e922-9df12016eba4.png)


## 本投稿のポイント

タイムゾーンを加味した処理が楽な `datetime` 型変数の `TimeZone` プロパティが見どころです。

簡単な例だと、

```matlab
t1 = datetime();
t1.TimeZone = 'Asia/Shanghai'
t2 = t1;
t2.TimeZone = 'Europe/London'
```

と実行すると

```
t1 = 
  datetime
   2019/10/26 07:00:14
t2 = 
  datetime
   2019/10/26 00:00:14
```

と**表示は異なります**が、以下のように時間情報としては同値です。

```
>> isequal(t1,t2)
ans =
  logical
   1
```

## 関連記事、ページ

ThingSpeak 自体や、Twitter で呟くのに必要な設定やコードは以下で紹介していますので、良ければ参考にしてください。

> [Qiita: ThingSpeak x MATLAB で Twitter bot 実装](https://qiita.com/eigs/items/4342676a1d453733d514)

実際の Channel は [こちら](https://thingspeak.com/channels/890134) で確認できますが、一応以下の２つの情報もトラックしています。

- **total_items**: MATLAB タグが付いた記事の合計数
- **total_followers**: MATLAB タグのフォロワー数

# 本題の MATLAB Analysis

コード全文は最後に纏めて再掲しますので、ここでは要所だけ解説します。ThingSpeak の Time Control 設定によって１時間に１回実行され、

- 新着チェック
- 新着情報を Tweet

する仕組みとしています。


まず、Qiita API を使って最新20件のリストを作ります。


```matlab

% ここから新着記事のチェック（最新20個取ればOKでしょう・・）
url = "https://qiita.com/api/v2/tags/matlab/items?page=1&per_page=20";
tmp = webread(url,opts);

% 投稿時刻をチェック（TimeZone は日本時間に設定）
created_at = datetime(vertcat(tmp.created_at),...
    'InputFormat', "uuuu-MM-dd'T'HH:mm:ss'+09:00",'TimeZone','Asia/Tokyo');
titles = string({tmp.title}');
urls = string({tmp.url}');
item_list = timetable(titles, urls, 'RowTimes', created_at,...
    'VariableNames',{'titles', 'urls'})
```

![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/8b349b29-a003-13ed-e4b8-427262ed9d6e.png)

この時、時間情報は `TimeZone`, `Asia/Tokyo` と設定して `timetable` 型変数：`item_list` としてまとめます。



現時刻から1時間以内に投稿されていればそれは新着記事。現時刻から過去１時間の間に投稿されたものだけを、`item_list` から抜き出します。

```matlab
% 新着かどうかのチェック
% このスクリプトは 1時間に1回実行する設定にします。（ThingSpeak の Time Control 設定）
interval = duration(1,0,0);
tnow = datetime;
% ThingSpeak が動いているところでは TimeZone が UTC であるところに注意
tnow.TimeZone = 'UTC'; 
trange = timerange(tnow-interval,tnow) % 過去一時間以内の投稿だけを抽出
newitem_list = item_list(trange,:);
```

`trange` 変数につかう時間情報は `TimeZone`, `UTC` に設定しています。



# まとめ
ThingSpeak を使って [@Qiita_MATLAB](https://twitter.com/qiita_matlab) bot を作りました。
ThingSpeak 上の時間設定は `UTC` ですが、Qiita API からとれる投稿時間は `JST` ということで時間情報に時差がありましたが、`datetime` 型変数の `TimeZone` プロパティで対処しています。

MATLAB タグのついた投稿頻度は**まだ**高くないので、bot としては少し寂しいですね。。こんなこと呟いてみたら？など提案ありましたら何なりと。


# MATLAB コード全文
各 APIKey だけ設定すればそのまま機能するはず。

```matlab
% アクセストークン使用
% accessToken = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
% opts = weboptions('HeaderFields',{'Authorization',accessToken});
% アクセストークン使用しない場合
opts = weboptions;


% ThingSpeak ログ用：記事合計数、フォロワー数の取得
url = "https://qiita.com/api/v2/tags/matlab";
tmp = webread(url,opts);
items_count = tmp.items_count;
followers_count = tmp.followers_count;

channelID = 890134;
writeAPIKey = 'XXXXXXXXXXXXXXXX'; % それぞれの Channel に固有の APIKey
readAPIKey = 'XXXXXXXXXXXXXXXX'; % それぞれの Channel に固有の APIKey
% Fields:
%       1: total_items
%       2: total_followers

% Channel に情報送信
data = {items_count, followers_count};
thingSpeakWrite(channelID, data , 'WriteKey', writeAPIKey);


% ここから新着記事のチェック（最新20個取ればOKでしょう・・）
url = "https://qiita.com/api/v2/tags/matlab/items?page=1&per_page=20";
tmp = webread(url,opts);

% 投稿時刻をチェック（TimeZone は日本時間に設定）
created_at = datetime(vertcat(tmp.created_at),...
    'InputFormat', "uuuu-MM-dd'T'HH:mm:ss'+09:00",'TimeZone','Asia/Tokyo');
titles = string({tmp.title}');
urls = string({tmp.url}');
item_list = timetable(titles, urls, 'RowTimes', created_at,...
    'VariableNames',{'titles', 'urls'})

% 新着かどうかのチェック
% このスクリプトは 1時間に1回実行する設定にします。（ThingSpeak の Time Control 設定）
% なので、、現時刻から1時間以内に投稿されていればそれは新着記事とします。
interval = duration(1,0,0);
tnow = datetime;
% ThingSpeak が動いているところでは TimeZone が UTC であるところに注意
tnow.TimeZone = 'UTC'; 
trange = timerange(tnow-interval,tnow) % 過去一時間以内の投稿だけを抽出
newitem_list = item_list(trange,:);


% ThingTweet 設定
tturl='https://api.thingspeak.com/apps/thingtweet/1/statuses/update';
api_key = 'XXXXXXXXXXXXXX'; % Twitterをリンクして APIKey を取得してください。
options = weboptions('MediaType','application/x-www-form-urlencoded');
options.Timeout = 10;

tweetFlag = true;
% 新着の数だけ呟きます（無ければ呟かない）
for ii=1:height(newitem_list)
    
    % 投稿文
    status = "#Qiita #MATLAB" + newline;
    status = status + newitem_list.titles(ii);
    status = status + newitem_list.urls(ii);
    disp(status);
    
    if tweetFlag
        try
            webwrite(tturl, 'api_key', api_key, 'status', status, options);
        catch ME
            disp(ME)
        end
    end
end
```