Commit 949549d4 by wutianyang

Merge branch 'master' of http://47.100.14.92:8929/nongyingchen/AppMonitorSubscriber

* 'master' of http://47.100.14.92:8929/nongyingchen/AppMonitorSubscriber:
  add monitor scrip in here
  添加发送每日在线列表的时间
  Update subscriber.json
parents 17c352f4 a2b1e00c
var gplay = require('google-play-scraper')
var nodemailer = require('nodemailer')
var fs = require('fs')
var username = require('os').userInfo().username
var request = require('request')
var util = require('util')
var getPromiss = util.promisify(request.get)
let subApi = "https://git.starwin.tech/nongyingchen/AppMonitorSubscriber/raw/master/subscriber.json"
log(`当前奔跑在:${username}`)
let ding = 'https://oapi.dingtalk.com/robot/send?access_token='
let debugDingding = `${ding}bf03c69128b771107b8715911b8a76db61a55cbd8b00e1a2c955578c2a3da719`
let notifyDingding = `${ding}61403ec65efd7a9e40cb6d490e1bfab8aff28800696918a23ec4dffdf5aa1315`
let daichao = `http://admin.uuang.co.id/admin/loan/listactive?current=0&size=10000&descs%5B0%5D=priority&packageId=10002`
// Config ------------------------------------------------------------
let sec = 1000;
let minute = sec * 60
let defaultIntervalTime = isTest() && (minute * 1) || (minute * 15) // 默认间隔15分钟
let defaultIntervalTimeForOurApp = isTest() ? 0 : 12 // 自有 app 默认时间间隔
let lastIntervalTime = defaultIntervalTime // 最新获取权限时间间隔
let sleepTime = isTest() && (sec * 2) || (sec * 5) // 每个请求间隔5秒
let requestTimeout = sec * 20
let requestTopAppNum = isTest() && 1 || 100
let aliveTime = 9 // 多少点后开始发送邮件
let theDaySendList = [1,2,3,4,5,6,7] // 发送列表的时间(周几)
let aliveInterval = isTest() && 0.1 || 3 // 发送邮件间隔时间
let start = true // 是否开始爬取监控
let dailyOnlineStartHours = 7
let dailyOnlineEndHours = 9
let crabName = `东南亚现金贷App监控${isTest() && '(Test)' || ''}`
let monitorRegion = {'vn': '越南', 'ph': '菲律宾', 'id': '印尼'}
let monitorType = {'FINANCE': '财务'}
let statusFile = `${process.cwd()}/status.json`
let monitorApps = `${process.cwd()}/google-play-monitor-apps.json`
let base_gp_url = 'https://play.google.com/store/apps/details?id='
let developer =['yingchen.nong@starwin.com']
let notifyEmail = developer
let daichaoApps = []
let ourAppIds = []
let ourApps = {}
let hitDaichao = isTest() ? 1 : 0
let hitOurs = isTest() ? 1 : 0
// 返回需要监控的自有 app
let isTimeToAppendOurApp = (apps) => {
// 需求变更, 是首次加入判断超过12小时就监控, 非每次12小时
// 遍历所有自有 app, 看当前时间与加入时间, 超过12小时就加入返回list
let needMonitorApps = []
for (let i in apps ) {
let key = apps[i]
let timeIn = status[key] && status[key].timeIn
if (!timeIn) {
continue
}
timeIn = new Date(timeIn)
let date = new Date()
// 加上初次监控间隔
timeIn.setHours(timeIn.getHours() + defaultIntervalTimeForOurApp)
if (date >= timeIn) {
log(`初次加入监控 ------------> ${key}`)
needMonitorApps.push(key)
}
}
return needMonitorApps
}
let allNames = names => {
let an = []
Object.keys(names).forEach(key => {
if (key == "ourApps") {
// 返回需要监控的自有 app
an = [...an, ...isTimeToAppendOurApp(names[key])]
} else {
an = [...an, ...names[key]]
}
})
return Array.from(new Set(an))
}
function log(content) {
if (isTest()) {
console.log(`[${new Date().toLocaleString()}]: ${content}`)
}
}
function isTest() {
let testName = ['taketrace']
return testName.includes(username)
}
// Code ------------------------------------------------------------
// 状态记录
let status = {}
let monitorNames = {}
let isFirstRun = false
// 获取记录上次状态得文件
try {
status = JSON.parse(fs.readFileSync(statusFile, 'utf-8'))
isFirstRun = false
} catch (err) {
isFirstRun = true
console.log(`状态文件不存在, 直接使用空的{}\n${err.toString()}`)
}
// 获取记录上次更新监控名得文件
try {
let fileNames = JSON.parse(fs.readFileSync(monitorApps, 'utf-8'))
if (Array.isArray(fileNames)) {
monitorNames['vn'] = fileNames
console.log('原来只记录数组形式, 现在变更为对象形式, 原数组放到vn数组中')
} else {
monitorNames = fileNames
}
isFirstRun = false
} catch (err) {
console.log(`监控列表文件不存在, 直接使用空的{}\n${err.toString()}`)
}
let newOnline = [] // 新上架
let newOffline = [] // 新下架
let permissionChange = {} // 权限变化
let failedApps = [] // 获取失败的
let newTopMonitorNames = {}
let errorLog = [] // 错误记录
log('log 打开')
// 开始监控
if (isTest()) {
// sendEmail(`《上3下4T4》【上4下5T8】`, developer)
startMonitor()
} else {
startMonitor()
}
async function startMonitor() {
log('开始监控')
while (start) {
log(`抓取一圈`)
await getConfig()
.then(getDaichao)
.then(getTop100)
.then(() => fs.writeFileSync(monitorApps, JSON.stringify(monitorNames))) // 保存到本地
.then(() => { // 动态修改间隔得值
// 自有 app 没到时间不会进入监控
let allN = allNames(monitorNames)
return allN
})
.then(allN => monitorIfOnline(allN))
.then(genMail)
.then(sendEmail)
.then(() => {
// 每日在线列表报告
if (!isInTimeInRangeToday(dailyOnlineStartHours, dailyOnlineEndHours)) {
log('今天不在时间段或者已发过当日在线 app 列表')
return
}
let onlineApps = ourAppIds.filter(val => status[val] && status[val].status || false)
let daichaoOnlines = daichaoApps.filter(val => status[val] && status[val].status || false)
let content = ''
content += wrapSummary(`Gitlab 在线 app (${onlineApps.length}/${ourAppIds.length})`, onlineApps.map(val => link(val)))
content += wrapSummary(`贷超在线 App (${daichaoOnlines.length}/${daichaoApps.length})`, daichaoOnlines.map(val => link(val)))
sendEmail(content)
})
.then(() => {
log('成功')
// 将status 写入到文件
fs.writeFileSync(statusFile, JSON.stringify(status))
log(`文件写入成功`)
})
.then(() => log('over'))
.catch(err => {
lastIntervalTime = lastIntervalTime * 2
let content = `监控出错${err}\n间隔时间调整为${(lastIntervalTime) / minute}分钟`
content += markError()
console.log(content)
sendEmail(content, developer)
dingDing(content)
if (err.toString().includes('ENOSPC')) {
sendEmail(`小老弟, 这个爬虫呆着的机器没空间了, ${err.toString()}`, 'chaolun.ni@starwin.com')
}
// 出错了需要重新抓, 需要清空之前缓存的状态
newOffline = []
newOnline = []
permissionChange = {}
failedApps = []
errorLog = []
newTopMonitorNames = {}
hitDaichao = 0
hitOurs = 0
})
await sleepForInterVal(lastIntervalTime)
}
}
async function getDaichao() {
await getPromiss(daichao)
.then(val => {
if (isTest()) {
daichaoApps = []
return
}
daichaoData = JSON.parse(val && val.body && val.body || "{}").data
daichaoApps = daichaoData && daichaoData.map(app => app.packageName) || []
log(`代超数据: ${daichaoApps.length} 个`)
monitorNames["daichao"] = daichaoApps
if (daichaoApps.length == 0) {
log('代超数据为空')
}
})
.catch(err => {
errorLog.push(`贷超获取失败:${err.toString()}`)
return
})
}
async function getConfig() {
await getPromiss(subApi).then(val => {
log('------------ get congfig from gitlab -----------')
log(val.body)
let dataes = {}
if (isTest()) {
try {
dataes = JSON.parse(val.body)
} catch (err) {
throw `哪位老哥, 配置文件写错了啊...>>>>>>>>>\n${err}\n<<<<<<<<<\n`
}
ourApps = dataes.ourApps || {}
ourAppIds = Object.keys(ourApps)
if (ourAppIds.length == 0) {
ourApps = {"com.globe.gcash.android": "测试我的"}
ourAppIds = ["com.globe.gcash.android"]
}
monitorNames["ourApps"] = ourAppIds
ourAppIds.forEach(id => {
// 添加进状态文件, 设置上名字 (因为后面的能知道名字的操作只有获取前100的时候, 获取权限是不知道名字的)
status[id] = {...(status[id] || {}), appName: ourApps[id]}
if (!status[id].timeIn) {
// 如果没有记录加入时间, 记录, 加入时间只记录一次, 在 isTimeToAppendOurApp 中判断记录时间, 超过12小时就开始监控
status[id] = { ...status[id], timeIn: Date() }
}
})
} else {
dataes = JSON.parse(val.body)
let config = dataes.config
let subscriber = dataes.subscriber
ourApps = dataes.ourApps || {}
ourAppIds = Object.keys(ourApps)
monitorNames["ourApps"] = ourAppIds
ourAppIds.forEach(id => {
// 添加进状态文件, 设置上名字 (因为后面的能知道名字的操作只有获取前100的时候, 获取权限是不知道名字的)
status[id] = {...(status[id] || {}), appName: ourApps[id]}
if (!status[id].timeIn) {
// 如果没有记录加入时间, 记录, 加入时间只记录一次, 在 isTimeToAppendOurApp 中判断记录时间, 超过12小时就开始监控
status[id] = {...status[id], timeIn: Date()}
}
})
// 订阅人
notifyEmail = subscriber && Object.keys(subscriber) || notifyEmail
// 配置更新
defaultIntervalTime = minute * (config.defaultIntervalTime || defaultIntervalTime)
sleepTime = sec * (config.sleepTime || sleepTime)
requestTimeout = sec * (config.requestTimeout || requestTimeout)
requestTopAppNum = config.requestTopAppNum || requestTopAppNum
aliveTime = config.aliveTime || aliveTime
if (Array.isArray(config.theDaySendList)) {
theDaySendList = config.theDaySendList
} else {
theDaySendList = config.theDaySendList && [config.theDaySendList] || theDaySendList
}
aliveInterval = config.aliveInterval || aliveInterval
crabName = config.crabName || crabName
monitorRegion = config.monitorRegion || monitorRegion
monitorType = config.monitorType || monitorType
base_gp_url = config.base_gp_url || base_gp_url
defaultIntervalTimeForOurApp = config.defaultIntervalTimeForOurApp || defaultIntervalTimeForOurApp
start = config.start || start
dailyOnlineStartHours = config.dailyOnlineStartHours || dailyOnlineStartHours
dailyOnlineEndHours = config.dailyOnlineEndHours || dailyOnlineEndHours
log(JSON.stringify(config))
log(JSON.stringify(notifyEmail))
}
})
}
async function getTop100() {
log(`获取以下国家前${requestTopAppNum}: ${JSON.stringify(monitorRegion)}`)
let regions = Object.keys(monitorRegion)
let types = Object.keys(monitorType)
for (let i in regions) {
let region = regions[i]
log(`地区: ${region}`)
names = monitorNames[region] || []
newForRegion = []
for (let t in types) {
let type = types[t]
log(`分类: ${type}`)
// 数量分页
let getTimes = Math.floor(requestTopAppNum/120) + 1
let lastGetNum = requestTopAppNum % 120
if (getTimes > 5) {
if (getTimes > 6) {
lastGetNum = 120
}
getTimes = 5
}
for (let i = 0; i < getTimes; i++) {
let getNum = i == getTimes - 1 && lastGetNum || 119
log(`start: ${i * 120}, pageNum: ${getNum}`)
await sleep(sleepTime)
await gplay.list({
category: gplay.category[type],
collection: gplay.collection.TOP_FREE,
num: getNum,
start: i * 120,
lang: region,
country: region,
fullDetail: false,
requestOptions: { timeout: requestTimeout }
})
.then(res => {
console.log(`获取到 <${monitorRegion[region]}>[${monitorType[type]}]排名: ${i*120} ~ ${i*120+getNum}`)
if (res && res.length && res.length > 0) {
res.forEach(app => {
// --- 补齐/更新 app 名字, 不管是什么状态的, 前100得肯定都要加入监控, 直接设置名字
status[app.appId] = { ...(status[app.appId] || {}), appName: app.title }
// 补齐这个 app 分类
status[app.appId].category = type
if (!names.includes(app.appId)) {
names.push(app.appId)
newForRegion.push({ id: app.appId, name: app.title, region: monitorRegion[region], category: type })
log(`新加入<${monitorRegion[region]}>[${monitorType[type]}]监控: ${app.appId}`)
}
})
}
})
.catch(err => {
console.log(`获取排名<${monitorRegion[region]}> 错误: ${err.message}`)
throw err
})
}
}
if (newForRegion.length > 0) {
newTopMonitorNames[region] = [...(newTopMonitorNames[region] && newTopMonitorNames[region] || []), ...newForRegion]
monitorNames[region] = names
}
}
}
async function sleepForInterVal(val) {
log(`进行睡眠: ${lastIntervalTime}`)
await sleep(val)
}
async function monitorIfOnline(names) {
log(`获取数量: ${names.length}`)
for (let i in names) {
let name = names[i]
log(`获取: ${name}`)
await sleep(sleepTime)
await gplay.app({ appId: name, requestOptions: { timeout: requestTimeout } })
.then((val) => {
log(`获取到(${status[name] && status[name].category || 'noType'}): ${name}`)
judgeNewOnline(name)
// judgePermissionChanged(name, val)
status[name] = {
...(status[name] || {}),
// permissions: val,
status: true,
date: Date().toString()
}
})
.catch((err) => {
if (err.toString().includes('404')) {
console.log(`获取不到: ${name}, error: ${err}`)
failedApps.push(name)
judgeNewOffline(name)
let a = status[name] || {}
status[name] = { ...a, status: false, date: Date().toString() }
} else if (err.toString().includes('ETIMEDOUT')) {
console.log(`连接超时: ${err.toString()}`)
throw err
} else {
errorLog.push(`Motitor Online Error: ${link(name, true)} - ${err.message}`)
console.log(`获取在线错误: ${name}, ${err.message}`)
}
})
}
}
function link(name, countOurs) {
let ourName = isOurs(name, countOurs)
return `${ourName}
<a href="${base_gp_url}${name}">
${getRegion(name)}[${monitorType[status[name] && status[name].category || ''] || ''}] - ${name}
<br/>
名字: ${(status[name] && (status[name].appName || `(noName:这次更新数据里没有进前${requestTopAppNum})`))}
</a>`
}
function getRegion(name) {
let regions = Object.keys(monitorNames)
for (let i in regions) {
let key = regions[i]
if (monitorNames[key].includes(name)) {
return monitorRegion[key] || key
}
}
}
function markError() {
let emailContent = ''
log(`发生意外错误, 生错错误邮件: ${errorLog.toString()}`)
emailContent += `<details>`
emailContent += `<summary>虫子拿权限发生意外事故</summary>`
emailContent += `<dl>`
errorLog.forEach(e => {
emailContent += `<dt>${e}</dt>`
})
emailContent += `</dl>`
emailContent += `</details>`
errorLog = []
return emailContent
}
function genMail() {
let firstLine = '' // 第一行不用打开邮箱就能显示, 用来展示关键信息
let emailContent = ''
let lastSendListDate = new Date(status.sendListDate || 'Tue Jan 29 2019 19:32:24 GMT+0800 (CST)')
let today = new Date()
let needSendList = (theDaySendList.includes(today.getDay())) && (lastSendListDate.toLocaleDateString() != today.toLocaleDateString())
if (!isFirstRun
&& !needSendList
&& newOffline.length == 0
&& newOnline.length == 0
&& Object.keys(permissionChange).length == 0
&& Object.keys(newTopMonitorNames).length == 0) {
log(`没有更新, 不生成内容邮件`)
if (errorLog.length > 0) {
emailContent += `Error: ${markError()}`
return emailContent
}
return null
}
log(`第一次跑: ${isFirstRun}, 新下: ${newOffline.length}, 新上: ${newOnline.length}, 权限改变: ${Object.keys(permissionChange).length}`)
if (errorLog.length > 0) {
emailContent += markError()
}
if (failedApps.length > 0 && isFirstRun) {
emailContent += `<div>本次第一次监控</div>`
failedApps.forEach(name => {
emailContent += `<div>获取失败}: ${link(name, true)} </div>`
})
}
if (isFirstRun) {
isFirstRun = false
}
if (daichaoApps.length == 0) {
emailContent += '<div>没有从贷超监控中获取数据</div>'
}
// --------- 判断上下线和进入 top 中我们 app 的数量
let ourTop = []
let ourDown = ourAppIds.filter(val => newOffline.includes(val))
let ourUp = ourAppIds.filter(val => newOnline.includes(val))
let daichaoTop = []
let daichaoDown = daichaoApps.filter(val => newOffline.includes(val))
let daichaoUp = daichaoApps.filter(val => newOnline.includes(val))
// --------- 判断上下线和进入 top 中我们 app 的数量
if (Object.keys(newTopMonitorNames).length > 0) {
emailContent += `<div>------------从${Object.keys(newTopMonitorNames).length}个国家新增监控:-----------</div>`
Object.keys(newTopMonitorNames).forEach(key => {
let names = newTopMonitorNames[key]
if (names.length > 0) {
// 判断每个国家新增里自己的 app, 累加
ourTop = [...ourTop, ...ourAppIds.filter(val => names.includes(val))]
daichaoTop = [...daichaoTop, ...daichaoApps.filter(val => names.includes(val))]
emailContent += wrapSummary(`本次从<${monitorRegion[key]}>top${requestTopAppNum}新增监控: ${names.length} 个`,
names.map(n => `${link(n.id, true)}进top100`))
}
})
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
}
// 自己 app
firstLine = `《${firstLine}${ourUp.length > 0 ? `上${ourUp.length}` : ''}`
firstLine = `${firstLine}${ourDown.length > 0 ? `下${ourDown.length}` : ''}`
firstLine = `${firstLine}${ourTop.length > 0 ? `T${ourTop.length}` : ''}》`
// 贷超
firstLine = `${firstLine}${daichaoUp.length > 0 ? `上${daichaoUp.length}` : ''}`
firstLine = `${firstLine}${daichaoDown.length > 0 ? `下${daichaoDown.length}` : ''}`
firstLine = `${firstLine}${daichaoTop.length > 0 ? `T${daichaoTop.length}` : ''}】`
// 统计
hitOurs = ourUp.length + ourDown.length + ourTop.length
hitDaichao = daichaoUp.length + daichaoDown.length + daichaoTop.length
if (newOffline.length == 0) {
emailContent += '<div>没有登记中的产品被新下架</div>'
} else {
emailContent += `<br/>------------新下架: ${newOffline.length} 个-----------<br/>`
newOffline.forEach(name => {
let his = (status[name] && status[name].permissionHis && status[name].permissionHis) || {}
his.lastPermissions = (status[name] && status[name].permissions && status[name].permissions) || []
emailContent += getPermissionChangeContent(name, his, `新下架ಥ_ಥ(及上次权限情况)`)
// emailContent += `<div>检测到新下架ಥ_ಥ: ${link(name)}</div>`
})
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
}
if (newOnline.length == 0) {
emailContent += `<div>没有登记中的产品新上架</div>`
} else {
emailContent += `<div>-----------新上架: ${newOnline.length} 个---------------------</div>`
newOnline.forEach(name => {
if (permissionChange[name]) {
emailContent += getPermissionChangeContent(name, permissionChange[name], `新上架😃: `)
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
delete permissionChange[name]
} else {
emailContent += wrapSummary(`<div>新上架^_^: ${link(name, true)}</div>`,
((status[name] && status[name].permissions && status[name].permissions) || []))
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
}
})
}
if (Object.keys(permissionChange).length == 0) {
emailContent += `<div>没有检测到有产品仅权限改变</div>`
} else {
log('监测到有权限改变')
emailContent += `<br/>---------------权限改变: ${Object.keys(permissionChange).length} 个-------------<br/>`
Object.keys(permissionChange).forEach(val => {
emailContent += getPermissionChangeContent(val, permissionChange[val])
})
emailContent += `<br/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
}
// 发送当前监控列表
if (needSendList) {
emailContent += `<br/><br/><br/>`
let countrys = Object.keys(monitorRegion)
monitorRegion
emailContent += `<div>下面是监控列表<br/>当前监控${countrys.length}个国家</div>`
let total = 0
Object.keys(monitorNames).forEach(val => {
let num = monitorNames[val].length
total += num
emailContent += wrapSummary(`${monitorRegion[val] || val}(${num}个)`, monitorNames[val].map(id => link(id, false)))
})
emailContent += `<div>监控总数量: ${total}</div>`
status.sendListDate = today.toString()
}
emailContent += `<br/><br/><br/>${new Date().toLocaleString()}`
log(`生成邮件内容: \n${emailContent}`)
// 清空临时栈
newOffline = []
newOnline = []
permissionChange = {}
failedApps = []
errorLog = []
newTopMonitorNames = {}
return `<div>${firstLine}</div><br/>${emailContent}`
}
function isOurs(name, countOurs) {
if (daichaoApps.includes(name)) {
return "🏦(贷超)"
}
if (ourAppIds.includes(name)) {
return `📌(${ourApps[name] || 'No Name in Gitlab'})`
}
return ''
}
function getPermissionChangeContent(id, obj, title) {
changes = []
if (obj.adds && obj.adds.length > 0) { changes.push(wrapSummary(`添加`, obj.adds, "green")) }
if (obj.deletes && obj.deletes.length > 0) { changes.push(wrapSummary(`删除`, obj.deletes, "red")) }
if (obj.stills && obj.stills.length > 0) { changes.push(wrapSummary(`保留`, obj.stills, "gray")) }
if (obj.newPermission && obj.newPermission.length > 0) { changes.push(wrapSummary(`新权限`, obj.newPermission)) }
if (obj.lastPermissions && obj.lastPermissions.length > 0) { changes.push(wrapSummary(`旧权限`, obj.lastPermissions)) }
log(`权限改变: ${id}: ${changes.length}`)
return wrapSummary(`- <div>${title || '权限改变'}:<br/>${link(id, true)}</div>`, changes)
}
function setPermissionHis(name, obj) {
status[name].permissionHis = {adds: obj.adds, deletes: obj.deletes, stills: obj.stills}
}
function aliveContent(date, lastSend) {
let emailContent = ''
emailContent += `<div>现在是: ${date.toLocaleString()}, 监控还活着</div>`
let allN = allNames(monitorNames).length
emailContent += `<div>当前总监控: ${allN}, \n设置间隔时间: ${( lastIntervalTime / minute)}\n上次记录存活时间: ${lastSend.toLocaleString()}</div>`
log(emailContent)
return emailContent
}
function sendEmail(content, to = notifyEmail) {
if (content == null || content == undefined || content == '') {
console.log('没有生成内容, 检查心跳')
let date = new Date()
let lastDing = new Date(status.lastDingDate || 'Tue Jan 29 2019 19:32:24 GMT+0800 (CST)')
let lastSend = new Date(status.lastSendDate || 'Tue Jan 29 2019 19:32:24 GMT+0800 (CST)')
if ((date.getHours() - lastDing.getHours()) >= aliveInterval) {
log('钉钉发送心跳')
dingDing(aliveContent(date, lastDing))
status['lastDingDate'] = date.toString()
}
if (date.toLocaleDateString() != lastSend.toLocaleDateString()) {
// 不是同一天, 且是9点, 发送, 发送后重新保存发送时间为当天, 当天的就不会发送是否还活着
log(`当前时间: ${date.toLocaleString()}, 上次存活提示时间: ${lastSend.toLocaleString()}`)
if (date.getHours() > aliveTime) {
log(`发送心跳`)
content = aliveContent(date, lastSend)
status['lastSendDate'] = date.toString()
} else {
return
}
} else {
return
}
return
}
console.log(`发送email: ${content.length}`)
if (content.indexOf('Error') != -1) {
to = developer
} else {
// to = [...to, 添加只对自己app监控的人]
}
let myEmail = 'chaolun.ni@starwin.com'
let emailTo = to.join(', ')
let trans = nodemailer.createTransport({
host: 'smtp.exmail.qq.com',
port: 587,
secure: false,
auth: {
user: myEmail,
pass: '3JkTpbNQ3DeNRJbu'
}
})
let appendTitle = hitOurs > 0 ? `📌${hitOurs}` : ''
appendTitle = hitDaichao > 0 ? `${appendTitle}🏦${hitDaichao}` : `${appendTitle}`
let mailOption = {
from: myEmail,
to: emailTo,
subject: `${appendTitle}.${crabName}`,
text: content,
html: content,
}
trans.sendMail(mailOption, (error, info) => {
if (error) {
return console.log(`发生错误: ${error}`);
}
console.log(`message ${info.messageId} send: ${info.response}`)
})
dingDing(content, notifyDingding)
// 清空计数
hitDaichao = 0
hitOurs = 0
}
function dingDing(content, toDing=debugDingding) {
log(`发送钉钉~`)
content = `${crabName}\n` + content
request.post(toDing, {
headers: { 'content-type': 'application/json;charset=utf-8'},
body: JSON.stringify({
msgtype: 'text',
text: {content: content}
})
}, (err, param) => param.statusCode != 200 && log(`Error:${err}\nParam: ${JSON.stringify(param)}`))
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function judgeNewOnline(name) {
if (status[name] && status[name].status == false) {
log(`${name} 新上架 😃`)
newOnline.push(name)
}
}
function judgeNewOffline(name) {
if (status[name] && status[name].status == true) {
log(`${name} 被下架了 ಥ_ಥ`)
newOffline.push(name)
}
}
function judgePermissionChanged(name, newPermission) {
log(`检查${name}权限是否变化`)
if (status[name] == undefined || status[name].permissions == undefined) {
log(`拿不到这个名字${name}记录, 不做权限变化检测了`)
return
}
let oldPermissions = (status[name] && status[name].permissions && status[name].permissions) || []
let oldPSet = new Set(oldPermissions)
let newPSet = new Set(newPermission || [])
let deletes = new Set([...oldPSet].filter(x => !newPSet.has(x)))
let adds = new Set([...newPSet].filter(x => !oldPSet.has(x)))
let stills = new Set([...oldPSet].filter(x => newPSet.has(x)))
let situation = {
adds: Array.from(adds),
deletes: Array.from(deletes),
stills: Array.from(stills),
}
if (oldPermissions.length != newPermission.length) {
log(`${name} 有权限改变`)
permissionChange[name] = {
name: name,
newPermission: newPermission,
lastPermissions: oldPermissions,
...situation,
}
setPermissionHis(name, situation)
return
}
if (deletes.size > 0 || adds.size > 0) {
log(`${name} 有权限改变`)
permissionChange[name] = {
name: name,
newPermission: newPermission,
lastPermissions: oldPermissions,
...situation,
}
setPermissionHis(name, situation)
}
}
function wrapSummary(title, list, color='black') {
let emailContent = ''
emailContent += `<details style="color:${color}">`
emailContent += `<summary>${title}: </summary>`
emailContent += `<dl>`
list.forEach(l => {
emailContent += `<dt>- ${l}</dt>`
})
emailContent += `</dl>`
emailContent += `</details>`
return emailContent
}
function isInTimeInRangeToday(start, end) {
let dayKey = "lastDailyOnlinesAppsDate"
let now = new Date()
let lastDate = new Date(status[dayKey] || 'Tue Jan 29 2019 19:32:24 GMT+0800 (CST)')
lastDate.setHours(lastDate.getHours() + 24)
if (start < now.getHours() && now.getHours() < end && now > lastDate) {
status[dayKey] = Date()
return true
}
return false
}
{
"config": {
"dailyOnlineStartHours": 7,
"dailyOnlineEndHours": 9,
"defaultIntervalTimeForOurApp": 6,
"start": true,
"aliveInterval": 3,
......@@ -82,6 +84,7 @@
"com.tuvay.yet":"2043 VayTuyet",
"com.ancash.vaytien":"2045 AnCash",
"com.ucdong":"2046 ucDong",
"com.gogleplay.okvay":"2048 Okvay",
"com.bayvay.moky":"2049 BayVay",
"com.sundong.katana":"2053 SunDong",
"com.fast.mypesos": "3001 Filipino Solution深圳乐瀛菲律宾",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment