This commit is contained in:
Jay 2018-07-13 23:05:37 +08:00
commit 8b75f41d55
19 changed files with 199 additions and 48 deletions

View File

@ -5,6 +5,9 @@ RUN mkdir -p /data
WORKDIR /data WORKDIR /data
COPY . . COPY . .
RUN rm -f .env RUN rm -f .env
RUN apt-get update -qqy
RUN apt-get install -qqy imagemagick graphicsmagick
RUN apt-get clean
RUN npm install RUN npm install
EXPOSE ${NODE_PORT} EXPOSE ${NODE_PORT}
CMD ["npm", "run", "dbrun"] CMD ["npm", "run", "dbrun"]

View File

@ -6,7 +6,8 @@
{"file": "20180702-1.sql", "version": 4}, {"file": "20180702-1.sql", "version": 4},
{"file": "20180706-1.sql", "version": 5}, {"file": "20180706-1.sql", "version": 5},
{"file": "20180710-1.sql", "version": 6}, {"file": "20180710-1.sql", "version": 6},
{"file": "20180711-1.sql", "version": 7} {"file": "20180711-1.sql", "version": 7},
{"file": "20180712-1.sql", "version": 8}
], ],
"test": [] "test": []
} }

View File

@ -1,6 +1,7 @@
/* eslint-disable no-unused-expressions */ /* eslint-disable no-unused-expressions */
require('module-alias/register')
const pg = require('pg') const pg = require('pg')
const config = require('../config') const config = require('@config/index')
const path = require('path') const path = require('path')
const fs = require('fs') const fs = require('fs')

View File

@ -1,6 +1,7 @@
module.exports = { module.exports = {
port: process.env.NODE_PORT || 10230, port: process.env.NODE_PORT || 10230,
url: process.env.HOST_URL || '', url: process.env.HOST_URL || '',
image_root: process.env.IMAGE_ROOT || '/image',
line: { line: {
secret: process.env.LINE_SECRET || '', secret: process.env.LINE_SECRET || '',
access: process.env.LINE_ACCESS || '' access: process.env.LINE_ACCESS || ''

View File

@ -1,3 +1,4 @@
require('module-alias/register')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
try { try {

11
jsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@libs/*": ["libs/*"],
"@config/*": ["config/*"],
"@route/*": ["route/*"]
}
}
}

View File

@ -1,5 +1,5 @@
const axios = require('axios') const axios = require('axios')
const config = require('../../config') const config = require('@config/index')
const qs = require('querystring') const qs = require('querystring')
const queryYoutubeName = async (id = '') => { const queryYoutubeName = async (id = '') => {

View File

@ -1,5 +1,5 @@
const axios = require('axios') const axios = require('axios')
const config = require('../../config') const config = require('@config/index')
const client = axios.create({ const client = axios.create({
baseURL: 'https://api.line.me/v2/bot', baseURL: 'https://api.line.me/v2/bot',
@ -44,6 +44,16 @@ const textObject = (txt = '') => {
} }
} }
const imageObject = (txt = '') => {
if (typeof txt !== 'string' || txt.trim().length === 0) return null
txt = txt.split(';')
return {
type: 'image',
originalContentUrl: txt[0],
previewImageUrl: txt[1]
}
}
/** /**
* send reply message * send reply message
* @param {string} replyToken line message reply token * @param {string} replyToken line message reply token
@ -59,6 +69,7 @@ const replyMessage = async (replyToken, message) => {
if (m !== null && m.length > 1) { if (m !== null && m.length > 1) {
switch (m[1]) { switch (m[1]) {
case 'image': case 'image':
obj = imageObject(message)
break break
case 'text': case 'text':
obj = textObject(message) obj = textObject(message)
@ -66,6 +77,8 @@ const replyMessage = async (replyToken, message) => {
default: default:
obj = textObject(message) obj = textObject(message)
} }
} else {
obj = textObject(message)
} }
if (obj !== null) { if (obj !== null) {

View File

@ -1,5 +1,5 @@
const axios = require('axios') const axios = require('axios')
const config = require('../../config') const config = require('@config/index')
const client = axios.create({ const client = axios.create({
baseURL: 'https://api.twitch.tv/helix', baseURL: 'https://api.twitch.tv/helix',
headers: { headers: {

View File

@ -1,5 +1,5 @@
const pg = require('pg') const pg = require('pg')
const config = require('../config') const config = require('@config/index')
const pool = new pg.Pool({ const pool = new pg.Pool({
user: config.database.user, user: config.database.user,

View File

@ -1,5 +1,5 @@
const api = require('../../../api-action') const api = require('@libs/api-action')
const DB = require('../../../database') const DB = require('@libs/database')
const axios = require('axios') const axios = require('axios')
async function run (fn = null, txt, source) { async function run (fn = null, txt, source) {

View File

@ -1,4 +1,4 @@
const DB = require('../../database') const DB = require('@libs/database')
const actions = require('./actions') const actions = require('./actions')
const parseCMD = async (text = '', source = {}) => { const parseCMD = async (text = '', source = {}) => {
@ -7,7 +7,8 @@ const parseCMD = async (text = '', source = {}) => {
let txt = text.trim() let txt = text.trim()
let arr = txt.split(' ').map(t => t.trim()) let arr = txt.split(' ').map(t => t.trim())
if (arr.length === 0) return null if (arr.length === 0) return null
if (arr[0][0] !== '!') return null let cmdMsg = false
if (arr[0][0] === '!') cmdMsg = true
let cmd = arr[0].replace(/^!/, '') let cmd = arr[0].replace(/^!/, '')
cmd = cmd.toLowerCase() cmd = cmd.toLowerCase()
@ -16,6 +17,7 @@ const parseCMD = async (text = '', source = {}) => {
try { try {
// query normal command // query normal command
if (cmdMsg) {
let result = await db.query({ let result = await db.query({
text: `select "message", "group" from "public"."commands" where "cmd" = $1 and ("group" = '' or "group" = $2)`, text: `select "message", "group" from "public"."commands" where "cmd" = $1 and ("group" = '' or "group" = $2)`,
values: [cmd, source.groupId] values: [cmd, source.groupId]
@ -41,31 +43,44 @@ const parseCMD = async (text = '', source = {}) => {
} }
} }
} }
}
if (reply === null) { if (reply === null) {
console.log('enter key command')
// query keyword commands // query keyword commands
let keyCMD = await db.query({ let keyCMD = await db.query({
text: `select "message", "group", "cmd" from "public"."key_commands" where ("group" = '' or "group" = $1)`, text: `select "message", "group", "key" from "public"."key_commands" where ("group" = '' or "group" = $1)`,
values: [source.groupId] values: [source.groupId]
}) })
console.log(keyCMD.rows)
if (keyCMD.rowCount > 0) { if (keyCMD.rowCount > 0) {
let obj = keyCMD.rows.filter(t => t.group === '') let obj = keyCMD.rows.filter(t => t.group === '')
let obj2 = keyCMD.rows.filter(t => t.group === source.groupId) let obj2 = keyCMD.rows.filter(t => t.group === source.groupId)
obj = obj.map(t => { obj = obj.map(t => {
for (let i of obj2) { for (let i of obj2) {
if (i.cmd === t.cmd && i.group !== '') return i if (i.key === t.key && i.group !== '') return i
} }
return t return t
}) })
let tmp = obj2.filter(t => {
for (let i of obj) {
if (i.key === t.key) return false
}
return true
})
obj = [...obj, ...tmp]
let regex = null let regex = null
let txt = '' let txt = ''
console.log('obj ::: ', obj)
for (let i of obj) { for (let i of obj) {
txt += (txt.length > 0 ? '|' : '') + i.cmd txt += (txt.length > 0 ? '|' : '') + i.key
} }
regex = new RegExp(`(${txt})`) regex = new RegExp(`(${txt})`)
let m = arr.slice(1).join(' ').match(regex) console.log(regex)
let m = text.match(regex)
console.log('match :::: ', m)
if (m !== null && m.length > 0) { if (m !== null && m.length > 0) {
let key = obj.filter(t => t.cmd === m[0]) let key = obj.filter(t => t.key === m[0])
if (key.length > 0) { if (key.length > 0) {
let content = key[0].message let content = key[0].message
let m = content.match(/{{(.+?)}}/g) let m = content.match(/{{(.+?)}}/g)
@ -74,7 +89,7 @@ const parseCMD = async (text = '', source = {}) => {
let c = m[i].replace(/^{{/, '').replace(/}}$/, '') let c = m[i].replace(/^{{/, '').replace(/}}$/, '')
let carr = c.split('=') let carr = c.split('=')
if (carr.length > 1) c = carr if (carr.length > 1) c = carr
let res = await actions(c, arr.slice(1).join(' '), source) let res = await actions(c, text, source)
content = content.replace(m[i], res || '') content = content.replace(m[i], res || '')
} }
} }

View File

@ -1,6 +1,6 @@
const commands = require('./commands') const commands = require('./commands')
const api = require('../api-action')
const DB = require('@libs/database') const DB = require('@libs/database')
const api = require('@libs/api-action')
/** /**
* parse text message object * parse text message object

View File

@ -1,4 +1,4 @@
const config = require('../../config') const config = require('@config/index')
const rawBody = require('raw-body') const rawBody = require('raw-body')
const crypto = require('crypto') const crypto = require('crypto')

View File

@ -17,10 +17,12 @@
"cheerio": "^1.0.0-rc.2", "cheerio": "^1.0.0-rc.2",
"cron": "^1.3.0", "cron": "^1.3.0",
"dotenv": "^6.0.0", "dotenv": "^6.0.0",
"gm": "^1.23.1",
"koa": "^2.5.1", "koa": "^2.5.1",
"koa-body": "^4.0.3", "koa-body": "^4.0.3",
"koa-logger": "^3.2.0", "koa-logger": "^3.2.0",
"koa-router": "^7.4.0", "koa-router": "^7.4.0",
"module-alias": "^2.1.0",
"pg": "^7.4.3", "pg": "^7.4.3",
"raw-body": "^2.3.3", "raw-body": "^2.3.3",
"request": "^2.87.0", "request": "^2.87.0",
@ -28,5 +30,10 @@
}, },
"devDependencies": { "devDependencies": {
"standard": "^11.0.1" "standard": "^11.0.1"
},
"_moduleAliases": {
"@libs": "libs",
"@config": "config",
"@route": "route"
} }
} }

View File

@ -4,9 +4,9 @@ const r = new Router()
// const koaBody = require('koa-body') // const koaBody = require('koa-body')
const { const {
getRaw getRaw
} = require('../../libs/middleware') } = require('@libs/middleware')
const api = require('../../libs/api-action') const api = require('@libs/api-action')
const DB = require('../../libs/database') const DB = require('@libs/database')
r.get('/youtube/webhook', async (c, n) => { r.get('/youtube/webhook', async (c, n) => {
let db = await DB.connect() let db = await DB.connect()

View File

@ -1,5 +1,103 @@
const Router = require('koa-router') const Router = require('koa-router')
const r = new Router() const r = new Router()
const gm = require('gm')
const config = require('@config/index')
const fs = require('fs')
const path = require('path')
const getImageToRes = async (c, n) => {
let filepath = path.resolve(config.image_root, c.state.file)
console.log(filepath)
try {
fs.accessSync(filepath)
} catch (err) {
c.throw(404, 'image not found')
}
let buf = null
let imgSize = await getImageSize(filepath)
if (imgSize === null) c.throw(500)
if (c.state.ori === true) {
// max 1024x1024
if (imgSize.width > 1024 || imgSize.height > 1024) {
buf = await resizeImage(filepath, 1024)
if (buf === null) c.throw(500)
}
} else {
// max 240x240
if (imgSize.width > 240 || imgSize.height > 240) {
buf = await resizeImage(filepath, 240)
if (buf === null) c.throw(500)
}
}
if (buf === null) {
let format = await getImageFormat(filepath)
if (format === null) c.throw(500)
if (format !== 'JPEG') {
buf = await convertToJPEG(filepath)
if (buf === null) c.throw(500)
} else {
buf = fs.readFileSync(filepath)
}
}
c.type = 'image/jpeg'
c.body = buf
}
const convertToJPEG = async (file = null) => {
let buf = await new Promise((resolve) => {
gm(file).toBuffer('JPEG', (err, buf) => {
resolve(err ? null : buf)
})
})
return buf
}
const getImageFormat = async (file = null) => {
let format = await new Promise((resolve) => {
gm(file).format((err, format) => {
resolve(err ? null : format)
})
})
return format
}
const getImageSize = async (file = null) => {
let size = await new Promise((resolve) => {
gm(file).size((err, val) => {
resolve(err ? null : val)
})
})
return size
}
const resizeImage = async (file = null, size = 1024) => {
let buf = await new Promise((resolve) => {
gm(file).resize(size, size).toBuffer('JPEG', (err, buf) => {
resolve(err ? null : buf)
})
})
return buf
}
r.get('/image/origin/:name', async (c, n) => {
c.state.ori = true
let name = c.params.name || ''
if (typeof name !== 'string' || name.trim().length === 0) c.throw('image name not valid', 400)
c.state.file = name
return n()
}, getImageToRes)
r.get('/image/thumbnail/:name', async (c, n) => {
c.state.ori = false
let name = c.params.name || ''
if (typeof name !== 'string' || name.trim().length === 0) c.throw('image name not valid', 400)
c.state.file = name
return n()
}, getImageToRes)
r.use('/line', require('./line').routes()) r.use('/line', require('./line').routes())
r.use('/google', require('./google').routes()) r.use('/google', require('./google').routes())

View File

@ -4,10 +4,10 @@ const r = new Router()
const { const {
verifyLine, verifyLine,
getRaw getRaw
} = require('../../libs/middleware') } = require('@libs/middleware')
const { const {
textMessage textMessage
} = require('../../libs/line-message') } = require('@libs/line-message')
r.post('/', getRaw, verifyLine, async (c, n) => { r.post('/', getRaw, verifyLine, async (c, n) => {
console.log(JSON.stringify(c.request.body, null, 2)) console.log(JSON.stringify(c.request.body, null, 2))

View File

@ -2,9 +2,9 @@ const Router = require('koa-router')
const r = new Router() const r = new Router()
const { const {
getRaw getRaw
} = require('../../libs/middleware') } = require('@libs/middleware')
const DB = require('../../libs/database') const DB = require('@libs/database')
const api = require('../../libs/api-action') const api = require('@libs/api-action')
// const config = require('../../config') // const config = require('../../config')
r.get('/webhook', async (c, n) => { r.get('/webhook', async (c, n) => {