3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

5kg太ったのでイケメンがダイエットを応援してくれるLine bot作ろうとしてた話

クソアプリ Advent Calendar 2019がバズってるのを見て、約2年前に作ろうとしたクソ設計☆クソアプリを思い出した。。。

どんなアプリ

イケメン(仮)に「目標体重」と「今日の体重」を教えて、その差分から罵倒されたり褒められたりするLineBot。


(実際の体重ではございません)

2年前の私

ワイ 「おもちもおせちも美味しい。みかんも食べ放題。幸せだ...」
(久々に体重計乗る)
ワイ 「うわ!5kg太った!!!!!!(泣)」
ワイ 「痩せなきゃ。どうすればいいんだ。イケメンに叱られたら痩せるのに。」
ワイ 「....」
ワイ 「そうか、罵倒してくれるイケメンおらんかったら作ればいいのか(脳死)」

使ってた技術

  • Messaging API (LINE)
  • ruby on rails 5.2.3
  • Heroku

おそらく参考にしてた記事

今の私

とりあえず、Line Bot自体はみつからなかったから、コードだけよんでみよう...
ん?なんだこれは.....
クソアプリ以前にクソ設計じゃん!!!!(大声)

【クソポイント 1】 私の目標体重はいずこへ...

とりあえず、データの構造を見てみよう...
ん...? app/modelsの中に何も書いてない。もちろんdbの中にも何もない...

私の目標体重はいずこへ...

クラス変数に格納されてた。

このアプリでは、linebot_controller.rbにしかほとんんどコードが書いておらず、そこに全ての処理が書いてあった。

linebot_controller.rb
class LinebotController < ApplicationController
  require "line/bot"  # gem "line-bot-api"

  # callbackアクションのCSRFトークン認証を無効
  protect_from_forgery :except => [:callback]

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_ACCESS_TOKEN"]
    }
  end

  def callback
    body = request.body.read
    signature = request.env["HTTP_X_LINE_SIGNATURE"]
    unless client.validate_signature(body, signature)
      error 400 do "Bad Request" end
    end

    events = client.parse_events_from(body)

    ・・・

    events.each { |event|
      case event
      when Line::Bot::Event::Message
        case event.type
        when Line::Bot::Event::MessageType::Text

          if event.message["text"].match(/設定/)
            if t = event.message["text"].match(/([1-9][0-9]{0,2}|0)(\.[0-9])?/)
              @@targetWeight =  t[0].to_f
              ・・・
            end
          elsif ・・・
           ・・・
          end
          client.reply_message(event["replyToken"], message)
        end
      end
    }
  end
end

うん、つっこみどころ満載。

Messaging APIのリクエストボディでは、destination(ボットのユーザーID)とevents(ユーザーが発火)が格納されており、eventsの中は下記のようなjsonオブジェクトになってます。

{
  "replyToken": "",
  "type": "message",
  "mode": "active",
  "timestamp": 1462629479859,
  "source": {
    "type": "user",
    "userId": "..."
  },
  "message": {
    "id": "325708",
    "type": "text",
    "text": "目標体重を50kgに設定して"
  }
}

ユーザーを識別することは非常に簡単そう。

それなのにユーザーごとのデータを管理せずにクラス変数で目標体重を管理している。
つまり、この目標体重は全ユーザー共通で書き換え自由な状態になっていたのだ。
自分の目標体重、丸わかり。。。。

あれかな。みんなのイケメン(仮)になるのが嫌だったのかな。

【クソポイント 2】 性癖.yml

DBがないけどイケメンはセリフを返す。
しかも、目標体重に近づけば優しくなる。
これはどうゆう仕組みなんだろ...と探っていったら...

性癖.yml
※ これ以上はお見せできません

イケメン(仮)に言われたいセリフがみっちり書いてある性癖.ymlが発掘されました。
全部自分で羅列してったのか...痛いぞ、自分。

また、yamlも絶妙に読みづらい。
入れ子になった配列がずらーーーっとならんでおり、voice["message"][差分][乱数]で取ってくるって感じ。
配列にする必要なかった部分まで配列...

linebot_controller.rb
# ymlファイル読み込み
voice = YAML.load_file("#{Rails.root}/config/project.yml")

# diffは目標体重と現在の体重の差分
message_length = voice["message"][diff].length - 1
diet_message = voice["message"][diff][rand(message_length)]

message = {
  type: "text",
  text: "今日の体重は#{weight}kgで、目標体重の#{@@target}まであと#{sprintf("%.1f", diff)}kg減か!#{diet_message}"
}

【クソポイント 3】
ワイ『今日は23歳の誕生日!50kgだったよ!』
イケメン(仮)『今日の体重は23kg』

messageに数字があったら、必ず最初に出てくる数字を体重だと扱う処理がかいてあるため、イケメン(仮)と円滑な会話が全くできない仕様。
書き方もつっこみどころ満載...

if myWeight = event.message["text"].match(/([1-9][0-9]{0,2}|0)(\.[0-9])?/)
  myWeight = myWeight[0].to_f #やばい
 # 果てしなく痛い処理の連続
end

実際のところ

Q. このbotをつかいましたか?
A. 使ってないです。性癖.ymlを書いてる時に目が覚めました。

Q. 痩せました?
A. 全くもって痩せなかったです。

さいごに

しょうもない記事を最後まで読んでくださり、ありがとうございます。
いつもは結構真面目に記事を書いてるので、よかったら読んでください。

ちなみに、ダイエットに一番効力あったのは、好きな人に言われた「肉団子」のひとこと。
痩せたい。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
3
Help us understand the problem. What are the problem?