fix sr公告推送转发消息无法获取e.bot (#165)

This commit is contained in:
story-x 2023-06-07 04:51:35 +08:00 committed by GitHub
parent 86b2b7d60a
commit 765719533f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 295 additions and 285 deletions

View File

@ -1,6 +1,6 @@
import plugin from '../../../lib/plugins/plugin.js' import plugin from '../../../lib/plugins/plugin.js'
import MysNews from '../model/mysNews.js' import MysNews from '../model/mysNews.js'
import srNews from '../model/srmysNews.js' import MysSrNews from '../model/mysSrNews.js'
import fs from 'node:fs' import fs from 'node:fs'
import lodash from 'lodash' import lodash from 'lodash'
import gsCfg from '../model/gsCfg.js' import gsCfg from '../model/gsCfg.js'
@ -25,16 +25,16 @@ export class mysNews extends plugin {
}, },
{ {
reg: '^(#*铁道(公告|资讯|活动)|#*星铁(公告|资讯|活动)|#星穹公告|#星穹资讯|#星穹活动)[0-9]*$', reg: '^(#*铁道(公告|资讯|活动)|#*星铁(公告|资讯|活动)|#星穹公告|#星穹资讯|#星穹活动)[0-9]*$',
fnc: 'srnews' fnc: 'srNews'
}, },
{ {
reg: '^#*(开启|关闭)(铁道|星铁|星穹)(公告|资讯)推送$', reg: '^#*(开启|关闭)(铁道|星铁|星穹)(公告|资讯)推送$',
fnc: 'srsetPush' fnc: 'srSetPush'
}, },
{ {
reg: '^#推送(铁道|星铁|星穹)(公告|资讯)$', reg: '^#推送(铁道|星铁|星穹)(公告|资讯)$',
permission: 'master', permission: 'master',
fnc: 'srmysNewsTask' fnc: 'srMysNewsTask'
}, },
{ {
reg: '(.*)(bbs.mihoyo.com|miyoushe.com)/ys(.*)/article(.*)', reg: '(.*)(bbs.mihoyo.com|miyoushe.com)/ys(.*)/article(.*)',
@ -70,7 +70,7 @@ export class mysNews extends plugin {
{ {
cron: gsCfg.getConfig('mys', 'pushNews').pushTime, cron: gsCfg.getConfig('mys', 'pushNews').pushTime,
name: '崩坏星穹铁道公告推送任务', name: '崩坏星穹铁道公告推送任务',
fnc: () => this.srmysNewsTask(), fnc: () => this.srMysNewsTask(),
log: false log: false
} }
] ]
@ -88,8 +88,8 @@ export class mysNews extends plugin {
await this.reply(data) await this.reply(data)
} }
async srnews () { async srNews () {
let data = await new srNews(this.e).getNews() let data = await new MysSrNews(this.e).getNews()
if (!data) return if (!data) return
await this.reply(data) await this.reply(data)
} }
@ -99,8 +99,8 @@ export class mysNews extends plugin {
await mysNews.mysNewsTask() await mysNews.mysNewsTask()
} }
async srmysNewsTask () { async srMysNewsTask () {
let mysNews = new srNews(this.e) let mysNews = new MysSrNews(this.e)
await mysNews.mysNewsTask() await mysNews.mysNewsTask()
} }
@ -123,7 +123,7 @@ export class mysNews extends plugin {
await this.reply(data) await this.reply(data)
} }
async srsetPush () { async srSetPush () {
if (!this.e.isGroup) { if (!this.e.isGroup) {
await this.reply('推送请在群聊中设置') await this.reply('推送请在群聊中设置')
return return
@ -200,4 +200,4 @@ export class mysNews extends plugin {
logger.mark(`${this.e.logFnc} ${model}${typeName}推送:${this.e.group_id}`) logger.mark(`${this.e.logFnc} ${model}${typeName}推送:${this.e.group_id}`)
await this.reply(msg) await this.reply(msg)
} }
} }

View File

@ -1,274 +1,284 @@
import base from './base.js' import base from './base.js'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import lodash from 'lodash' import lodash from 'lodash'
import puppeteer from '../../../lib/puppeteer/puppeteer.js' import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import common from '../../../lib/common/common.js' import common from '../../../lib/common/common.js'
import gsCfg from '../model/gsCfg.js' import gsCfg from '../model/gsCfg.js'
const _path = process.cwd() let emoticon
let emoticon
export default class MysSrNews extends base {
export default class MysNews extends base { constructor (e) {
constructor (e) { super(e)
super(e) this.model = 'mysNews'
this.model = 'mysNews' }
}
async getNews () {
async getNews () { let type = 1
let type = 1 let typeName = '公告'
let typeName = '公告' if (this.e.msg.includes('资讯')) {
if (this.e.msg.includes('资讯')) { type = '3'
type = '3' typeName = '资讯'
typeName = '资讯' }
} if (this.e.msg.includes('活动')) {
if (this.e.msg.includes('活动')) { type = '2'
type = '2' typeName = '活动'
typeName = '活动' }
}
const res = await this.postData('getNewsList', { gids: 6, page_size: 20, type })
const res = await this.postData('getNewsList', { gids: 6, page_size: 20, type }) if (!res) return
if (!res) return
const data = res.data.list
const data = res.data.list if (data.length == 0) {
if (data.length == 0) { return true
return true }
}
const page = this.e.msg.replace(/#||星铁|星穹|铁道|公告|资讯|活动/g, '').trim() || 1
const page = this.e.msg.replace(/#||星铁|星穹|铁道|公告|资讯|活动/g, '').trim() || 1 if (page > data.length) {
if (page > data.length) { await this.e.reply('目前只查前20条最新的公告请输入1-20之间的整数。')
await this.e.reply('目前只查前20条最新的公告请输入1-20之间的整数。') return true
return true }
}
const postId = data[page - 1].post.post_id
const postId = data[page - 1].post.post_id
const param = await this.newsDetail(postId)
const param = await this.newsDetail(postId)
const img = await this.render(param)
const img = await this.render(param)
return await this.replyMsg(img, `崩坏星穹铁道${typeName}${param.data.post.subject}`)
return await this.replyMsg(img, `崩坏星穹铁道${typeName}${param.data.post.subject}`) }
}
async render (param) {
async render (param) { return await puppeteer.screenshots(this.model, param)
return await puppeteer.screenshots(this.model, param) }
}
async newsDetail (postId) {
async newsDetail (postId) { const res = await this.postData('getPostFull', { gids: 6, read: 1, post_id: postId })
const res = await this.postData('getPostFull', { gids: 6, read: 1, post_id: postId }) if (!res) return
if (!res) return
const data = await this.detalData(res.data.post)
const data = await this.detalData(res.data.post)
return {
return { ...this.screenData,
...this.screenData, saveId: postId,
saveId: postId, dataConent: data.post.content,
dataConent: data.post.content, data
data }
} }
}
postApi (type, data) {
postApi (type, data) { let host = 'https://bbs-api-static.mihoyo.com/'
let host = 'https://bbs-api-static.mihoyo.com/' let param = []
let param = [] lodash.forEach(data, (v, i) => param.push(`${i}=${v}`))
lodash.forEach(data, (v, i) => param.push(`${i}=${v}`)) param = param.join('&')
param = param.join('&') switch (type) {
switch (type) { // 搜索
// 搜索 case 'searchPosts':
case 'searchPosts': host = 'https://bbs-api.mihoyo.com/post/wapi/searchPosts?'
host = 'https://bbs-api.mihoyo.com/post/wapi/searchPosts?' break
break // 帖子详情
// 帖子详情 case 'getPostFull':
case 'getPostFull': host += 'post/wapi/getPostFull?'
host += 'post/wapi/getPostFull?' break
break // 公告列表
// 公告列表 case 'getNewsList':
case 'getNewsList': host += 'post/wapi/getNewsList?'
host += 'post/wapi/getNewsList?' break
break case 'emoticon':
case 'emoticon': host += 'misc/api/emoticon_set?'
host += 'misc/api/emoticon_set?' break
break }
} return host + param
return host + param }
}
async postData (type, data) {
async postData (type, data) { const url = this.postApi(type, data)
const url = this.postApi(type, data) const headers = {
const headers = { Referer: 'https://bbs.mihoyo.com/',
Referer: 'https://bbs.mihoyo.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' }
} let response
let response try {
try { response = await fetch(url, { method: 'get', headers })
response = await fetch(url, { method: 'get', headers }) } catch (error) {
} catch (error) { logger.error(error.toString())
logger.error(error.toString()) return false
return false }
}
if (!response.ok) {
if (!response.ok) { logger.error(`[米游社接口错误][${type}] ${response.status} ${response.statusText}`)
logger.error(`[米游社接口错误][${type}] ${response.status} ${response.statusText}`) return false
return false }
} const res = await response.json()
const res = await response.json() return res
return res }
}
async detalData (data) {
async detalData (data) { let json
let json try {
try { json = JSON.parse(data.post.content)
json = JSON.parse(data.post.content) } catch (error) {
} catch (error) {
}
}
if (typeof json == 'object') {
if (typeof json == 'object') { if (json.imgs && json.imgs.length > 0) {
if (json.imgs && json.imgs.length > 0) { for (const val of json.imgs) {
for (const val of json.imgs) { data.post.content = ` <div class="ql-image-box"><img src="${val}?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,png"></div>`
data.post.content = ` <div class="ql-image-box"><img src="${val}?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,png"></div>` }
} }
} } else {
} else { for (const img of data.post.images) {
for (const img of data.post.images) { data.post.content = data.post.content.replace(img, img + '?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,jpg')
data.post.content = data.post.content.replace(img, img + '?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,jpg') }
}
if (!emoticon) {
if (!emoticon) { emoticon = await this.mysEmoticon()
emoticon = await this.mysEmoticon() }
}
data.post.content = data.post.content.replace(/_\([^)]*\)/g, function (t, e) {
data.post.content = data.post.content.replace(/_\([^)]*\)/g, function (t, e) { t = t.replace(/_\(|\)/g, '')
t = t.replace(/_\(|\)/g, '') if (emoticon.has(t)) {
if (emoticon.has(t)) { return `<img class="emoticon-image" src="${emoticon.get(t)}"/>`
return `<img class="emoticon-image" src="${emoticon.get(t)}"/>` } else {
} else { return ''
return '' }
} })
})
const arrEntities = { lt: '<', gt: '>', nbsp: ' ', amp: '&', quot: '"' }
const arrEntities = { lt: '<', gt: '>', nbsp: ' ', amp: '&', quot: '"' } data.post.content = data.post.content.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
data.post.content = data.post.content.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) { return arrEntities[t]
return arrEntities[t] })
}) }
}
data.post.created_time = new Date(data.post.created_at * 1000).toLocaleString()
data.post.created_time = new Date(data.post.created_at * 1000).toLocaleString()
for (const i in data.stat) {
for (const i in data.stat) { data.stat[i] = data.stat[i] > 10000 ? (data.stat[i] / 10000).toFixed(2) + '万' : data.stat[i]
data.stat[i] = data.stat[i] > 10000 ? (data.stat[i] / 10000).toFixed(2) + '万' : data.stat[i] }
}
return data
return data }
}
async mysEmoticon () {
async mysEmoticon () { const emp = new Map()
const emp = new Map()
const res = await this.postData('emoticon', { gids: 6 })
const res = await this.postData('emoticon', { gids: 6 })
if (res.retcode != 0) {
if (res.retcode != 0) { return emp
return emp }
}
for (const val of res.data.list) {
for (const val of res.data.list) { if (!val.icon) continue
if (!val.icon) continue for (const list of val.list) {
for (const list of val.list) { if (!list.icon) continue
if (!list.icon) continue emp.set(list.name, list.icon)
emp.set(list.name, list.icon) }
} }
}
return emp
return emp }
}
async replyMsg (img, titile) {
async replyMsg (img, titile) { if (!img || img.length <= 0) return false
if (!img || img.length <= 0) return false if (img.length == 1) {
if (img.length == 1) { return img[0]
return img[0] } else {
} else { let msg = [titile, ...img]
let msg = [titile, ...img] return await common.makeForwardMsg(this.e, msg, titile).catch((err) => {
return await common.makeForwardMsg(this.e, msg, titile).catch((err) => { logger.error(err)
logger.error(err) })
}) }
} }
}
async mysNewsTask (type = 1) {
async mysNewsTask (type = 1) { let cfg = gsCfg.getConfig('mys', 'pushNews')
let cfg = gsCfg.getConfig('mys', 'pushNews')
// 推送2小时内的公告资讯
// 推送2小时内的公告资讯 let interval = 7200
let interval = 7200 // 最多同时推送两条
// 最多同时推送两条 this.maxNum = cfg.maxNum
this.maxNum = cfg.maxNum // 包含关键字不推送
// 包含关键字不推送 let banWord = /冒险助力礼包|纪行|预下载|脚本外挂|集中反馈|已开奖|云·原神|魔神任务|传说任务说明/g
let banWord = /冒险助力礼包|纪行|预下载|脚本外挂|集中反馈|已开奖|云·原神|魔神任务|传说任务说明/g
let anno = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 1 })
let anno = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 1 }) let info = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 3 })
let info = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 3 })
let news = []
let news = [] if (anno) anno.data.list.forEach(v => { news.push({ ...v, typeName: '公告', post_id: v.post.post_id }) })
if (anno) anno.data.list.forEach(v => { news.push({ ...v, typeName: '公告', post_id: v.post.post_id }) }) if (info) info.data.list.forEach(v => { news.push({ ...v, typeName: '资讯', post_id: v.post.post_id }) })
if (info) info.data.list.forEach(v => { news.push({ ...v, typeName: '资讯', post_id: v.post.post_id }) }) if (news.length <= 0) return
if (news.length <= 0) return
news = lodash.orderBy(news, ['post_id'], ['asc'])
news = lodash.orderBy(news, ['post_id'], ['asc'])
let now = Date.now() / 1000
let now = Date.now() / 1000
this.key = 'Yz:genshin:mys:newPush:'
this.key = 'Yz:genshin:mys:newPush:' this.e.isGroup = true
this.e.isGroup = true this.pushGroup = []
this.pushGroup = [] for (let val of news) {
for (let val of news) { if (Number(now - val.post.created_at) > interval) {
if (Number(now - val.post.created_at) > interval) { continue
continue }
} if (new RegExp(banWord).test(val.post.subject)) {
if (new RegExp(banWord).test(val.post.subject)) { continue
continue }
} if (val.typeName == '公告') {
if (val.typeName == '公告') { for (let groupId of cfg.srannounceGroup) {
for (let groupId of cfg.srannounceGroup) { await this.sendNews(groupId, val.typeName, val.post.post_id)
await this.sendNews(groupId, val.typeName, val.post.post_id) }
} }
} if (val.typeName == '资讯') {
if (val.typeName == '资讯') { for (let groupId of cfg.srinfoGroup) {
for (let groupId of cfg.srinfoGroup) { await this.sendNews(groupId, val.typeName, val.post.post_id)
await this.sendNews(groupId, val.typeName, val.post.post_id) }
} }
} }
} }
}
async sendNews (groupId, typeName, postId) {
async sendNews (groupId, typeName, postId) { if (!this.pushGroup[groupId]) this.pushGroup[groupId] = 0
if (!this.pushGroup[groupId]) this.pushGroup[groupId] = 0 if (this.pushGroup[groupId] >= this.maxNum) return
if (this.pushGroup[groupId] >= this.maxNum) return
let sended = await redis.get(`${this.key}${groupId}:${postId}`)
let sended = await redis.get(`${this.key}${groupId}:${postId}`) if (sended) return
if (sended) return
// TODO: 暂时处理,后续待更好的解决方案 定时任务无法获取e.bot
if (!this[postId]) { this.e.bot = Bot
const param = await this.newsDetail(postId)
// 判断是否存在群关系
logger.mark(`[崩坏星穹铁道${typeName}推送] ${param.data.post.subject}`) if (!this.e.bot.gl.get(Number(groupId))) {
logger.mark(`[崩坏星穹铁道${typeName}推送] 群${groupId}未关联`)
this[postId] = { return
img: await this.render(param), }
title: param.data.post.subject
} if (!this[postId]) {
} const param = await this.newsDetail(postId)
this.pushGroup[groupId]++ logger.mark(`[崩坏星穹铁道${typeName}推送] ${param.data.post.subject}`)
this.e.group = Bot.pickGroup(Number(groupId))
this.e.group_id = Number(groupId) this[postId] = {
let tmp = await this.replyMsg(this[postId].img, `崩坏星穹铁道${typeName}推送:${this[postId].title}`) img: await this.render(param),
title: param.data.post.subject
await common.sleep(1000) }
if (!tmp) return }
if (tmp?.type != 'xml') { this.pushGroup[groupId]++
tmp = [`崩坏星穹铁道${typeName}推送\n`, tmp] this.e.group = Bot.pickGroup(Number(groupId))
} this.e.group_id = Number(groupId)
let tmp = await this.replyMsg(this[postId].img, `崩坏星穹铁道${typeName}推送:${this[postId].title}`)
redis.set(`${this.key}${groupId}:${postId}`, '1', { EX: 3600 * 10 })
await this.e.group.sendMsg(tmp) await common.sleep(1000)
} if (!tmp) return
}
if (tmp?.type != 'xml') {
tmp = [`崩坏星穹铁道${typeName}推送\n`, tmp]
}
redis.set(`${this.key}${groupId}:${postId}`, '1', { EX: 3600 * 10 })
// 随机延迟10-90秒
await common.sleep(lodash.random(10, 90) * 1000)
await this.e.group.sendMsg(tmp)
}
}