UniversalViewer/Assets/KF3/Scripts/UpdateChecker.cs

179 lines
5.9 KiB
C#
Raw Permalink Normal View History

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Linq;
using UnityEngine;
using Newtonsoft.Json.Linq;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
public class UpdateChecker : MonoBehaviour
{
public void RequestUpdate()
{
var version = Settings.GameVersion;
var bundleUrl = "";
try { version = GetAndroidVersion(); }
catch { Error.Log(Color.red, $"Failed getting game version. Using {version} from settings"); }
if(version != Settings.GameVersion)
{
Settings.Instance.gameVersion = version;
Settings.Save();
}
try { bundleUrl = GetAssetbundleUrl(version); }
catch { Error.Log(Color.red, $"Failed getting assets url"); return; }
if(bundleUrl != Settings.AssetsUrl)
{
if(UpdateUrlFile(bundleUrl))
Error.Log(Color.green, "Update Successful! Please restart the viewer to download new files.");
}
else
{
Error.Log(Color.green, "You already have the newest files!");
}
}
public string GetAndroidVersion()
{
string url = "https://play.google.com/store/apps/details?id=com.sega.KemonoFriends3";
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
using (Stream stream = httpResponse.GetResponseStream())
using (StreamReader stringReader = new StreamReader(stream))
{
var response = stringReader.ReadToEnd();
var result = Regex.Match(response, @"""\b(\d+\.\d+\.\d+)\b""");
return result.Groups[1].Value;
}
}
public string GetAssetbundleUrl(string version)
{
string param = Encode($"{{'version':'{version}','dmm_viewer_id':0,'platform':1}}".Replace("'", "\""));
Debug.Log(param);
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("https://parade-mobile-prod-app.kemono-friends-3.jp/paradesv/common/GetUrl.do?param=" + param);
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0";
httpRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
using (Stream stream = httpResponse.GetResponseStream())
using (Stream decompress = new GZipStream(stream, CompressionMode.Decompress))
using (StreamReader stringReader = new StreamReader(decompress))
{
var response = stringReader.ReadToEnd();
var json = JObject.Parse(response);
return json["asset_bundle_url"].ToString();
}
}
private bool UpdateUrlFile(string newVersion)
{
try
{
if (File.Exists(Path.Combine(Settings.AssetListDirectory, "ab_list.txt")))
{
File.Delete(Path.Combine(Settings.AssetListDirectory, "ab_list.txt"));
}
Settings.Instance.assetsUrl = newVersion;
Settings.Save();
return true;
}
catch (Exception e)
{
Debug.LogError(e.Message);
return false;
}
}
public string Encode(string request)
{
MD5 md5 = MD5.Create();
string hashed = GetMd5Hash(md5, request);
string checksum = GetMd5Hash(md5, request + "DARAPAB ");
string key = BytesToHexString(md5.ComputeHash(HexStringToByteArray(hashed.Substring(0, 8))));
//xor with the key
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
byte[] keyBytes = HexStringToByteArray(key);
for (int i = 0; i < requestBytes.Length; i++)
{
requestBytes[i] ^= keyBytes[i % keyBytes.Length];
}
request = (hashed.Substring(0, 8) + BytesToHexString(requestBytes) + checksum);
return request;
}
public string Decode(string request)
{
MD5 md5 = MD5.Create();
string key = BytesToHexString(md5.ComputeHash(HexStringToByteArray(request.Substring(0, 8))));
string hash = request.Substring(8, request.Length - 40);
byte[] requestBytes = HexStringToByteArray(hash);
byte[] keyBytes = HexStringToByteArray(key);
for (int i = 0; i < requestBytes.Length; i++)
{
requestBytes[i] ^= keyBytes[i % keyBytes.Length];
}
return Encoding.UTF8.GetString(requestBytes);
}
public string GetMd5Hash(MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
public byte[] HexStringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public string BytesToHexString(byte[] data)
{
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}