🖼️

【.NET】Twitter APIを使って推しの画像に溺れたい 完

2023/03/25に公開

こんにちは。
ツイッターAPIが有料化される直前に公開しても意味がないのはわかっていますが、中途半端だとモヤモヤするので終わらせます。

リリースの前にちょっと修正

画像取得のリクエストがタイムアウトした場合を考慮していなかったので、入れておきます。
またツイート検索の時間指定をDateTime.Nowで行っていましたが、毎日00:00:00に実行させるので日付で指定するほうがよいです。
(00:00:00に実行しても、DateTime.Nowが厳密に00:00:00を指すとは限らないため)

Program.cs
// 600秒で支度しな!(広い心)
private static HttpClient httpClient = new()
+{
+    Timeout = TimeSpan.FromSeconds(600)
+};

// エラー処理を追加
private static async Task DownloadImgAsync(string url, string path)
{
+    try
+    {
        var response = await httpClient.GetAsync(url);
        if (response.StatusCode == HttpStatusCode.OK)
        {
	    using var stream = await response.Content.ReadAsStreamAsync();
	    using var outStream = File.Create(path);
	    stream.CopyTo(outStream);
        }
        else
        {
	    logger.Error($"Failed to fetch HTTP response. {response.StatusCode}:{response.ReasonPhrase}");
        }
+    }
+    catch(TaskCanceledException e)
+    {
+        logger.Error($"The request is calceled due to timeout. url: {url}");
+    }
+    catch(Exception e)
+    {
+        logger.Error(e);
+    }
}

次にappsettings_release.jsonとnlog_release.configを書き換えます。
appsettings_release.jsonはベースパスだけ変更、nlog_release.configはコンソール設定を削除、ログファイルとアーカイブファイルのパスを変更です。

appsettings.json
{
  "Env": "Release",
  "ApiKey": "aaa",
  "ApiKeySecret": "bbb",
  "AccessToken": "ccc",
  "AccessTokenSecret": "ddd",
  "BasePath": "/home/user/Public/share/oshipics",
  "Hashtags": [
    "soraArt",
    "ロボ子Art",
    ...
  ]
nlog_release.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      throwExceptions="true"
      internalLogLevel="Off" internalLogFile="../logs/nlog_internal.log">

    <targets>
    <!-- ファイル -->
        <target name="logFile"
                xsi:type="File"
                encoding="UTF-8"
                writeBom="true"
                lineEnding="Default"
                layout="${longdate} ${level:uppercase=true:padding=-5} [${threadid}] ${logger} - ${message} ${exception:format=tostring}"
                fileName="../Logs/${shortdate}.log"
		archiveFileName="../Logs/backup/${shortdate}.log"
                archiveEvery="Day"
                archiveNumbering="Sequence"
                maxArchiveFiles="100" />
    </targets>
    <rules>
	<logger name="*" minlevel="Trace" writeTo="logFile" />
    </rules>
</nlog>

リリースしよう

リリースするには、どこにリリースするか(Azure/IIS/フォルダ など)決める必要があります。
Visual Studioではこれを「プロファイル」として保存しておき、何回でも同じ設定でリリースし直すことができます。

ビルド > 選択範囲の公開 を選びます。

「発行プロファイルの追加」を選択します。

ターゲット:フォルダ
特定のターゲット:フォルダ
場所:そのまま
完了を選択します。


プロファイルが完成したら、「発行」を選択します。

ビルドログ
ビルドを開始しました...
1>------ ビルド開始: プロジェクト: OshiPicCollector, 構成: Release Any CPU ------
2>------ 公開の開始: プロジェクト: OshiPicCollector, 構成: Release Any CPU ------
2>OshiPicCollector -> C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\OshiPicCollector.dll
2>if "Release" == "Debug" (
2>    copy  /Y /V "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\appsettings_debug.json" "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\appsettings.json"
2>    copy  /Y /V "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\nlog_debug.config" "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\nlog.config"
2>)
2> 
2>if "Release" == "Release" (
2>    copy  /Y /V "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\appsettings_release.json" "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\appsettings.json"
2>    copy  /Y /V "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\nlog_release.config" "C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\nlog.config"
2>)
2>        1 個のファイルをコピーしました。
2>        1 個のファイルをコピーしました。
2>OshiPicCollector -> C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\publish\
========== ビルド: 成功 1、失敗 0、最新の状態 0、スキップ 0 ==========
========== 公開: 1 正常終了、0 失敗、0 スキップ ==========

成功したら、成果物フォルダ(C:\Users\user\source\repos\OshiPicCollector\OshiPicCollector\bin\Release\net6.0\publish)ができているか確認してください。

このフォルダをまるごとリリース先にコピーします。
フォルダ名は何でもよいです(Appとかに変えてOK)。

これでリリース完了!

RaspberryPiで実行

dotnetをRaspberryPiにインストール

Microsoftが手順を紹介してくれています。
インストールスクリプトをダウンロードして実行し、パスを通せばdotnetコマンドを使えるようになります。
https://learn.microsoft.com/ja-jp/dotnet/core/install/linux-scripted-manual#scripted-install

SSHログインして実行

GOGO!!

...あれぇ?

appsettings.jsonを取得するとき、Directory.GetCurrentDirectory()からファイルを探す設定にしていました。
つまりDLLを実行したディレクトリからappsettings.jsonを探してしまうため、ファイルないよと言われてしまうわけです。
アプリフォルダに移動すれば動作します。

systemdのserviceファイルとtimerファイルを作成

/etc/systemd/system/oshipic.service
[Unit]
Description=OshiPic Collector Service

[Service]
Type=simple
WorkingDirectory=/home/user/Public/share/oshipics/App
ExecStart=/home/user/.dotnet/dotnet /home/user/Public/share/oshipics/App/OshiPicCollector.dll

[Install]
WantedBy=multi-user.target
/etc/systemd/system/oshipic.timer
[Unit]
Description=MyDNS IP Service timer

[Timer]
OnCalendar=00:00:00
Unit=oshipic.service

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable /etc/systemd/system/oshipic.service
sudo systemctl enable /etc/systemd/system/oshipic.timer
# .serviceはstartさせない
sudo systemctl start /etc/systemd/system/oshipic.timer

タイマーリストに登録されればOKです。

タイマー動作

ログファイルが吐き出されていれば動作確認完了です。

最後に

結局ツイッターAPIは有料化してねえじゃねえか!!!
言うだけ言って結局おじゃんになるの、アメリカらしいな!!!!!!

Discussion