nasne で観てるアニメが百合だと思ったときに押すボタン

  • 17
    いいね
  • 0
    コメント

はやりのやつ

動作

なにしてるのか

  1. Amazon Dash Button のボタン押下をキャッチする
  2. nasne API 叩いて今流してるアニメのタイトルを取得する
  3. コマンド叩いて twitter に投稿する

1. Amazon Dash Button のイベントキャッチ

Ruby が慣れてるので dashed で書いたけど、なぜか find_dash が動かなかったので MAC アドレス取得だけ dash-button でやった。世の中には node.js 上で動くライブラリのほうが溢れてるっぽいので Javascript 苦手じゃない人はそっち使えばいいと思う。

2. nasne API 叩く

http://tateren.hateblo.jp/entry/2016/03/03/005415
http://pocketstudio.jp/log3/2014/12/07/nasune_api/

上記の記事を参考に色々試した結果、今 nasne で再生してるタイトルは以下の API で取れた。(もしかしたらもっと簡易なやり方あるかもしんないけど仕様がよくわからん)

最初に投げるリクエスト

$ curl -s 'http://<nasne_IP>:64210/status/dtcpipClientListGet'

録画/TV 再生で返ってくる JSON が異なるのでまずこれで判定する


録画を再生してるとき

{
  "errorcode": 0,
  "number": 1,
  "client": [
    {
      "id": 21600,
      "macAddr": "FC:0F:E6:51:67:04",
      "ipAddr": "192.168.0.101",
      "name": "PLAYSTATION 3",
      "purpose": 2,
      "content": { 
        "id": "14809556870000001262"
      },
      "encryptType": 1
    }
  ]
}

TV をそのまま再生してるとき

{
  "errorcode": 0,
  "number": 1,
  "client": [
    {
      "id": 21601,
      "macAddr": "FC:0F:E6:51:67:04",
      "ipAddr": "192.168.0.101",
      "name": "PLAYSTATION 3",
      "purpose": 1,
      "liveInfo": { 
        "broadcastingType": 2,
        "serviceId": 23608
      },
      "encryptType": 1
    }
  ]
}

録画した動画を再生してるとき

さっきの JSON の ["client"][0]["content"]["id"] が録画 ID なので、この ID に対応した録画情報を引っ張ってくると再生中のタイトルが取れる。

$ curl -s 'http://<nasne_IP>:64220/recorded/titleListGet?searchCriteria=0&filter=0&startingIndex=0&requestedCount=0&sortCriteria=0&id=<録画ID>'
ここだけポートが 64220 になってるのは typo じゃないです

{
  "errorcode": 0,
  "item": [
    {
      "id": "14809556870000001262",
      "title": "灼熱の卓球娘「第十球 わたしの卓球」",
      "description": "いよいよ両校の大将戦、こよりとくるりとの勝負が始まった。必殺のカーブドライブを繰り出すくるり。そしてこよりはくるりに、全力の“ドキドキ”で応えようとしていた。",
      "startDateTime": "2016-12-06T01:34:47+09:00",
      "duration": 1818,
      "conditionId": "w2",
      "quality": 100,
      "channelName": "テレビ東京1",
(...)

TV をそのまま再生してるとき

TV をそのまま再生してるときは、タイトル取るのに networkId, streamId, serviceId の組が必要っぽいのでまずそれを取得する。

$ curl -s "http://<nasne_IP>:64210/status/boxStatusListGet"

{
  "errorcode": 0,
  "powerStatus": {
    "status": 2
  },
  "tuningStatus": {
    "status": 2,
    "networkId": 32391,
    "transportStreamId": 32391,
    "serviceId": 23608
  },
(...)

で、ほしい ID が手に入ったらそれを使ってもっかい API 叩くとタイトルが取れる。

$ curl -s "http://<nasne_IP>:64210/status/channelInfoGet2?networkId=<NetworkId>&transportStreamId=<TransportStreamId>&serviceId=<ServiceId>"

{
  "errorcode": 0,
  "channel": {
    "broadcastingType": 2,
    "networkId": 32391,
    "transportStreamId": 32391,
    "serviceId": 23608,
    "networkName": "東京7",
    "remoteControlKeyId": 9,
    "tsName": "TOKYO MX",
    "EITFlag": 1,
    "EITScheduleFlag": 1,
    "EITPresentFollowingFlag": 1,
    "freeCAMode": 0,
    "channelNumber": 91,
    "branchNumber": 1,
    "service": {
      "serviceType": 1,
      "serviceProviderName": "",
      "serviceName": "TOKYO MX1"
    },
    "freqChannelNo": "16",
    "eventValidityFlag": 1,
    "eventId": 59786,
    "title": "人生酒場~唄は夜につれママにつれ~",
    "startDateTime": "2016-12-09T01:00:00+09:00",
(...)

3. コマンド叩いて twitter に投稿する

というわけでタイトル取れたらそれ使って twitter に投げるだけ。好きなやり方で post すればいいと思うけど、今回ネットワークインターフェース監視する関係で root で動かさなきゃいけないんだけど twitter って post するのに認証どうにかしなきゃいけなくて何もかもめんどくさくなって、以下では既に tw コマンドが動くユーザに sudo して直接コマンド叩くという極めて雑なことしている。

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'dashed'
require 'json'
require 'net/http'

MAC_ADDR = 'xx:xx:xx:xx:xx:xx'
IFACE = 'Amazon Dash Button のパケットを受け取るネットワークインターフェース'
NASNE_IP = 'xxx.xxx.xxx.xxx'
SHOUT = '百合じゃん!!!!!!!'
FOOTER = '* 百合だと思ったときに押すボタン *'

def tw(message)
  cmd = "sudo -u kishitani /home/kishitani/.gem/ruby/2.3.0/bin/tw --user=dkishitani --yes \'#{message}\'"
  puts "execute: " + cmd
  system cmd
end

def rest(path, port)
  return JSON.load(Net::HTTP.get(NASNE_IP, path, port))
end

puts 'waiting...'

Dashed::Button.new(MAC_ADDR, IFACE).on_press do
  current = rest('/status/dtcpipClientListGet', 64210)["client"][0]
  if current.key? "content"
    id = current["content"]["id"]
    title = rest("/recorded/titleListGet?searchCriteria=0&filter=0&startingIndex=0&requestedCount=0&sortCriteria=0&id=#{id}", 64220)["item"][0]["title"]
  else
    ids = rest('/status/boxStatusListGet', 64210)["tuningStatus"]
    networkId = ids['networkId']
    transportStreamId = ids['transportStreamId']
    serviceId = ids['serviceId']
    title = rest("/status/channelInfoGet2?networkId=#{networkId}&transportStreamId=#{transportStreamId}&serviceId=#{serviceId}", 64210)["channel"]["title"]
  end
  tw "「#{title}#{SHOUT} #{FOOTER}"
end

おわりに

本当はタイトル情報だけじゃなくて画面も一緒に投稿できるととてもわかりやすく有用なんだけど、Amazon Dash Button 押してから反応するまで数秒ラグがあるのでアニメだと使えないし、よしんば流行りを諦めて USB とかのボタン買ってきてラグらないようにしたとしても余計なものが映らないよう気をつけてカメラ置くのめんどくさいし、だからといって PS3 と TV の間に HDMI キャプチャボード噛ませるとかは準備大変だし…。