Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
feat: 🎸 增加 /login api,并作为默认推荐登录api & 代码和文案优化
Browse files Browse the repository at this point in the history
  • Loading branch information
chentianyu authored and danni-cool committed Oct 11, 2023
1 parent 5ea7b60 commit b3012e4
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PORT=3001
# 如果想自己处理收到消息的逻辑,在下面填上你的API地址, 默认为空
LOCAL_RECVD_MSG_API=
# 登录地址Token访问地址: http://localhost:3001/loginCheck?token=[LOCAL_LOGIN_API_TOKEN]
# 登录地址Token访问地址: http://localhost:3001/login?token=[LOCAL_LOGIN_API_TOKEN]
# 生成规则:src/utils/index.js -> generateToken
LOCAL_LOGIN_API_TOKEN=
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ curl --location --request POST 'http://localhost:3001/webhook/msg' \
| type | 表单类型 | `String` | `text` / `img` | |
| content | 传输的内容,文件也放在这个字段,如果是图片收到的就是二进制buffer, 如果 `isSystemEvent` 为 '1', 将收到 JSON String | `String` / `Binary` | | [示例](docs/recvdApi.example.md#formdatacontent) |
| source | 消息的相关发送方数据, JSON String | `String` | | [示例](docs/recvdApi.example.md#formdatasource) |
| isSystemEvent | 是否是来自系统消息事件(比如上线,掉线、异常事件)| `String` | 1 / 0 | |
| isSystemEvent | 是否是来自系统消息事件(比如上线,掉线、异常事件)| `String` | `1` `0` | |

### 3. 登录APi

Expand All @@ -156,8 +156,7 @@ curl --location --request POST 'http://localhost:3001/webhook/msg' \
#### 解决方案:

1. 在异常或者掉线事件触发后,通知你配置的 `RECVD_MSG_API`
2. 在收到通知后,访问登录 Api 处理扫码登录逻辑,外网映射
访问 http://localhost:3001/loginCheck?token=YOUR_PERSONAL_TOKEN。
2. 在收到通知后,访问登录 Api 扫码登录 http://localhost:3001/login?token=YOUR_PERSONAL_TOKEN。

ps: 有更好的方案 ✨[欢迎交流](/~https://github.com/danni-cool/docker-wechatbot-webhook/issues/22)

Expand All @@ -168,13 +167,13 @@ token 初次启动项目会自动生成,你也可以配置一个简单好记
1. docker 启动,参数为 -e LOGIN_API_TOKEN="YOUR_PERSONAL_TOKEN"
2. `.env` 文件中,配置 LOCAL_LOGIN_API_TOKEN=YOUR_PERSONAL_TOKEN

#### 请求体

- Methods: `GET`
- URL: http://localhost:3001/loginCheck?token=YOUR_PERSONAL_TOKEN

#### 返回体
| API 路径 | Query Params | Methods | 描述 |
|--|--|--|--|
| /login | token | `GET` | 登录成功,返回及当前用户。登录态掉了,跳转最新的登录二维码 |
| /loginCheck | token | `GET` | 获取登录状态 API,始终返回 json 格式,登录二维码在登录失败会放在 `message`|

##### /loginCheck 返回体
| JSON | 说明 | 数据类型 | 可选值 |
|--|--|--|--|
| success | 登录成功与否 | `Boolean` | `true` / `false` |
Expand Down
15 changes: 15 additions & 0 deletions src/middleware/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const fs = require('fs');
const path = require('path');

// 获取当前目录下的所有文件
const files = fs.readdirSync(__dirname);

files.forEach(file => {
// 排除当前的 index.js 文件
if (file !== 'index.js') {
// 导入文件
const module = require(path.join(__dirname, file));
// 导出文件中的所有内容
Object.assign(exports, module);
}
});
13 changes: 13 additions & 0 deletions src/middleware/verifyToken.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Token verification middleware
module.exports.verifyToken = (req, res, next) => {
const { token } = req.query;

if (token !== process.env.globalLoginToken) {
return res.status(401).json({
success: false,
message: 'Unauthorized: Access is denied due to invalid credentials.'
});
}

next();
};
2 changes: 1 addition & 1 deletion src/route/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// 此处批量管理注册的webhook
const registerMsgPusherRouter = require('./msg')
const registerLoginCheck = require('./loginCheck')
const registerLoginCheck = require('./login')

module.exports = function registerRoute({app, bot}) {
registerMsgPusherRouter({app, bot})
Expand Down
45 changes: 21 additions & 24 deletions src/route/loginCheck.js → src/route/login.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { sendMsg2RecvdApi } = require('../service/webhook')
const Service = require('../service')
const Middleware = require('../middleware')
const { TextMsg } = require('../utils/msg')

// 登录
Expand All @@ -19,7 +20,7 @@ module.exports = function registerLoginCheck({ app, bot }) {
success = true
currentUser = user
logOutWhenError = false
sendMsg2RecvdApi(new TextMsg({
Service.sendMsg2RecvdApi(new TextMsg({
text: JSON.stringify({ event: 'login', user }),
isSystemEvent: true
}))
Expand All @@ -29,21 +30,21 @@ module.exports = function registerLoginCheck({ app, bot }) {
currentUser = null
success = false
// 登出时给接收消息api发送特殊文本
sendMsg2RecvdApi(new TextMsg({
Service.sendMsg2RecvdApi(new TextMsg({
text: JSON.stringify({ event: 'logout', user }),
isSystemEvent: true
}))
})
.on('error', error => {
// 报错时接收特殊文本
sendMsg2RecvdApi(new TextMsg({
Service.sendMsg2RecvdApi(new TextMsg({
text: JSON.stringify({ event: 'error', error, user: currentUser }),
isSystemEvent: true
}))

// 处理异常错误后的登出上报,每次登录成功后掉线只上报一次
if (!logOutWhenError && !bot.isLoggedIn) {
sendMsg2RecvdApi(new TextMsg({
Service.sendMsg2RecvdApi(new TextMsg({
text: JSON.stringify({ event: 'logout', user: currentUser }),
isSystemEvent: true
}))
Expand All @@ -54,28 +55,24 @@ module.exports = function registerLoginCheck({ app, bot }) {
}
})

// 处理 POST 请求
app.get('/loginCheck', async (req, res) => {

// getLoginApiToken
const { token } = req.query

if (token !== process.env.globalLoginToken) {
return res.status(401).json({
success: false,
message: 'Unauthorized: Access is denied due to invalid credentials.'
});
}

try {
app.get('/login', Middleware.verifyToken, Service.handleError(async (req, res) => {
// 登录成功的话,返回登录信息
if (success) {
res.status(200).json({
success,
message
})

} catch (error) {
console.error('Error handling POST request:', error);
res.status(500).json({ success: false, message: 'Internal server error.' });
} else {
res.redirect(301, message);
}
});

}));


app.get('/loginCheck', Middleware.verifyToken, Service.handleError(async (req, res) => {
res.status(200).json({
success,
message
})
}));
}
8 changes: 4 additions & 4 deletions src/route/msg.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const { formatAndSendMsg } = require('../service/msg')
const Service = require('../service')
const Middleware = require('../middleware')
const { getUnvalidParamsList } = require('../utils/index')
const { dynamicStorageMiddleware } = require('../middleware/fileUpload')

module.exports = function registerPushHook({ app, bot }) {

// 处理 POST 请求
app.post('/webhook/msg', dynamicStorageMiddleware, async (req, res) => {
app.post('/webhook/msg', Middleware.dynamicStorageMiddleware, async (req, res) => {
try {
let to, isRoom, content, type
let unValidParamsStr = ''
Expand Down Expand Up @@ -52,7 +52,7 @@ module.exports = function registerPushHook({ app, bot }) {
await bot.Contact.find({ name: to })

if (msgReceiver) {
const sendStatus = await formatAndSendMsg({ bot, type, content, msgInstance: msgReceiver, res })
const sendStatus = await Service.formatAndSendMsg({ bot, type, content, msgInstance: msgReceiver, res })
res.status(200).json({ success: sendStatus, message: `Message sent ${sendStatus ? 'successfully' : 'failed'}.` });
} else {
res.status(200).json({ success: false, message: `${isRoom ? 'Room' : 'User'} is not found` });
Expand Down
9 changes: 9 additions & 0 deletions src/service/errorHandle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Error handling middleware
module.exports.handleError = (fn) => {
return async (req, res) => {
fn(req, res).catch(error => {
console.error('Error handling request:', error);
res.status(500).json({ success: false, message: 'Internal server error.' });
});
}
};
15 changes: 15 additions & 0 deletions src/service/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const fs = require('fs');
const path = require('path');

// 获取当前目录下的所有文件
const files = fs.readdirSync(__dirname);

files.forEach(file => {
// 排除当前的 index.js 文件
if (file !== 'index.js') {
// 导入文件
const module = require(path.join(__dirname, file));
// 导出文件中的所有内容
Object.assign(exports, module);
}
});
6 changes: 3 additions & 3 deletions src/wechaty/init.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { WechatyBuilder } = require('wechaty')
const { sendMsg2RecvdApi, getLoginApiToken } = require('../service/webhook')
const Service = require('../service')
const bot = WechatyBuilder.build() // get a Wechaty instance
const chalk = require('chalk')
const { PORT } = process.env
Expand All @@ -10,7 +10,7 @@ module.exports = function init() {
.on('scan', (qrcode) =>
console.log([
`\nAccess the URL to login: ${chalk.cyan('https://wechaty.js.org/qrcode/' + encodeURIComponent(qrcode))}`,
'You can also check login by API: ' + chalk.cyan(`http://localhost:${PORT}/loginCheck?token=${getLoginApiToken()}`)
'You can also login by API: ' + chalk.cyan(`http://localhost:${PORT}/login?token=${Service.getLoginApiToken()}`)
].join('\n')))
.on('login', async user => console.log(chalk.green(`User ${user} logged in`)))
.on('logout', async user => console.log(chalk.red(`User ${user} logout`)))
Expand All @@ -20,7 +20,7 @@ module.exports = function init() {
.on('message', async message => {
console.log(`Message: ${message}`)
//收到消息二次转发特殊处理
sendMsg2RecvdApi(message)
Service.sendMsg2RecvdApi(message)

})
.on('error', (error) => {
Expand Down

0 comments on commit b3012e4

Please sign in to comment.