mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 23:06:06 +08:00
更新通知服务
This commit is contained in:
parent
9534cda1f9
commit
f2dac51a62
|
@ -16,65 +16,66 @@ abstract class NotificationBaseInfo {
|
|||
}
|
||||
|
||||
export class GoCqHttpBotNotification extends NotificationBaseInfo {
|
||||
public GOBOT_URL = '';
|
||||
public GOBOT_TOKEN = '';
|
||||
public GOBOT_QQ = '';
|
||||
public goCqHttpBotUrl = '';
|
||||
public goCqHttpBotToken = '';
|
||||
public goCqHttpBotQq = '';
|
||||
}
|
||||
|
||||
export class ServerChanNotification extends NotificationBaseInfo {
|
||||
public SCKEY = '';
|
||||
public serverChanKey = '';
|
||||
}
|
||||
|
||||
export class BarkNotification extends NotificationBaseInfo {
|
||||
public BARK_PUSH = '';
|
||||
public BARK_SOUND = '';
|
||||
public BARK_GROUP = 'qinglong';
|
||||
public barkPush = '';
|
||||
public barkSound = '';
|
||||
public barkGroup = 'qinglong';
|
||||
}
|
||||
|
||||
export class TelegramBotNotification extends NotificationBaseInfo {
|
||||
public TG_BOT_TOKEN = '';
|
||||
public TG_USER_ID = '';
|
||||
public TG_PROXY_HOST = '';
|
||||
public TG_PROXY_PORT = '';
|
||||
public TG_PROXY_AUTH = '';
|
||||
public TG_API_HOST = 'api.telegram.org';
|
||||
public telegramBotToken = '';
|
||||
public telegramBotUserId = '';
|
||||
public telegramBotProxyHost = '';
|
||||
public telegramBotProxyPort = '';
|
||||
public telegramBotProxyAuth = '';
|
||||
public telegramBotApiHost = 'api.telegram.org';
|
||||
}
|
||||
|
||||
export class DingtalkBotNotification extends NotificationBaseInfo {
|
||||
public DD_BOT_TOKEN = '';
|
||||
public DD_BOT_SECRET = '';
|
||||
public dingtalkBotToken = '';
|
||||
public dingtalkBotSecret = '';
|
||||
}
|
||||
|
||||
export class WeWorkBotNotification extends NotificationBaseInfo {
|
||||
public QYWX_KEY = '';
|
||||
public weWorkBotKey = '';
|
||||
}
|
||||
|
||||
export class WeWorkAppNotification extends NotificationBaseInfo {
|
||||
public QYWX_AM = '';
|
||||
public weWorkAppKey = '';
|
||||
}
|
||||
|
||||
export class IGotNotification extends NotificationBaseInfo {
|
||||
public IGOT_PUSH_KEY = '';
|
||||
public iGotPushKey = '';
|
||||
}
|
||||
|
||||
export class PushPlusNotification extends NotificationBaseInfo {
|
||||
public PUSH_PLUS_TOKEN = '';
|
||||
public PUSH_PLUS_USER = '';
|
||||
public pushPlusToken = '';
|
||||
public pushPlusUser = '';
|
||||
}
|
||||
|
||||
export class EmailNotification extends NotificationBaseInfo {
|
||||
public service: string = '';
|
||||
public user: string = '';
|
||||
public pass: string = '';
|
||||
public emailService: string = '';
|
||||
public emailUser: string = '';
|
||||
public emailPass: string = '';
|
||||
}
|
||||
|
||||
export type NotificationInfo =
|
||||
| GoCqHttpBotNotification
|
||||
| ServerChanNotification
|
||||
| BarkNotification
|
||||
| TelegramBotNotification
|
||||
| DingtalkBotNotification
|
||||
| WeWorkBotNotification
|
||||
| IGotNotification
|
||||
| PushPlusNotification
|
||||
| EmailNotification;
|
||||
export interface NotificationInfo
|
||||
extends GoCqHttpBotNotification,
|
||||
ServerChanNotification,
|
||||
BarkNotification,
|
||||
TelegramBotNotification,
|
||||
DingtalkBotNotification,
|
||||
WeWorkBotNotification,
|
||||
WeWorkAppNotification,
|
||||
IGotNotification,
|
||||
PushPlusNotification,
|
||||
EmailNotification {}
|
||||
|
|
|
@ -14,12 +14,11 @@ import NotificationService from './notify';
|
|||
|
||||
@Service()
|
||||
export default class AuthService {
|
||||
@Inject((type) => NotificationService)
|
||||
private notificationService!: NotificationService;
|
||||
private authDb = new DataStore({ filename: config.authDbFile });
|
||||
|
||||
constructor(
|
||||
@Inject('logger') private logger: winston.Logger,
|
||||
private notificationService: NotificationService,
|
||||
) {
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {
|
||||
this.authDb.loadDatabase((err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
|
|
|
@ -2,9 +2,16 @@ import { NotificationInfo } from '../data/notify';
|
|||
import { Service, Inject } from 'typedi';
|
||||
import winston from 'winston';
|
||||
import AuthService from './auth';
|
||||
import got from 'got';
|
||||
import nodemailer from 'nodemailer';
|
||||
import crypto from 'crypto';
|
||||
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
|
||||
|
||||
@Service()
|
||||
export default class NotificationService {
|
||||
@Inject((type) => AuthService)
|
||||
private authService!: AuthService;
|
||||
|
||||
private modeMap = new Map([
|
||||
['goCqHttpBot', this.goCqHttpBot],
|
||||
['serverChan', this.serverChan],
|
||||
|
@ -18,14 +25,12 @@ export default class NotificationService {
|
|||
['email', this.email],
|
||||
]);
|
||||
|
||||
private timeout = 10000;
|
||||
private title = '';
|
||||
private content = '';
|
||||
private params!: Omit<NotificationInfo, 'type'>;
|
||||
|
||||
constructor(
|
||||
@Inject('logger') private logger: winston.Logger,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
|
||||
public async notify(title: string, content: string) {
|
||||
const { type, ...rest } = await this.authService.getNotificationMode();
|
||||
|
@ -38,22 +43,257 @@ export default class NotificationService {
|
|||
}
|
||||
}
|
||||
|
||||
private async goCqHttpBot() {}
|
||||
private async goCqHttpBot() {
|
||||
const { goCqHttpBotQq, goCqHttpBotToken, goCqHttpBotUrl } = this.params;
|
||||
const res: any = await got
|
||||
.post(
|
||||
`${goCqHttpBotUrl}?access_token=${goCqHttpBotToken}&${goCqHttpBotQq}`,
|
||||
{
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: { message: `${this.title}\n${this.content}` },
|
||||
},
|
||||
)
|
||||
.json();
|
||||
return res.retcode === 0;
|
||||
}
|
||||
|
||||
private async serverChan() {}
|
||||
private async serverChan() {
|
||||
const { serverChanKey } = this.params;
|
||||
const url = serverChanKey.includes('SCT')
|
||||
? `https://sctapi.ftqq.com/${SCKEY}.send`
|
||||
: `https://sc.ftqq.com/${SCKEY}.send`;
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
body: `text=${this.title}&desp=${this.content}`,
|
||||
})
|
||||
.json();
|
||||
return res.errno === 0 || res.data.errno === 0;
|
||||
}
|
||||
|
||||
private async bark() {}
|
||||
private async bark() {
|
||||
const { barkPush, barkSound, barkGroup } = this.params;
|
||||
const url = `${barkPush}/${encodeURIComponent(
|
||||
this.title,
|
||||
)}/${encodeURIComponent(
|
||||
this.content,
|
||||
)}?sound=${barkSound}&group=${barkGroup}`;
|
||||
const res: any = await got
|
||||
.get(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
})
|
||||
.json();
|
||||
return res.code === 200;
|
||||
}
|
||||
|
||||
private async telegramBot() {}
|
||||
private async telegramBot() {
|
||||
const {
|
||||
telegramBotApiHost,
|
||||
telegramBotProxyAuth,
|
||||
telegramBotProxyHost,
|
||||
telegramBotProxyPort,
|
||||
telegramBotToken,
|
||||
telegramBotUserId,
|
||||
} = this.params;
|
||||
const url = `https://${telegramBotApiHost}/bot${telegramBotToken}/sendMessage`;
|
||||
const options = {
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
maxSockets: 256,
|
||||
maxFreeSockets: 256,
|
||||
proxy: `http://${telegramBotProxyHost}:${telegramBotProxyPort}`,
|
||||
};
|
||||
const httpAgent = new HttpProxyAgent(options);
|
||||
const httpsAgent = new HttpsProxyAgent(options);
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
body: `chat_id=${telegramBotUserId}&text=${this.title}\n\n${this.content}&disable_web_page_preview=true`,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
agent: {
|
||||
http: httpAgent,
|
||||
https: httpsAgent,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
return !!res.ok;
|
||||
}
|
||||
|
||||
private async dingtalkBot() {}
|
||||
private async dingtalkBot() {
|
||||
const { dingtalkBotSecret, dingtalkBotToken } = this.params;
|
||||
let secretParam = '';
|
||||
if (dingtalkBotSecret) {
|
||||
const dateNow = Date.now();
|
||||
const hmac = crypto.createHmac('sha256', dingtalkBotSecret);
|
||||
hmac.update(`${dateNow}\n${dingtalkBotSecret}`);
|
||||
const result = encodeURIComponent(hmac.digest('base64'));
|
||||
secretParam = `×tamp=${dateNow}&sign=${result}`;
|
||||
}
|
||||
const url = `https://oapi.dingtalk.com/robot/send?access_token=${dingtalkBotToken}${secretParam}`;
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: {
|
||||
msgtype: 'text',
|
||||
text: {
|
||||
content: ` ${this.title}\n\n${this.content}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
.json();
|
||||
return res.errcode === 0;
|
||||
}
|
||||
|
||||
private async weWorkBot() {}
|
||||
private async weWorkBot() {
|
||||
const { weWorkBotKey } = this.params;
|
||||
const url = `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${weWorkBotKey}`;
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: {
|
||||
msgtype: 'text',
|
||||
text: {
|
||||
content: ` ${this.title}\n\n${this.content}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
.json();
|
||||
return res.errcode === 0;
|
||||
}
|
||||
|
||||
private async weWorkApp() {}
|
||||
private async iGot() {}
|
||||
private async weWorkApp() {
|
||||
const { weWorkAppKey } = this.params;
|
||||
const [corpid, corpsecret, touser, agentid, thumb_media_id = '1'] =
|
||||
weWorkAppKey.split(',');
|
||||
const url = `https://qyapi.weixin.qq.com/cgi-bin/gettoken`;
|
||||
const { access_token } = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: {
|
||||
corpid,
|
||||
corpsecret,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
||||
private async pushPlus() {}
|
||||
let options: any = {
|
||||
msgtype: 'mpnews',
|
||||
mpnews: {
|
||||
articles: [
|
||||
{
|
||||
title: `${this.title}`,
|
||||
thumb_media_id,
|
||||
author: `智能助手`,
|
||||
content_source_url: ``,
|
||||
content: `${this.content.replace(/\n/g, '<br/>')}`,
|
||||
digest: `${this.content}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
switch (thumb_media_id) {
|
||||
case '0':
|
||||
options = {
|
||||
msgtype: 'textcard',
|
||||
textcard: {
|
||||
title: `${this.title}`,
|
||||
description: `${this.content}`,
|
||||
url: 'https://github.com/whyour/qinglong',
|
||||
btntxt: '更多',
|
||||
},
|
||||
};
|
||||
break;
|
||||
|
||||
private async email() {}
|
||||
case '1':
|
||||
options = {
|
||||
msgtype: 'text',
|
||||
text: {
|
||||
content: `${this.title}\n\n${this.content}`,
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
const res: any = await got
|
||||
.post(
|
||||
`https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${access_token}`,
|
||||
{
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: {
|
||||
touser,
|
||||
agentid,
|
||||
safe: '0',
|
||||
...options,
|
||||
},
|
||||
},
|
||||
)
|
||||
.json();
|
||||
|
||||
return res.errcode === 0;
|
||||
}
|
||||
|
||||
private async iGot() {
|
||||
const { iGotPushKey } = this.params;
|
||||
const url = `https://push.hellyw.com/${iGotPushKey.toLowerCase()}`;
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
body: `title=${this.title}&content=${this.content}`,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
})
|
||||
.json();
|
||||
|
||||
return res.ret === 0;
|
||||
}
|
||||
|
||||
private async pushPlus() {
|
||||
const { pushPlusToken, pushPlusUser } = this.params;
|
||||
const url = `https://www.pushplus.plus/send`;
|
||||
const res: any = await got
|
||||
.post(url, {
|
||||
timeout: this.timeout,
|
||||
retry: 0,
|
||||
json: {
|
||||
token: `${pushPlusToken}`,
|
||||
title: `${this.title}`,
|
||||
content: `${this.content.replace(/[\n\r]/g, '<br>')}`,
|
||||
topic: `${pushPlusUser}`,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
||||
return res.code === 200;
|
||||
}
|
||||
|
||||
private async email() {
|
||||
const { emailPass, emailService, emailUser } = this.params;
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: emailService,
|
||||
auth: {
|
||||
user: emailUser,
|
||||
pass: emailPass,
|
||||
},
|
||||
});
|
||||
|
||||
const info = await transporter.sendMail({
|
||||
from: `"青龙快讯" <${emailUser}>`,
|
||||
to: `${emailUser}`,
|
||||
subject: `${this.title}`,
|
||||
html: `${this.content.replace(/\n/g, '<br/>')}`,
|
||||
});
|
||||
|
||||
transporter.close();
|
||||
|
||||
return !!info.messageId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,12 +34,14 @@
|
|||
"express-jwt": "^6.0.0",
|
||||
"express-urlrewrite": "^1.4.0",
|
||||
"got": "^11.8.2",
|
||||
"hpagent": "^0.1.2",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"lodash": "^4.17.21",
|
||||
"nedb": "^1.8.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-schedule": "^2.0.0",
|
||||
"nodemailer": "^6.6.3",
|
||||
"p-queue": "6.6.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"typedi": "^0.8.0",
|
||||
|
@ -58,6 +60,7 @@
|
|||
"@types/nedb": "^1.8.11",
|
||||
"@types/node": "^14.11.2",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/qrcode.react": "^1.0.1",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
|
|
|
@ -13,6 +13,7 @@ specifiers:
|
|||
'@types/nedb': ^1.8.11
|
||||
'@types/node': ^14.11.2
|
||||
'@types/node-fetch': ^2.5.8
|
||||
'@types/nodemailer': ^6.4.4
|
||||
'@types/qrcode.react': ^1.0.1
|
||||
'@types/react': ^17.0.0
|
||||
'@types/react-dom': ^17.0.0
|
||||
|
@ -30,6 +31,7 @@ specifiers:
|
|||
express-jwt: ^6.0.0
|
||||
express-urlrewrite: ^1.4.0
|
||||
got: ^11.8.2
|
||||
hpagent: ^0.1.2
|
||||
iconv-lite: ^0.6.3
|
||||
jsonwebtoken: ^8.5.1
|
||||
lint-staged: ^10.0.7
|
||||
|
@ -37,6 +39,7 @@ specifiers:
|
|||
nedb: ^1.8.0
|
||||
node-fetch: ^2.6.1
|
||||
node-schedule: ^2.0.0
|
||||
nodemailer: ^6.6.3
|
||||
nodemon: ^2.0.4
|
||||
p-queue: 6.6.2
|
||||
prettier: ^2.2.0
|
||||
|
@ -71,12 +74,14 @@ dependencies:
|
|||
express-jwt: 6.0.0
|
||||
express-urlrewrite: 1.4.0
|
||||
got: 11.8.2
|
||||
hpagent: 0.1.2
|
||||
iconv-lite: 0.6.3
|
||||
jsonwebtoken: 8.5.1
|
||||
lodash: 4.17.21
|
||||
nedb: 1.8.0
|
||||
node-fetch: 2.6.1
|
||||
node-schedule: 2.0.0
|
||||
nodemailer: 6.6.3
|
||||
p-queue: 6.6.2
|
||||
reflect-metadata: 0.1.13
|
||||
typedi: 0.8.0
|
||||
|
@ -95,6 +100,7 @@ devDependencies:
|
|||
'@types/nedb': 1.8.11
|
||||
'@types/node': 14.14.45
|
||||
'@types/node-fetch': 2.5.10
|
||||
'@types/nodemailer': 6.4.4
|
||||
'@types/qrcode.react': 1.0.1
|
||||
'@types/react': 17.0.5
|
||||
'@types/react-dom': 17.0.5
|
||||
|
@ -1186,6 +1192,16 @@ packages:
|
|||
resolution: {integrity: sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==}
|
||||
dev: false
|
||||
|
||||
/@types/node/14.17.16:
|
||||
resolution: {integrity: sha512-WiFf2izl01P1CpeY8WqFAeKWwByMueBEkND38EcN8N68qb0aDG3oIS1P5MhAX5kUdr469qRyqsY/MjanLjsFbQ==}
|
||||
dev: true
|
||||
|
||||
/@types/nodemailer/6.4.4:
|
||||
resolution: {integrity: sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==}
|
||||
dependencies:
|
||||
'@types/node': 14.17.16
|
||||
dev: true
|
||||
|
||||
/@types/normalize-package-data/2.4.0:
|
||||
resolution: {integrity: sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==}
|
||||
dev: true
|
||||
|
@ -4232,6 +4248,10 @@ packages:
|
|||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
dev: true
|
||||
|
||||
/hpagent/0.1.2:
|
||||
resolution: {integrity: sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==}
|
||||
dev: false
|
||||
|
||||
/html-encoding-sniffer/1.0.2:
|
||||
resolution: {integrity: sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==}
|
||||
dependencies:
|
||||
|
@ -6162,6 +6182,11 @@ packages:
|
|||
sorted-array-functions: 1.3.0
|
||||
dev: false
|
||||
|
||||
/nodemailer/6.6.3:
|
||||
resolution: {integrity: sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: false
|
||||
|
||||
/nodemon/2.0.7:
|
||||
resolution: {integrity: sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
|
Loading…
Reference in New Issue
Block a user