Skip to content

Commit

Permalink
Merge pull request #10 from Astrian/dev
Browse files Browse the repository at this point in the history
Add new features
  • Loading branch information
Astrian Zheng authored Apr 8, 2019
2 parents d4d7135 + f8c758e commit e95141a
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 75 deletions.
27 changes: 27 additions & 0 deletions api/importrsvp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Import Airtable API and config
const Airtable = require('airtable');
const debug = require('debug')('rsvpbot:importrsvp.js')

// Import RSVP base
const base = new Airtable({apiKey: process.env.AIRTABLE_TOKEN}).base(process.env.BASE_ID);

module.exports = async function (faction, location, rsvplist) {
let counter = 0
for (let i in rsvplist) {
// check agent imported
let agentsbase = await base(location).select({
view: "Grid view",
filterByFormula: `{特工代号} = '${rsvplist[i]}'`
}).firstPage()
if (agentsbase.length) { debug(`特工 ${rsvplist[i]} 已在本场有所记录,将被忽略。`) }
else {
// if the agent not be logged into sheet, add a record for him/her
let newrec = {}
newrec['特工代号'] = rsvplist[i]
newrec['阵营'] = faction
await base(location).create(newrec)
counter++
}
}
return `有 ${counter} 位特工的 RSVP 信息成功被录入。`
}
5 changes: 3 additions & 2 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module.exports = {
checkapstatus: require('./checkapstatus'),
checkupagents: require('./checkupagents'),
checkstatus: require('./checkstatus'),
logaplevel: require('./logaplevel'),
logdata: require('./logdata'),
checkoutstatus: require('./checkoutstatus'),
cancelaprec: require('./cancelaprec')
cancelaprec: require('./cancelaprec'),
importrsvp: require('./importrsvp')
}
6 changes: 4 additions & 2 deletions api/logaplevel.js → api/logdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ const debug = require('debug')('rsvpbot:logaplevel.js')
// Import RSVP base
const base = new Airtable({apiKey: process.env.AIRTABLE_TOKEN}).base(process.env.BASE_ID);

module.exports = async function (faction, location, level, ap, operator) {
debug(faction, location, level, ap, operator)
module.exports = async function (faction, location, level, ap, trekker, operator) {
debug(faction, location, level, ap, trekker, operator)
// get agent record
let agentsbase = await base(location).select({
view: "Grid view",
Expand All @@ -20,12 +20,14 @@ module.exports = async function (faction, location, level, ap, operator) {
data['已签到'] = true
data['入场初始经验'] = parseInt(ap)
data['入场初始等级'] = level
data['入场步行距离'] = parseInt(trekker)
data['正在登记经验值'] = null
data['操作人'] = null
}
else if (record.get('正在登记经验值') === 2) {
data['活动结束经验'] = parseInt(ap)
data['活动结束等级'] = level
data['活动结束步行距离'] = parseInt(trekker)
data['正在登记经验值'] = null
data['操作人'] = null
}
Expand Down
44 changes: 38 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ telegrafbot.telegram.setWebhook(process.env.DOMAIN + process.env.RANDOM_ADDRESS)
telegrafbot.command('start', async (ctx) => {
try {
let info = await API.checkpoc(ctx.message.from.id)
telegrambot.sendMessage(ctx.message.from.id, `欢迎你,${info.location}${info.faction} PoC。\n/checkin - 进行签到\n/checkout - 进行签退`, {parse_mode: "Markdown"})
telegrambot.sendMessage(ctx.message.from.id, `欢迎你,${info.location}${info.faction} 签到人员。\n\n/importrsvp - 导入你所在阵营的特工\n/checkin - 进行签到\n/checkout - 进行签退`, {parse_mode: "Markdown"})
} catch (err) {
telegrambot.sendMessage(ctx.message.from.id, err, {parse_mode: "Markdown"})
}
Expand Down Expand Up @@ -101,6 +101,37 @@ telegrafbot.command('cancelaprec', async (ctx) => {
telegrambot.sendMessage(ctx.message.from.id, err, {parse_mode: "Markdown"})
}
})
telegrafbot.command('importrsvp', async (ctx) =>{
try {
let info = await API.checkpoc(ctx.message.from.id)

// if user only send the '/importrsvp' command, reply the help infomation
if (ctx.message.text.slice(12) === '') {
let reply = ''
reply += '请以 `/importrsvp+空格+RSVP 玩家列表` 的形式,来导入你所管理阵营的签到/签退特工。例如:\n'
reply += '```\n'
reply += '/importrsvp sampleagent1\n'
reply += 'sampleagent2\n'
reply += 'sampleagent3\n'
reply += '```\n'
reply += '小提示:直接从 FevGames 中复制特工列表并直接粘贴,效率更高噢,但请记得在指令后添加一个空格。'
throw reply
}

// process list into array
let list = (ctx.message.text.slice(12)).split('\n')

// import info
let recinfo = await API.importrsvp(info.faction, info.location, list)

// output list result
telegrambot.sendMessage(ctx.message.from.id, recinfo, {parse_mode: "Markdown"})
} catch (err) {
console.log('error accourd!')
console.log(err)
telegrambot.sendMessage(ctx.message.from.id, err, {parse_mode: "Markdown"})
}
})

// Inline button
telegrafbot.on('callback_query', async (ctx) => {
Expand Down Expand Up @@ -142,7 +173,7 @@ telegrafbot.on('callback_query', async (ctx) => {
ctx.update.callback_query.from.id,
ctx.update.callback_query.message.message_id,
null,
`请在消息框中写上 agent ${(ctx.update.callback_query.data.split(':'))[1]} 目前等级和 AP,以半角逗号 \`,\` 区隔。\n例如:\`16,40000000\`(大部分设备点击/长按示例可复制)`,
`请在消息框中写上 agent ${(ctx.update.callback_query.data.split(':'))[1]} 目前等级、AP 和步行距离数据,以半角逗号 \`,\` 区隔。\n例如:\`16,40000000,2500\`(大部分设备点击/长按示例可复制)`,
{
parse_mode: 'Markdown'
}
Expand Down Expand Up @@ -190,7 +221,7 @@ telegrafbot.on('callback_query', async (ctx) => {
ctx.update.callback_query.from.id,
ctx.update.callback_query.message.message_id,
null,
`请在消息框中写上 agent ${(ctx.update.callback_query.data.split(':'))[1]} 目前等级和 AP,以半角逗号 \`,\` 区隔。\n例如:\`16,40000000\`(大部分设备点击/长按示例可复制)`,
`请在消息框中写上 agent ${(ctx.update.callback_query.data.split(':'))[1]} 目前等级、AP 和步行距离数据,以半角逗号 \`,\` 区隔。\n例如:\`16,40000000,2500\`(大部分设备点击/长按示例可复制)`,
{
parse_mode: 'Markdown'
}
Expand Down Expand Up @@ -233,11 +264,12 @@ telegrafbot.on('callback_query', async (ctx) => {
}
})

// recive AP/Level
telegrafbot.hears(new RegExp(/\d{1,2},\d{1,}/), async (ctx) => {
// recive AP/Level/trekker data
telegrafbot.hears(new RegExp(/\d{1,2},\d{1,},\d{1,}/), async (ctx) => {
try {
if (parseInt(ctx.message.text.split(',')[0]) > 16 || parseInt(ctx.message.text.split(',')[0]) < 1) throw `等级错误,请尝试重新输入。`
let info = await API.checkpoc(ctx.message.from.id)
await API.logaplevel(info.faction, info.location, (ctx.message.text.split(','))[0], (ctx.message.text.split(','))[1], ctx.message.from.id)
await API.logdata(info.faction, info.location, (ctx.message.text.split(','))[0], (ctx.message.text.split(','))[1], (ctx.message.text.split(','))[2], ctx.message.from.id)
telegrambot.sendMessage(ctx.message.from.id, `签到/签退已完成。`, {parse_mode: "Markdown"})
} catch (err) {
telegrambot.sendMessage(ctx.message.from.id, err, {parse_mode: "Markdown"})
Expand Down
11 changes: 8 additions & 3 deletions debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ async function main(tgid) {
debug('completed')
debug('\n')

debug('importing rsvp list...')
let list = ['sampleagent', 'sampleplayer']
let recinfo = await API.importrsvp(info.faction, info.location, list)
debug(recinfo)

debug('fetching agents first-letter list with checkin...')
let firstletterdict = await API.checkupagents(info.faction, info.location, null, 'in', tgid)
debug(firstletterdict)
Expand All @@ -29,7 +34,7 @@ async function main(tgid) {
debug('\n')

debug('set agent "sampleagent" ap and level with checkin')
await API.logaplevel(info.faction, info.location, '16', 40000000, tgid)
await API.logdata(info.faction, info.location, '16', 40000000, 2500, tgid)
debug('\n')

debug('fetching agents first-letter list with checkout...')
Expand All @@ -42,12 +47,12 @@ async function main(tgid) {
debug(kagentslist)
debug('\n')

debug('set agent Kirrior into ap-logging status')
debug('set agent "sampleagent" into ap-logging status')
await API.checkstatus(info.faction, info.location, 'sampleagent', 'out', tgid)
debug('\n')

debug('set agent "sampleagent" ap and level with checkout')
await API.logaplevel(info.faction, info.location, '16', 50000000, tgid)
await API.logdata(info.faction, info.location, '16', 50000000, 2600, tgid)
debug('\n')

debug('debug test done.')
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ifs-rsvp-bot",
"version": "1.0.0",
"version": "0.3.0",
"description": "",
"engines": {
"node": "10.x"
Expand Down
69 changes: 8 additions & 61 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,31 @@
# IFS RSVP 登记助手机器人

[![部署至 Heroku](https://img.shields.io/badge/Deploy-to%20Heroku-6762a6.svg?logo=heroku)](https://heroku.com/deploy) [![机器人更新频道](https://img.shields.io/badge/Channel-%40ifsrsvpbot-blue.svg?logo=telegram)](https://t.me/ifsrsvpbot) [![机器人反馈群](https://img.shields.io/badge/Group-Click_to_join-blue.svg?logo=telegram)](https://t.me/joinchat/A0P0mxHipaEeJ-4vzKgTuQ)

## 介绍 & 功能
这是一款专用于 Ingress First Saturday 活动中 PoC 统计到场人员 RSVP、AP 与等级情况的 Telegram Bot。

目前拥有功能:

- 一键部署至 Heroku
- 快速从 FevGames 导入 RSVP 数据
- 快速签到 / 签退
- 登记玩家等级与 AP(经验值)
- 登记玩家等级、AP(经验值)与 Trekker(步行里程)数据
- 限定 PoC 访问 Bot,支持多 PoC 操作
- 联动 Airtable 服务,快速根据 AP 差额生成全阵营榜单、独立阵营榜单,并可链接访问

## 部署方法
### 准备 AirTable

你需要一个 Airtable 帐户(如果没有,[点击这里注册](https://airtable.com/invite/r/TCqAJZhy))。

访问 [示例库](https://airtable.com/invite/l?inviteId=inv61JtROyXz3yLfa&inviteToken=d27558b20f20a5f78c5768cbd11a914e41e21faf3e7916fd4ab569f17f2778f5)

在 Bases 中,点击「Add a workspace」来新建一个工作空间,你可以任意定名你的工作空间。

![新工作空间示例](https://i.imgur.com/VjKJ0et.png)

在 Bases 中的「IFS Base Sample」空间中,点击「Base Sample」右下角的箭头,选择「Duplicate base」,然后在 Choose workspace 中找到你刚才新建的工作空间。切记关闭「Duplicate records」选项。

![复制 Base](https://i.imgur.com/puxE12J.png)

进入你刚才复制的 Base 中。给表格改个名字,改成 IFS 所在地区的名字。如果你所在城市有多场 IFS,那么可以选择「Duplicate table」,并用相同方式,为新表改名为另一个地区的名字。

![改名字](https://i.imgur.com/lxpozq6.png)

在表中登记 agents 信息。只需要登记特工代号和阵营即可。

然后,[进入你的 Airtable 设置](https://airtable.com/account),点击「Generate API Key」并保留你的 API 密钥。

然后到 [API 文档](https://airtable.com/api),找到你刚才复制的 Base(如果你没有改 Base 的名字,那它应该是「Base Sample Copy」)。

按照下图,找到你的 base 的 ID(右侧选中部分)。保留好。

![获取 Base ID](https://i.imgur.com/5zPDjFQ.png)

## 准备 Telegram bot

[BotFather](https://t.me/botfather) 对话,新建一个 bot。BotFather 会在创建 bot 之后给你这个 bot 的 token(形如 `123456:1234567890ABCDEFGabcdefg`),保留它。

然后 ENL PoC 和 RES PoC 各向 [Get ID Bot](https://t.me/get_id_bot) 发送一条消息。这个 bot 会将你的数字 ID 返回给你(`Your Chat ID = 000000`,后面的数字就是你的数字 ID)。也要保留它。

## 部署至 Heroku

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

点击以上按钮进入部署页面(如果你还没有注册 Heroku,上面的链接也可以进入注册),然后填写一堆上面刚刚收集好的信息:

- `AIRTABLE_TOKEN`:Airtable 帐户 API 密钥。
- `BASE_ID`:Airtable 库 ID。
- `DOMAIN`:你先填好页面上方的 `App name`,那么这一项就是 `https://<App name>.herokuapp.com`。切记 `https://` 开头,末尾不要有 `/`
- `IFS_INFO`:填写 IFS 场次的 JSON 信息(后文给示例)。
- `RANDOM_ADDRESS`:以 `/` 开头,然后随便输入一些符合 URL 规范的字符串。
- `TELEGRAM_TOKEN`:BotFather 给你的 bot token。

`IFS_INFO` 的示例如下:

```
[{"location":"南海","enlpoc":[123456,789012],"respoc":[345678,901234]}]
```

```
[{"location":"天河","enlpoc":[123456],"respoc":[789012]},{"location":"海珠","enlpoc":[345678],"respoc":[901234]}]
```
点击以下按钮可进行快速部署。

其中:
[![部署至 Heroku](https://img.shields.io/badge/Deploy-to%20Heroku-6762a6.svg?logo=heroku)](https://heroku.com/deploy)

- `location` 字段要与上面你自己改的表格名字一样,否则 bot 无法读取是哪一场 IFS 活动的名单。
- `enlpoc` 字段填写 ENL PoC 的 Telegram 数字 ID,以数组包裹。
- `respoc` 字段填写 RES PoC 的 Telegram 数字 ID,以数组包裹。
有关快速部署的详细说明,敬请参阅「[快速部署指南](https://github.com/Astrian/IFS-RSVP-Bot/wiki/QuickDeployGuide)」。如果你需要对 bot 进行定制化修改,敬请参阅「[高级部署指南](https://github.com/Astrian/IFS-RSVP-Bot/wiki/AdvancedDeployGuide)」。

## TODO

- ~~支援多个 PoC 进行操作~~(已经支持)
- 快速登记 RSVP 信息
- ~~快速登记 RSVP 信息~~(已经支持)
- OCR 识别 agent AP/等级资料

## License & Disclaimer
Expand Down

0 comments on commit e95141a

Please sign in to comment.