🎉 now you can push message to wechat

This commit is contained in:
Song
2021-01-17 16:45:52 +08:00
parent 0e9c7d9086
commit d36680aea1
7 changed files with 142 additions and 51 deletions
+5 -6
View File
@@ -7,16 +7,15 @@ async function initializeTokenStore() {
users.forEach((user) => {
if (user.wechatAppId) {
tokenStore.set(user.prefix, {
appId: user.wechatAppId,
appSecret: user.wechatAppSecret,
templateId: user.wechatTemplateId,
openId: user.wechatOpenId,
serverVerifyToken: user.wechatVerifyToken,
wechatAppId: user.wechatAppId,
wechatAppSecret: user.wechatAppSecret,
wechatTemplateId: user.wechatTemplateId,
wechatOpenId: user.wechatOpenId,
wechatVerifyToken: user.wechatVerifyToken,
token: '',
});
}
});
console.debug(tokenStore);
console.log('Token store initialized.');
}
+10 -5
View File
@@ -3,8 +3,9 @@ const { tokenStore } = require('./token');
const config = require('../config');
async function refreshToken() {
for (const item of tokenStore) {
item.token = await this.requestToken();
for (let [key, value] of tokenStore) {
value.token = await requestToken(value.wechatAppId, value.wechatAppSecret);
tokenStore.set(key, value);
}
console.log('Token refreshed.');
}
@@ -15,9 +16,13 @@ async function requestToken(appId, appSecret) {
let res = await axios.get(
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`
);
console.log(res);
if (res && res.data && res.data.access_token) {
token = res.data.access_token;
// console.debug(res);
if (res && res.data) {
if (res.data.access_token) {
token = res.data.access_token;
} else {
console.error(res.data);
}
}
} catch (e) {
console.error(e);
+10 -16
View File
@@ -3,36 +3,30 @@ const config = require('../config');
exports.userRequired = (req, res, next) => {
if (req.session.user) {
if (req.session.user.isBlocked) {
return res.render('message', {
isError: true,
message: '用户账户被禁用,请联系管理员',
link: '/feedback',
});
req.flash('message', '用户账户被禁用,请联系管理员');
return res.redirect('/');
}
} else {
return res.render('message', {
isError: false,
message: '用户尚未登录,请登录',
link: '/login',
});
req.flash('message', '用户尚未登录,请登录');
return res.redirect('/login');
}
next();
};
exports.adminRequired = (req, res, next) => {
if (!req.session.user || !req.session.user.isAdmin) {
return res.render('message', {
isError: true,
message: '需要超级管理员权限',
});
req.flash('message', '需要管理员权限');
return res.redirect('/login');
}
next();
};
exports.allowRegister = (req, res, next) => {
if (!config.allowRegister) {
req.flash('message', '管理员未开放注册!');
return res.redirect('/');
if (!req.session.user || !req.session.user.isAdmin) {
req.flash('message', '管理员未开放注册!');
return res.redirect('/');
}
}
next();
};
+47 -12
View File
@@ -2,7 +2,12 @@ const express = require('express');
const router = express.Router();
const { User } = require('../models');
const { tokenStore } = require('../common/token');
const { allowRegister } = require('../middlewares/web_auth');
const { requestToken } = require('../common/wechat');
const {
userRequired,
adminRequired,
allowRegister,
} = require('../middlewares/web_auth');
const config = require('../config');
router.get('/', (req, res, next) => {
@@ -12,7 +17,9 @@ router.get('/', (req, res, next) => {
});
router.get('/login', (req, res, next) => {
res.render('login');
res.render('login', {
message: req.flash('message'),
});
});
router.post('/login', async (req, res, next) => {
@@ -45,7 +52,7 @@ router.post('/login', async (req, res, next) => {
});
});
router.get('/logout', (req, res, next) => {
router.get('/logout', userRequired, (req, res, next) => {
req.session.user = undefined;
req.flash('message', '已退出登录');
res.redirect('/');
@@ -67,7 +74,13 @@ router.post('/register', allowRegister, async (req, res, next) => {
}
});
router.post('/configure', async (req, res, next) => {
router.get('/configure', userRequired, (req, res, next) => {
res.locals.message = req.flash('message');
res.render('configure', req.session.user);
});
router.post('/configure', userRequired, async (req, res, next) => {
let id = req.session.user.id;
let user = {
username: req.body.username,
password: req.body.password,
@@ -80,19 +93,41 @@ router.post('/configure', async (req, res, next) => {
wechatOpenId: req.body.wechatOpenId,
wechatVerifyToken: req.body.wechatVerifyToken,
};
for (let field in user) {
let value = user[field];
value = value.trim();
if (value) {
user[field] = value;
} else {
delete user[field];
}
}
let message = '';
try {
user = await User.create(user);
tokenStore.set(user.prefix, {
appId: user.wechatAppId,
appSecret: user.wechatAppSecret,
templateId: user.wechatTemplateId,
openId: user.wechatOpenId,
wechatVerifyToken: user.wechatVerifyToken,
token: '',
let userObj = await User.findOne({
where: {
id: id,
},
});
if (userObj) {
await userObj.update(user);
}
req.session.user = userObj;
tokenStore.set(userObj.prefix, {
appId: userObj.wechatAppId,
appSecret: userObj.wechatAppSecret,
templateId: userObj.wechatTemplateId,
openId: userObj.wechatOpenId,
wechatVerifyToken: userObj.wechatVerifyToken,
token: requestToken(userObj.wechatAppId, userObj.wechatAppSecret),
});
message = '配置更新成功';
} catch (e) {
console.error(e);
message = e.message;
}
req.flash('message', message);
res.redirect('/configure');
});
module.exports = router;
+10 -4
View File
@@ -6,10 +6,6 @@ const { tokenStore } = require('../common/token');
const router = express.Router();
router.get('/:userPrefix/configure', (req, res, next) => {
res.render('configure');
});
router.all('/:userPrefix/verify', (req, res, next) => {
// 验证消息来自微信服务器:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
const userPrefix = req.params.userPrefix;
@@ -25,6 +21,16 @@ router.all('/:userPrefix/verify', (req, res, next) => {
}
});
router.all('/:userPrefix/:description', async (req, res, next) => {
const userPrefix = req.params.userPrefix;
let message = {
type: '0',
title: '无标题',
description: req.params.description,
};
res.json(await processMessage(userPrefix, message));
});
router.all('/:userPrefix', async (req, res, next) => {
const userPrefix = req.params.userPrefix;
let message = {
+58 -7
View File
@@ -3,48 +3,99 @@
<div class="normal-container">
<div>
<h2 class="title">配置页面</h2>
<%- include('./partials/message') %>
<form action="/configure" method="post">
<div class="field">
<label class="label">APP ID</label>
<div class="control">
<input class="input" name="APP_ID" type="text" required placeholder="请输入 APP ID">
<input class="input" name="wechatAppId" value="<%- wechatAppId %>" type="text" required placeholder="请输入 APP ID">
</div>
</div>
<div class="field">
<label class="label">APP SECRET</label>
<div class="control">
<input class="input" name="APP_SECRET" type="text" required placeholder="请输入 APP SECRET">
<input class="input" name="wechatAppSecret" value="<%- wechatAppSecret %>" type="text" required placeholder="请输入 APP SECRET">
</div>
</div>
<div class="field">
<label class="label">OPEN ID</label>
<div class="control">
<input class="input" name="OPEN_ID" type="text" required placeholder="请输入你的 OPEN ID">
<input class="input" name="wechatOpenId" value="<%- wechatOpenId %>" type="text" required placeholder="请输入你的 OPEN ID">
</div>
</div>
<div class="field">
<label class="label">TEMPLATE ID</label>
<div class="control">
<input class="input" name="TEMPLATE_ID" type="text" required placeholder="请输入一个模板通知 ID">
<input class="input" name="wechatTemplateId" value="<%- wechatTemplateId %>" type="text" required placeholder="请输入一个模板通知 ID">
</div>
</div>
<div class="field">
<label class="label">TOKEN</label>
<div class="control">
<input class="input" name="TOKEN" type="text" required placeholder="请输入你的 TOKEN">
<input class="input" name="wechatVerifyToken" value="<%- wechatVerifyToken %>" type="text" required placeholder="请输入你的 TOKEN">
</div>
</div>
<div class="field">
<label class="label">前缀</label>
<article class="message">
<div class="message-body">
前缀默认和用户名相同,如非必要,无需修改
</div>
</article>
<div class="control">
<input class="input" name="prefix" value="<%- prefix %>" type="text" placeholder="请输入你的 TOKEN">
</div>
</div>
<div class="field">
<label class="label">ACCESS TOKEN</label>
<article class="message">
<div class="message-body">
Access Token 可防止未授权者利用本系统向你发送消息,留空则不做该检查
</div>
</article>
<div class="control">
<input class="input" name="accessToken" value="<%- accessToken %>" type="text" placeholder="请设置新的 ACCESS TOKEN(可不填)">
</div>
</div>
<div class="field">
<label class="label">邮箱</label>
<article class="message">
<div class="message-body">
后续版本将支持选择将消息发送到邮箱
</div>
</article>
<div class="control">
<input class="input" name="email" value="<%- email %>" type="text" placeholder="请输入你的邮箱(可不填)">
</div>
</div>
<div class="field">
<label class="label">用户名</label>
<div class="control">
<input class="input" name="username" value="<%- username %>" type="text" placeholder="请输入新的用户名">
</div>
</div>
<div class="field">
<label class="label">密码</label>
<div class="control">
<input class="input" name="password" type="text" placeholder="请输入新的密码">
</div>
</div>
<div class="field is-grouped is-grouped-right">
<div class="control">
<input type="submit" class="button is-link" value="提交">
<input type="submit" class="button is-light" value="提交">
</div>
<div class="control">
<input type="reset" class="button is-link is-light" value="重置">
<input type="reset" class="button is-light" value="重置">
</div>
</div>
</form>
+2 -1
View File
@@ -15,13 +15,14 @@
<div id="mainNavbar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/"> 首页 </a>
<a class="navbar-item" target="_blank" href="https://github.com/songquanpeng/message-pusher"> 帮助 </a>
<a class="navbar-item" target="_blank" href="https://github.com/songquanpeng/message-pusher/blob/master/README.md"> 帮助 </a>
<a class="navbar-item" target="_blank" href="https://iamazing.cn/page/message-pusher"> 关于 </a>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<% if (isLogged) { %>
<a class="button is-light" href="/configure">配置</a>
<a class="button is-light" href="/logout">退出</a>
<% } else { %>
<a class="button is-light" href="/register">注册</a>