From 51951f769742bc2fbb9d4d227dd6069f0a65b44c Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 13 Feb 2018 00:34:26 +0800 Subject: [PATCH] update --- config/index.js | 3 +- libs/botClient.js | 61 ++++++++++++++++++++++++++++++- libs/messageQueue.js | 3 +- libs/twitchParser.js | 87 ++++++++++++++++++++++++++++++-------------- package.json | 1 + 5 files changed, 123 insertions(+), 32 deletions(-) diff --git a/config/index.js b/config/index.js index 5f99a16..f3e43fc 100644 --- a/config/index.js +++ b/config/index.js @@ -7,7 +7,8 @@ module.exports = { chat_port: 443, redirect_uri: process.env.REDIRECT_URI || '', client_id: process.env.CLIENT_ID || '', - secret: process.env.SECRET || '' + secret: process.env.SECRET || '', + refresh_token: process.env.REFRESH_TOKEN || '' }, database: { host: process.env.DB_HOST || 'localhost', diff --git a/libs/botClient.js b/libs/botClient.js index dc993c1..9fc2478 100644 --- a/libs/botClient.js +++ b/libs/botClient.js @@ -1,14 +1,71 @@ const WebSocket = require('ws') const config = require('../config') +const dbPool = require('./database') +const request = require('request') +const log = require('debug')('BOT:IRC') +const { msgSplit } = require('./twitchParser') const ws = new WebSocket(`wss://${config.twitch.chat_host}:443`, 'irc') -ws.on('open', () => { +ws.on('open', async () => { + let db = await dbPool.connect() + let body = null + try { + let options = { + method: 'POST', + url: config.twitch.token_url, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json' + }, + form: { + grant_type: 'refresh_token', + refresh_token: config.twitch.refresh_token, + client_id: config.twitch.client_id, + client_secret: config.twitch.secret + } + } + body = await new Promise((resolve, reject) => { + request(options, function (error, response, body) { + if (error) { + reject(error) + return + } + console.log(response.statusCode) + resolve(body) + }) + }) + } catch (err) { + console.log(err) + } + console.log(typeof body) + if (body === null || !('access_token' in body)) throw new Error('access token not found') + + ws.send('PASS oauth:' + body.access_token) + ws.send('NICK mtfosbot') + ws.send('CAP REQ :twitch.tv/membership :twitch.tv/commands') + + let query = `select "name", "join" from "public"."channels" where "join" = $1` + let param = [true] + let result = await db.query(query, param) + if (result !== null && result.rows.length > 0) { + for (let row of result.rows) { + if ('name' in row) { + ws.send('JOIN #' + row.name) + } + } + } }) ws.on('message', (data) => { - if (typeof data !== 'string') data = data.toString() + let d = data.toString() + let darr = d.split(/\n/).filter(t => t).map(t => t.replace(/\r$/, '')) + + for (let i in darr) { + log(darr[i]) + msgSplit(ws, darr[i]).then(() => { }) + } }) ws.on('error', (err) => { diff --git a/libs/messageQueue.js b/libs/messageQueue.js index 6062391..49c5875 100644 --- a/libs/messageQueue.js +++ b/libs/messageQueue.js @@ -1,8 +1,7 @@ class MessageQueue { - constructor() { + constructor () { this.queue = {} - } } diff --git a/libs/twitchParser.js b/libs/twitchParser.js index 0cba6a3..ffc6115 100644 --- a/libs/twitchParser.js +++ b/libs/twitchParser.js @@ -1,50 +1,83 @@ +const dbPool = require('./database') /** + * @param {WebSocket} ws * @param {string} msg */ -const msgSplit = function (msg) { +const msgSplit = async function (ws, msg) { if (!msg || typeof msg !== 'string') return null let txtarr = msg.split(' ') if (txtarr.length > 2) { if (/^ping$/i.test(txtarr[0])) { - return { - type: 'ack', - msg: `PONG ${txtarr[1]}` - } + ws.send(`PONG ${txtarr[1]}`) + return } // chat message if (/^privmsg$/i.test(txtarr[1])) { let user = txtarr[0].split('!')[0].substr(1) + if (user === 'mtfosbot') return let channel = txtarr[2] txtarr = txtarr.slice(3, txtarr.length) - let m = txtarr.join(' ').substr(1) - if (m.startsWith('!刺蝟')) { - return { - type: 'msg', - channel, - user, - msg: '女裝呢!!!?' - } - } else if (m.startsWith('!zoe')) { - return { - type: 'msg', - channel, - user, - msg: '跟KKBOX犯沖' - } - } else if (m.startsWith('!紫色')) { - return { - type: 'msg', - channel, - user, - msg: '肛刺蝟' - } + + let result = await parseCMD(user, channel, m) + if (result && typeof result === 'string') { + ws.send(`PRIVMSG ${channel} :${result}`) } } } } +/** + * + * @param {string} user + * @param {string} channel + * @param {string} msg + */ +const parseCMD = async function (user, channel, msg) { + let db = await dbPool.connect() + let m = null + try { + let txt = msg.trim().split(' ') + let ch = channel[0] === '#' ? channel.substr(1) : channel + if (txt.length < 1) { + await db.end() + return null + } + // add cmd + if (/^!\+/.test(txt[0])) { + let cmd = txt[0].substr(2) + let tmpmsg = txt.slice(1, txt.length).join(' ') + let query = `insert into "public"."commands" ("command", "channel", "message") values + ($1, $2, $3) + on conflict ("command", "channel") do update set + "message" = $3, + "active" = true` + let param = [cmd, ch, tmpmsg] + await db.query(query, param) + } else if (/^!-/.test(txt[0])) { + let cmd = txt[0].substr(2) + let query = `update "public"."commands" set "active" = $1 where "command" = $2 and "channel" = $3` + let param = [false, cmd, ch] + await db.query(query, param) + m = `command "${cmd}" has removed` + } else if (/^!/.test(txt[0])) { + let cmd = txt[0].substr(1) + let query = `select "message", "command" from "public"."commands" where "command" = $1 and "channel" = $2 and "active" = $3 limit 1` + let param = [cmd, ch, true] + let result = await db.query(query, param) + if (result === null || result.rows.length === 0) return null + m = result.rows[0].message + } + } catch (err) { + console.error(err) + } finally { + await db.end() + } + + return m +} + module.exports = { msgSplit } diff --git a/package.json b/package.json index a234b29..5d1a32f 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "main": "index.js", "scripts": { + "check": "standard --fix --verbose", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [],