* Pixiview/Utils/Stores.cs:
* Pixiview/Pixiview.projitems: * Pixiview/Utils/IllustData.cs: * Pixiview/Utils/HttpUtility.cs: * Pixiview/Utils/IllustLegacy.cs: * Pixiview/Illust/ViewIllustPage.xaml: * Pixiview/Illust/ViewIllustPage.xaml.cs: feature: view animate * Pixiview/Illust/FavoritesPage.xaml.cs: lazy load favorites page * Pixiview/UI/CardView.cs: * Pixiview/UI/AdaptedPage.cs: * Pixiview/Utils/Converters.cs: * Pixiview/UI/StyleDefinition.cs: * Pixiview/UI/Theme/ThemeBase.cs: * Pixiview/Illust/RankingPage.xaml: * Pixiview/Illust/RankingPage.xaml.cs: * Pixiview/Resources/Languages/zh-CN.xml: * Pixiview/Illust/IllustCollectionPage.cs: * Pixiview.iOS/Renderers/SegmentedControlRenderer.cs: feature: filter ranking * Pixiview.iOS/Info.plist: * Pixiview.iOS/Pixiview.iOS.csproj: * Pixiview.iOS.OpenExtension/Info.plist: * Pixiview.Android/Pixiview.Android.csproj: * Pixiview.Android/Properties/AndroidManifest.xml: version update
This commit is contained in:
@@ -3,8 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Pixiview.Illust;
|
||||
@@ -25,6 +23,7 @@ namespace Pixiview.Utils
|
||||
private const string favoriteFile = "favorites.json";
|
||||
private const string imageFolder = "img-original";
|
||||
private const string previewFolder = "img-master";
|
||||
private const string ugoiraFolder = "img-zip-ugoira";
|
||||
private const string illustFile = "illust.json";
|
||||
|
||||
private const string pagesFolder = "pages";
|
||||
@@ -100,79 +99,41 @@ namespace Pixiview.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static T LoadObject<T>(string file, string url, string referer, bool force = false, Func<string, string> action = null)
|
||||
public static ImageSource LoadUgoiraImage(string zip, string frame)
|
||||
{
|
||||
string content = null;
|
||||
if (!force && file != null && File.Exists(file))
|
||||
var file = Path.Combine(PersonalFolder, ugoiraFolder, zip, frame);
|
||||
if (File.Exists(file))
|
||||
{
|
||||
try
|
||||
{
|
||||
content = File.ReadAllText(file);
|
||||
return ImageSource.FromFile(file);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.DebugError("load", $"failed to read file: {file}, error: {ex.Message}");
|
||||
App.DebugError("load.ugoira", $"failed to load ugoira frame: {zip}/{frame}, error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
if (content == null)
|
||||
{
|
||||
var response = Download(url, headers =>
|
||||
{
|
||||
if (referer != null)
|
||||
{
|
||||
headers.Referrer = new Uri(referer);
|
||||
}
|
||||
headers.Add("User-Agent", Configs.UserAgent);
|
||||
headers.Add("Accept", Configs.AcceptJson);
|
||||
headers.Add("Cookie", Configs.Cookie);
|
||||
headers.Add("X-User-Id", Configs.UserId);
|
||||
});
|
||||
if (response == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
using (response)
|
||||
{
|
||||
try
|
||||
{
|
||||
content = response.Content.ReadAsStringAsync().Result;
|
||||
if (action != null)
|
||||
{
|
||||
content = action(content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.DebugError("load.strea", $"failed to read stream, error: {ex.Message}");
|
||||
return default;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var folder = Path.GetDirectoryName(file);
|
||||
if (!Directory.Exists(folder))
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
}
|
||||
File.WriteAllText(file, content, Encoding.UTF8);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.DebugError("save", $"failed to save illust JSON object, error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static string SaveUgoiraImage(string zip, string frame, byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(content);
|
||||
var directory = Path.Combine(PersonalFolder, ugoiraFolder, zip);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var file = Path.Combine(directory, frame);
|
||||
File.WriteAllBytes(file, data);
|
||||
return file;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.DebugError("load", $"failed to parse illust JSON object, error: {ex.Message}");
|
||||
return default;
|
||||
App.DebugError("save.ugoira", $"failed to save ugoira frame: {zip}/{frame}, error: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,14 +198,52 @@ namespace Pixiview.Utils
|
||||
public static IllustData LoadIllustData(bool force = false)
|
||||
{
|
||||
var file = Path.Combine(PersonalFolder, illustFile);
|
||||
var result = LoadObject<IllustData>(
|
||||
var result = HttpUtility.LoadObject<IllustData>(
|
||||
file,
|
||||
Configs.UrlIllustList,
|
||||
Configs.Referer,
|
||||
force: force);
|
||||
if (result == null || result.error)
|
||||
{
|
||||
App.DebugPrint($"error when load illust data: {result?.message} ({force})");
|
||||
App.DebugPrint($"error when load illust data: {result?.message}, force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IllustRankingData LoadIllustRankingData(string mode, string date, int page, bool force = false)
|
||||
{
|
||||
var file = Path.Combine(CacheFolder, $"{mode}_{date}_{page}.json");
|
||||
string query = $"mode={mode}";
|
||||
if (mode != "male" && mode != "male_r18")
|
||||
{
|
||||
query += "&content=illust";
|
||||
}
|
||||
if (date != null)
|
||||
{
|
||||
query += $"&date={date}";
|
||||
}
|
||||
var referer = string.Format(Configs.RefererIllustRanking, query);
|
||||
if (page > 1)
|
||||
{
|
||||
query += $"&p={page}";
|
||||
}
|
||||
query += "&format=json";
|
||||
var result = HttpUtility.LoadObject<IllustRankingData>(
|
||||
file,
|
||||
string.Format(Configs.UrlIllustRanking, query),
|
||||
referer,
|
||||
namehandler: rst =>
|
||||
{
|
||||
return Path.Combine(CacheFolder, $"{mode}_{rst.date}_{page}.json");
|
||||
},
|
||||
header: headers =>
|
||||
{
|
||||
headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
},
|
||||
force: force);
|
||||
if (result == null)
|
||||
{
|
||||
App.DebugPrint($"error when load ranking data: mode({mode}), date({date}), page({page}), force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -252,7 +251,7 @@ namespace Pixiview.Utils
|
||||
public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false)
|
||||
{
|
||||
var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json");
|
||||
var result = LoadObject<IllustPreloadBody>(
|
||||
var result = HttpUtility.LoadObject<IllustPreloadBody>(
|
||||
file,
|
||||
string.Format(Configs.UrlIllust, id),
|
||||
null,
|
||||
@@ -271,47 +270,66 @@ namespace Pixiview.Utils
|
||||
}
|
||||
return content;
|
||||
});
|
||||
if (result == null)
|
||||
{
|
||||
App.DebugPrint($"error when load preload data: force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IllustPageData LoadIllustPageData(string id, bool force = false)
|
||||
{
|
||||
var file = Path.Combine(CacheFolder, pagesFolder, $"{id}.json");
|
||||
var result = LoadObject<IllustPageData>(
|
||||
var result = HttpUtility.LoadObject<IllustPageData>(
|
||||
file,
|
||||
string.Format(Configs.UrlIllustPage, id),
|
||||
string.Format(Configs.UrlIllust, id),
|
||||
string.Format(Configs.RefererIllust, id),
|
||||
force: force);
|
||||
if (result == null || result.error)
|
||||
{
|
||||
App.DebugPrint($"error when load page data: {result?.message} ({force})");
|
||||
App.DebugPrint($"error when load page data: {result?.message}, force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IllustUgoiraData LoadIllustUgoiraData(string id, bool force = false)
|
||||
{
|
||||
var file = Path.Combine(PersonalFolder, ugoiraFolder, $"{id}.json");
|
||||
var result = HttpUtility.LoadObject<IllustUgoiraData>(
|
||||
file,
|
||||
string.Format(Configs.UrlIllustUgoira, id),
|
||||
string.Format(Configs.RefererIllust, id),
|
||||
force: force);
|
||||
if (result == null || result.error)
|
||||
{
|
||||
App.DebugPrint($"error when load ugoira data: {result?.message}, force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IllustUserData LoadIllustUserData(string userId, bool force = false)
|
||||
{
|
||||
var list = LoadObject<IllustUserListData>(
|
||||
var list = HttpUtility.LoadObject<IllustUserListData>(
|
||||
null,
|
||||
string.Format(Configs.UrlIllustUserAll, userId),
|
||||
string.Format(Configs.UrlIllustUser, userId),
|
||||
string.Format(Configs.RefererIllustUser, userId),
|
||||
force: force);
|
||||
if (list == null || list.error)
|
||||
{
|
||||
App.DebugPrint($"error when load user data: {list?.message} ({force})");
|
||||
App.DebugPrint($"error when load user data: {list?.message}, force({force})");
|
||||
}
|
||||
|
||||
// TODO
|
||||
var ids = string.Join("", list.body.illusts.Keys.Take(20).Select(id => $"ids%5B%5D={id}&"));
|
||||
|
||||
var result = LoadObject<IllustUserData>(
|
||||
var result = HttpUtility.LoadObject<IllustUserData>(
|
||||
null,
|
||||
string.Format(Configs.UrlIllustUserArtworks, userId, ids, 1),
|
||||
string.Format(Configs.UrlIllustUser, userId),
|
||||
string.Format(Configs.RefererIllustUser, userId),
|
||||
force: force);
|
||||
if (result == null || result.error)
|
||||
{
|
||||
App.DebugPrint($"error when load user illust data: {result?.message} ({force})");
|
||||
App.DebugPrint($"error when load user illust data: {result?.message}, force({force})");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -374,7 +392,7 @@ namespace Pixiview.Utils
|
||||
}
|
||||
if (downloading && image == null)
|
||||
{
|
||||
file = DownloadImage(url, working, folder);
|
||||
file = HttpUtility.DownloadImage(url, working, folder);
|
||||
if (file != null)
|
||||
{
|
||||
return ImageSource.FromFile(file);
|
||||
@@ -382,101 +400,6 @@ namespace Pixiview.Utils
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private static string DownloadImage(string url, string working, string folder)
|
||||
{
|
||||
try
|
||||
{
|
||||
var directory = Path.Combine(working, 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, headers =>
|
||||
{
|
||||
headers.Referrer = new Uri(Configs.Referer);
|
||||
headers.Add("User-Agent", Configs.UserAgent);
|
||||
headers.Add("Accept", Configs.AcceptImage);
|
||||
});
|
||||
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<T>(Func<T> 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, Action<HttpRequestHeaders> headerAction)
|
||||
{
|
||||
App.DebugPrint($"GET: {url}");
|
||||
var uri = new Uri(url);
|
||||
var proxy = Configs.Proxy;
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
|
||||
UseCookies = false
|
||||
};
|
||||
if (proxy != null)
|
||||
{
|
||||
handler.Proxy = proxy;
|
||||
handler.UseProxy = true;
|
||||
}
|
||||
var client = new HttpClient(handler)
|
||||
{
|
||||
BaseAddress = new Uri($"{uri.Scheme}://{uri.Host}"),
|
||||
Timeout = TimeSpan.FromSeconds(30)
|
||||
};
|
||||
return TryCount(() =>
|
||||
{
|
||||
using (var request = new HttpRequestMessage(HttpMethod.Get, uri.PathAndQuery)
|
||||
{
|
||||
Version = new Version(2, 0)
|
||||
})
|
||||
{
|
||||
var headers = request.Headers;
|
||||
headerAction(headers);
|
||||
headers.Add("x-reverse", "yes");
|
||||
headers.Add("Accept-Language", Configs.AcceptLanguage);
|
||||
//headers.Add("Accept-Encoding", Configs.AcceptEncoding);
|
||||
return client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class Configs
|
||||
@@ -487,6 +410,9 @@ namespace Pixiview.Utils
|
||||
|
||||
public const int MaxThreads = 3;
|
||||
public const string Referer = "https://www.pixiv.net/";
|
||||
public const string RefererIllust = "https://www.pixiv.net/artworks/{0}";
|
||||
public const string RefererIllustRanking = "https://www.pixiv.net/ranking.php?{0}";
|
||||
public const string RefererIllustUser = "https://www.pixiv.net/users/{0}/artworks";
|
||||
|
||||
public static WebProxy Proxy;
|
||||
private static string Prefix => Proxy == null ?
|
||||
@@ -497,26 +423,37 @@ namespace Pixiview.Utils
|
||||
public const int SuffixPreloadLength = 33; // SuffixPreload.Length
|
||||
public static string UrlIllustList => Prefix + "ajax/top/illust?mode=all&lang=zh";
|
||||
public static string UrlIllust => Prefix + "artworks/{0}";
|
||||
public static string UrlIllustRanking => Prefix + "ranking.php?{0}";
|
||||
public static string UrlIllustUserAll => Prefix + "ajax/user/{0}/profile/all?lang=zh";
|
||||
public static string UrlIllustUserArtworks => Prefix + "ajax/user/{0}/profile/illusts?{1}work_category=illustManga&is_first_page={2}&lang=zh";
|
||||
public static string UrlIllustUser => Prefix + "users/{0}/artworks";
|
||||
public static string UrlIllustPage => Prefix + "ajax/illust/{0}/pages?lang=zh";
|
||||
public static string UrlIllustUgoira => Prefix + "ajax/illust/{0}/ugoira_meta?lang=zh";
|
||||
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.138 Safari/537.36";
|
||||
public const string AcceptImage = "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5";
|
||||
public const string AcceptJson = "application/json";
|
||||
//public const string AcceptEncoding = "gzip, deflate";
|
||||
public const string AcceptLanguage = "zh-cn";
|
||||
|
||||
public const string UserId = "53887721";
|
||||
//public const string UserId = "53887721";
|
||||
//public const string Cookie =
|
||||
// "PHPSESSID=5sn8n049j5c18l0tlj91qrjhesgddhjv; " +
|
||||
// "a_type=0; b_type=1; c_type=29; d_type=2; " +
|
||||
// "p_ab_d_id=1021624041; p_ab_id=2; p_ab_id_2=0; " +
|
||||
// "privacy_policy_agreement=2; " +
|
||||
// "login_ever=yes; " +
|
||||
// "__cfduid=d84153bf70ae67315a8bc297299d39eb61588856027; " +
|
||||
// "first_visit_datetime_pc=2020-05-07+21%3A53%3A47; " +
|
||||
// "yuid_b=MYkIJXc";
|
||||
public const string UserId = "2603358";
|
||||
public const string Cookie =
|
||||
"PHPSESSID=5sn8n049j5c18l0tlj91qrjhesgddhjv; " +
|
||||
"a_type=0; b_type=1; c_type=29; d_type=2; " +
|
||||
"p_ab_d_id=1021624041; p_ab_id=2; p_ab_id_2=0; " +
|
||||
"privacy_policy_agreement=2; " +
|
||||
"login_ever=yes; " +
|
||||
"__cfduid=d84153bf70ae67315a8bc297299d39eb61588856027; " +
|
||||
"first_visit_datetime_pc=2020-05-07+21%3A53%3A47; " +
|
||||
"yuid_b=MYkIJXc";
|
||||
"PHPSESSID=2603358_VHyGPeRaz7LpeoFkRsHvjXIpApCMb56a; " +
|
||||
"a_type=0; b_type=1; c_type=31; d_type=2; " +
|
||||
"p_ab_id=2; p_ab_id_2=6; p_ab_d_id=1155161977; " +
|
||||
"privacy_policy_agreement=2; " +
|
||||
"login_ever=yes; " +
|
||||
"__cfduid=d9fa2d4d1ddd30db85ebb519f9855d2561587806747; " +
|
||||
"first_visit_datetime_pc=2019-10-29+22%3A05%3A30; " +
|
||||
"yuid_b=NgcXQWQ";
|
||||
|
||||
public static string GetThumbnailUrl(string url)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user