using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Xamarin.Essentials; using Xamarin.Forms; namespace Pixiview.Utils { public class Stores { public static readonly string PersonalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); //public static readonly string CacheFolder = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); private const string imageFolder = "img-master"; private const string thumbFolder = "img-thumb"; private const string userFolder = "user-profile"; private const string illustFile = "illust.json"; public static bool NetworkAvailable { get { try { return Connectivity.NetworkAccess == NetworkAccess.Internet || Connectivity.NetworkAccess == NetworkAccess.ConstrainedInternet; } catch { return false; } } } public static async Task LoadIllustData() { var file = Path.Combine(PersonalFolder, illustFile); string content = null; if (File.Exists(file)) { try { content = File.ReadAllText(file); } catch (Exception ex) { App.DebugError("illust.load", $"failed to read file: {file}, error: {ex.Message}"); } } if (content == null) { var response = Download(Configs.UrlIllust, headers: new[] { ("cookie", Configs.Cookie), ("x-user-id", Configs.UserId) }); if (response == null) { return null; } using (response) { content = await response.Content.ReadAsStringAsync(); try { File.WriteAllText(file, content, Encoding.UTF8); } catch (Exception ex) { App.DebugError("illust.save", $"failed to save illust JSON object, error: {ex.Message}"); } } } try { return JsonConvert.DeserializeObject(content); } catch (Exception ex) { App.DebugError("illust.load", $"failed to parse illust JSON object, error: {ex.Message}"); return null; } } public static ImageSource LoadIllustImage(string url) { return LoadImage(url, imageFolder); } public static ImageSource LoadThumbnailImage(string url) { return LoadImage(url, thumbFolder); } public static ImageSource LoadUserProfileImage(string url) { return LoadImage(url, userFolder); } public static ImageSource LoadImage(string url, string folder) { var file = Path.Combine(PersonalFolder, folder, Path.GetFileName(url)); if (!File.Exists(file)) { file = DownloadImage(url, folder); } if (file != null) { return ImageSource.FromFile(file); } return null; } public static string DownloadImage(string url, string folder) { try { var directory = Path.Combine(PersonalFolder, folder); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var file = Path.Combine(directory, Path.GetFileName(url)); App.DebugPrint($"download, url: {url}"); var response = Download(url); if (response == null) { return null; } using (response) using (var fs = File.OpenWrite(file)) { response.Content.CopyToAsync(fs).Wait(); //if (response.Headers.Date != null) //{ // File.SetLastWriteTimeUtc(file, response.Headers.Date.Value.UtcDateTime); //} } return file; } catch (Exception ex) { App.DebugError("image.download", ex.Message); return null; } } private static T TryCount(Func func, int tryCount = 3) { int tries = 0; while (tries < tryCount) { try { return func(); } catch (Exception ex) { tries++; System.Threading.Thread.Sleep(400); App.DebugError("try.do", $"tries: {tries}, error: {ex.Message}"); } } return default; } private static HttpResponseMessage Download(string url, string referer = null, IEnumerable<(string header, string value)> headers = null) { App.DebugPrint($"GET: {url}"); var uri = new Uri(url); var handler = new HttpClientHandler { Proxy = Configs.Proxy, UseProxy = true }; var client = new HttpClient(handler) { BaseAddress = new Uri($"{uri.Scheme}://{uri.Host}") }; return TryCount(() => { using (var request = new HttpRequestMessage(HttpMethod.Get, uri.PathAndQuery) { Version = new Version(2, 0) }) { request.Headers.Referrer = referer == null ? Configs.Referer : new Uri(referer); request.Headers.Add("user-agent", Configs.UserAgent); if (headers != null) { foreach (var (header, value) in headers) { request.Headers.Add(header, value); } } return client.SendAsync(request).Result; } }); } } public static class Configs { public static readonly WebProxy Proxy = new WebProxy("router.tsanie.us", 8088); public static readonly Uri Referer = new Uri("https://www.pixiv.net/"); public const int MaxThreads = 3; public const string UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"; public const string UrlIllust = "https://www.pixiv.net/ajax/top/illust?mode=all&lang=zh"; public const string Cookie = "first_visit_datetime_pc=2019-10-29+22%3A05%3A30; p_ab_id=2; p_ab_id_2=6;" + " p_ab_d_id=1155161977; a_type=0; b_type=1; d_type=2; module_orders_mypage=%5B%7B%22name%22%3A%22s" + "ketch_live%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22tag_follow%22%2C%22visible%22%3Atrue" + "%7D%2C%7B%22name%22%3A%22recommended_illusts%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22ev" + "eryone_new_illusts%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22following_new_illusts%22%2C%" + "22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22mypixiv_new_illusts%22%2C%22visible%22%3Atrue%7D%2C%7" + "B%22name%22%3A%22spotlight%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22fanbox%22%2C%22visib" + "le%22%3Atrue%7D%2C%7B%22name%22%3A%22featured_tags%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3" + "A%22contests%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22user_events%22%2C%22visible%22%3At" + "rue%7D%2C%7B%22name%22%3A%22sensei_courses%22%2C%22visible%22%3Atrue%7D%2C%7B%22name%22%3A%22boot" + "h_follow_items%22%2C%22visible%22%3Atrue%7D%5D; yuid_b=NgcXQWQ; login_ever=yes; c_type=31; PHPSES" + "SID=2603358_VHyGPeRaz7LpeoFkRsHvjXIpApCMb56a; __cfduid=d9fa2d4d1ddd30db85ebb519f9855d256158780674" + "7; privacy_policy_agreement=2"; public const string UserId = "2603358"; public static string GetThumbnailUrl(string url) { url = url.Replace("/custom-thumb/", "/img-master/"); var index = url.LastIndexOf("_square1200.jpg"); if (index < 0) { index = url.LastIndexOf("_custom1200.jpg"); } if (index >= 0) { return url.Substring(0, index) + "_master1200.jpg"; } return url; } } }