あいつの日誌β

働きながら旅しています。

How to get the real URL behind a shortened URL using cURL and axios

こういうのを Node.js でやりたい時は

$ curl -sLI http://shortened_url | grep -i Location

axios の get に以下のようなオプションを渡してあげるとよい

const axios = require('axios')

async function main () {
  const res = await axios.get('https://t.co/q0wn9eZvvY', {
    maxRedirects: 0,
    validateStatus: null
  })  
  console.log(res.headers.location)
}

main()

TypeORM で本番環境にデプロイしたら自動的に migration させる方法

あらすじ

typeORM で新規サービスを始めるときに、そういえば TypeORM の migration ってどうするんだっけ?ってなったので調べました。

環境

mysql --version
mysql  Ver 8.0.18 for osx10.15 on x86_64 (Homebrew)

% node -v
v12.13.0

% typeorm -v
0.2.22

雛形を作成

mkdir practice-typeorm-migration && cd $_
typeorm init --database mysql

この時点ではまだ node_modules に必要なモジュールがインストールされていないのでインストールします

yarn install

既にDBに接続する方法が ormconfig.json に記述されているのでそれを活用します。mysql に接続用のユーザー test が存在しない場合は以下のようにして作成してください。

mysql> create user 'test'@'localhost' IDENTIFIED WITH password BY 'test';
mysql> grant all on *.* to 'test'@'localhost' with grant option;
mysql> flush privileges;

なお、Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client というエラーメッセージが表示された場合は MySQL 8.0からパスワードの認証形式が変更され、ライブラリ側で互換対応がされていない ため、以下のように古いパスワード認証を利用します。

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

typeorm で本番運用を考える

おそらく以下のようにするのが無難だと思われるのでこの作法を模倣する

https://qiita.com/jnst/items/9a4c1a9f15b165e0e420 https://medium.com/better-programming/typeorm-migrations-explained-fdb4f27cb1b3

ormconfig の設定で synchronize: false にする

以下のように ormconfig.json を修正します。

{
   "type": "mysql",
   "host": "localhost",
   "port": 3306,
   "username": "test",
   "password": "test",
   "database": "test",
+   "synchronize": false,
-   "synchronize": true,
   "logging": false,
   "entities": [
      "src/entity/**/*.ts"
   ],
   "migrations": [
      "src/migration/**/*.ts"
   ],
   "subscribers": [
      "src/subscriber/**/*.ts"
   ],
   "cli": {
      "entitiesDir": "src/entity",
      "migrationsDir": "src/migration",
      "subscribersDir": "src/subscriber"
   }
}

この状態で ts-node src/index.ts を実行すると users テーブルがまだ生成されていないためエラーが発生します。Entity と synchronize させていると開発初期には便利ですが、運用を考えると synchronize は false の方が良いと思います。

続いてこの Entity の migration ファイルを作成します。

% ts-node ./node_modules/.bin/typeorm migration:generate -n InitialSchema

migration を実行します。

ts-node ./node_modules/.bin/typeorm migration:run

もう一度以下のコマンドが実行して動作することを確認してください。

ts-node src/index.ts

ormconfig の設定で migrationsRun: true にする

続いて ormconfig.json に migrationsRun を追加します。

{
   "type": "mysql",
   "host": "localhost",
   "port": 3306,
   "username": "test",
   "password": "test",
   "database": "test",
   "synchronize": false,
+   "migrationsRun": true,
   "logging": false,
   "entities": [
      "src/entity/**/*.ts"
   ],
   "migrations": [
      "src/migration/**/*.ts"
   ],
   "subscribers": [
      "src/subscriber/**/*.ts"
   ],
   "cli": {
      "entitiesDir": "src/entity",
      "migrationsDir": "src/migration",
      "subscribersDir": "src/subscriber"
   }
}

この設定で node-ts src/index.ts を実行してみます。migration が全て実行されている状態だと思いますので特に DB に変化は起きないと思います。一度 revert してみます。

ts-node ./node_modules/.bin/typeorm migration:revert

revert が成功したら user TABLE が削除されていると思いますがもう一度以下のコマンドを実行してください。Node プロセスが起動するたびに DB への migration が行われるようになりました。

% ts-node src/index.ts
Inserting a new user into the database...
Saved a new user with id: 1
Loading users from the database...
Loaded users:  [ User { id: 1, firstName: 'Timber', lastName: 'Saw', age: 25 } ]
Here you can setup and run express/koa/any other framework.

まとめ

TypeORM が使われているプロジェクトで本番環境での migration をどのようにするべきかを考察しました。DB schema に変更があった場合、ソースコードからプロセスを起動した瞬間に migration が実行されるので本番へのデプロイが容易に行えると思います。

開発環境と本願環境で ormconfig.json を切り替えたり、そういった作法も必要なのかもしれませんが、それらに関する考察はきっと後世のエンジニアがもっと良い記事を書いてくれると思います。

こちらからは以上です。

DynamoDB と Lambda を local で動作させるチュートリアル

久しぶりに DynamoDB の案件がやってきたので素振りをしようと思ったらすっかりやり方が分からなくなっているのでメモを残しました。

なお、私のシステム環境は以下の通りです。

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.2
BuildVersion:   19C57

% java -version
java version "13.0.2" 2020-01-14
Java(TM) SE Runtime Environment (build 13.0.2+8)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)

% node -v
v12.13.1

% sls -v
Framework Core: 1.61.2
Plugin: 3.2.7
SDK: 2.2.1
Components Core: 1.1.2
Components CLI: 1.4.0

% aws --version
aws-cli/1.17.5 Python/2.7.16 Darwin/19.2.0 botocore/1.14.

awscli は dynamodb に直接クエリを発行して動作確認したいだけなので、必ずしも必要というわけではないです。serverless cli はこのチュートリアルにおいては必ず必要です。

プロジェクトの雛形を作成する

sls create --template aws-nodejs --path dynamodb-local-tutorial && cd $_
yarn init -y
mkdir seeds
touch seeds/articles.json

DynamoDB を offline で動作できるようにする

yarn add -D aws-sdk serverless-offline serverless-dynamodb-local
serverless dynamodb install

テストデータを用意

`seeds/articles.json` に以下の様にテストデータとなる JSON を用意しておきます。

[
{
  "id": "1",
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "description": "quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto",
  "isFavorite": false
},
{
  "id": "2",
  "title": "qui est esse",
  "description": "est rerum tempore vitae sequi sint nihil reprehenderit dolor beatae ea dolores neque fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis qui aperiam non debitis possimus qui neque nisi nulla",
  "isFavorite": true
}
]

serverless.yml を修正

service: aws-nodejs-rest-dynamodb

plugins:
  - serverless-dynamodb-local
  - serverless-offline

custom:
  dynamodb:
    stages:
      - ${self:provider.stage}
    start:
      port: 8000
      inMemory: true
      migrate: true
      seed: true
    seed:
      development:
        sources:
          - table: articles
            sources: [./seeds/articles.json]

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1
  environment:
    DYNAMODB_TABLE: articles
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"

resources:
  Resources:
    ArticlesTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: articles
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

この状態で sls dynamodb start を実行すると local で動作するようになります。

ここまでの動作確認

awscli を使って動作確認をします。

% aws dynamodb list-tables --endpoint-url http://localhost:8000
% aws dynamodb scan --table-name hotels --endpoint-url http://localhost:8000

Lambda 経由で動作させる

今度は Lamdba を動作させます。

yarn add aws-sdk express serverless-http

serverless.yml を少し修正します。

+
+functions:
+  app:
+    handler: handler.main
+    events:
+      - http:
+          method: ANY
+          path: '/'
+          cors: true
+      - http:
+          method: ANY
+          path: '{proxy+}'
+          cors: true

serverless offline を実行してから以下のコマンドの動作確認をします。

BASE_URL="http://localhost:3000"
curl -s -X GET "${BASE_URL}/api/articles"
curl -s -X GET "${BASE_URL}/api/articles/1" | jq .
curl -s -X PUT "${BASE_URL}/api/articles/1/favorite"
curl -s -X GET "${BASE_URL}/api/articles/1" | jq .article.isFavorite
curl -s -X PUT "${BASE_URL}/api/articles/1/unfavorite"
curl -s -X GET "${BASE_URL}/api/articles/1" | jq .article.isFavorite

まとめ

というわけで 8000 port で DyanamoDB を、3000 port で Lamdba を実行できました。あとは sls deploy して本番に公開したり、 sls remove したりすると良いでしょう。

こちらからは以上です。

年末始の休暇を利用して2週間で台北・ホーチミン・バンコク・シンガポールを周遊してきた

f:id:okamuuu:20191231200709j:plain

というわけでいつもの様に働きながら旅をしました。天気に恵まれてほとんど雨が降らない、恵まれた旅でした。最近は海外でノマドしたいと思っているので、実際に現地に訪れて自分の肌に合うのかを試してみたいと思っていました。そういうわけで年末年始のタイミングを利用することにしました。

旅費

Date place hotel price
12/24-12/26 Taipei Meander 1948 Hostel 2泊 6288 yen
12/26-12/29 Ho Chi Minh Sky Gem Central Hotel 3泊 20253 yen
12/29-1/3 Bankok Marwin Villa 5泊 46462 yen
1/3-1/5 Singapore M Social Singapore 2泊 31044 yen
1/5-1/7 Taipei Star Hostel Taipei Main Station 2泊 4980 yen

宿泊施設は合計で 11万円ぐらいです

airline from to price
Peach 12/24 12:40 NRT Terminal3 12/24 16:05 TPE Terminal1 25050 yen
Vietjet 12/26 19:00 TPE Terminal1 12/26 21:25 SGN 11380 yen
Vietjet 12/29 11:30 SGN Terminal2 12/29 13:00 BKK 8620 yen
Scoot 1/3 11:40 BKK 1/3 15:25 SIG 11050 yen
Scoot 1/5 12:20 SIN Terminal 1 1/5 17:05 TPE Terminal 1 13924 yen
Peach 1/7 12:00 TPE Terminal 1 1/7 16:05 NRT Terminal 3 20280 yen

飛行機代が大体9万円ぐらい

宿泊費 宿泊費 合計
109033 yen 90304 yen 199337 yen

合計で大体20万円でした。

それから各国で2万円程度両替をしています。ほぼほぼクレジットカードが使えるので現金を用意する必要はそこまでないのですが、以下の場面ではどうしても現金がいるなあと思いました。

とういわけでたぶんなんだかんだで30万円ぐらい財布から出て行ったんだと思います。

便利だったWEBサイトとアプリ

  • Google Flight
  • Agoda
  • GigSky
  • Grab
  • Tinder
  • WeChat
  • Currency
  • Kindle

Google Flight

格安の航空チケットを調べるときに使いました。Skyticket よりも私は Google Flight の方が使いやすい気がするのですが、チケットを安く取れる日付を調べる事ができるんでしたらどんなサイトでも良いと思います。

Agoda

Expedia と booking.com と Agoda を比較した場合、Agoda が割引となっているケースが多く見受けられたので私は最近 Agoda を重宝しています。あくまで個人の感想なので、本当に一番安いかどうか、分かりません。もしかしたら直接ホテルのサイトから申込したほうが安いのかもしれませんが、同じ UI で予約、問合せができる、というプラットフォームのメリットが大きいので私は Agoda を愛用しています。

GigSky ギクスカイ

私は現在 iPhone 11 Pro を使っているのですが、これには eSIM と呼ばれる機能があります。読んで字の如くで私は成田で飛行機を待っている間にオンライン決済をしました。App Store からアプリをダウンロードして、カード番号を入力すればすぐに使えるようになります。

最初に購入したのは15日プラン 2GB 3600円でしたが旅の折り返しとなる一週間手前で足りなくなってしまったので買い足しました。どうしても初めての土地では Google Map を多用してしまいました。

といわけで私が言うには初めての土地を1週間程度訪問する場合は 2GB だと足りなくなる可能性があります(Google Map の他にもネットサーフィンして近所のお店を検索したりして意外と消耗する)

Grab

今回の旅ではタクシーの利用は全て配車アプリを使用しました。理由は単純に「知らない土地でぼったくりにあって精神的に消耗したくないから」です。体験としては勉強になるかもしれませんが、すでに回避する方法があるので使わない理由はないです。

ちなみに日本でアプリをインストールした後、クレジットカードを登録しようとしても、日本では登録できません。Grab が使える国に移動すれば登録できます。

そしてアジアでは Grab の位置情報はとても正確でした。高いビルが少ないとここまで位置が正確にわかるんだなあ、と思いました。

Tinder

私は普段マッチングアプリは使ったことがないのですが、現地の人とカジュアルに話がしたかったので試してみました。会話が続いた人たちは、ごくわずかでしたがが現地の情報を教えてもらえたりしてとても楽しかったです。そして意外と英語の勉強になったので海外でマッチングアプリを使うのは面白いなと思いました。

WeChat

台湾では会話が始まった人が意外と多かったのですが、WeChat を使いたがる人がとても多かったです。これは単純に WeChat の翻訳機能が強力らしく、中国語と英語の変換が簡単らしいです。

残念ながら私は WeChat をインストールしてなかったのでかなりの人たちと会話を続けることができませんでした。もし WeChat があれば、彼女たちは中国語、私は英語で会話すれば、彼女たちは普段慣れた文字入力をしながら翻訳ツールによって意思の疎通も容易なので、私のような日本人との会話でもストレスがないはずです。リアルタイムでなければ我々はもう世界中の人たちと簡単にコミュニケーションとれちゃうなあと思いました。

Currency

各国の通貨を比較することができるアプリです。今回日本円をそこまで持っていかなかったので各国で2万円程度両替するのではなくクレジットカードのキャッシング機能を使いました。空港の ATM では現地の通貨でいくらキャッシングするのか?という表示がでるのでいくら借りればいいのか一瞬迷ってしまいますが、こういうアプリがあると大変便利です。

ちなみに10000円は2020年1月だと各国の通貨はこれぐらいの価値です。これに加えて各国で物価が異なりますので適切な値段かどうかは状況によると思います。

10000
2742 ニュー台湾ドル
2124342 ドン
2773 バーツ
123 シンガポールドル

kindle

別にこれを皆様に紹介する必要はないのですが、たぶん私はこの記事を次回の旅に行く前に読み返すので未来の自分に向けて書いておきました。私はよく旅行に行くので、その時に飛行機の中で読む為に割とカジュアルに書籍を購入してストックしています。なんですが読みたい本は、ちゃんとダウンロードしておきましょう

LCCについて

今回 Peach, Vietjet Air, Scoot を利用しました。Scoot に関しては全く不満はありませんでした。Peach はまあ LCC なのでどちらを選ぶかは好みの問題だと思います。Vietjet Air は昼の便が夕方に変更されてしまいました。まあこういうものだと認識しておいて利用しないとだめだな、と思いました。

Peach に関しては成田 -> 台北へ出発した際に出発の時間が遅れていたのですが一切アナウンスがなかったのでいつまで待てばいいのかなーと思っていました。あとは台北 -> 成田の時に着陸した場所がかなりターミナルから遠くて、バスに乗り継いでから降りるまでかなり時間がかかりました。まあ成田空港は工事が多いのである意味仕方がないかもしれません。

Vietjet Air に関しては旅慣れた人たちに聞いても「普通便の時間が変更されることはない」という事だったので結構珍しいオペレーションだと思います。ネットを見ると「何度も変更された」などの口コミもあったのでこれはもう仕方がないのかも。なので Vietjet に乗る人たちがいらっしゃったらそういう事も起こり得るのでスケジュールが厳密に決まっている人はご注意ください。

ベトナムホーチミンの思い出

f:id:okamuuu:20191227120300j:plain

初めてのベトナム旅行でホーチミンを訪れました。本当はダナンに行きたかったのですが、ダナンは年末年始は雨季の時期らしいのでホーチミンに変更しました。泊まったホテルはスカイ ジェム セントラル ホテル (Sky Gem Central Hotel)というところです。レタントン通りという日本人街の近くにあって、そこには徒歩でも訪れることができます。

初めての土地だったのでなんとなく日本人街の近くでホテルがいっぱいある場所を選んだのですが、この日本人街はどちらかというとたぶん昭和の歌舞伎町のような雰囲気です。危険ではないのですが、欲望を満たす路地裏と表現すればいいのか、そんな感じの場所です。昔の日本もこうだったんだろうなあと思いながら散策しました。

それからブイビエン通りに行きたかったのですが、私は旅行前に足を少し怪我していたので今回の旅では断念しました。代わりにホテルの隣にあるマッサージ屋さんで2時間ほどマッサージを受けました。合計で5000円ぐらいかな?随分安いなあと思いました。こちらはちょっと高い値段のお店らしく、その為かスタッフは英語が割と通じました。

それから Tinder で現地の人に Godmother Bake & Brunch というカフェを教えてもらいました。こちらは土曜日に訪れたのでかなり人が多かったのですが、若い人たちがたくさんいる人気店でした。カフェ好きの人はチェックしてみると良いと思います。

洗濯物はホテルでもお願いできるのですが Laundry 75 / Bao Chau Laundry という場所を利用しました。かなり安いですが品質は問題ないのでここはおすすめです。

あとなぜかホテルの WifiスマートフォンかPCか、どちらかとしか接続できない現象が発生してちょっと困りました。あれは一体なんだったんだろう。

f:id:okamuuu:20191227191845j:plain

あとベトナムはごはんが思った以上に美味しかったです。

タイ・バンコクの思い出

f:id:okamuuu:20191230224846j:plain

バンコクでは年越しのときに花火を打ち上げる、という話を聞き、なんとなくバンコクで年越しをすることにしました。バンコクは思った以上に発達しており、ネットもかなり安定していたので作業しやすかったです。物価も安く、ごはんもおいしかったので花粉の時期の避難所としてとても良いと思います。

マルウィン ヴィラという割とお手頃の価格のホテルに泊まりました。年末年始での利用だったので少し高にはなりましたが値段に大して十分な設備でした。立地も優れていてセントラルパークという一番賑やかと思われる場所まで少し歩きますが、それでも徒歩で訪れる事ができるので観光には便利な場所だと思います。不満があるとすればシャワーの水圧が弱い、ということです。でもこれはこのホテルに限らずですが。

私が最も気に入った場所は HoBs The Playhouse という音楽を聞きながらお酒が飲める BAR です。年末の時期だったというのもあると思いますがバンドによる生演奏を楽しみながら飲むお酒は美味しかったです。

このホテルから歩いて行ける場所に Talad Neon という夜市の場所があって、ここはかなり快適でした、十分な広さにほどよい人数の現地の人、観光客が訪れていて、穏やかな雰囲気の中食事を楽しみました。

f:id:okamuuu:20191230125331j:plain

Tシャツがかなり安かったので買い足しました。1枚90バーツ(300円ぐらい)です。orky っていうタイを紹介しているブロガーさんがおすすめしていたTシャツをプラチナム ファッションモールの4Fで買いました。旅先で着るには十分のクオリティだと思います。バンコクに住んだら生活費かからないきがするなあ。

シンガポールの思い出

f:id:okamuuu:20200103162255j:plain

宿泊したのは M ソーシャル シンガポール というホテルです。ここはクラークキーと呼ばれるお酒が楽しめる場所の近くで、夕暮れ時に川沿を散歩してフォトジェニックな風景を堪能しました。クラークキーではバンコクと同様に生演奏を聞きながらお酒を飲んで、素敵な空間を満喫しました。

f:id:okamuuu:20200103203352j:plain

クラークキー周辺は少しお酒が高いですが、川を挟んだ向こう側に Brewerkz というクラフトビールが楽しめるお店があり、こちらはお値段がお手頃でおすすめです。

あとチャンギ空港では手荷物検査が各ゲートの前で行われます。トランジットなどで世界中のHUBとなる設計がされているんだな、と思いました。そしてホテルから空港まで Grab を使って移動したのですが20分弱で20シンガポールドル(1600円程度)でした。かなり安いし MTR を乗り継ぐよりも速いので空港まで車を使った方が良いと思います。

意外と食べ物や交通手段の物価は高くなかったのと、お酒も場所によってはそこまで高くなかったです。住居に関しては値段が高めなのですが、シンガポールに移住するのもありかもしれない、と思いました。

台湾の思い出

f:id:okamuuu:20200106143511j:plain

台北には何度か訪れていて、私のお気に入りの国です。たぶん今年の春も花粉症から逃れる為に台北に行こうと思います。宿泊したホテルはスター ホステル 台北駅 (Star Hostel Taipei Main Station)とミアンダー 1948 ホステル タイペイ メイン ステーション (Meander 1948 Hostel - Taipei Main Station) です。

この二つは距離も違いのでどちらかに泊まった事がある人でしたらたぶん両方のホテルに迷わずにたどりつけると思います。比較するとユーザー体験として面白いのは Star Hostel で、設備が綺麗なのはミアンダーだと思います。スターホステルは夜クラフトビールを販売してたりするので個人的にはそっちが好きです。でもどちらも素敵なホステルなので是非とも両方試してみてください。

ちなみにミアンダーのスタッフに教えてもらった 軍火庫精醸啤酒専門店 BeerAmmo Craft Beer と 西門街の Guru House というハンバーガーとクラフトビールのお店が良かったです。

まとめ

というわけで海外でノマド生活をするための下調べをしてきました。実は今回の旅ですが、ハロウィンの前日に右足の小指を亀裂骨折しており、完治しないまま旅をしました。右足をやや引きづりながら歩く私をどの国の人たちも道を譲ってくれました。どこの国の人たちも、みんな優しかったです。

前回の旅から私のツールも進化して e-Shim を使ってどこに行っても簡単にネットに繋がるし、配車アプリのおかげで足を痛めていてもどこにでも自由に行き来できるし、Tinder でまだ会ったことのない人に現地のいろいろな事を教えてもらったり、世の中ずいぶん便利になったなあと思いました。

いつか「このアプリのおかげでずいぶん便利になったよね」と言われる、そんなアプリを開発してみたいです。以上です。

Nuxt.js + Auth Module + Auth0 で Logout したい

あらすじ

nux-auth と Auth0 で SSO(シングルサインオン)するプロジェクトに関わる事になったので試しに example を用意したんですが logout がうまくできない

起きている事

  • logout を実行する
  • 再度 login すると ID, PW の入力不要でログインできてしまう。

解決方法

ポイントは2点

  • Auth0 の logout URL を直接叩く
  • Auth0 の設定画面で Allowed Logout URLs に logout 後に戻りたい URL を指定する

以下のようなコードを書いて

async logout() {
  await this.$auth.logout()
  window.location.href = "https://your-tenant.auth0.com/v2/logout?returnTo=http://localhost:3000"
}

それから以下のようにセッティングを追加すれば OK

f:id:okamuuu:20191126112740p:plain

LINE Smart City ハッカソンに参加してきました

f:id:okamuuu:20191026091104j:plain

10/26(土), 10/27(日) に博多で行われた スマートシティを実現できるサービスを作ってみよう! というコンテストに参加してきました。

line.connpass.com

ハッカソンのお題

以下のような課題を軸に、各自でアイデアを出し合いました。

  • 観光客が福岡をより楽しめるようにする
  • 福岡名物の屋台を便利にするようなサービス
  • スポーツ観戦がより楽しくなるようなサービス
  • 子育てがより便利になるサービス
  • 街のクリーンアップに役立つサービス

参加してできたもの

今回私たちが作ったものは Line Food Helper という bot を作成しました。よかったら使ってみてください。

f:id:okamuuu:20191028115005p:plain

下記のQRコードで良かったらボットとお友達になってみてください

f:id:okamuuu:20191028113655p:plain

この bot には以下の機能を持たせています。

  • chiken を含む言葉を発言すると近隣の 焼き鳥屋のお店一覧 を返す
  • motsunabe を含む言葉を発言すると近隣の もつ鍋のお店一覧 を返す
  • fish を含む言葉を発言すると近隣の 寿司屋一覧 を返す
  • hungry を含む言葉を発言すると名前を呼びつつ おすすめの料理一覧 を返す
  • それ以外の言葉はお腹すいていると判断して名前を呼びつつ おすすめの料理一覧 を返す
  • 位置情報を伝えると、以後その近辺に関するお店の情報を取得するようになる

といってもデモ用のボットなので実在しないデータを返しています。

https://github.com/okamuuu/smartcity-hackathon-linebot

開発で苦労したところ

今回事前に VUI Fukuoka が行なっているハンズオンの資料が公開されていたのでこちらで予習することができました。事前に Messaging API と clova の予習をしていたので現地についてからの苦労はそんなにしませんでした。

チーム編成ですが今回は4人チームを組みました。ハッカソン慣れしているエンジニアが私ひとりだけだったのでほぼ私が実装を担当しました。ですが Flex Message といった一部の機能を駆け出しのエンジニアにお任せしたりできたので割とタスクの切り出しもうまくできました。とりあえずエンジニアリングは私が仕切ったのでそこは問題はありませんでした。

ただエンジニアが仕切りすぎて他の方がアイデアを自由に出せない状況を作ってしまったなーと正直反省しています。

それから、どうしたらいいのかなー、と思ったのが Webhook URL です。開発中は Webhook が ngrok で繋いでいる私の Macbook に届くようにしていたのですが、それとは別にステージングサーバーにデプロイして作業していました。そうすると Webhook URL が二つ必要になるのですが、そのために Messaging api のチャンネルを2個登録する必要があったので、そこがちょっと不便でした。

あとは ngrok は無料版だと都度 url が変わってしまうのでそうするとコンソール画面で都度 Webhook URL を変えないといけないのもちょっと面倒かも*1

反省点と良かった点

チーム内をエンジニアである私がが仕切りすぎたせいで、実装は可能なんだけどあまり特徴のないアプリになってしまい、当然ながら賞を頂くことはできませんでした。もうちょっと夢と理想を考えてみてもよかったと思います。

でも早めに実装切り上げて「これ使ってマネタイズとグロースどうする?」っていう話を最後に1時間ぐらい、みんなでできたのはとても楽しかったです。

最終的に得た学び

今回のハッカソンに参加して Bot アプリに可能性を感じました。Messaging API や Clova のような音声対話での User Interface はまだ新しく、今後いろんな使われ方がされるんだろうな、と思いました。特に音声入力が必要な仕事がたくさん生まれると思うので今の段階で学習できたので良かったです。

もし、音声対話の事あんまり良くわかっていないから最短で知りたい、という人がいたら以下の資料を読む事をお勧めします。

https://vuifukuoka.connpass.com/event/150316/

まとめ

というわけでこのような会を開催して頂きましてありがとうござます。参加者は確かに2日間だけは大変でしたが運営のみなさまはもっと長い間大変だったと思います。お疲れさまでした。おかげさまでまたエンジニアとしての経験値をたくさん稼ぐ事ができました。またこのようなチャレンジできる機会を頂けるとうれしいです。ありがとうございました。

こちらからは以上です。

*1:まあでもそれはお金で解決できる

parcel src/index.html 的なコマンドを実行すると Cannot find module 'babel-plugin-babel-root-slash-import' と言われる場合

こんな感じの .babelrc を用意してあげると良いでしょう。

 {
  "plugins": [
    ["module-resolver", {
      "root": ["./src"]
    }]  
  ]
}

あとそれから

Uncaught ReferenceError: regeneratorRuntime is not defined とか言われたら require('babel-polyfill') とかしておけばいいでしょう。

おしまい