8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Slackで特定のキーワードに反応して自動的にReactionをつけるBotを作った

Last updated at Posted at 2016-11-04

例えばこんな感じでReactionがつきます。チャット内がReactionで賑やかになります。
demo.gif

GitHubで公開中です。
https://github.com/kuluna/OverReaction
使い方や導入方法はGitHubのほうにまとめました。
みんなに使ってもらえるよう英語ドキュメントも泣きながら整備します :cry:

ひとつの文にワードが複数あるとリアクションがバババッと連続でつきます。楽しい!

使用ツール・フレームワーク

  • Visual Studio 2015 コレがないと始まらない(個人差はあります)
  • ASP.NET Core
  • EntityFrameworkCore
  • AngularJS
  • AngularMaterial

小さいアプリだしどうせならと思い.NET Coreに手を出してみました。

ASP.NET CoreではWebAPI機能をメインに使っています。
AngularJSでAPIからReaction設定を読み出し、画面に表示しています。
見た目はカッコよくしたかったのでマテリアルデザインを採用しました。AngularJSならAngularMaterialというライブラリがあるので割と楽に適用できます。

ちなみにフロントはこんな感じで動きます。
addmemo.gif

ここでは.NET Coreをメインに実装方法などを解説します。

ASP.NET Core

ASP.NET Coreのソースを紐解く順番

従来のASP.NETの構成と異なるのでどこからソースを読み始めればいいかわからない人も多いと思います。
私は以下の順番で見ています。

  • project.json または Startup.cs
  • Controllersフォルダ内のxxxController.cs
  • Modelsフォルダ内
  • Viewsフォルダ内の.htmlcs または wwwrootフォルダ内の.html

project.json

プロジェクトに関する情報が書かれています。この中のdependenciesを見るとどういったライブラリが使われているか見ることができます。
Visual StudioのASP.NET Core WebAPIのテンプレートで作成するといくつかライブラリが登録されていますが、それに加えてこの3つをさらに登録しました。

project.json
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.EntityFrameworkCore.Sqlite": "1.0.1",
"Swashbuckle": "6.0.0-beta902"

1つめはhtmlや画像を扱えるようにするためのライブラリです。WebAPIだと不要なのでデフォルトでは入ってないんですね。
2つはみんな大好きEntityFrameworkの.NET Core版です。今回はSQLiteを使いました。
3つめはSwaggerというAPIドキュメントを作成するためのライブラリです。

Startup.cs

ASP.NET Coreからは後から追加したライブラリを使用する宣言をStartup.csに書く必要があります。
Startup.csにはConfigureServicesメソッドとConfigureメソッドがあります。ライブラリを追加していくとAddXXXやUseXXXメソッドが追加されていくのでここで利用を宣言します。

例えばSwaggerを追加するにはAddSwaggerGenメソッドを呼び出します。一部のライブラリはデリゲートで設定を書くこともできます。

Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddOptions();
    services.AddMvc();
    
    services.AddSwaggerGen(setting =>
    {
        var location = Assembly.GetEntryAssembly().Location;
        var xmlPath = location.Replace("dll", "xml");
        setting.IncludeXmlComments(xmlPath);
    });

    services.Configure<AppSetting>(Configuration.GetSection(nameof(AppSetting)));
}

ASP.NET Coreではサービスを追加しただけでは(おそらく)使われません。UseXXXを呼び出すことで実際に使われるようになります。
気を付けなければならないのが__呼び出す順番がある__ものが存在します。例えばUseDefaultFiles()はwwwrootにあるdefault.htmlやindex.htmlをURLのルートで開けるようにするためのメソッドですが、UseStaticFiles()より先に呼び出さないとうまく動作しません。

Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseDefaultFiles(); // 必ずUseStaticFiles()より上!
    app.UseStaticFiles();

    app.UseSwagger();
    app.UseSwaggerUi();

    app.UseMvc(); // 常に一番下!
}

Controllers

ASP.NET Coreではサーバーサイドの処理はControllersフォルダにあります。
クラス名にRouteアノテーションがついていますが、こうすることによってapi/コントローラ名でアクセスできます。ReactionsControllerの場合はapi/reactionsになります。

ReactionsController.cs
[Route("api/[controller]")]
public class ReactionsController : Controller
{
    public ReactionsController()
    {
        using (var db = new ReactionContext())
        {
            db.Initialize();
        }
    }

    [HttpGet]
    public List<Reaction> GetAll()
    {
        using (var db = new ReactionContext())
        {
            return db.Reactions.ToList();
        }
    }
    .
    .
    .

あとはASP.NET WebAPI2とほぼ同じです。ここを見ればアプリがだいたい何をやっているかがわかります。

EntityFrameworkCore

噂ではEntityFramework6より速いとか。書き方はほぼ同じですね。
自動マイグレーションがまだ機能不足なところがあります。Core版ではテーブルの自動生成はありますが、自動マイグレはまだありません。なのでControllerから毎回実行されるようにInitialize()を独自で追加しています。

Reaction.cs
public class Reaction
{
    /// <summary>
    /// ID(登録順連番)
    /// </summary>
    [Key]
    public int Id { get; set; }
    /// <summary>
    /// 検索ワード
    /// </summary>
    [Required]
    public string Word { get; set; }
    /// <summary>
    /// 絵文字
    /// </summary>
    [Required]
    public string Emoji { get; set; }
}

/// <summary>
/// データベースコンテキスト
/// </summary>
public class ReactionContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionString = new SqliteConnectionStringBuilder { DataSource = "overreaction.sqlite" }.ToString();
        optionsBuilder.UseSqlite(connectionString);
    }

    /// <summary>
    /// Slack Reaction データベース
    /// </summary>
    public DbSet<Reaction> Reactions { get; set; }

    /// <summary>
    /// データベースにテーブルがなければ作成し、カラムに変更があればマイグレーションを実行します。変更がない場合は何もしません。
    /// </summary>
    public void Initialize()
    {
        // Database initialize
        Database.Migrate();
    }
}

Azure WebAppにデプロイ

appsettings.jsonを設定すればこのソースをそのままAzure WebAppに投げると動きます。Azureの中の妖精さん(Kudu)がASP.NET Core用に自動でデプロイしてくれるようです。

そしてAzureADとの連携も

AzureADとの絡みについては ASP.NET Advent Calendar 2016に書こうと思います。

所感

  • ASP.NETの雰囲気を残しながらもこれでクロスプラットフォームで動くとかすごい
  • UseXXXの並びは割と罠だと思う
  • Azureはいいぞ
8
6
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
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?