Skip to content

Instantly share code, notes, and snippets.

@LiuQixuan
Last active May 15, 2024 17:27
Show Gist options
  • Save LiuQixuan/19791ac41f976dfce3b662f8f383a862 to your computer and use it in GitHub Desktop.
Save LiuQixuan/19791ac41f976dfce3b662f8f383a862 to your computer and use it in GitHub Desktop.
从官网下载不同服版本的差异文件并打包
#先读我
#脚本需要PowerShell 7.0+环境 在终端中执行命令: `winget install Microsoft.PowerShell` 自动安装PowerShell 7.0+
#configPath为配置文件,配置文件获取地址: https://gist.github.com/LiuQixuan/205c6f4cc38b3a45ccd8d2592155e026
$configPath = "G:\Setup\GenshinImpact\creatDiffPackage\backup_config.json"
$startPageData = [PSCustomObject]@{
title = "差异化文件创建脚本"
description = "欢迎使用差异化文件创建脚本,请按照提示一步一步操作"
gameversion = "检测到当前安装了{0},版本号为{1},路径为{2}"
selection = "数字键键入您的需求:"
activity = @("替换资源下载进度", "子项目进度")
status = @("下载总进度:", "{0}版本下载进度:")
currentOperation = "正在下载{0}版本的{1}文件..."
optgroups = @(
@{
text = "下载"
opts = [ordered]@{
'1' = '下载国际服差异文件'
'2' = '下载国服差异文件'
'3' = '下载双服差异文件'
}
alert = "按enter键开始下载,esc返回开始页面,ctrl+C放弃操作退出脚本"
after = "按enter键开始打包差异文件,esc返回开始页面,ctrl+C放弃操作退出脚本"
rank = 1
}
@{
text = "后续操作"
opts = [ordered]@{
c = '清理缓存'
x = '清理所有已下载的文件'
}
alert = "即将清理文件夹按任意键确认清理,ctrl+C放弃操作,ctrl+C放弃操作退出脚本"
after = "清理完成,按任意键返回开始页面"
rank = 2
}
)
configPath = $configPath
}
function Get-GameVersion([string]$path) {
(Select-String -Path (Join-Path -path $path -ChildPath 'config.ini') -Pattern 'game_version=(?<version>[\d|\.]+)').Matches[0].Groups['version'].Value
}
function Get-GameServeVersion() {
$regItem = Get-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FeatureUsage\AppSwitched"
$pathlist = $regItem.GetValueNames() | Where-Object { $_ -Match '(genshin)|(yuanshen)' }
$result = @{OSREL = $null; CNREL = $null }
$pathlist.ForEach({
if ((Split-Path $_ -Leaf) -eq "genshinImpact.exe") {
$result.OSREL = @{path = $null; version = $null }
$result.OSREL.path = Split-Path $_
}
elseif ((Split-Path $_ -Leaf) -eq "yuanshen.exe") {
$result.CNREL = @{path = $null; version = $null }
$result.CNREL.path = Split-Path $_
}
elseif (((Split-Path $_ -Leaf) -eq "launcher.exe") -or ((Split-Path $_ | Split-Path -Leaf) -eq "Genshin Impact")) {
if ((Get-ChildItem -Path (Join-Path -Path (Split-Path $_) -ChildPath "Genshin Impact game") -Directory | Join-String -Property Name -Separator '') -match "genshin") {
$result.OSREL = @{path = $null; version = $null }
$result.OSREL.path = (Join-Path -Path (Split-Path $_) -ChildPath "Genshin Impact game")
}
else {
$result.CNREL = @{path = $null; version = $null }
$result.CNREL.path = (Join-Path -Path (Split-Path $_) -ChildPath "Genshin Impact game")
}
}
})
$result.keys | ForEach-Object { if ($null -ne $result[$_]) { $result[$_]['version'] = Get-GameVersion -Path $result[$_].path } }
return $result
}
class TaskManager {
$config = @{}
download([string]$url, [string]$path) {
try {
Invoke-WebRequest -Uri $url -OutFile $path
}
catch {
Write-Error ("<{0}> download fail." -f $url)
("<{0}> download fail." -f $url)>>(Join-Path -Path $PSScriptRoot -ChildPath ("./debug.creatDiffPackage_{0}.log" -f (Get-Date -Format 'yyyy-MM-dd-HH-mm-ss')))
}
}
[PSCustomObject]getScatteredURL([string]$vkey) {
$urls = "https://sdk-os-static.mihoyo.com/hk4e_global/mdk/launcher/api/resource?launcher_id=10&key=gcStgarh", "https://sdk-static.mihoyo.com/hk4e_cn/mdk/launcher/api/resource?launcher_id=18&key=eYd89JmJ"
$url = $null
$scatteredURL = $null
switch ($vkey) {
'OSREL' {
$url = $urls[0]
break
}
'CNREL' {
$url = $urls[1]
break
}
Default {
Write-Error "Error,vKey."
}
}
if ($null -ne $url) {
$respose = Invoke-WebRequest -Uri $url -Method Get -ContentType 'text/plain'
$json = ConvertFrom-Json -InputObject $respose.Content
if ($json.retcode -eq 0) {
$this.config['resVersion'] = $json.data.game.latest.version
$scatteredURL = $json.data.game.latest.decompressed_path
#Write-Host $name,$json.data.game.latest.entry
#Out-File -FilePath (Join-Path -Path $PSScriptRoot -ChildPath ("./{0}_v{1}-{2}.json" -f $name, $version, (Get-Date -UFormat "%Y_%m_%d_%H_%M"))) -Encoding utf8 -InputObject $respose.Content
}
else {
Write-Host "bad request."
}
}
return $scatteredURL
}
TaskManager($data) {
#todo
$this.config.data = $data
$this.initianlizing()
}
[void]run() {
$this.prompting()
# $this.configuring()
# $this.writing()
# $this.conflicts()
# $this.install()
# $this.end()
}
initianlizing() {
#todo
$global:host.ui.RawUI.WindowTitle = $this.config.data.title
Write-Host "initianlizing!"
if (Test-Path -Path ( Join-Path -Path $PSScriptRoot -ChildPath 'release')) {
$this.config['historyVersion'] = Get-ChildItem -Path (Join-Path $PSScriptRoot -ChildPath 'release') | ForEach-Object { $_.Name }
# Write-Host $this.config.historyVersion
}
$this.config['currentVersion'] = Get-GameServeVersion
$this.config['versionTag'] = @{OSREL = "GenshinImpact"; CNREL = "YuanShen" }
$this.run()
}
printTitle($data) {
Write-Host ($data.description) -ForegroundColor red -BackgroundColor White
}
printProgress($ddata) {
Write-Progress -Id 0 -Activity $this.config.data.activity[0] -Status $this.config.data.status[0] -PercentComplete ([Math]::Round($ddata.i / $ddata.total * 100)) -Completed
Write-Progress -Id 1 -ParentId 0 -Activity $this.config.data.activity[1] -Status ($this.config.data.status[1] -f $ddata.vKey) -PercentComplete ([Math]::Round($ddata.i / $ddata.all * 100)) -CurrentOperation ($this.config.data.currentOperation -f $ddata.vKey, $ddata.name) -Completed
}
printStartPage($data) {
$this.printTitle($data)
foreach ($_ in $this.config.currentVersion.keys) {
if ($null -ne $this.config.currentVersion[$_]) {
$tmp = $this.config.currentVersion[$_].Values.ForEach({ $_ })
Write-Host ($this.config.data.gameversion -f @($_, $tmp[1], $tmp[0]))
}
}
Write-Host $data.selection
$opt = $data.optgroups[0]
Write-Host $opt.text
$opt.opts.keys.foreach({Write-Host ("`t[{0}]`t{1}" -f $_,$opt.opts[$_])})
}
[PSCustomObject]getFileList() {
$coreFileList = @()
$otherFileList = @{'OSREL'=@();'CNREL'=@()}
$coreJson = Get-Content -Path $this.config.data.configPath -Raw | ConvertFrom-Json
$this.config['configVersion'] = $coreJson.gameVersion
$coreJson.copyTasks.foreach({
$dir = $_.dir
$_.items.foreach({
if ('String' -ne $_.getType()) {
#$_.foreach({ Write-Host "-ne>>>>>"$_ ; $coreFileList+=($_.filename.replace('LANGUAGE', $lang)) })
}
else {
$coreFileList += (('' -ne $dir)?(Join-Path $dir -ChildPath $_):$_)
}
})
})
#$coreJson.includeItems.foreach({ if($_.language.contains($lang)){$_.list.foreach({$coreFileList+=( $_.replace('Data',"{0}_Data" -f $gameName))})} })
$coreJson.includeItems.foreach({ $list = $_.list; $_.version.foreach({ $i = $_; $list.foreach({ $otherFileList[$i] += $this.config.versionTag[$i]+$_ }) }) })
# $coreJson.includeItems.foreach({ $_.list.foreach({ $otherFileList[$_.version] += $gameName }) })
return @($coreFileList, $otherFileList)
}
[PSCustomObject]getDownloadList([array]$vKeys) {
$result = @{'OSREL' = @(); 'CNREL' = @() }
$FileLists = $this.getFileList()
write-host ">>>"$FileLists[1]['OSREL'] $FileLists[1]['CNREL']
$vKeys.foreach({
$lang = $null
$gameName = $null
$vkey = $_
switch ($vkey) {
'OSREL' {
$lang = 'English'
$gameName = 'GenshinImpact'
break
}
'CNREL' {
$lang = 'Chinese'
$gameName = 'YuanShen'
break
}
Default {
Write-Error "Error,vKey."
}
}
$scatteredURL = $this.getScatteredURL($_)
# Write-Debug $scatteredURL
$FileLists[0].foreach({
$result[$vkey] += ('{0}/{1}' -f $scatteredURL, ($_.StartsWith('Data')? ("{0}_{1}" -f $gameName, $_):($_.StartsWith('Audio')?$_.replace('LANGUAGE', $lang):$_)))
})
$FileLists[1][$vkey].foreach({
$result[$vkey] += ('{0}/{1}' -f $scatteredURL, ($_.StartsWith('Data')? ("{0}_{1}" -f $gameName, $_):("{0}{1}" -f $gameName, $_) ))
})
})
return $result
}
printDownloadPage($vKeys) {
$scatteredURLs = $this.getDownloadList($vKeys )
# Write-Host ">>>>>>"$scatteredURLs['CNREL']
$total = 0
$vKeys.foreach({
# Write-Host ">>>>>"$_, $scatteredURLs[$_].count
$total += $scatteredURLs[$_].count
})
$vKeys.foreach({
$vKey = $_
$dpath = Join-Path -Path $PSScriptRoot -ChildPath ('./release/{0}/{1}' -f $this.config.resVersion, $_)
New-Item -ItemType Directory -Path $dpath -Force
for ($i = 0; $i -lt $scatteredURLs[$_].Length; ++$i) {
$filePath = Join-Path -Path $dpath -ChildPath $scatteredURLs[$_][$i].split('ScatteredFiles/')[1]
if(-not (Test-Path -Path (Split-Path -path $filePath))){
New-Item -ItemType Directory -Path (Split-Path -Path $filePath)
}
$this.download($scatteredURLs[$_][$i],$filePath)
# Start-Sleep -Milliseconds 250
$ddata = @{vKey = $vKey; name = $scatteredURLs[$_][$i].split('ScatteredFiles/')[1]; total = $total; all = $scatteredURLs[$_].Length; i = $i }
# $this.printProgress($ddata)
Write-Progress -Id 0 -Activity $this.config.data.activity[0] -Status $this.config.data.status[0] -PercentComplete ([Math]::Round($ddata.i / $ddata.total * 100))
Write-Progress -Id 1 -ParentId 0 -Activity $this.config.data.activity[1] -Status ($this.config.data.status[1] -f $ddata.vKey) -PercentComplete ([Math]::Round($ddata.i / $ddata.all * 100)) -CurrentOperation ($this.config.data.currentOperation -f $ddata.vKey, $ddata.name)
}
})
Clear-History
}
printClearPage() {
}
compressZip(){
$releasePath = Join-Path -Path $PSScriptRoot -ChildPath ('./release/{0}' -f $this.config.resVersion)
Compress-Archive -Path $releasePath -CompressionLevel Optimal -DestinationPath (Join-Path -Path $PSScriptRoot -ChildPath ('./release/release_v{0}.zip' -f $this.config.resVersion))
}
clearTmp(){
Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'release') | Where-Object -Property 'Attributes' -EQ 'Directory'|Remove-Item -Force -Recurse
}
prompting() {
#todo
$vKey = @('CNREL', 'OSREL')
$this.printStartPage($this.config.data)
$userInput = Read-Host $this.config.data.optgroups[0].alert
switch ($userInput) {
"1" {
$vKey = @('OSREL')
break
}
"2" {
$vKey = @('CNREL')
break
}
"3" {
# $vKey = @('CNREL', 'OSREL')
break
}
Default {
Write-Error "[ERROR]:input Error key."
Write-Error "Script will download all server version files."
}
}
$this.printDownloadPage($vKey)
Read-Host $this.config.data.optgroups[0].after
$this.compressZip()
Read-Host $this.config.data.optgroups[1].alert
$this.clearTmp()
Read-Host $this.config.data.optgroups[1].after
Clear-Host
$this.printStartPage($this.config.data)
}
configuring() {
#todo
}
writing() {
#todo
}
conflicts() {
#todo
}
install() {
#todo
}
end(){
#todo
Read-Host "按任意键退出"
}
}
$taskManager = [TaskManager]::new($startPageData)
$taskManager.end()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment