/
ArtStationAPI.cs
91 lines (83 loc) · 4.33 KB
/
ArtStationAPI.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Threading.Tasks;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace ArtAPI
{
public sealed class ArtStationAPI : RequestArt
{
private const string ApiUrl = @"https://artstation.com/users/{0}/projects?page=";
private const string AssetsUrl = @"https://www.artstation.com/projects/{0}.json";
public ArtStationAPI()
{
IsLoggedIn = true;
LoginState = LoginStatus.LoggedIn;
}
public override Task<Uri> CreateUrlFromName(string artistName)
{
return Task.FromResult(new Uri(string.Format($@"https://www.artstation.com/{artistName}")));
}
public override async Task<bool> CheckArtistExistsAsync(string artistName)
{
var response = await Client.GetAsync(await CreateUrlFromName(artistName));
return response.IsSuccessStatusCode;
}
public override async Task GetImagesAsync(Uri artistUrl)
{
OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadPreparing));
var artistname = artistUrl?.AbsolutePath.Split('/')[1];
if (artistname == null) return;
CreateSaveDir(artistname);
await GetImagesMetadataAsync(string.Format(ApiUrl, artistname)).ConfigureAwait(false);
await DownloadImagesAsync().ConfigureAwait(false);
}
protected override async Task GetImagesMetadataAsync(string apiUrl)
{
JContainer allPages;
var settings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Concat };
try
{
string rawResponse = await Client.GetStringAsync(apiUrl).ConfigureAwait(false);
var responseJson = JObject.Parse(rawResponse);
int totalCount = Int32.Parse(responseJson["total_count"]?.ToString() ?? throw new Exception("Bad API Response"));
var pages = (totalCount / 50) + 1;
allPages = (JContainer)responseJson["data"]; // add the first page to the container
for (int page = pages; page > 1; page--) // go through the remaining pages and add them to the container
{
rawResponse = await Client.GetStringAsync(apiUrl + $"{page}").ConfigureAwait(false);
allPages.Merge((JContainer)JObject.Parse(rawResponse)["data"], settings);
}
}
catch (Exception e)
{ OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadCanceled, e.Message)); return; }
// each project can have one or more images (assets)
var t = Task.WhenAll(allPages.Select(project => Task.Run(async () => { await GetAssets(project["hash_id"].ToString(), project["title"].ToString()).ConfigureAwait(false); })).ToArray());
try { await t.ConfigureAwait(false); }
catch (Exception e)
{ OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadCanceled, e.Message)); }
}
// get all the images from a project
private async Task GetAssets(string hash_id, string name)
{
var response = await Client.GetStringAsync(string.Format(AssetsUrl, hash_id)).ConfigureAwait(false);
var assetsJson = JObject.Parse(response);
foreach (var image in assetsJson["assets"] as JContainer)
{
lock (ImagesToDownload)
{
ImagesToDownload.Add(new ImageModel()
{
Url = image["image_url"].ToString().Replace("/large/", "/4k/")
.Replace("/covers/", "/images/")
.Replace("/video_clips/", "/images/")
.Replace("/videos/", "/images/")
.Replace("/panos/", "/images/"), // workaround to download 4k images, maybe there's a better way, I might change this later
Name = name,
ID = image["id"].ToString(),
FileType = image["image_url"].ToString().Split('?')[0].Split('/').Last().Split('.')[1]
});
}
}
}
}
}