This commit is contained in:
2024-07-17 17:07:46 +08:00
parent 60bc7b43ee
commit 2aa754d471
48 changed files with 2256 additions and 3804 deletions

View File

@@ -28,7 +28,7 @@ const start = async () => {
lang: data.lang,
export_time: formatDate(new Date()),
export_timestamp: Math.ceil(Date.now() / 1000),
export_app: 'star-rail-warp-export',
export_app: 'zzz-signal-search-export',
export_app_version: `v${version}`,
region_time_zone: data.region_time_zone,
srgf_version: 'v1.0'

View File

@@ -12,8 +12,8 @@ const { mergeData } = require('./utils/mergeData')
const gachaTypeRaw = require('../gachaType.json')
const dataMap = new Map()
const order = ['11', '12', '1', '2']
let apiDomain = 'https://api-takumi.mihoyo.com'
const order = ['2', '3', '1', '5']
let apiDomain = 'https://public-operation-nap.mihoyo.com'
const saveData = async (data, url) => {
const obj = Object.assign({}, data)
@@ -23,10 +23,10 @@ const saveData = async (data, url) => {
}
const defaultTypeMap = new Map([
['11', '角色活动跃迁'],
['12', '光锥活动跃迁'],
['1', '常驻跃迁'],
['2', '新手跃迁']
['2', '独家频段'],
['3', '音擎频段'],
['1', '常驻频段'],
['5', '邦布频段']
])
const findDataFiles = async (dataPath, fileMap) => {
@@ -86,7 +86,7 @@ const changeCurrent = async (uid) => {
const detectGameLocale = async (userPath) => {
let list = []
const lang = app.getLocale()
const arr = ['/miHoYo/崩坏:星穹铁道/', '/Cognosphere/Star Rail/']
const arr = ['/miHoYo/绝区零/', '/Cognosphere/Zenless Zone Zero/']
arr.forEach(str => {
try {
const pathname = path.join(userPath, '/AppData/LocalLow/', str, 'Player.log')
@@ -165,7 +165,7 @@ const readLog = async () => {
const getGachaLog = async ({ key, page, name, retryCount, url, endId }) => {
const text = i18n.log
try {
const res = await request(`${url}&gacha_type=${key}&page=${page}&size=${20}${endId ? '&end_id=' + endId : ''}`)
const res = await request(`${url}&real_gacha_type=${key}&page=${page}&size=${20}${endId ? '&end_id=' + endId : ''}`)
if (res?.data?.list) {
return res?.data
}
@@ -262,7 +262,7 @@ const tryGetUid = async (queryString) => {
const url = `${apiDomain}/common/gacha_record/api/getGachaLog?${queryString}`
try {
for (let [key] of defaultTypeMap) {
const res = await request(`${url}&gacha_type=${key}&page=1&size=6`)
const res = await request(`${url}&real_gacha_type=${key}&page=1&size=6`)
if (res.data.list && res.data.list.length) {
return res.data.list[0].uid
}
@@ -291,7 +291,7 @@ const getQuerystring = (url) => {
if (host.includes('webstatic-sea') || host.includes('hkrpg-api-os') || host.includes('api-os-takumi') || host.includes('hoyoverse.com')) {
apiDomain = 'https://api-os-takumi.mihoyo.com'
} else {
apiDomain = 'https://api-takumi.mihoyo.com'
apiDomain = 'https://public-operation-nap.mihoyo.com'
}
const authkey = searchParams.get('authkey')
if (!authkey) {
@@ -300,7 +300,7 @@ const getQuerystring = (url) => {
}
searchParams.delete('page')
searchParams.delete('size')
searchParams.delete('gacha_type')
searchParams.delete('real_gacha_type')
searchParams.delete('end_id')
return searchParams
}
@@ -357,7 +357,7 @@ const getUrlFromConfig = () => {
const tryRequest = async (url, retry = false) => {
const queryString = getQuerystring(url)
if (!queryString) return false
const gachaTypeUrl = `${apiDomain}/common/gacha_record/api/getGachaLog?${queryString}&page=1&size=5&gacha_type=1&end_id=0`
const gachaTypeUrl = `${apiDomain}/common/gacha_record/api/getGachaLog?${queryString}&page=1&size=5&real_gacha_type=1&end_id=0`
try {
const res = await request(gachaTypeUrl)
checkResStatus(res)

View File

@@ -1,17 +1,7 @@
const raw = {
'zh-cn': require('../i18n/简体中文.json'),
'zh-tw': require('../i18n/繁體中文.json'),
'de-de': require('../i18n/Deutsch.json'),
'en-us': require('../i18n/English.json'),
'es-es': require('../i18n/Español.json'),
'fr-fr': require('../i18n/Français.json'),
'id-id': require('../i18n/Indonesia.json'),
'ja-jp': require('../i18n/日本語.json'),
'ko-kr': require('../i18n/한국어.json'),
'pt-pt': require('../i18n/Português.json'),
'ru-ru': require('../i18n/Pусский.json'),
'th-th': require('../i18n/ภาษาไทย.json'),
'vi-vn': require('../i18n/Tiếng Việt.json')
'en-us': require('../i18n/English.json')
}
const config = require('./config')
const isPlainObject = require('lodash/isPlainObject')

View File

@@ -5,7 +5,6 @@ require('./getData')
require('./bridge')
require('./excel')
require('./SRGFJson')
const { getUpdateInfo } = require('./update/index')
const isDev = !app.isPackaged
let win = null
@@ -54,12 +53,6 @@ if (!isFirstInstance) {
if (proxyStatus.started) {
disableProxy()
}
if (getUpdateInfo().status === 'moving') {
e.preventDefault()
setTimeout(() => {
app.quit()
}, 3000)
}
})
app.on('quit', () => {

View File

@@ -1,185 +0,0 @@
// Copyright (c) 2014 Max Ogden and other contributors
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// https://github.com/maxogden/extract-zip
// eslint-disable-next-line node/no-unsupported-features/node-builtins
const { createWriteStream, promises: fs } = require('original-fs')
const getStream = require('get-stream')
const path = require('path')
const { promisify } = require('util')
const stream = require('stream')
const yauzl = require('yauzl')
const openZip = promisify(yauzl.open)
const pipeline = promisify(stream.pipeline)
class Extractor {
constructor (zipPath, opts) {
this.zipPath = zipPath
this.opts = opts
}
async extract () {
this.zipfile = await openZip(this.zipPath, { lazyEntries: true })
this.canceled = false
return new Promise((resolve, reject) => {
this.zipfile.on('error', err => {
this.canceled = true
reject(err)
})
this.zipfile.readEntry()
this.zipfile.on('close', () => {
if (!this.canceled) {
resolve()
}
})
this.zipfile.on('entry', async entry => {
/* istanbul ignore if */
if (this.canceled) {
return
}
if (entry.fileName.startsWith('__MACOSX/')) {
this.zipfile.readEntry()
return
}
const destDir = path.dirname(path.join(this.opts.dir, entry.fileName))
try {
await fs.mkdir(destDir, { recursive: true })
const canonicalDestDir = await fs.realpath(destDir)
const relativeDestDir = path.relative(this.opts.dir, canonicalDestDir)
if (relativeDestDir.split(path.sep).includes('..')) {
throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`)
}
await this.extractEntry(entry)
this.zipfile.readEntry()
} catch (err) {
this.canceled = true
this.zipfile.close()
reject(err)
}
})
})
}
async extractEntry (entry) {
/* istanbul ignore if */
if (this.canceled) {
return
}
if (this.opts.onEntry) {
this.opts.onEntry(entry, this.zipfile)
}
const dest = path.join(this.opts.dir, entry.fileName)
// convert external file attr int into a fs stat mode int
const mode = (entry.externalFileAttributes >> 16) & 0xFFFF
// check if it's a symlink or dir (using stat mode constants)
const IFMT = 61440
const IFDIR = 16384
const IFLNK = 40960
const symlink = (mode & IFMT) === IFLNK
let isDir = (mode & IFMT) === IFDIR
// Failsafe, borrowed from jsZip
if (!isDir && entry.fileName.endsWith('/')) {
isDir = true
}
// check for windows weird way of specifying a directory
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
const madeBy = entry.versionMadeBy >> 8
if (!isDir) isDir = (madeBy === 0 && entry.externalFileAttributes === 16)
const procMode = this.getExtractedMode(mode, isDir) & 0o777
// always ensure folders are created
const destDir = isDir ? dest : path.dirname(dest)
const mkdirOptions = { recursive: true }
if (isDir) {
mkdirOptions.mode = procMode
}
await fs.mkdir(destDir, mkdirOptions)
if (isDir) return
const readStream = await promisify(this.zipfile.openReadStream.bind(this.zipfile))(entry)
if (symlink) {
const link = await getStream(readStream)
await fs.symlink(link, dest)
} else {
await pipeline(readStream, createWriteStream(dest, { mode: procMode }))
}
}
getExtractedMode (entryMode, isDir) {
let mode = entryMode
// Set defaults, if necessary
if (mode === 0) {
if (isDir) {
if (this.opts.defaultDirMode) {
mode = parseInt(this.opts.defaultDirMode, 10)
}
if (!mode) {
mode = 0o755
}
} else {
if (this.opts.defaultFileMode) {
mode = parseInt(this.opts.defaultFileMode, 10)
}
if (!mode) {
mode = 0o644
}
}
}
return mode
}
}
module.exports = async function (zipPath, opts) {
if (!path.isAbsolute(opts.dir)) {
throw new Error('Target directory is expected to be absolute')
}
await fs.mkdir(opts.dir, { recursive: true })
opts.dir = await fs.realpath(opts.dir)
return new Extractor(zipPath, opts).extract()
}

View File

@@ -1,65 +0,0 @@
const { app } = require('electron')
const fetch = require('electron-fetch').default
const semver = require('semver')
const util = require('util')
const path = require('path')
const fs = require('fs-extra')
const extract = require('../module/extract-zip')
const { version } = require('../../../package.json')
const { hash, sendMsg } = require('../utils')
const config = require('../config')
const i18n = require('../i18n')
const streamPipeline = util.promisify(require('stream').pipeline)
async function download(url, filePath) {
const response = await fetch(url)
if (!response.ok) throw new Error(`unexpected response ${response.statusText}`)
await streamPipeline(response.body, fs.createWriteStream(filePath))
}
const updateInfo = {
status: 'init'
}
const isDev = !app.isPackaged
const appPath = isDev ? path.resolve(__dirname, '../../', 'update-dev/app'): app.getAppPath()
const updatePath = isDev ? path.resolve(__dirname, '../../', 'update-dev/download') : path.resolve(appPath, '..', '..', 'update')
const update = async () => {
if (isDev) return
try {
const url = 'https://star-rail-warp-export.css.moe/update'
const res = await fetch(`${url}/manifest.json?t=${Math.floor(Date.now() / (1000 * 60 * 10))}`)
const data = await res.json()
if (!data.active) return
if (semver.gt(data.version, version) && semver.gte(version, data.from)) {
await fs.emptyDir(updatePath)
const filePath = path.join(updatePath, data.name)
if (!config.autoUpdate) {
sendMsg(data.version, 'NEW_VERSION')
return
}
updateInfo.status = 'downloading'
await download(`${url}/${data.name}`, filePath)
const buffer = await fs.readFile(filePath)
const sha256 = hash(buffer)
if (sha256 !== data.hash) return
const appPathTemp = path.join(updatePath, 'app')
await extract(filePath, { dir: appPathTemp })
updateInfo.status = 'moving'
await fs.emptyDir(appPath)
await fs.copy(appPathTemp, appPath)
updateInfo.status = 'finished'
sendMsg(i18n.log.autoUpdate.success, 'UPDATE_HINT')
}
} catch (e) {
updateInfo.status = 'failed'
sendMsg(e, 'ERROR')
}
}
const getUpdateInfo = () => updateInfo
setTimeout(update, 1000)
exports.getUpdateInfo = getUpdateInfo

View File

@@ -103,33 +103,13 @@ const sortData = (data) => {
const langMap = new Map([
['zh-cn', '简体中文'],
['zh-tw', '繁體中文'],
['de-de', 'Deutsch'],
['en-us', 'English'],
['es-es', 'Español'],
['fr-fr', 'Français'],
['id-id', 'Indonesia'],
['ja-jp', '日本語'],
['ko-kr', '한국어'],
['pt-pt', 'Português'],
['ru-ru', 'Pусский'],
['th-th', 'ภาษาไทย'],
['vi-vn', 'Tiếng Việt']
['en-us', 'English']
])
const localeMap = new Map([
['zh-cn', ['zh', 'zh-CN']],
['zh-tw', ['zh-TW']],
['de-de', ['de-AT', 'de-CH', 'de-DE', 'de']],
['en-us', ['en-AU', 'en-CA', 'en-GB', 'en-NZ', 'en-US', 'en-ZA', 'en']],
['es-es', ['es', 'es-419']],
['fr-fr', ['fr-CA', 'fr-CH', 'fr-FR', 'fr']],
['id-id', ['id']],
['ja-jp', ['ja']],
['ko-kr', ['ko']],
['pt-pt', ['pt-BR', 'pt-PT', 'pt']],
['ru-ru', ['ru']],
['th-th', ['th']],
['vi-vn', ['vi']]
['en-us', ['en-AU', 'en-CA', 'en-GB', 'en-NZ', 'en-US', 'en-ZA', 'en']]
])
const detectLocale = (value) => {