From 5ed1e462b33c3320cbb792709cac471bc2093258 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 10 Jul 2018 23:48:26 +0800 Subject: [PATCH] add youtube new video notify --- bin/dbVersion.json | 4 +- libs/api-action/google.js | 16 ++++- libs/line-message/commands/actions/group.js | 6 +- libs/line-message/commands/actions/index.js | 2 +- libs/line-message/index.js | 1 + route/google/index.js | 79 +++++++++++++++++++-- schema/20180710-1.sql | 2 + 7 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 schema/20180710-1.sql diff --git a/bin/dbVersion.json b/bin/dbVersion.json index ec4ccb4..82b2739 100644 --- a/bin/dbVersion.json +++ b/bin/dbVersion.json @@ -3,7 +3,9 @@ {"file": "main.sql", "version": 1}, {"file": "20180628-1.sql", "version": 2}, {"file": "20180628-2.sql", "version": 3}, - {"file": "20180702-1.sql", "version": 4} + {"file": "20180702-1.sql", "version": 4}, + {"file": "20180706-1.sql", "version": 5}, + {"file": "20180710-1.sql", "version": 6} ], "test": [] } \ No newline at end of file diff --git a/libs/api-action/google.js b/libs/api-action/google.js index 7eed6bc..22ae02a 100644 --- a/libs/api-action/google.js +++ b/libs/api-action/google.js @@ -1,5 +1,6 @@ const axios = require('axios') const config = require('../../config') +const qs = require('querystring') const queryYoutubeName = async (id = '') => { if (typeof id !== 'string' || id.trim().length === 0) return null @@ -16,11 +17,14 @@ const queryYoutubeName = async (id = '') => { method: 'get', params }) - if (!result || !('data' in result) || !('items' in result.data) || Array.isArray(result.data.items) || result.data.items.length === 0) return null + + if (!result || !('data' in result) || !('items' in result.data) || !Array.isArray(result.data.items) || result.data.items.length === 0) return null let data = result.data.items[0] + console.log('youtube data ::: ', JSON.stringify(data, null, 2)) if (!('snippet' in data) || !('title' in data.snippet)) return null return data.snippet.title } catch (err) { + console.log(err) return null } } @@ -32,6 +36,7 @@ const subYoutube = async (id = '') => { let data = { 'hub.mode': 'subscribe', + 'hub.verify': 'async', 'hub.topic': `https://www.youtube.com/xml/feeds/videos.xml?channel_id=${id}`, 'hub.callback': `${config.url.replace(/\/$/, '')}/google/youtube/webhook?id=${id}`, 'hub.lease_seconds': 86400 @@ -39,11 +44,16 @@ const subYoutube = async (id = '') => { try { await axios({ - data, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + data: qs.stringify(data), url, method: 'post' }) - } catch (err) {} + } catch (err) { + console.log(err) + } return null } diff --git a/libs/line-message/commands/actions/group.js b/libs/line-message/commands/actions/group.js index d80949d..97a0308 100644 --- a/libs/line-message/commands/actions/group.js +++ b/libs/line-message/commands/actions/group.js @@ -404,7 +404,9 @@ const addYoutube = async (txt = '', source = {}, db) => { return { reply } } + console.log('youtube id ::: ', id) let youtubeName = await api.google.queryYoutubeName(id) + console.log('youtubr name :::: ', youtubeName) if (youtubeName === null) return null text = `select "id" from "public"."youtube_channel" where "id" = $1` @@ -436,7 +438,9 @@ const addYoutube = async (txt = '', source = {}, db) => { try { await api.google.subYoutube(id) - } catch (err) {} + } catch (err) { + console.log(err) + } return { reply: 'add youtube channel success' diff --git a/libs/line-message/commands/actions/index.js b/libs/line-message/commands/actions/index.js index 51db6aa..d3595c3 100644 --- a/libs/line-message/commands/actions/index.js +++ b/libs/line-message/commands/actions/index.js @@ -27,7 +27,7 @@ const runAct = async (cmd, txt = '', source = {}) => { if (!cmd || typeof cmd !== 'string' || cmd.length === 0) return null if (!(cmd in cmds)) return null let result = await cmds[cmd](txt, source) - return result + return result.reply } module.exports = runAct diff --git a/libs/line-message/index.js b/libs/line-message/index.js index 1fdff7f..d911280 100644 --- a/libs/line-message/index.js +++ b/libs/line-message/index.js @@ -17,6 +17,7 @@ const textMessage = async (evt) => { let result = await commands(text, source) if (result === null) return if (typeof result === 'object' && 'reply' in result) { + console.log('reply message :::: ', result.reply) await api.line.replyMessage(replyToken, result.reply) } } diff --git a/route/google/index.js b/route/google/index.js index daa8a7f..b58f12b 100644 --- a/route/google/index.js +++ b/route/google/index.js @@ -5,17 +5,28 @@ const r = new Router() const { getRaw } = require('../../libs/middleware') -const { - textMessage -} = require('../../libs/line-message') +const api = require('../../libs/api-action') +const DB = require('../../libs/database') r.get('/youtube/webhook', async (c, n) => { + let db = await DB.connect() let mode = c.query['hub.mode'] || '' - let verifyToken = c.query['hub.verify_token'] || '' + // let verifyToken = c.query['hub.verify_token'] || '' let challenge = c.query['hub.challenge'] + let id = c.query['id'] || '' + if (mode) { - if (mode === 'subscribe') { + if (mode === 'subscribe' && typeof id === 'string' && id.trim().length > 0) { + let time = Math.floor((Date.now() + (86400 * 1000)) / 1000) + try { + await db.query({ + text: `update "public"."youtube_channel" set "expire" = $1, "mtime" = now() where "id" = $2`, + values: [time, id] + }) + } catch (err) { + console.log(err) + } c.status = 200 c.body = challenge } else { @@ -23,10 +34,66 @@ r.get('/youtube/webhook', async (c, n) => { c.body = '' } } + + db.release() }) r.post('/youtube/webhook', getRaw, async (c, n) => { - console.log(JSON.stringify(c.request.body, null, 2)) + let db = await DB.connect() + let xmlStr = c.request.raw.toString() + // console.log(xmlStr) + let data = await new Promise((resolve) => { + xml2js.parseString(xmlStr, (err, res) => { + if (err) return resolve(null) + resolve(res) + }) + }) + // console.log(JSON.stringify(data, null, 2)) + + try { + let ytid = data.feed.entry[0].id[0] + let title = data.feed.entry[0].title[0] + let link = data.feed.entry[0].link[0]['$']['href'] + let id = c.query['id'] || '' + + console.log(`yt: ${ytid} / link: ${link} / id: ${id}`) + + let text = `select rt."tmpl" as tmpl, line."id" as group from "public"."line_youtube_rt" rt + left join "public"."youtube_channel" ch + on ch."id" = rt."youtube" + left join "public"."line_group" line + on line."id" = rt."line" + where + ch."id" = $1 + and ch."lastvideo" != $2 + and line."notify" = true` + let values = [id, ytid] + let result = await db.query({ + text, + values + }) + if (result.rowCount > 0) { + result.rows.forEach(t => { + let msg = t.tmpl || '' + if (typeof msg !== 'string' || msg.trim().length === 0) { + msg = `${title || ''}\n${link}` + } else { + msg = msg.replace(/{link}/, link).replace(/{txt}/, title).replace(/\\n/, '\n') + } + api.line.pushMessage(t.group, msg).then(() => {}).catch(() => {}) + }) + } + await db.query({ + text: `update "public"."youtube_channel" set "lastvideo" = $1, "mtime" = now() where "id" = $2`, + values: [ytid, id] + }) + } catch (err) { + console.log(err) + } + + c.status = 200 + c.body = 'success' + db.release() }) module.exports = r diff --git a/schema/20180710-1.sql b/schema/20180710-1.sql new file mode 100644 index 0000000..0691673 --- /dev/null +++ b/schema/20180710-1.sql @@ -0,0 +1,2 @@ +insert into "public"."commands" ("cmd", "message", "ctime", "mtime", "group") values +('addyoutube', '{{addyoutube}}', now(), now(), ''); \ No newline at end of file