This commit is contained in:
Jay 2018-02-12 23:08:42 +08:00
commit c65d29e81a
14 changed files with 3021 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.env
node_modules
wstest.js

30
app.js Normal file
View File

@ -0,0 +1,30 @@
const Koa = require('koa')
const config = require('./config')
const path = require('path')
const app = new Koa()
// load koa middleware
const koaLogger = require('koa-morgan')
const koaSession = require('koa-session2')
const rootRouter = require('./route')
const koaRender = require('koa-ejs')
// set middleware
app.use(koaLogger('dev'))
app.use(koaSession())
app.use(rootRouter.allowedMethods())
app.use(rootRouter.routes())
koaRender(app, {
root: path.join(__dirname, 'views'),
layout: 'template',
viewExt: 'ejs',
cache: false,
debug: false
})
const server = app.listen(config.port, () => {
console.log(`server start on port ${server.address().port}`)
})
module.exports = server

19
config/index.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
port: process.env.PORT || 10230,
twitch: {
auth_url: 'https://api.twitch.tv/kraken/oauth2/authorize',
token_url: 'https://api.twitch.tv/kraken/oauth2/token',
chat_host: 'irc-ws.chat.twitch.tv',
chat_port: 443,
redirect_uri: process.env.REDIRECT_URI || '',
client_id: process.env.CLIENT_ID || '',
secret: process.env.SECRET || ''
},
database: {
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 5432,
user: process.env.DB_USER || 'postgres',
pass: process.env.DB_PASS || null,
db_name: process.env.DB_NAME || 'twitch_bot'
}
}

4
index.js Normal file
View File

@ -0,0 +1,4 @@
// load .env file
require('dotenv').config()
// load server
require('./app')

23
libs/botClient.js Normal file
View File

@ -0,0 +1,23 @@
const WebSocket = require('ws')
const config = require('../config')
const ws = new WebSocket(`wss://${config.twitch.chat_host}:443`, 'irc')
ws.on('open', () => {
})
ws.on('message', (data) => {
if (typeof data !== 'string') data = data.toString()
})
ws.on('error', (err) => {
console.error(err)
})
ws.on('close', (code, reason) => {
console.log('exit', code, reason)
})
module.exports = ws

2
libs/database.js Normal file
View File

@ -0,0 +1,2 @@
const pg = require('pg')
const config = require('../config')

9
libs/messageQueue.js Normal file
View File

@ -0,0 +1,9 @@
class MessageQueue {
constructor() {
this.queue = {}
}
}
module.exports = new MessageQueue()

50
libs/twitchParser.js Normal file
View File

@ -0,0 +1,50 @@
/**
* @param {string} msg
*/
const msgSplit = function (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]}`
}
}
// chat message
if (/^privmsg$/i.test(txtarr[1])) {
let user = txtarr[0].split('!')[0].substr(1)
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: '肛刺蝟'
}
}
}
}
}
module.exports = {
msgSplit
}

2733
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "twitch-bot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.17.1",
"debug": "^3.1.0",
"dotenv": "^5.0.0",
"koa": "^2.4.1",
"koa-body": "^2.5.0",
"koa-ejs": "^4.1.0",
"koa-morgan": "^1.0.1",
"koa-mount": "^3.0.0",
"koa-router": "^7.4.0",
"koa-session2": "^2.2.5",
"koa-static": "^4.0.2",
"pg": "^7.4.1",
"request": "^2.83.0",
"ws": "^4.0.0"
},
"devDependencies": {
"standard": "^10.0.3"
}
}

100
route/index.js Normal file
View File

@ -0,0 +1,100 @@
const Router = require('koa-router')
const r = new Router()
const config = require('../config')
const qs = require('querystring')
const request = require('request')
r.get('/', async (c, n) => {
await c.render('index')
})
r.get('/chat_login', async (c, n) => {
let url = config.twitch.auth_url
let qsObj = {
client_id: config.twitch.client_id,
redirect_uri: config.twitch.redirect_uri,
response_type: 'code',
scope: 'chat_login'
}
let qsStr = qs.stringify(qsObj)
let toUrl = `${url}?${qsStr}`
c.redirect(toUrl)
})
r.get('/login', async (c, n) => {
let url = config.twitch.auth_url
let qsObj = {
client_id: config.twitch.client_id,
redirect_uri: config.twitch.redirect_uri,
response_type: 'code',
scope: 'user_read'
}
let qsStr = qs.stringify(qsObj)
let toUrl = `${url}?${qsStr}`
c.redirect(toUrl)
})
r.get('/twitch/oauth', async (c, n) => {
let code = c.query.code || ''
if (!code) {
await c.render('test', {
data: {
msg: 'code not found'
}
})
return
}
let url = config.twitch.token_url
let qsObj = {
client_id: config.twitch.client_id,
client_secret: config.twitch.secret,
code,
grant_type: 'authorization_code',
redirect_uri: config.twitch.redirect_uri
}
let qsStr = qs.stringify(qsObj)
let toUrl = `${url}?${qsStr}`
let body = await new Promise((resolve, reject) => {
request.post(toUrl, (err, res, body) => {
if (err) {
reject(err)
return
}
try {
resolve(JSON.parse(body))
} catch (err) {
resolve(body)
}
})
})
let opts = {
url: 'https://api.twitch.tv/kraken/user',
headers: {
'Client-ID': config.twitch.client_id,
'Authorization': 'OAuth ' + body.access_token
},
method: 'get'
}
let userProfile = await new Promise((resolve) => {
request(opts, (err, res, body) => {
console.log('get profile', body)
if (err) {
resolve(null)
return
}
resolve(body)
})
})
await c.render('test', { data: { body, userProfile } })
})
module.exports = r

4
views/index.ejs Normal file
View File

@ -0,0 +1,4 @@
index page
<p>
<a href="/login">LoginTwitch</a>
</p>

12
views/template.ejs Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>TwitchBot</title>
</head>
<body>
<%- body %>
</body>
</html>

1
views/test.ejs Normal file
View File

@ -0,0 +1 @@
<%- JSON.stringify(data) %>