たくみん成長日記

開発したアプリやプログラミングの備忘録を不定期に上げていきます。

SSの通知は高海千歌ちゃんにしてほしい

はじめに

こんちか!!たくみんです。これは、ラブライブ アドベントカレンダー 24日目(実質初日)の記事です。ほんとは18日にしていたんですけど、時間がなくて記事が書けなかったので24日に移動しました。 adventar.org

この記事では、僕が一番最初に作成したAqours SlackBotのSS通知 高海千歌BOTを紹介します。

SSとは

SS(Short Story)とはいわゆる2次創作の小説のようなものです。

dic.nicovideo.jp

なぜ作ろうと思ったのか

僕はラブライブのSSを読むのが日課になっており、ひどい時には1日中SSをあさっては読むということを繰り返していました。そうなると「新しいSSまとめられてるかな?」→「まだ出てない」→10分後 →「出てるかな」→「出てない」ということが多くなりました。いちいちサイトを確認して更新されているかどうかを確認するのは少々めんどくさいので更新されているかどうか通知する何かを作ればいいのではないかと思うようになりました。そこで、せっかくラブライブのSSを通知するのであればAqoursのキャラのBOTを作ればいいのでは???と思い開発することにしました。

通知する内容

通知する内容は、以下のサイトの内容です。

ss2ch.r401.net

このサイトの赤ワクで囲まれたタイトル(URL)と登場人物などの箇所を取得します。 f:id:takuminv:20191223205532p:plain:w500

ソースコード

Model

Modelは以下の3つになります。タイトルとURLを管理するShortstory、登場人物等のTagを管理するTag、それらの中間テーブルのShortstoryTagの3つです。以前は私のお気に入りの別サイトからSSの情報を取得していました。その時はSS:Tag=1:多の関係だったのでわざわざ中間テーブルを設けています。現在 scrapingしているサイトはTagが1つになってしまったので意味のない中間テーブルになっています(また別サイトから取得することになった時のために残している)。

Shortstory

class Shortstory < ApplicationRecord
  has_many :shortstory_tag
  has_many :tag, through: :shortstory_tag


  accepts_nested_attributes_for :shortstory_tag, allow_destroy: true
  
  validates :title, presence: true
  validates :url, presence: true, uniqueness: true
end

ShortstoryTag

class ShortstoryTag < ApplicationRecord

  belongs_to :shortstory
  belongs_to :tag
end

Tag

class Tag < ApplicationRecord
    has_many :shortstory_tag
  has_many :shortstory, through: :shortstory_tag
  accepts_nested_attributes_for :shortstory_tag
  
  validates :name, presence: true, uniqueness: true
end

rakeTask

このSSBotはRailsのrakeタスクを用いています。DBへの登録などはRailsにお任せしています。

# coding: utf-8
require 'http'
require 'json'
require 'uri'
require 'dotenv'

namespace :shortstory do
  desc "ss_set"
  task :ss_set => :environment do

    # SS情報を取得
    new_ss_count = 0
    Dotenv.load
    doc = ss_scraping(ENV["NOKOGIRI_URL"])
    p doc
    p ENV["NOKOGIRI_URL"]
    15.times do |k|
      ss_title = doc.css(".title")[k].children[1].children[1].text
      ss_url = doc.css(".title")[k].children[1].children[1]["href"]
      ss = Shortstory.new(title: ss_title, url: ss_url)
      tag = doc.css(".words")[k].text
      ss_tag = Tag.new(name: tag)

     # SS情報をDBに登録
      if ss_tag.save
        ss.tag << ss_tag
      else
        ss.tag << Tag.find_by(name: tag)
      end
      if ss.save
       
        # 最初だけセリフ付き
        if (new_ss_count == 0)
          slack_post_text(ENV["SLACK_POST_URL"])
          new_ss_count += 1
        end

        # SlackにPOST
        slack_post(ss,ENV["SLACK_POST_URL"])
      end
    end
  end
end

   # SS情報を取得
   def ss_scraping(url)
    charset = nil
    html = open(url) do |f|
      charset = f.charset
      f.read
    end

    doc = Nokogiri::HTML.parse(html, nil, charset)
    return doc
  end

  # SlackにPOST
  def slack_post(ss,url)
    uri = URI.parse(url)
    fields = []
    ss.tag.each_with_index do |t,k|
      fields[k] = {:title=>t.name}
    end
    payload = {
      attachments: [
        {
          title: ss.title,
          title_link:  ss.url,
          fields: fields,
          color: "#36a64f"
        }
      ]
    }
    Net::HTTP.post_form(uri, { payload: payload.to_json })
  end

  # セリフを言う
  def slack_post_text(url)
     uri = URI.parse(url)
    payload = {
      text: "<@XXXX> ssが更新されたよ~"
    }
    Net::HTTP.post_form(uri, { payload: payload.to_json })
  end

完成したもの

完成したSSBotです。これで安心してSSを読むことができますね。

f:id:takuminv:20191223213524p:plain:w500

おわりに

いつ記事にしようか迷っていたものを記事にできてよかったです。これからもラブライブに関連する何かを作れたらいいなと思います。ではでは。

PS Aqours総SlackBot化計画

僕の野望としてAqours総SlackBot化計画があります。これは「Aqours9人のBotを開発することで実質9人と一緒にいるのと同じではないか」という野望です。今現在、高海千歌Botを含め、3人のBotを開発しています。

桜内梨子Bot

takuminv.hatenablog.jp

黒澤ダイヤBot

takuminv.hatenablog.jp

9人全員のBotを作るのはいつになるのか。