Skip to content

Commit

Permalink
hoyoplay service and better gameid
Browse files Browse the repository at this point in the history
  • Loading branch information
Scighost committed Nov 25, 2024
1 parent afbc317 commit 0a454ee
Show file tree
Hide file tree
Showing 4 changed files with 359 additions and 4 deletions.
6 changes: 3 additions & 3 deletions src/Starward.Core/HoYoPlay/GameId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ public class GameId : IEquatable<GameId>
GameBiz.bh3_asia => new GameId { Id = "wkE5P5WsIf", GameBiz = "bh3_global" },
GameBiz.hk4e_cn => new GameId { Id = "1Z8W5NHUQb", GameBiz = "hk4e_cn" },
GameBiz.hk4e_global => new GameId { Id = "gopR6Cufr3", GameBiz = "hk4e_global" },
GameBiz.hk4e_bilibili => new GameId { Id = "T2S0Gz4Dr2", GameBiz = "hk4e_cn" },
GameBiz.hk4e_bilibili => new GameId { Id = "T2S0Gz4Dr2", GameBiz = "hk4e_bilibili" },
GameBiz.hkrpg_cn => new GameId { Id = "64kMb5iAWu", GameBiz = "hkrpg_cn" },
GameBiz.hkrpg_global => new GameId { Id = "4ziysqXOQ8", GameBiz = "hkrpg_global" },
GameBiz.hkrpg_bilibili => new GameId { Id = "EdtUqXfCHh", GameBiz = "hkrpg_cn" },
GameBiz.hkrpg_bilibili => new GameId { Id = "EdtUqXfCHh", GameBiz = "hkrpg_bilibili" },
GameBiz.nap_cn => new GameId { Id = "x6znKlJ0xK", GameBiz = "nap_cn" },
GameBiz.nap_global => new GameId { Id = "U5hbdsT9W7", GameBiz = "nap_global" },
GameBiz.nap_bilibili => new GameId { Id = "HXAFlmYa17", GameBiz = "nap_cn" },
GameBiz.nap_bilibili => new GameId { Id = "HXAFlmYa17", GameBiz = "nap_bilibili" },
_ => null,
};
}
Expand Down
5 changes: 5 additions & 0 deletions src/Starward.Core/HoYoPlay/LauncherId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ public static bool IsBilibili(string launcherId)
GameBiz.hk4e_bilibili => BilibiliGenshin,
GameBiz.hkrpg_bilibili => BilibiliStarRail,
GameBiz.nap_bilibili => BilibiliZZZ,
string value when value.EndsWith("_cn") => ChinaOfficial,
string value when value.EndsWith("_global") => GlobalOfficial,
_ => null,
};
}


public static string? FromGameId(GameId gameId) => FromGameBiz(gameId.GameBiz);


public static List<(GameBiz GameBiz, string LauncherId)> GetBilibiliLaunchers()
{
return new List<(GameBiz, string)>
Expand Down
2 changes: 1 addition & 1 deletion src/Starward/Features/Database/DatabaseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal static class DatabaseService
private static string _connectionString;


private static Lock _lock;
private static Lock _lock = new();


static DatabaseService()
Expand Down
350 changes: 350 additions & 0 deletions src/Starward/Features/HoYoPlay/HoYoPlayService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
using Microsoft.Extensions.Logging;
using Starward.Core;
using Starward.Core.HoYoPlay;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace Starward.Features.HoYoPlay;

public class HoYoPlayService
{


private readonly ILogger<HoYoPlayService> _logger;

private readonly HoYoPlayClient _client;

private readonly HttpClient _httpClient;

private readonly System.Timers.Timer _timer;


public HoYoPlayService(ILogger<HoYoPlayService> logger, HoYoPlayClient client, HttpClient httpClient)
{
_logger = logger;
_client = client;
_httpClient = httpClient;
_timer = new System.Timers.Timer
{
AutoReset = true,
Enabled = true,
Interval = TimeSpan.FromMinutes(10).TotalMilliseconds,
};
_timer.Elapsed += async (_, _) => await PrepareDataAsync();
}




private ConcurrentDictionary<GameId, GameInfo> _gameInfo = new();


private ConcurrentDictionary<GameId, GameBackgroundInfo> _gameBackground = new();


private ConcurrentDictionary<GameId, GameContent> _gameContent = new();


private ConcurrentDictionary<GameId, GamePackage> _gamePackage = new();


private ConcurrentDictionary<GameId, GameConfig> _gameConfig = new();



public void ClearCache()
{
_gameInfo.Clear();
_gameBackground.Clear();
_gameContent.Clear();
_gamePackage.Clear();
}




public async Task PrepareDataAsync()
{
try
{
ClearCache();
string lang = CultureInfo.CurrentUICulture.Name;
List<Task> tasks = [];
tasks.Add(PrepareDataForServerAsync(LauncherId.ChinaOfficial, lang));
tasks.Add(PrepareDataForServerAsync(LauncherId.GlobalOfficial, lang));
tasks.Add(PrepareDataForBilibiliServerAsync(lang));
await Task.WhenAll(tasks);
await PrepareImagesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, nameof(PrepareDataAsync));
}
}



private async Task PrepareDataForServerAsync(string launcherId, string? language = null)
{
try
{
language ??= CultureInfo.CurrentUICulture.Name;
List<GameInfo> infos = await _client.GetGameInfoAsync(launcherId, language);
foreach (GameInfo item in infos)
{
_gameInfo[item] = item;
}
List<GameBackgroundInfo> backgrounds = await _client.GetGameBackgroundAsync(launcherId, language);
foreach (GameBackgroundInfo item in backgrounds)
{
_gameBackground[item.GameId] = item;
}
foreach (var item in infos)
{
GameContent content = await _client.GetGameContentAsync(launcherId, language, item);
_gameContent[content.GameId] = content;
}
List<GamePackage> packages = await _client.GetGamePackageAsync(launcherId, language);
foreach (GamePackage item in packages)
{
_gamePackage[item.GameId] = item;
}
List<GameConfig> configs = await _client.GetGameConfigAsync(launcherId, language);
foreach (GameConfig item in configs)
{
_gameConfig[item.GameId] = item;
}
}
catch (Exception ex)
{
_logger.LogError(ex, nameof(PrepareDataForServerAsync));
}
}



private async Task PrepareDataForBilibiliServerAsync(string? language = null)
{
try
{
language ??= CultureInfo.CurrentUICulture.Name;
foreach ((GameBiz biz, string launcherId) in LauncherId.GetBilibiliLaunchers())
{
List<GameInfo> infos = await _client.GetGameInfoAsync(launcherId, language);
foreach (GameInfo item in infos)
{
_gameInfo[item] = item;
}
List<GameBackgroundInfo> backgrounds = await _client.GetGameBackgroundAsync(launcherId, language);
foreach (GameBackgroundInfo item in backgrounds)
{
_gameBackground[item.GameId] = item;
}
foreach (GameInfo item in infos)
{
GameContent content = await _client.GetGameContentAsync(launcherId, language, item);
_gameContent[item] = content;
}
List<GamePackage> packages = await _client.GetGamePackageAsync(launcherId, language);
foreach (GamePackage item in packages)
{
_gamePackage[item.GameId] = item;
}
List<GameConfig> configs = await _client.GetGameConfigAsync(launcherId, language);
foreach (GameConfig item in configs)
{
_gameConfig[item.GameId] = item;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, nameof(PrepareDataForBilibiliServerAsync));
}
}



private async Task PrepareImagesAsync()
{
try
{
List<GameBiz> bizs = GetSelectedGameBizs();
List<string> urls = [];
foreach (GameBiz biz in bizs)
{
if (GameId.FromGameBiz(biz) is GameId gameId)
{
if (_gameInfo.TryGetValue(gameId, out GameInfo? info))
{
urls.Add(info.Display.Background.Url);
}
if (_gameBackground.TryGetValue(gameId, out GameBackgroundInfo? background))
{
urls.AddRange(background.Backgrounds.Select(x => x.Background.Url));
}
}
}
string bg = Path.Combine(AppConfig.UserDataFolder, "bg");
Directory.CreateDirectory(bg);
await Parallel.ForEachAsync(urls, async (url, _) =>
{
try
{
if (string.IsNullOrWhiteSpace(url))
{
return;
}
string name = Path.GetFileName(url);
string path = Path.Combine(bg, name);
if (!File.Exists(path))
{
byte[] bytes = await _httpClient.GetByteArrayAsync(url);
await File.WriteAllBytesAsync(path, bytes);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Download image: {url}", url);
}
});
}
catch (Exception ex)
{
_logger.LogError(ex, nameof(PrepareImagesAsync));
}
}



private static List<GameBiz> GetSelectedGameBizs()
{
List<GameBiz> bizs = new();
foreach (string str in AppConfig.SelectedGameBizs?.Split(',') ?? [])
{
if (GameBiz.TryParse(str, out GameBiz biz))
{
bizs.Add(biz);
}
}
return bizs;
}




public async Task<GameInfo> GetGameInfoAsync(GameId gameId)
{
if (!_gameInfo.TryGetValue(gameId, out GameInfo? info))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameInfoAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameInfo[item] = item;
}
info = list.First(x => x == gameId);
}
return info;
}



public async Task<GameBackgroundInfo> GetGameBackgroundAsync(GameId gameId)
{
if (!_gameBackground.TryGetValue(gameId, out GameBackgroundInfo? background))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameBackgroundAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameBackground[item.GameId] = item;
}
background = list.First(x => x.GameId == gameId);
}
return background;
}



public async Task<GameContent> GetGameContentAsync(GameId gameId)
{
if (!_gameContent.TryGetValue(gameId, out GameContent? content))
{
string lang = CultureInfo.CurrentUICulture.Name;
content = await _client.GetGameContentAsync(LauncherId.FromGameId(gameId)!, lang, gameId);
_gameContent[gameId] = content;
}
return content;
}



public async Task<GamePackage> GetGamePackageAsync(GameId gameId)
{
if (!_gamePackage.TryGetValue(gameId, out GamePackage? package))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGamePackageAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gamePackage[item.GameId] = item;
}
package = list.First(x => x.GameId == gameId);
}
return package;
}



public async Task<GameConfig?> GetGameConfigAsync(GameId gameId)
{
if (!_gameConfig.TryGetValue(gameId, out GameConfig? config))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameConfigAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameConfig[item.GameId] = item;
}
config = list.FirstOrDefault(x => x.GameId == gameId);
}
return config;
}



public async Task<List<GameDeprecatedFile>> GetGameDeprecatedFilesAsync(GameId gameId)
{
var launcherId = LauncherId.FromGameId(gameId);
if (launcherId is not null)
{
var fileConfig = await _client.GetGameDeprecatedFileConfigAsync(launcherId, "en-us", gameId);
if (fileConfig != null)
{
return fileConfig.DeprecatedFiles;
}
}
return [];
}



public async Task<GameChannelSDK?> GetGameChannelSDKAsync(GameId gameId)
{
var launcherId = LauncherId.FromGameId(gameId);
if (launcherId is not null)
{
return await _client.GetGameChannelSDKAsync(launcherId, "en-us", gameId);
}
return null;
}


}

0 comments on commit 0a454ee

Please sign in to comment.