Skip to content

Commit

Permalink
Init first version
Browse files Browse the repository at this point in the history
  • Loading branch information
sailxjx committed Jan 29, 2016
1 parent c723444 commit 01e9ba5
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 16 deletions.
1 change: 1 addition & 0 deletions config/default.coffee
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports =
port: 8201
dbPath: 'db'
webhookUrl: null
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"graceful-logger": "^0.4.3",
"lodash": "^4.0.1",
"moment": "^2.11.1",
"nedb": "^1.7.2"
"nedb": "^1.7.2",
"request": "^2.69.0"
}
}
145 changes: 134 additions & 11 deletions src/bot.coffee
Original file line number Diff line number Diff line change
@@ -1,25 +1,148 @@
config = require 'config'
cron = require 'cron'
_ = require 'lodash'
Promise = require 'bluebird'
logger = require 'graceful-logger'
moment = require 'moment'
{CronJob} = cron
request = require 'request'

requestAsync = Promise.promisify request

model = require './model'
rules = require './rules'

class Bot

module.exports = (app) ->
isActive: ->
config.activeDate is moment().format('YYYYMMDD')

active: ->
config.activeDate = moment().format('YYYYMMDD')

bot = new Bot

_messageHandler = (req, res) ->
return res.status(400).send("Missing creator") unless req.body.creator

# 动态记录频道 id,以便发送记录
if req.body._storyId
config._targetId = req.body._storyId
config.targetType = 'story'
else if req.body._roomId
config._targetId = req.body._roomId
config.targetType = 'room'

bot.active()

checkinData =
_creatorId: req.body.creator._id
name: req.body.creator.name
time: Date.now()

model.addCheckin checkinData

.then ->

# 提取回复规则
replyRule = null
rules.replies.some (reply) ->
switch
when reply.match and req.body.body?.match(reply.match)
replyRule = reply
return true
else return false

return res.status(200).send('ok') unless replyRule

# 构造回复消息
replyMsg =
switch
when replyRule.msg
replyRule.msg = [replyRule.msg] if toString.call(replyRule.msg) is '[object String]'
replyMsg = replyRule.msg[_.random(0, replyRule.msg.length - 1)]

return res.status(200).send('ok') unless replyMsg

bot = new Bot
# 预处理回复消息
if rules.replaces
for key, val of rules.replaces
replyMsg = replyMsg.replace key, val

app.post '/messages', (req, res) ->
# 构造消息结构
message = content: replyMsg
# 回应消息
res.status(200).send message

return res.status(400).send({error: "Missing creator"}) unless req.body.creator
.catch (err) -> res.status(400).send error: err.message

_sendCheckinSummary = ->
return unless bot.isActive()
return unless rules.members and config._targetId and config.webhookUrl
model.getCheckins().then (checkins) ->
nonCheckMembers = rules.members.filter (memberName) ->
return false if checkins._creatorId is memberName
return false if checkins.name.indexOf(memberName) > -1
return true
if nonCheckMembers.length
msg = "#{nonCheckMembers.join('')} 这几个家伙还没签到,去哪儿啦?"
else
msg = "大家来的好早,每一位都签到啦"

message = content: msg

switch config.targetType
when 'story' then message._storyId = config._targetId
when 'room' then message._roomId = config._targetId
else return false

requestAsync
method: 'POST'
url: config.webhookUrl
json: true
body: message

.catch (err) -> logger.warn err.stack

_sendCronData = (cronData) ->

return ->

return unless bot.isActive()
return unless config.webhookUrl and config._targetId and cronData.msg

message = content: msg

switch config.targetType
when 'story' then message._storyId = config._targetId
when 'room' then message._roomId = config._targetId
else return false

console.log "Send message",
method: 'POST'
url: config.webhookUrl
json: true
body: message

requestAsync
method: 'POST'
url: config.webhookUrl
json: true
body: message
.catch (err) -> logger.warn err.stack

module.exports = (app) ->

checkinData =
_creatorId: req.body.creator._id
name: req.body.creator.name
time: Date.now()
app.post '/incoming', (req, res) ->
_messageHandler req, res

model.addCheckin checkinData
app.use (err, req, res, next) ->
res.status(500).send error: err.message

.then -> res.status(200).send ok: 1
new CronJob '0 0 10 * * 1-5', _sendCheckinSummary

.catch (err) -> res.status(400).send error: err.message
if rules.crons
for cronRule, cronData of rules.crons
new CronJob cronRule, _sendCronData(cronData)

bot
45 changes: 45 additions & 0 deletions src/rules.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
moment = require 'moment'

module.exports = rules =
replies: [
match: /.*/
msg: [
'%welcome,安排一下今天的计划吧~'
'%welcome,我是偷工减料的签到机器人'
'我实在是找不出还有什么话能回复了'
'您先忙着,我去去就来'
'你是猴子请来的救兵吗'
'我喊你一声你敢应吗'
]
]
# 列表中的成员如果没有签到,会在 10 点收到通知
members: [
'博深'
'陈涌'
'丹青'
'品章'
'砰砰'
'王连杰'
'王卫'
'晶鑫'
'王艺霖'
'徐亮'
'郁飞'
'晓连'
'俊官'
]
# 替换 msg 中的字符串
replaces:
'%welcome': ->
txt = ''
hour = moment().hour()
switch
when hour > 7 and hour < 9 then txt = '早上好'
when hour >= 9 and hour < 11 then txt = '上午好'
when hour >= 11 and hour < 13 then txt = '中午好'
when hour >=13 and hour < 18 then txt = '下午好'
else txt = '晚上好'
txt
crons:
'0 0 18 * * 1-5':
msg: '忙碌了一天,大家都辛苦啦,好好休息吧'
10 changes: 6 additions & 4 deletions test/main.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,31 @@ describe 'Bot', ->

it 'should record the first checkin time of user', (done) ->

request(app).post '/messages'
request(app).post '/incoming'
.set 'Content-Type': 'application/json'
.send
creator:
_id: 1
name: 'xxx'
body: 'Hello'
event: 'message.create'
.end (err, res) ->
res.body.should.eql ok: 1
res.statusCode.should.eql 200
done err

it 'should update the last visit time of user', (done) ->

# Checkin again
request(app).post '/messages'
request(app).post '/incoming'
.set 'Content-Type': 'application/json'
.send
creator:
_id: 1
name: 'xxx'
body: 'Hello Again'
event: 'message.create'
.end (err, res) ->
res.body.should.eql ok: 1
res.statusCode.should.eql 200
done err

it 'should get all the checkin data', (done) ->
Expand Down

0 comments on commit 01e9ba5

Please sign in to comment.