1.21 jigowatts

Great Scott!

Twitter BOTを作る

概要

C#で.NET Twitter ライブラリ「CoreTweet」を使って、Twitter BOTを作ってみます。つぶやく内容は前回のLivedoorの気象データ配信サービス「Weather Hacks」のお天気WebサービスLivedoor Weather Web Service / LWWS)から取得する天気情報です。

環境

Microsoft Visual Studio Community 2013
Windows 8.1

はじめに

Twitterと連携するためにトークンが必要なので、前準備としてTwitter Developersサイトよりアプリを作成します。

アプリの作成

画面下のMagage Your Appsリンクを押下します。
f:id:sh_yoshida:20150810002541p:plain
Application Management画面へ遷移するのでCreate New Appを押下します。
f:id:sh_yoshida:20150810003635p:plain
必須項目にそれぞれアプリ名、説明、WebサイトのURLを入力します。
f:id:sh_yoshida:20150810003736p:plain
規約を読んでYes,I agreeにチェックを入れ、Create your Twitter applicationを押下します。
f:id:sh_yoshida:20150810003927p:plain

アクセス許可の変更

アプリの登録が出来たら、登録したアプリのPermissionsタブを開きます。
AccessRead and Writeに設定されていなければ変更します。
f:id:sh_yoshida:20150810004635p:plain

API KeyとAccess Token

Keys and Access Tokensタブを開きます。
以下の赤枠でくくったAPI Key、API Secret、Access Token、Access Token Secretの4つのキーをCoreTweetで使用します。このキーをうっかりGitHubとかにアップしてしまわないよう注意しましょう。
f:id:sh_yoshida:20150810005105p:plain

実装

コンソールアプリケーションのプロジェクトを作成します。
Package Manager ConsoleよりCoreTweetをインストールします。

PM> Install-Package CoreTweet

TweetBot/Program.cs
App.Configに設定してもいいですが、今回はコンソールアプリの実行時引数に先ほどの4つのキーを渡すようにします。

using System;
using System.IO;
using System.Text;
using TweetBot.Services;

namespace TweetBot
{
    class Program
    {
        static string GetFilePath()
        {
            var currentDir = System.IO.Directory.GetCurrentDirectory();
            return System.IO.Path.Combine(currentDir, "tb.log");            
        }

        static void Main(string[] args)
        {
            using (StreamWriter sw = new StreamWriter(GetFilePath(), true, Encoding.GetEncoding("Shift-JIS")))
            using (TextWriter syncWriter = TextWriter.Synchronized(sw))
            {
                try
                {
                    if (args.Length != 4)
                    {
                        syncWriter.WriteLine("{0} [Error] args.Length:{1}",DateTime.Now.ToString(), args.Length.ToString());
                        return;
                    }

                    var APIKey = args[0];
                    var APISecret = args[1];
                    var AccessToken = args[2];
                    var AccessTokenSecret = args[3];
                    var tokens = CoreTweet.Tokens.Create(APIKey, APISecret, AccessToken, AccessTokenSecret);
                    syncWriter.WriteLine("{0} [Normal]",DateTime.Now.ToString());

                    var service = new WeatherTweetService();
                    var text = service.GetWeatherText();
                    System.Diagnostics.Debug.WriteLine(text);
                    tokens.Statuses.Update(status => text);
                }
                catch (Exception ex)
                {
                    syncWriter.WriteLine("{0} [Error] Message:{1}",DateTime.Now.ToString(), ex.Message);

                }
            }
        }
    }
}

TweetBot/Services/WeatherTweetService.cs

using Codeplex.Data;
using System;
using System.Net;
using System.Text;

namespace TweetBot.Services
{
    public class WeatherTweetService
    {
        const string NO_VALUE = "---";
        public string GetWeatherText() 
        {

            var url = "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010";
            var req = WebRequest.Create(url);

            using (var res = req.GetResponse())
            using (var s = res.GetResponseStream())
            {
                dynamic json = DynamicJson.Parse(s);

                //天気(今日)
                dynamic today = json.forecasts[0];

                string dateLabel = today.dateLabel;
                string date = today.date;
                string telop = today.telop;                
                
                var sbTempMax = new StringBuilder();                
                dynamic todayTemperatureMax = today.temperature.max;
                if (todayTemperatureMax != null)
                {
                    sbTempMax.AppendFormat("{0}℃", todayTemperatureMax.celsius);
                }
                else
                {
                    sbTempMax.Append(NO_VALUE);
                }

                var sbTempMin = new StringBuilder();
                dynamic todayTemperatureMin = today.temperature.min;
                if (todayTemperatureMin != null)
                {
                    sbTempMin.AppendFormat("{0}℃", todayTemperatureMin.celsius);
                }
                else
                {
                    sbTempMin.Append(NO_VALUE);
                }

                //Copyright
                var title = json.copyright.title;

                return string.Format("{0} {1}  最高気温 {2} 最低気温 {3} {4}",date,telop,sbTempMax.ToString(),sbTempMin.ToString(),title);
            }            
        }
    }
}

Tweet.bat
バッチファイルからコンソールアプリをコールします。そして、このバッチをタスクスケジューラに登録します。

@echo off

REM 設定
Call Env.bat

REM 自動ツイートアプリ起動
Call %appPath%\TweetBot.exe %apiKey% %apiSecret% %accessToken% %accessTokenSecret%
if %errorlevel% neq 0 echo %date% %time% Error >> Tweet.log
if %errorlevel% equ 0 echo %date% %time% Success >> Success.log


Env.bat
アプリケーションパスと4つのキーを設定します。それぞれの環境に読み替えてください。

@echo off

set appPath="D:\"
set apiKey="*****"
set apiSecret="*****"
set accessToken="*****"
set accessTokenSecret="*****"

exit /b

タスクスケジューラによるジョブ実行

[コントロール パネル]-[すべてのコントロール パネル項目]-[管理ツール]よりタスクスケジューラを起動します。
[操作]ペインよりタスクの作成...を選択します。
f:id:sh_yoshida:20150810012941p:plain
全般タブで名前、説明、ユーザログオン状態での実行を設定します。今回はPCの電源が入っていればログオンしていなくても実行してくれるように設定します。
f:id:sh_yoshida:20150810013031p:plain
トリガータブで実行タイミングを設定します。毎日決まった時間にツイートしてくれるように設定します。
f:id:sh_yoshida:20150810013217p:plain
操作タブでプログラムの開始にコンソールアプリをコールするバッチファイルを指定します。
f:id:sh_yoshida:20150810013318p:plain

結果

ありゃ、雨降るのか!
f:id:sh_yoshida:20150810014158p:plain