20200918のNode.jsに関する記事は7件です。

〇〇のセールを見逃さないサービス作りました。【AV半額オブザーバー】

はじめに

みなさんは、AVのセールを見逃して後悔した事はありませんか?

私にはあります。と言うことでAVの割引を見逃さない為のサービスを作りました。具体的に言うと、割引になってる作品を人気順の一覧で見れるページと、会員登録から『指定の作品が割引になったとき』のみ通知を送るページを通して、より便利な購入体験を提供します。


無題.png

https://hao.japaneast.cloudapp.azure.com (18歳未満はアクセス禁止です)



出来ること

①割引作品を人気順に表示

一覧.png

これが一応メインコンテンツですね。紳士淑女のみなさんはFanzaから定期的に似たようなメールが届くかもしれませんが、メールをいちいち確認するのって面倒じゃないですか?

しかもキャンペーンページは一時的な物なのでブックマーク出来ません。なので割引作品の一覧を毎日更新し、人気順に表示するリストを作成しました。両サイドにはリストの前後40件の作品画像を背景として使用しています。一覧性という面ではかなり拘った仕様なので、使っていただけると幸いです。




②女優別で割引作品をリスト化

女優.png

例によって黒塗りの多い画面ですが、女優さんの名前を登録すると出演作品が割引になった場合自動でリストに表示する事ができます。お気に入りの女優さんの作品がセールになってないか確認したい。そういう時にぜひご活用ください。




③マイリストを設定
リスト.png
URLを直接入力することで監視リストに動画を追加することができます。Fanzaにも似たような機能はあるのですが、ポチポチって押してるとすぐリストの件数が膨れ上がりがちなので、「これぞ!」と思うお気に入り動画の記録にオススメです。




開発の舞台裏


「個人開発だし、どうせフロントはJSで書くからNode.js使おう」

技術選定に関しては多分ここから始まったと思います。PHPという選択肢もあったのですが、今更感が強かったので今回は不採用。逆にフロントは詳しくなかったので資料が充実しているVue.jsを選びました。インフラはKeyVaultなる素敵機能を使ってみたかったのでAzureです。

image.png

(大正義KeyVault君、実際これが無ければ普通にAWS選んでた気がする)





大まかな開発の流れとしては
①設計
②バッチの実装
③バックエンドの実装(ルーティングとか主要なAPI)
④フロント(htmlやVue.js)の実装
⑤バックエンドの修正(フロントを実装した事でバグや考慮漏れが多数発覚)
⑥デザイン
⑦インフラ周りの設定とか
⑧リリース

という感じだったような気がします。一応番号は振りましたが④⑤⑥に関しては「プロトタイプが欲しい」「今日はデザインの気分じゃない」「あれ実装してないじゃん」みたいな理由で結構反復横跳びしてますね。


まあ時系列順に振り返ると、設計に関しては結構グダりました。
というのも、今までオープン系のアプリ開発しかやったことがないし、ましてや設計なんて初めてなので、「DBから作ろうぜ!」って発想になる訳です。

まあこれも依存の方向から考えると一定の合理性はあるのですが、そうなると問題なのが「アレこうした方が良くね(仕様変更)(仕様漏れ)」からの「DB設計直さなきゃ駄目じゃん……」からの「既存設計に引きずられて苦しい………(死)」となる黄金パターン。今回はどっぷり嵌りました。

ねー、WebバックエンドのDB設計なんて機能が増えれば当然カラム増えるのになんで最初にやったんだろね。
今から思えば裏側はモックに留めてフロントから仕様をガチッと固めてしまうのが最速な気がしますが、その反省は次回に活かすとします。



そしてある程度設計が固まってから実装に取り掛かったのが5月の頭ですね。
この段階ではフロントエンド全然わからんマンだったのと、バックエンドもいきなりWebサーバ書くのは脆弱性作りそうだったので消去法でバッチから作り始めました。(その結果、後で半分以上書き直しになった)

特に大変だった所は無いと思いますが、JSをガッツリ書くのは何気に初めてだったので、バッチ処理全体を書くのに丸々1か月も掛けてしまいました。Promiseが全然分からなくて死んでたり、コードのどこが非同期処理で動いてるのか今一掴めずに「forが動かねぇ……」って絶望してたのも今となっては懐かしい思い出です。


6月は丸々ルーティングとHTML、ログイン認証の実装に使いました。
後述しますが、特にログイン機能の実装は結構大変でした。まず認証が通らなかったり、逆にどんな値でも通ったり、通ってもセッションを保持できなかったりとてんやわんやです。SNS認証とか実装しなくて本当に良かった

7月はようやく機能とデザインの実装です。
CRUDとかバックエンドの側の実装は6月から並行でちょいちょい着手してたのですが、いざ動かしてみたら変な所で止まったりバグッたりと散々だったので、実質書き直しになりましたね。

デザインに関してはTailwindCSSを使って見たのですが、今思えば教養として素のCSSを書いたほうが良かったかもしれません。TailwindCSS、作る時は便利なんですがHTMLが汚くなるし、sm:invisibleするとSafariで表示崩れるし、運用フェーズだと都度都度ビルド要るしでなかなか面倒。



8月前半は細かいデバッグや表示の追加をメインに行いました。レスポンシブの対応とかもそうですが実際使ってみると思ったより使い勝手微妙だなみたいな感じになったので位置を修正したり、ツールチップを実装したりしました。表示に関してはあまりゴテゴテするのも良くないかもとか思ったけど、余白を生かしたデザインとかアレはアレで高度芸能(素人は手を出さない方が無難)なので、今回は出来るだけ詰め込んでみました。次回作はもっとゴリゴリに表示を動かしたいを思います。

8月後半は予定を繰り上げてAzure上にVMを立ち上げ、テスト環境を構築。
まあ私のTwitter見てる方は既にご存知かもしれませんが、詰まりに詰まり散らかしました。うん、何というか3ヶ月半掛けて作った動くはずのアプリが突然動かなくなったら焦るよね。

まあ原因の9割はmysqlのせいだったんですけど、テーブル名にキャメルケースを使ってはいけない。大事な事なのでもう一回言うけど、テーブル名にキャメルケースを使ってはいけない。Do you understand?
データベースオブジェクトの命名規約

9月はほぼ消化試合でしたね。本番移行って言っても丸々同じ手順を繰り返すだけですし、まあ強いて言えば、ここに来てダダ下がりしたモチベの維持が大変でした。リアルでも色々忙しかったのもあり、ここの工程はボリューム的には正味一週間ぐらいで終わりそうな感じだったのですが、何やかんやで丸1か月掛かりました。


ちなみにAzureのVMやKeyVaultで幾らか詰まると思ったのですが、その辺りは意外にも公式ドキュメントだけですんなり構築できました。流石マイクロソフト謹製のPaaSですね。ネタに出来なくて残念です




出来なかった事

・TypeScript
・Nuxt.jsとかのナウいフレームワーク
・綺麗なコード
・自動テストとか

image.png

まあ今回の1件でJavaScriptとSQLさえ書ければ全てが解決するという事を証明してしまったので、学習意欲はわりかし低めです。下2つは時間があったら極めたいなと思いつつ「時間があったら」などと逃げ口上かましてる時点でやる気無いんだよなぁ   みつお


それにTypeScriptは記法の癖が強いし、Nuxt.jsも何というか色々勝手にやってくれる代わりに覚えること多いしで、個人的にあんまり好きじゃないです。あときれいなコードは目指したかったんだけど、それが開発速度を担保してくれるかって言うとそうでもないので、動いて読めてそこそこ整理されてればいいかって感じに妥協しました。



一つ反省点を上げるとすれば、自動テストを導入するかどうかをさておいても、テスタブルな実装は目指すべきだったなと思います。

具体的な所で言うと、APサーバの実装で内部の処理とレスポンスの返却を同じメソッドに書いてしまった結果、単体でテスト出来ないコードが生まれたりって感じですね。インターフェースいちいち考えるの面倒くさかったとは言え、最後のテストが地味に大変だったので、ここはもうちょっと拘っても良かった気がします。






頑張った点とか

①自動ログイン

これは今日日どんなサイトでも付いてる機能なのでどうにか実装したかったのですが、結構手間取りました。というのもnode-modulesにあるpassport君は自動ログインをサポートしてないので、認証の発火とCookieへの読み書き、ハッシュ化したトークンの生成や管理は自前で実装する必要があります。(あれ?これもう自分でミドルウェア実装したほうが早くない?)

まあ最終的にランダムかつ一意なハッシュを定期的にセットし、passport経由で認証を通すことに成功しました。まあメッセージ返す部分は結局解決できなくて、ログイン認証の前に「ログイン認証のメッセージ」を返すAPIを叩くことで解決しました。悔しい……



②女優検索

DBはmysqlなのですが、流石にLike検索で返すのは遅い&不便なので、ngramによるフルテキストキーを貼ってあいまい検索を実装しています。細かい調整とかは出来なかったのですが、まあまあ実用範囲かなと、本当はサジェストとかやりたかったんですが、それは次回の宿題ですね。



③ツールチップ
これはログイン先にあるマイページでの演出なのですが、URLや縮小画像にマウスカーソルを持っていくと近傍にオリジナルのパッケージ写真を表示するようになっています。

実装としてはシンプルにJSでイベントを発火してdiv要素の内容とCSSを都度都度DOMで書き換える感じです。ただ何故かz-indexが適用されず、悩みに悩んで一日詰まった結果、div要素の位置を5回ぐらい変更してようやく適応される位置を見つけることが出来ました。


④reCAPTCHA
このサービス、実はそこそこセキュリティにも力を入れていて、ログイン画面にはDDoSにも対応したBOTの検出機能を実装したりしています。ただ登録画面に関しては人とBOTを区別するのは難しいのでreCAPTCHAを使用しました。

セキュリティ上バックにも実装が必要って言うのは分かりますが、フロント側で一度作り込んだJSを書き換えるのは結構ヒヤヒヤしました。登録時に実際のURLが必要ですが、実装するなら最初からテンプレートを組み込んでコメントアウトしておいた方が良いです。



ちなみにバックの実装はこんな感じの関数を書いて適宜叩けばOKなので意外と楽でしたね。

reCAPTCHA
function reCaptcha(token){
    if(!token){
        console.log("Error token is null");
        return false;
    }
    let options = {
        url: 'https://www.google.com/recaptcha/api/siteverify',
        method: 'POST',
        form: {
          secret:/*シークレット*/,
          response:token
        },
        json: true
      }
      request(options, (error, response, body) => {
        if (error) {
          console.log(error);
          return false;
        }
        // 閾値により判定する
        if (body.score < 0.5) {
            return false;
        }else{
            return true;
        }
    });
}



⑤Slackの活用
通知の送信用として使用しているG Suiteには2000通/日の送信制限があります。まあ制限にかかることは無いと思いますが、容量を無駄に削るのも嫌なので、自分宛ての通知(お問い合わせとか鯖の情報とか)はバックエンドからSlackAPIを経由して送信するようにしています。

これが中々便利で、メールと違ってスマホにプッシュ通知が出るので通知を見逃すという事もありません。これから個人開発を始めようという方はぜひ使ってみて下さい。




詰まった所とか

①Promise

最初はメソッドチェーンとか面倒臭いなって感想しか出てこなかったんですが、短い関数でちゃっちゃっとPromise返したら、async/awaitで普通に同期実行できると知ってすぐに手のひらクルーしました。

便利ですねこれ。………………え?まだコールバック関数とか使ってる人居るんですか?


Promise自体の説明に関してはやめ太郎さんの書かれた記事が日本一分かりやすいので是非どうぞ
4歳娘「パパ、Promiseやasync/awaitって何?」〜Promise編〜




②passport

前述の通りログイン関係でPassportを使っているのですが、ログインした後セッションを有効化出来ないという現象が発生しました。具体的にはユーザー情報が入ってるはずのreq.userが何故かundefinedのまま……………


まあ結論から言えば犯人はAxios君でしたね。

axios.defaults.withCredentials = true;

を適当な所に書いてあげれば、認証情報を含むCookieをサーバに送信できるようになります。




③Cheerio

スクレイピングと言えばCheerio君。ただコイツには結構苦労させられました。結論から言えば近傍5つ以内にClassが振ってない要素を取得するには新卒Sierを秒で退職してMicrosoftに就職を成功させるぐらいの豪運を必要とします。実質砂金掘りですね。

必要な要素が取れないときは闇雲に試行回数を増やすよりも、別のページから同じ情報が取れないか探したり、PCの電源ケーブルを抜き差ししたり、懐かしのゲームを楽しむのが肝要です。実際私も自棄になり、開発をほったらかして一日中エスコン6をプレイしていたら何故か要素が取れない問題が解決しました。

あとeachで要素の取得をぶん回すとき、attr("href")は先に find("a")を指定しないとちゃんと拾ってくれないので気を付けましょう。




④Vue.js

まあこれに関しては後で別の記事に起こそうと思いますが、特に苦労した部分だけでも紹介したいと思います。


・v-modelの変更を監視してイベントを発火したい。

まあ誰しも一度はやると思いますが、<input v-model="hoge" @change="huga()">みたいな感じのやつです。
ちなみに↑のコードはv-model@changeでイベントリスナーが二重になってるので@changeは動きません。
一応公式ではv-modelをv-bindに書き換える方法が推奨ですが、v-bindだと何故かバインド出来ない現象が発生したので別の対策を講じます。(←今思えば普通にタイポだった可能性ある)

対策、new Vue()の時にmodelのリスナーを追加する

let vue = new Vue({
  el:'#app',
  data:{},
  watch:{/*監視したいv-modelの名前*/:function(){

    //変更があった時に走らせたい処理を記述

  }}
});



・new Vue()の中からMethodsのメソッドを呼びたい。

当然ですがthisが必要です。この例に限らず、Vueでundefinedって怒られた時はまずthisの付け忘れを疑いましょう。





⑤Linux

これLinux(Ubuntu)君は全然悪くないけど、環境移行する時に結構詰まったので覚え書きを残しておきます。

まずアプリを雑にインストールするとWindowsとバージョンが違うという事を肝に命じておくべきだと思う。Node.jsとか結構顕著で、何と12.18.3 LTSだとtry{hoge()}catch{/*何もしない*/}みたいな変な文法のコードを書いても普通に動いたりする。動くなや

あと一度やった変更はメモったほうが良いですね。ミスした時もリカバリが効きやすいのと、環境立て直す時「何かCronの動きがおかしい」→「時刻設定がグリニッジ標準時でした」とかやりがちなので対策したほうがベターです。




⑥mysql

リピートアフターミー、テーブル名にキャメルケースを使ってはいけない。

何故かって言うと雑にmysqlをインストールした時、WindowsとLinuxでバージョンが違うから。8.0(win)だとCREATE TABLEの時に名前を全部小文字にしやがるしてくれるけど、5.7(Lin)だと普通に通る。なので突然テーブルが見つかりませんとか言われて死にます。死にました。

あとLinux版は権限周りが固いっぽいので、雑にパスワードを設定するとERROR 1819 (HY000): Your password does not satisfy the current policy requirementsで怒られます。

良い子のみんなはRSA2048に記号挟んだパスワードをぶち込んでいこうな!




まとめ



作り終わった今だから思うのですが、半分以上無駄な機能を作ってしまった気がします。

作った当初はDMMにお気に入り機能があると知らなかったのでガッツリ作り込む気満々でしたが、ただ単に「半額〇〇の一覧をブックマークできるサイト」というコンセプトならログイン機能とか付けずにトップページだけ作って2~3ヶ月でリリースするのが最適解でした。

まあそのおかげでCRUDの実装とかも出来ましたし、Linux触ったり、SQLをガッツリ書く経験も積めたので結果オーライだと思います。これで私も真にフルスタックエンジニアの仲間入りですね。



まあそんな与太は置いておくとしても、やはり個人開発に関して大切なのは『モチベの維持』と『まあいいかの精神』だと思います。

というのも納期が無い開発で仕様なんて固まってる訳ないですし、設計はグダグダ、人手は足りてないといった具合に個人開発はおおよそ炎上or凍結プロジェクトの前提条件を満たした状態でスタートします。今回モチベの維持としては主にGitHubを利用しました。定期的にPushしないと芝が枯れるという危機感は進捗にかなり貢献してくれますね。後はまあ今のバイト先が普通にブラックなのでそこから脱出したいという思いも地味にあったりします。

『まあいいかの精神』と言うのは、一定以上のクオリティを求めない事ですね。今回実はパフォーマンスに関しては結構ザルでして、VMのスペックに関しては同接100~200ぐらいしか見込んでないですし、アプリ自体もDBにインデックス張ったぐらいで計算量の最適化はやってなかったりと中々お粗末な仕上がりです。

ただ、同人界隈でも「出ない神本より出る糞本」という言葉がありますし、「それでも要件は満たすから良いだろ」ぐらいの割り切りが肝要だと自分は思います。それに今回アプリを作ることで、間違いなく自分の実力は伸びました。実を言うと9月にモチベが枯れかけた理由も半分以上それで、急に実力が上がったせいか「今更これを公開するのか?」みたいな躊躇いと気恥ずかしさを乗り越える必要がありました。ここだけの秘密ですよ。


あとここまで辿り着けた要因の一つとして、Twitterで進捗を呟く度に「いいね」を下さるファボ魔(約2名)の存在も大きかったと思います。多分アレが無ければ8月ぐらいで折れていた疑惑ある。大変感謝です。


それとこれは余談なのですが、次回作については既に設計が上がっています。詳しいコンセプトはまだ秘密ですが、今度こそきっと皆様の度肝を抜くサービスをお届け出来ると思います。それではまた次回、goodbye

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Twitter広告APIを利用してキャンペーンを作ってみる その4~Tiwtter広告APIのAPI申請編~

経緯

私が所属している会社では待ラノという小説投稿サイトを運営しています。
待ラノではオススメ小説のランキング上位5作を定期的にTwitterの公式アカウントで紹介しています。
紹介された小説をTwitter広告のキャンペーンを利用してプロモーションをしようってなりました。

そもそもTwitter広告のキャンペーンって何?

Twitter広告のキャンペーンですが、簡単いうと1日にかける予算や期間内にかける総予算を指定して、Twitterに広告を出す機能です。

Twitter広告APIでキャンペーンを作る理由

1つのキャンペーンで複数のツイートをプロモーションする場合、1日にかける予算を一気に消化されてしまいます。
しかもどのツイートにどれだけ予算が消化されているかがわかりません。
そのため、1つのツイートに1キャンペーンを紐付けることで消化される予算の見える化を行うことになりました。

ただ手動でTwitterの広告コンソールから、1ツイートに1キャンペーンを毎回作ることになると結構手間です。
というわけで、Twitter広告APIを利用して動的にキャンペーンを作成することになりました。

Twitter広告APIでキャンペーンを作成するためには

以下の手順が必要です。

  1. Tiwtterアカウントを作成する(省略)
  2. Tiwtterアカウントにメールアドレスと電話番号を設定する(省略)
  3. TiwtterAPIの利用申請をする
  4. TiwtterAPIのAPIキーとトークンを取得する
  5. TiwtterAPIを利用してツイートをする
  6. Tiwtter広告APIの利用申請をする ←イマココ
  7. Tiwtter広告APIでを利用してツイートを使ったキャンペーンを作る

今回は6の【Tiwtter広告APIの利用申請をする】について説明していきます。
本稿は、その1その2が完了している前提で記載されております。

1.Twitter広告APIガイドのページ(英語)にアクセス

まずはTwitterにログインした状態で、Twitter広告APIガイドへアクセスします。
注:日本語のTwitter広告APIガイドは存在しておりますが、申請フォームがバグっているせいでチェックボックス等が正しく押せない状態になっておりますので、こちらの記事同様に英語ページで申請を行ってください。

2.「Apply for Ads API Access」ボタンをクリックします。

スクリーンショット 2020-09-18 14.44.11.png

3.英語で申請フォームに回答していきます。

まずは「基本情報」です。

以下の項目を入力していきます。

  • Company(企業名)」
  • Country(国)」
  • State/Province(都道府県)」
  • City(市)」

スクリーンショット 2020-09-18 14.52.34.png


Company Handle(Twitterの企業アカウントID)」
スクリーンショット 2020-09-18 14.58.57.png


App ID(アプリID)」
スクリーンショット 2020-09-18 14.59.08.png

その2で作成したアプリのIDを取得します。
developer.twitter.com/en/apps/のリンクをクリックしてください。
そうすると開発ポータルに遷移するので、対象のアプリの「設定(歯車)」ボタンをクリックしてください。
スクリーンショット 2020-09-18 15.04.49.png

「アプリID」が表示されますので、先程の入力フォームに記載してください。
スクリーンショット 2020-09-18 15.05.09.png


I acknowledge that the provided app will be capped at 5 tokens for the Developer phase.(指定されたアプリは開発者フェーズについてトークンが5つまでに制限されることに同意します。)」

こちらのラジオボタンをチェックしてください。
スクリーンショット 2020-09-18 14.59.25.png


次に「代表連絡先」です。
以下の項目を入力していきます。

  • First Name(名)」
  • Last Name(姓)」
  • Title(役職)」
  • Job Function(職務)」
  • Job Level(職務レベル)」
  • Email(メールアドレス)」
  • Phone(電話番号)」

スクリーンショット 2020-09-18 15.28.30.png


次に「Twitter広告APIの利用目的」です。

Of the following, which best describes your business?(次のうち、御社の事業について最もよく当てはまる説明はどれですか?)」
スクリーンショット 2020-09-18 15.35.23.png

Of the following, which best describes your business?(次のうち、御社の事業について最もよく当てはまる説明はどれですか?)」
スクリーンショット 2020-09-18 15.35.30.png

...tell us about your business(御社のビジネスについて教えてください)」
スクリーンショット 2020-09-18 15.35.44.png

...what do you plan to build on the Ads API?(広告APIに何を構築する予定ですか?)」
スクリーンショット 2020-09-18 15.35.52.png

...describe your unique differentiators in the Ad Tech ecosystem(広告テクノロジー市場での御社の差別化要素について説明してください)」
スクリーンショット 2020-09-18 15.36.01.png

Do you have API partnerships on any other platforms?(Twitter以外のプラットフォームでAPIパートナーシップを組んでいますか?)」
スクリーンショット 2020-09-18 15.36.10.png


次に「顧客情報」です。

Where are your customers based? Please indicate your top market(顧客基盤はどこにありますか?御社の最大市場を教えてください)」
スクリーンショット 2020-09-18 15.51.20.png

Which industries are most common among your customers?(どの業界の顧客が最も多いですか?)」
スクリーンショット 2020-09-18 15.51.28.png

Tell us more about your strategic customers/advertisers(御社の戦略顧客/広告主について詳しく教えてください)」
スクリーンショット 2020-09-18 15.51.36.png


次に「商品情報」です。

Of the following campaign objectives, where is your offering strongest?(次のキャンペーン目的のうち、御社の商品が最も優れている部分はどこにありますか?)」
スクリーンショット 2020-09-18 15.57.06.png

How is your product distributed?(商品の流通方法を教えてください)」
スクリーンショット 2020-09-18 15.57.14.png

List the languages that your product supports(商品がサポートする言語を列挙してください)」
スクリーンショット 2020-09-18 15.57.25.png

Does your product currently use or plan to utilize any other Twitter APIs?(御社の製品にほかのTwitterAPIを現在使用していますか?または、今後、利用する予定がありますか?)」
スクリーンショット 2020-09-18 15.57.37.png

Do you license data from Twitter's Data APIs?(TwitterのデータAPIから取得したデータをライセンスの対象にしますか?)」
スクリーンショット 2020-09-18 15.57.46.png


次に「Twitter広告API制約」です。

スクリーンショット 2020-09-18 16.06.15.png

以下の項目はラジオボタンにチェックしてください。

  • Yes, I agree to the terms of the Twitter Ads Products and Services Agreement.(はい、Twitter広告商品およびサービス契約書の条件に同意します。)」
  • I acknowledge that by agreeing to this Twitter Ads Products and Services Agreement, I agree to the Twitter Privacy Policy, Terms of Service, Developer Agreement and Policy, Trademark and Brand Guidelines, and applicable Twitter Master Services Agreement.(このTwitter広告商品およびサービス契約書に同意することにより、Twitterプライバシーポリシー、利用規約、開発者契約およびポリシー、商標およびブランドガイドライン、および適用対象となるTwitterマスターサービス契約に同意することに同意いたします。)」
  • I further acknowledge that by agreeing to this Twitter Ads Products and Services Agreement, I agree to the Twitter Ads policies, including those for Conversion Tracking and Tailored Audiences, and Twitter's Data Processing Addendum.(さらに、このTwitter広告商品およびサービス契約書に同意することにより、Twitter広告ポリシー(コンバージョントラッキングおよびテイラードオーディエンスのポリシー、Twitterのデータ処理補遺を含む)に同意することに同意いたします。)」

以下はどちらを選んでも問題ありません。
選択後は、「Submit」ボタンをクリックします。

  • By clicking on Yes below, you agree to receive various marketing communications (like tech updates, version notifications, events) via email from Twitter. You may unsubscribe at any time.(以下で [はい] をクリックすると、Twitterからさまざまなマーケティング関連のメール(技術更新、バージョンの通知、イベントなど)を受信することに同意するものとします。購読登録はいつでも解除できます。)」 スクリーンショット 2020-09-18 16.14.20.png

4.Twitterからの申請の承認メールが届きます。

以下のようなメールが届いたら承認が完了です。
スクリーンショット 2020-09-18 16.21.23.png


■「Twitter広告APIを利用してキャンペーンを作ってみる 」シリーズ

  1. その1~TwitterAPI申請編~
  2. その2~TiwtterAPIのAPIキーとトークンの取得編~
  3. その3~TwitterAPIでツイート編~
  4. その4~Tiwtter広告APIのAPI申請編~ ←イマココ
  5. その5~Twitter広告APIでキャンペーン作成編~
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サーバレスプラットフォームのCode Engine(IBM Cloud)を試してみた

IBM Cloud Code Engineのベータ版のリリースがアナウンスされました:tada::tada::tada:
これは、GCPで言うところのCloud Runに似た機能を持っており、コンテナ上で稼働するアプリケーションをサーバレスで稼働させることができます。ベースとなっているのは、

  • Kubernetes
  • Knative
  • Istio
  • Tekton

等となっています。特徴的なのは

Code Engine ではソースコードをビルドパックと呼ばれるランタイム環境と組み合わせてコンテナを作成し、実行することもできるため、コンテナイメージがなくても利用が可能です。

と言うところですね。
ビルドを行うステップを飛ばしてデプロイすることができるので、きっとCI/CD周りの設定が少し楽になるのではないかな、と思います。

とりあえず新しいものは触っておけ、と言うことでGetting started with IBM Cloud Code Engine (Beta)を参考に、Node.jsでHello Worldを出してみます!
必要なのは、ソースコードのみ。コンテナイメージを使わないデプロイを試してみます!

事前準備

IBM Cloud のアカウントを準備する。

ライトプランは不可みたいです。ご注意ください。(ちなみに、β版の間は課金は内容です。(用意されているのが無料プランだけでした。))

Container Registoryのnamespaceを用意する

下記のように好きな名前をつけてnamespaceを作っておきましょう。今回はtest-demo-code-engineと言うnamespaceを用意しました。

image.png

APIキーを取得する

画面上部の管理→アクセス(IAM)→APIキーをクリックして、APIキーを生成。生成されたキーをコピーして控えておいてください。

image.png

Code Engineを準備する

カタログからCode Engineを探して開きます。下記の画面がでたらRun your source codeを選択し、Start Creatingを押しましょう。

image.png

プロジェクトを作成する

createを押すと名称の入力ができます。

image.png

現在、サポートされているロケーションはダラスだけのようですね。

image.png

プロジェクトを作成すると下記のような画面になります。

image.png

ビルドの詳細を設定する

Specify build detailsを押して設定を進めましょう

ソースコードリポジトリを設定する

ブランチを設定することができます。重要なのは、Context directoryです。実際に動かしたいソースコードが入っていディレクトリを指定してください。(デモの場合は、/helloとなります。※必ず/から始まる文字列で指定してください)

image.png

DockerFileの場所を指定する

デモをそのまま使う場合には、特に変更する必要はありません。Context directory配下のDockerFileを指定しましょう。また、使用するリソースもここで指定することができます。

image.png

コンテナレジストリを指定する

コンテナレジストリの参照を設定しましょう。Addを押して
image.png

Registry nameには準備の時に作成したコンテナレジストリのnamespaceを入れます。レジストリサーバは、コンテナレジストリのURLです。今回はダラスに作っているので、us.icr.ioとなっています。パスワードはAPIキーです。

image.png

Addを押したら最後にリポジトリ名を入れましょう。今回はtest-code-engineとしています。tagは必要に応じてつけてください。デフォルトはlatestです。

image.png

デプロイ

ここまで来たら画面右下のDeployを押しましょう

image.png

動作を確認する

デプロイ後にはこのようなダッシュボード的な画面に遷移します。
image.png

右上のApplication URLを押すと、該当のアプリケーションを開くことができます。下記のようにHello Worldが出れば成功です!

image.png

ちなみに、デモアプリケーションでは、Worldの部分が環境変数により変更可能となっています。
このようにTARGETに指定した内容を反映することもできます。(変更を反映するためにはSave and Deployが必要です。)

image.png

触ってみた感想

まだβ版と言うこともあり、機能としては最小限といったところでしょうか。(デプロイして動かすくらいしかできない)
今後は、コンテナイメージなしで動かせる利点を活かしてPipelinesとの統合などに利便性を見出せるかもしれません。もちろん、リクエスト単位での課金なのでバックアップとして持っておくと言う選択肢もありそうです!

(おまけ)Cloud Run(フルマネージド)との差分(9/18時点)

利点

  • ソースコードだけでデプロイが可能!Dockerイメージを用意する必要がない
  • Docker Hubからもデプロイ可能
  • vCPUが0.01〜8まで選べるので選択肢が広い。(Cloud Runは1か2)
  • メモリも128MiBから32GiBまで選べる(Cloud Runは4GiBが上限)→ただ、サーバレスでそこまで必要か?と言う気もする

足りない点(きっとこれから実装されるはず!)

  • リビジョンごとのトラフィックの割合の変更が簡単にできない。リビジョン毎にURLが発行できるわけでもない
  • コンテナのログがみられない
  • リージョンがダラスしかないのでレイテンシが気になる
  • 自動スケールするときの最大数が250(Cloud Runは1,000)
  • Cloud Runで言うところの、 Serverless VPC Access Connector がない。ローカルIPでDBなどにはアクセスしたい。
  • その他いろいろ。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Twitter広告APIを利用してキャンペーンを作ってみる その2~TiwtterAPIのAPIキーとトークンの取得編~

経緯

私が所属している会社では待ラノという小説投稿サイトを運営しています。
待ラノではオススメ小説のランキング上位5作を定期的にTwitterの公式アカウントで紹介しています。
紹介された小説をTwitter広告のキャンペーンを利用してプロモーションをしようってなりました。

そもそもTwitter広告のキャンペーンって何?

Twitter広告のキャンペーンですが、簡単いうと1日にかける予算や期間内にかける総予算を指定して、Twitterに広告を出す機能です。

Twitter広告APIでキャンペーンを作る理由

1つのキャンペーンで複数のツイートをプロモーションする場合、1日にかける予算を一気に消化されてしまいます。
しかもどのツイートにどれだけ予算が消化されているかがわかりません。
そのため、1つのツイートに1キャンペーンを紐付けることで消化される予算の見える化を行うことになりました。

ただ手動でTwitterの広告コンソールから、1ツイートに1キャンペーンを毎回作ることになると結構手間です。
というわけで、Twitter広告APIを利用して動的にキャンペーンを作成することになりました。

Twitter広告APIでキャンペーンを作成するためには

以下の手順が必要です。

  1. Tiwtterアカウントを作成する(省略)
  2. Tiwtterアカウントにメールアドレスと電話番号を設定する(省略)
  3. TiwtterAPIの利用申請をする
  4. TiwtterAPIのAPIキーとトークンを取得する ←イマココ
  5. TiwtterAPIを利用してツイートをする
  6. Tiwtter広告APIの利用申請をする
  7. Tiwtter広告APIでを利用してツイートを使ったキャンペーンを作る

今回は4の【TiwtterAPIのAPIキーとトークンを取得する】について説明していきます。

1.Twitter Developerのページにアクセス

まずはTwitterにログインした状態で、Deeloperサイトへアクセスします。

2.「Create an app」ボタンをクリックします。

APIキーとトークンを取得するためにはTiwtter内でアプリを作成する必要があります。
スクリーンショット 2020-09-14 4.32.14.png

3.英語でアプリの詳細を回答していきます。

まずは「App Name(アプリ名)」
スクリーンショット 2020-09-14 4.23.55.png


「Application description(アプリの説明)」
スクリーンショット 2020-09-14 4.23.56.png


「WebSite URL(ウェブサイトのURL)」
スクリーンショット 2020-09-14 4.23.57.png


「allow this application to be used to sing in with twitter(アプリの利用にはTwitterにサインインが必要か)」
今回は必要ではないので、チェックを「オフ」にします。
スクリーンショット 2020-09-14 4.23.58.png


下記項目は必要に応じて記入します。
未記入でも問題はありません。

「Callback URLs(コールバックのURL)」
スクリーンショット 2020-09-14 4.23.59.png
「Terms of Service URL(利用規約ページのURL)」
「Privacy policy URL(プライバシーポリシーページのURL)」
「Organization name(企業名)」
「Organization website URL(企業のウェブサイトのURL)」
スクリーンショット 2020-09-14 4.24.00.png


「Tell us how this app will be used(アプリの使用方法を説明してください)」
記入後、「Create」ボタンをクリックします。
スクリーンショット 2020-09-14 4.24.01.png

4.デベロッパー規約を確認してから、再度「Create」ボタンをクリックします。

スクリーンショット 2020-09-14 4.24.02.png

5.入力した内容が詳細として表示されるので「Keys and tokens」タブをクリックすます。

さらに「Access token & access token secret」の「Generate」ボタンをクリックするとトークンが出力されます。
スクリーンショット 2020-09-14 4.24.03.png

今後必要になるのが以下の4項目になります。

  • 「API key」
  • 「API secret key」
  • 「Access token」
  • 「Access token secret」

■「Twitter広告APIを利用してキャンペーンを作ってみる 」シリーズ

  1. その1~TwitterAPI申請編~
  2. その2~TiwtterAPIのAPIキーとトークンの取得編~ ←イマココ
  3. その3~TwitterAPIでツイート編~
  4. その4~Tiwtter広告APIのAPI申請編~
  5. その5~Twitter広告APIでキャンペーン作成編~
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Puppeteerの`waitFor`は`waitForTimeout`に書き換えた方がよいみたい(v5.3.0)

概要

警告が出たので調査

waitFor is deprecated and will be removed in a future release. See https://github.com/puppeteer/puppeteer/issues/6214 for details and how to migrate your code.

結論

-  await page.waitFor(5000)
+  await page.waitForTimeout(5000)

参考

詳しく書いてあるので詳細はGitHubのページを参照してください

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

discord.jsでapiの情報を取得する

すえきゅーですどうも
今回は discord.jsでapiから情報を取得して出力する方法をここに書こうと思います

使うもの
Api
Node fetch
jsonを読む力

この3つです
次にNode fetch
こいつがないとダメです
$ npm install node-fetch
こいつをターミナルで実行しましょう

準備完了 コードをここに置きます

コード
const discord = require("discord.js");
const fetch = require("node-fetch");
const client = new discord.Client()

client.on('ready', async () => {

const msg = await client.channels.cache
    .get("送信したいチャンネルid") //チャンネルを取得
    .send("Status"); //送信

setInterval(async () => { //任意のミリ秒ごとに繰り返す
    const res = await fetch("Api"); //取得
    if (!res.ok) { //取得できなかったら
      console.log(await res.text()); //コンソールにメッセージを出力する
      return;
    }

const json = await res.json(); //json

msg.edit({
        embed: {
          color: 0x00ff00,
          title: "thinking",
          description:
            "Api test",
        footer: {
           text: "thinkingbot",
}, 

          fields: [
            {
              name: "fields",
              value: json.test.status, //Apiの情報を書く json.~~~~で行ける

            }
]
}
})

  }, 1500); //1.5秒ごとに繰り返す

こんな感じで出力出来ると思います
何か間違ってることや質問があるならこちらに参加して質問してください

最後まで見てくれてありがとうございました

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【npm】パッケージとモジュールの違いって何?

はじめに

普段、Node関連の記事を書いていたり、業務で説明をする時などに、曖昧になりやすい パッケージモジュール の違いについて公式のドキュメントをもとに簡単にまとめます。

npmにあるのはパッケージなのかモジュールなのか

The npm registry contains packages, many of which are also Node modules,

公式にはnpmレジストリーにはパッケージが含まれており、その多くはNodeモジュールです。

そもそもパッケージとは何なのか

A package is a file or directory that is described by a package.json file.

パッケージとは package.json によって記述されるファイルもしくはディレクトリのことを指します。

そもそもモジュールとは何なのか

A module is any file or directory in the node_modules directory that can be loaded by the Node.js require() function.

モジュールとは、Node.jsの require 機能によって呼び出すことができる node_modules 内のファイルまたはディレクトリのことを指します。

To be loaded by the Node.js require() function, a module must be one of the following:
・ A folder with a package.json file containing a "main" field.
・ A folder with an index.js file in it.
・ A JavaScript file.

モジュールとして require 機能によって読み込まれる為には、次のいずれかである必要があります。

  • package.json を含むフォルダーであり、mainフィールドを含むファイルであること。
  • index.js というファイルが入っているフォルダであること。
  • JavaScript ファイルであること。

結局のところ何が違うのか

npm経由でインストールされたパッケージは、ほとんどがファイルの中でロードされて使用されます。

つまり、これらはモジュールと言えるでしょう。

モジュールに該当しないパッケージもある

npm経由でインストールされるパッケージは、ほとんどがファイルの中でロードされる為、モジュールであると書きましたが、中にはターミナルなどのコマンドラインで実行するパッケージもあると思います。

このように main フィールドを持たないパッケージはモジュールとは言えません。

まとめ

長々と書きましたが、簡潔にかくと以下のようになります。

ファイルの中でrequireして読み込みNode.jsが使用するmainフィールドが含まれていればモジュールという認識でOK

参考文献

About packages and modules

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む