嗨~ 各位肥宅同袍,我是Robin。
咳咳嗯~
这篇要分享上次肥宅的第一步后续,
还没看的可以先回去看看,里面有这次小专案的故事背景动机,
来了各位!
经过我内心非常积极但实际行动缓慢的这一两週时间,
没日没夜的研究,终于先写出一个过渡品,
至少能满足现在我的需求。
实际上其实这两週睡得很好xDD,然后前几天同事约我去吃麦当劳,
我还是没有优惠券用 TAT
于是在这两天努力写出来xDD
更新一下现况
我把专案移动至 aws 的 ec2 了目前先自肥和身边週遭的朋友没有要造福大众一次解决了上篇的打 API 延迟和 Heroku 的机器休眠。然后我是用 ec2 免费套餐所以管控好使用方式基本上是不会造成费用的,像我就是设定 如果超过 0.5 美金就寄信提醒我。
(超级客家做法
就因为时不时要与同事增进感情吃麦当劳,没有优惠券整个就不对了,所以先行实施自肥计画,长远的就持续更新啰。
此篇学习目标 ◑ω◐ :
这篇目标也只有一个,每天自动领取并且通知我领到什么。
增加一个 API 并使用排程达到每天自动执行的目的。使用 LINE Notify 超级简单方便的服务来通知我抽到什么 。注意须知:
这目前只是我个人想做的专案,如果我构思上不够完整或是有更好的方式,可以在下面留言跟我交流,身为小菜鸡的我一定会努力尽我所能的学习,感恩。
如果你也是小菜鸡,也可以跟我提出你疑问 :+1:
如果我回答不出来太艰深的问题是很正常的~
因为~~~
增加一个 API 并使用排程达到每天自动执行的目的
先看成果
打 API 开始自动领取
Line Notify 主动通知
申请 Line Notify Token
至官方登入 点我连结
申请权杖(Token)
申请传送至1对1聊天室,并设定名称(我这边就乱取叫油光降临)
拿取 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
这两天实作过程中发现还有很多需要改进的地方...
目前窘境:
如果要分享给不会打 API 的人使用整个就是不可能,
(除非他愿意给出帐号密码,这样又不太妥。
所以可能需要一个介面让他输入帐号密码拿取 Token
-> 输入 Line Notify 的 Token
-> 介面按下送出自动领取并传送至他给的 Line Notify。
看了一下文件发现 node-schedule 要在事后取消单一 job 好像有点困难,所以我如果要取消就是把所有取消,然后在伺服器重开之后所有 job 都会无效需要重新再打一次 API。
目前想法是要用 DB 纪录每个打进来的 user 状态,重启的时候依照状态去决定要不要重新自动排程。
传送进来的 request 格式其实我都没做检查,例外处理也没做,整个不及格xDDD
没什想法,就是要花时间做。QQ
应该做一个可以查询自己目前有没有在自动领取的排程中,然后可以回传说下次领取时间为何。
蠢事分享
我写完之后 local 测试都正常,找了很久才发现是 ec2 时区跟我不一样,我以为架设在日本就是日本,结果最后发现他还是 utc+0
...
所以记得要设定时区,不要跟我一样犯蠢。
sudo timedatectl set-timezone Asia/Taipei
以上
欢迎留言或私讯讨论~
感谢你