iT邦幫忙

2

【我可以你也可以的Node.js】第十八篇 - 打造一個 API 讓自己減肥永遠都是夢想- 肥宅的第二步 #自動領取 #Express #麥當勞報報優惠券

嗨~ 各位肥宅同袍,我是Robin。
咳咳嗯~
這篇要分享上次肥宅的第一步後續,
還沒看的可以先回去看看,裡面有這次小專案的故事背景動機,

來了各位!

經過我內心非常積極但實際行動緩慢的這一兩週時間,
沒日沒夜的研究,終於先寫出一個過渡品,
至少能滿足現在我的需求。

實際上其實這兩週睡得很好xDD,然後前幾天同事約我去吃麥當勞,
我還是沒有優惠券用 TAT
於是在這兩天努力寫出來xDD

更新一下現況

  • 我把專案移動至 aws 的 ec2 了

    一次解決了上篇的打 API 延遲和 Heroku 的機器休眠。然後我是用 ec2 免費套餐所以管控好使用方式基本上是不會造成費用的,像我就是設定 如果超過 0.5 美金就寄信提醒我。
    (超級客家做法

  • 目前先自肥和身邊週遭的朋友沒有要造福大眾

    就因為時不時要與同事增進感情吃麥當勞,沒有優惠券整個就不對了,所以先行實施自肥計畫,長遠的就持續更新囉。


此篇學習目標 ◑ω◐ :

這篇目標也只有一個,每天自動領取並且通知我領到什麼。

  • 增加一個 API 並使用排程達到每天自動執行的目的。
  • 使用 LINE Notify 超級簡單方便的服務來通知我抽到什麼 。

注意須知:

這目前只是我個人想做的專案,如果我構思上不夠完整或是有更好的方式,可以在下面留言跟我交流,身為小菜雞的我一定會努力盡我所能的學習,感恩。
如果你也是小菜雞,也可以跟我提出你疑問 :+1:
如果我回答不出來太艱深的問題是很正常的~
因為~~~


增加一個 API 並使用排程達到每天自動執行的目的

先看成果

  • 打 API 開始自動領取

  • Line Notify 主動通知

申請 Line Notify Token

  1. 至官方登入 點我連結

  2. 申請權杖(Token)

  3. 申請傳送至1對1聊天室,並設定名稱(我這邊就亂取叫油光降臨

  4. 拿取 Token

測試 token 能否發送訊息

curl --request POST \
  --url https://notify-api.line.me/api/notify \
  --header 'authorization: Bearer <yourToken>' 
  --form 'message=Test'

開始撰寫自動領取的 API

一樣我不會一一解釋,但是我會說明寫的時候的目的和想法。
如果有疑問可以底下留言(搞不好只是我單純犯蠢 xD。

Router

目的只有一個,就是增加一個 Endpont 目的就是自動領取。

app.js

增加以下內容

const subscriptionRouter = require('./routes/subscriptionRouter');

app.use('/api/subscription', subscriptionRouter);

subscriptionRouter.js

增加以下內容,進來之後到 subscriptionController

const express = require('express');
const subscriptionController = require('../controllers/subscriptionController');

const router = express.Router();

router.post('/', subscriptionController);

module.exports = router;

Controller

這邊目的就是接收 request 的內容並且傳遞給呼叫寫好的排程 model ,並回傳結果和排程的名稱。

subscriptionController.js

const subscription = require('../models/subscription.js');

module.exports = async (req, res) => {
  const resp = await subscription(
    req.body.accessToken,
    req.body.lineNotifiyToken,
    req.body.cronFormat,
  );
  res.status(200);
  await res.json({
    name: resp.name,
    message: 'success',
  });
};

Model

這部分會有兩個

  • 寄送 line notify 訊息
  • 排程執行自動領取

sendLineNotify.js

這邊就是單純寫一個你給我 token 和訊息內容我就幫你打出去~

const { postRequest } = require('./request');

module.exports = async (messageContent, lineNotifiyToken) => {
  const options = {
    url: 'https://notify-api.line.me/api/notify',
    headers: {
      'content-type': 'multipart/form-data',
      authorization: `Bearer ${lineNotifiyToken}`,
    },
    formData: { message: messageContent },
  };
  const resp = await postRequest(options);
  return resp;
};

subscription.js

這邊主要是使用人家寫好的 module -> node-schedule
基本上這邊邏輯就是打進來開始設定排程,時間是依照 cron format,
我這邊預設的 .env 檔案會設定以下,預設是每天的 00:01:00

CRON_FORMAT = '1 0 * * *'

如果拿優惠券 status code 或是 rc 有問題就送出領取失敗的訊息。
否則就直接告知我領取結果。

檔案內容:

const { scheduleJob } = require('node-schedule');
const sendLineNotify = require('./sendLineNotify.js');
const { getLottery } = require('./lottery');
require('dotenv').config();


module.exports = (accessToken, lineNotifiyToken, cronFormat = process.env.CRON_FORMAT) => {
  const resp = scheduleJob(cronFormat, async () => {
    const getLotteryResp = await getLottery(accessToken);
    if (getLotteryResp.statusCode !== 200) return sendLineNotify(`領取失敗,因為 statusCode 拿到 ${getLotteryResp.statusCode}`, lineNotifiyToken);
    if (getLotteryResp.body.rc !== 1) return sendLineNotify(`領取失敗,因為麥當勞報報 API RC 拿到 ${getLotteryResp.body.rc}`, lineNotifiyToken);
    return sendLineNotify(`\n${getLotteryResp.body.results.coupon.object_info.title}`, lineNotifiyToken);
  });
  return resp;
};

專案目前情況

專案持續更新,直到我做到完全滿足我的需求為止。
GitHub Link: mcdonaldLottery

這兩天實作過程中發現還有很多需要改進的地方...
目前窘境:

  1. 如果要分享給不會打 API 的人使用整個就是不可能,
    (除非他願意給出帳號密碼,這樣又不太妥。
    所以可能需要一個介面讓他輸入帳號密碼拿取 Token -> 輸入 Line Notify 的 Token -> 介面按下送出自動領取並傳送至他給的 Line Notify。

  2. 看了一下文件發現 node-schedule 要在事後取消單一 job 好像有點困難,所以我如果要取消就是把所有取消,然後在伺服器重開之後所有 job 都會無效需要重新再打一次 API。
    目前想法是要用 DB 紀錄每個打進來的 user 狀態,重啟的時候依照狀態去決定要不要重新自動排程。

  3. 傳送進來的 request 格式其實我都沒做檢查,例外處理也沒做,整個不及格xDDD
    沒什想法,就是要花時間做。QQ

  4. 應該做一個可以查詢自己目前有沒有在自動領取的排程中,然後可以回傳說下次領取時間為何。

蠢事分享

我寫完之後 local 測試都正常,找了很久才發現是 ec2 時區跟我不一樣,我以為架設在日本就是日本,結果最後發現他還是 utc+0 ...
所以記得要設定時區,不要跟我一樣犯蠢。

sudo timedatectl set-timezone Asia/Taipei

以上
歡迎留言或私訊討論~
感謝你


尚未有邦友留言

立即登入留言