ぐうたら備忘録

趣味で作ったものなどをぼちぼち書いていきます。

ぐるなびAPIでうどん屋を検索できるLINEBotを作った話

はじめに

私の趣味はうどん屋巡りですので、うどん屋のみの検索機能を持ったLINEBotを作成してみました。
このBotで簡単に周囲3km以内の数件のうどん屋を検索できます。作成時期は本記事の記述の丸一年以上前ですが…w。
ちなみに現在は運用を停止しています。

使ったもの

Bot作成に使用したもの諸々は以下。
どれも無料で利用できるものですので、ご自身で目的に合ったBot作成もできますねぇ。

  1. Node.js
  2. line-bot-sdk-nodejs
  3. Heroku
  4. ぐるなびAPI

使い方

  1. 通常のLINEの使い方と同様に友達追加して、位置情報を送信します。
  2. 半径3Km以内で該当した上位2件の店舗詳細と地図情報とぐるなびへのリンク、残りの該当店舗をいくつかリストアップします。

f:id:gootalife:20190323153710j:plain

終わりに

ソースはBitbucketにありますが、諸事情で非公開に設定しています。
ぐるなびAPIは手軽に触れるAPIでもあるので、API利用関連の練習に結構良いかも。

ニコ動風コメントシステム「Textream」×「EzCommenter」

はじめに

砕けたプレゼンテーションなんかに使えそうなコメントシステムを考えてみました。
今回は、C#×WCFとNode.js×expressを使ってみました。このシステムでは、ブラウザからコメントを打つことができ、端末を選ばないようになっています。

  • Textream」コメントを流すやつ
  • 「EzCommenter」コメントを打つやつ

使い方


1. コメントを受け取りたいPCで「Textream.exe」を管理者権限で起動します。(WCFによる通信機能を使用するため)
2. 以下のような初期画面にIPアドレスが表示されます。
f:id:gootalife:20181224045112p:plain
3. 同PCで「EzCommenter」のディレクトリに移動し、コマンドプロンプト等から

npm start

を実行し、「EzCommenter」を起動します。
4. コメントを打ちたい端末からブラウザで「http://aaa.bbb.ccc.ddd:3000/」のようにアクセスします。aaa~は2.で表示されているIPアドレスです。
5. 以下のような画面が開きます。
f:id:gootalife:20181224050613p:plain
6. コメントを入力し、Enterキーを押すか送信をクリックすると以下のように「Textream」を起動しているPCの画面上にコメントが右から流れてきます。コメントの左に書かれている時間は、「EzCommenter」の起動からの時間となっています。
f:id:gootalife:20181224051000p:plain

上記の手順で画面の最前面に文字列が流れてくるようになります。
終了したいときは、タスクバーから「Textream」のバツから終了できます。
「EzCommenter」は起動した状態でコマンドプロンプトからCtrl+C二回で終了できます。
また、コメントのログが「EzCommenter」のディレクトリに「CommentLog.json」として時間とコメントがそれぞれ保存されています。
f:id:gootalife:20181224052007p:plain

終わりに

WCFというフレームワークを用いると今回実装したかった機能が簡単に実装できました。
ソースコードは以下で公開しています。気になったら見てみてください。
あと「Textream」はWindowsでしか動きません。
github.com
github.com

Discordのチャットを読み上げるアプリ「Yomisen」のGUI版「Yomisen2」を作った話

Yomisenは意外と使い物になった!?

面倒くさかったのでCUIでちゃちゃっと作ってしまいましたが、意外と使用する機会がありました。
例えば、実家に帰省しているとき、リビングで通話に参加したいとします。
当然、家族の迷惑になるので通話に参加しても喋ることができません。
このとき、Yomisenを使って棒読みちゃんにチャットを読み上げさせます。
この棒読みちゃんの音声をDiscordのマイク入力として渡せば、
ゆっくりボイスでの通話の参加が可能となります。まぁ、別途設定が必要になってくるんですが。
この設定については、別の記事で書こうと思います。

Yomisen2について

動作内容は殆ど同じなので、核となるコードはほぼ移植して、
ボタンのイベントやグリッドの操作を追加したぐらいです。
GUIということで、CUIのYomisenよりは感覚的に使えるようにしました。
ログイン処理は、一度行えばトークンを保存するので、ログアウトするまで必要ありません。
トークンが残っていれば、起動時に自動でログインしてくれます。
メインウィンドウは以下。

f:id:gootalife:20180831022705p:plain

各グリッドに、読み上げさせたいチャンネルかユーザーのIDを登録します。
後は、棒読みちゃんを起動しておくだけです。

ゲーマーの方ならDiscordを使う機会はあると思うので、ぜひ使ってみてください!

github.com

TwitterのTLがニコ動風に流れてくるアプリを作ってみた

はじめに

TwiiterのAPIを使うとおもちゃが簡単に作れるということで今回は、
StreamingAPIを利用し、Twitterのタイムラインがニコニコ動画風に
右から左へ流れていくアプリを作ってみました。
名前は「TLN2」です。(名前そのまんまかよ)

使用したもの

言語等
  • VisualStudio2017
  • C#
  • WPF
ライブラリ
  • CoreTweet.0.8.1.394
  • Hardcodet.NotifyIcon.Wpf.1.0.8
  • Newtonsoft.Json.10.0.3
  • System.Reactive.Core.3.1.1
  • System.Reactive.Interfaces.3.1.1
  • System.Reactive.Linq.3.1.1

機能紹介

タイムラインがリアルタイムで流れてきます。
f:id:gootalife:20180530133641g:plain

検索ワードが指定できて、FF外もリアルタイムで監視できます。
(画像は「草」を指定してみた結果)
f:id:gootalife:20180530133801p:plain

  • ツイートに含まれるURLをクリックするとブラウザで開きます。
  • ツイート文をクリックするとツイートをブラウザで開きます。(デフォルトはOFF)
  • ツイート主のユーザIDの表示・非表示切り替え可
  • 棒読みちゃんに読み上げさせることが可能。(デフォルトはOFF)

棒読みちゃんを起動しておけば読み上げが開始します。
棒読みちゃん - ダウンロード(音声合成で日本語文章を読み上げ)

あと、誠に勝手ながら日本圏以外のツイートは弾いてます。

一応、Windowsでしか動きません。

ソースコード

ソースコードGitHubに公開しています。
バイナリ版も置いてあるのでAPIKeyをTwitter Application Management
取得してアプリ内で入力すればすぐに利用できます。

github.com

最後に

StreamingAPI廃止が辛いンゴ…。
寿命が来るまで個人で使います。

C#×WPFでデスクトップマスコットを作ってみた

どんなもの?

そもそも私がこのアプリを作ったきっかけって、メイプルストーリーのメイプルキノコをデスクトップに居座らせたかったからってだけなんですよね。
なのでメイプルキノコがデスクトップでぴょこぴょこ動きます。
あと、それだけでは物足りないので色々便利な機能を付けてみました。右クリックで現れるコンテキストメニューから機能を選べます。

使用したライブラリ

  • CoreTweet.0.8.1.394
  • Newtonsoft.Json.10.0.3
  • WpfAnimatedGif.1.4.16

機能紹介

時計とツイート機能
f:id:gootalife:20180522172829g:plain

タイマー機能
f:id:gootalife:20180522172834g:plain

他にも天気予報の取得や、メモ機能などを搭載しています。

また、マスコットはResourcesフォルダ内にmascot.gifという名前の画像を入れていただくと画像の差し替えができます。

プラグインによる機能追加

IPluginインタフェースを継承したクラスライブラリとその依存関係をPluginsフォルダに入れると機能の追加が自由にできるようになっています。(誰か作って)
ぶっちゃけインタフェース周りは初見だったのでめちゃくちゃ手こずりました。

ソースコード

ソースコードは以下で公開しています。
コメントまみれで逆に見づらいかもですが自分が忘れやすいので...
github.com
キノコの素材は公開すると版権が危うい気がしたので差し替えてあります。
ご自身で画像をご用意ください。

Discordの通知を棒読みちゃんに読み上げてもらおう!~Discord.Netを添えて~

この記事はSLP KBIT Advent Calendar 2017 - Adventarの19日目の記事となります。

いい感じの導入

生粋のゲーマーである私は、「壁を隔てたお友達」と遊ぶ時に
Discordというナウいゲーマー熱いアプリを公開当初から通話に使っています。
そこで通話するとき、聞き専(「リビングゲーマー」、「ママが怖い」等の理由で、
ボイスチャットに声で参加できない人)のチャットを見るために、
ゲーム画面から目を離せないときがあります。そこで棒読みちゃんに読んでもらおうと思いました。
(Discord自体に標準で読み上げ機能はあるけどもゆっくりボイスがいい)
そこで爆誕したDiscordと棒読みちゃんの仲介人である「Yomisen」を紹介したいと思います。

用意したもの

アプローチの手順

  1. Discordにログイン
  2. チャットの通知を受け取る
  3. 棒読みちゃんに指示を送る
  4. ゆっくりしていってね

実は超簡単な棒読みちゃんへの指示出し

棒読みちゃんのサブフォルダ「SampleSrc\IpcClientChannelで読み上げ指示を送る(ローカル専用・.NET専用)\Src\BouyomiChanSample」にあるBouyomiChanClient.csをプロジェクトにそのまま追加します。
これは作者様が開発用に提供してくださっているものです。
BouyomiChanClientクラスを使用すると

var bc = new BouyomiChanClient();
bc.AddTalkTask("読み上げたい内容");
bc.Dispose();

または、

using (var bc = new BouyomiChanClient())
{
    bc.AddTalkTask("読み上げたい内容");
}

のように簡単に棒読みちゃんに読み上げたい内容を送信できます。(棒読みちゃんを事前に起動しておく)
また、using構文はリソース解放の記述をしなくてもブロックを抜けると自動的にリソースを開放してくれます。
なので、下のほうがリソース解放の書き忘れの心配がないので安心できると思います。

ソースコード

概要

  • Program.cs (メイン)
  • DiscordApiHelper.cs (メールアドレスとパスワードでトークンを取得してくれるヘルパークラス)
  • BouyomiChanClient.cs (棒読みちゃんとの接続を簡単にしてくれるクラス)

Program.cs

一部省略

using Discord;
using Discord.WebSocket;
using FNF.Utility;
using System;
using System.Threading.Tasks;

namespace Yomisen
{
    class Program
    {
        static void Main(string[] args) => MainAsync().GetAwaiter().GetResult();

        /// <summary>
        /// 非同期Mainメソッド
        /// </summary>
        static async Task MainAsync()
        {
            // トークンのチェック
            await CheckTokenAsync();
            // ログイン処理
            Console.WriteLine("ログイン中…");
            var client = new DiscordSocketClient();
            await client.LoginAsync(TokenType.User, Properties.Settings.Default.Token);
            await client.StartAsync();
            Console.WriteLine("ログイン完了");
            // 始めのあいさつ(大事)
            var task = Task.Run(() =>
            {
                using (var start = new BouyomiChanClient())
                {
                    start.AddTalkTask("棒読みちゃん起動~!");
                }
            });
            // メッセージ受信時のイベントを追加
            client.MessageReceived += Talk;
            // 各種コマンド
            InputCommand();
            // 終わりのあいさつ(大事)
            task = Task.Run(() =>
            {
                using (var end = new BouyomiChanClient())
                {
                    end.AddTalkTask("棒読みちゃん終了~!");
                }
            });
            Console.WriteLine("キー入力で終了");
            Console.ReadLine();
        }

        /// <summary>
        /// メッセージを受け取った時の処理
        /// </summary>
        static async Task Talk(SocketMessage arg)
        {
            await Task.Run(() =>
            {
                // チャンネル一覧にあるなら
                if (Properties.Settings.Default.TextChannels.IndexOf(arg.Channel.Id.ToString()) >= 0)
                {
                    // 読み上げ
                    using (var bc = new BouyomiChanClient())
                    {
                        bc.AddTalkTask(arg.Content);
                    }
                }
            });
        }

    ~以下省略~

    }
}

メッセージの通知を受信したときのイベントで、棒読みちゃんへの指示を行っています。
受信したメッセージのチャンネルIDが読み上げたいチャンネルIDとして登録されていれば読み上げが行われるようにします。

~省略~
// メッセージ受信時のイベントを追加
client.MessageReceived += Talk;
~省略~

// 読み上げ
static async Task Talk(SocketMessage arg)
{
    await Task.Run(() =>
    {
        // チャンネル一覧にあるなら
        if (Properties.Settings.Default.TextChannels.IndexOf(arg.Channel.Id.ToString()) >= 0)
        {
            // 読み上げ
            using (var bc = new BouyomiChanClient())
            {
                bc.AddTalkTask(arg.Content);
            }
        }
    });
}

Properties.Settings.Default.~~はアプリの設定ファイルで、設定値等を保存しておくことができるものです。
今回は、チャンネルIDの配列を保存しています。
f:id:gootalife:20171212174558p:plain
機能として、コマンド入力によって読み上げたいテキストチャンネルのIDを登録・削除・列挙することができます。
トークンのリセットをした場合は一度終了となり、再度ログイン作業が必要となります。
f:id:gootalife:20171212172653p:plain
テキストチャンネルのIDを調べる方法

  1. 設定>テーマ>開発者モード をオン
  2. テキストチャンネルの名前の上で右クリック
  3. IDをコピー でクリップボードにコピーされる

f:id:gootalife:20171212172943p:plain

> add 012345678901234567

のように18桁のIDを正しく入力することでテキストチャンネルのIDを登録できます。
(適当に登録しても、自身のアカウントの知れる範囲のものでないと通知は来ません)

DiscordApiHelper.cs

Discord.Netではサポートされていないメールアドレスとパスワードによる
トークンの取得を実現するためのヘルパークラスです。

using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Yomisen
{
    public static class DiscordApiHelper
    {
        /// <summary>
        /// EmailとPasswordでトークンを取得します
        /// </summary>
        public static async Task<string> LogInAsync(string mail, string password)
        {
            var baseUrl = "https://discordapp.com/api/";
            var appName = "Yomisen";
            var discordAccount = new { email = mail, password = password };
            var json = JsonConvert.SerializeObject(discordAccount);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var res = await GetClient(appName).PostAsync(new Uri($@"{baseUrl}/auth/login"), content);

            if (res.IsSuccessStatusCode == true)
            {
                var resJson = await res.Content.ReadAsStringAsync();
                var deserializedJson = JsonConvert.DeserializeAnonymousType(resJson, new { token = "" });
                return deserializedJson.token;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// ヘッダーの追加
        /// </summary>
        public static HttpClient GetClient(string appName)
        {
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("User-Agent", appName);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            return client;
        }
    }
}

discordapp.com
このあたりの書式に沿ってヘッダーの編集などをしてJSON形式でトークンを貰います。
このトークンは、
Discord上で「ctrl+shift+i」>Appliacationタブ>Local Storage>https://discordapp.com>token
の値と同値になると思います。
f:id:gootalife:20171212182844p:plain

BouyomiChanClient.cs

特に手を加えてないので省略しますが、中を覗くと
IPCChannelを使って通信しているみたいです。興味のある方は、
棒読みちゃんをDL、または下記の私のGitHubリポジトリから閲覧してみて下さい。

使い方

  1. 棒読みちゃんを起動(音量・速度等はこちらで設定)
  2. Yomisenを起動
  3. Discordのメールアドレスとパスワードを入力(初回・リセット時のみ)
  4. テキストチャンネルIDの登録
  5. ゆっくりしていってね

GitHub

この記事では、ソースコードは一部省略していましたが、以下に公開しています。
github.com

最後に

Botを使わない方針でやってみましたが、うまく動作してくれてよかったです。
棒読みちゃんの扱いが簡単すぎて驚きました。
ユーザー指定機能もできれば追加したいですね。
あと、SkypeはアンインストールしてDiscordを使いましょう。(Discord過激派)

2017/12/20 追記
Win8以上でないと動作しません。

2018/05/22 追記
ユーザ指定機能追加しました

Visual Studio 2017 でビルド後のコマンドを指定する

ビルド後にファイルを指定の位置に移動させる

コマンドの設定画面は、
プロジェクト右クリック→プロパティ→ビルドイベント
から開くことができる。

今回は、ビルド後に、自作のプラグインのクラスライブラリ(.dll)を、
実行ファイル(.exe)が存在するフォルダのサブフォルダ「Plugins」に
自動的に移動させたいと思った。

そこで、以下のように設定した。
f:id:gootalife:20171026021857p:plain
ビルド後に、出力フォルダに移動して「Plugin」フォルダを作成して、
拡張子が.dllのファイルををすべて「Plugin」フォルダ配下に移動している。

これだけでは読み込んでくれない

サブフォルダのdllを参照するときにはconfigファイルにも変更が必要なようだ。
プロジェクトの「~.config」を開いて以下を追記

<configuration>
    <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="Plugins"/>
      </assemblyBinding>
    </runtime>
</configuration>

これでサブフォルダ内の読み込みができるようになる

privatePath="Plugins"

の部分を変更することで読み込みたいフォルダを変更、追加できる。

結果

実行ファイルのあるフォルダがごちゃごちゃしなくてスッキリ!