diff --git a/ArtAPI/ArtAPI.csproj b/ArtAPI/ArtAPI.csproj
index 01774f4..a20d0b1 100644
--- a/ArtAPI/ArtAPI.csproj
+++ b/ArtAPI/ArtAPI.csproj
@@ -12,4 +12,8 @@
+
+
+
+
diff --git a/ArtAPI/ArtStationAPI.cs b/ArtAPI/ArtStationAPI.cs
index 498e27f..2948520 100644
--- a/ArtAPI/ArtStationAPI.cs
+++ b/ArtAPI/ArtStationAPI.cs
@@ -20,11 +20,6 @@ public override async Task CheckArtistExistsAsync(string artistName)
return response.IsSuccessStatusCode;
}
- public override async Task GetImagesAsync(string artistUrl)
- {
- await GetImagesAsync(new Uri(artistUrl)).ConfigureAwait(false);
- }
-
public override async Task GetImagesAsync(Uri artistUrl)
{
OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadPreparing));
@@ -32,6 +27,7 @@ public override async Task GetImagesAsync(Uri artistUrl)
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)
@@ -60,7 +56,6 @@ protected override async Task GetImagesMetadataAsync(string apiUrl)
try { await t.ConfigureAwait(false); }
catch (Exception e)
{ OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadCanceled, e.Message)); return; }
- await DownloadImagesAsync().ConfigureAwait(false);
}
// get all the images from a project
diff --git a/ArtAPI/DeviantArtAPI.cs b/ArtAPI/DeviantArtAPI.cs
new file mode 100644
index 0000000..7af61f3
--- /dev/null
+++ b/ArtAPI/DeviantArtAPI.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+
+namespace ArtAPI
+{
+ public sealed class DeviantArtAPI : RequestArt
+ {
+ private const string
+ ClientID = "12774",
+ ClientSecret = "597114f315705b9624c7c1d74ad729e1",
+ AUTH_URL = "https://www.deviantart.com/oauth2/token",
+ GALLERY_URL = "https://www.deviantart.com/api/v1/oauth2/gallery/all?mature_content=true&limit=20&username={0}&offset=";
+
+ private const int Offset = 20;
+
+ public bool IsLoggedIn { get; private set; }
+
+ public override Uri CreateUrlFromName(string artistName)
+ {
+ return new Uri($"https://www.deviantart.com/{artistName}");
+ }
+
+ public override async Task CheckArtistExistsAsync(string artistName)
+ {
+ var response = await Client.GetAsync($"https://www.deviantart.com/{artistName}");
+ return response.IsSuccessStatusCode;
+ }
+
+ public override async Task GetImagesAsync(Uri artistUrl)
+ {
+ if (!IsLoggedIn)
+ {
+ OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadCanceled, "not logged in"));
+ return;
+ }
+ OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadPreparing));
+ var artistName = artistUrl?.AbsolutePath.Split('/')[1];
+ if (artistName == null) return;
+ CreateSaveDir(artistName);
+ await GetImagesMetadataAsync(string.Format(GALLERY_URL, artistName)).ConfigureAwait(false);
+ await DownloadImagesAsync().ConfigureAwait(false);
+ }
+
+ protected override async Task GetImagesMetadataAsync(string apiUrl)
+ {
+ var paginationOffset = 0;
+ while (true)
+ {
+ var rawResponse = await Client.GetStringAsync(apiUrl + paginationOffset).ConfigureAwait(false);
+ var responseJson = JObject.Parse(rawResponse);
+ var Gallery = (JContainer)responseJson["results"];
+ if (!(Gallery.HasValues)) return; // check if the user has any images in his gallery
+ foreach (var image in Gallery)
+ {
+ if (image["content"] == null) continue;
+ ImagesToDownload.Add(new ImageModel()
+ {
+ Url = image["content"]["src"].ToString(),
+ Name = image["title"].ToString(),
+ ID = image["deviationid"].ToString()
+ }
+ );
+ }
+ if (responseJson["has_more"].ToString() == "False") return;
+ paginationOffset += Offset;
+ }
+ }
+
+ public override async Task auth(string refreshToken)
+ {
+ var data = new Dictionary()
+ {
+ {"grant_type", "client_credentials" },
+ {"client_id", ClientID},
+ {"client_secret", ClientSecret}
+ };
+ using var content = new FormUrlEncodedContent(data);
+ try
+ {
+ var response = await Client.PostAsync(AUTH_URL, content).ConfigureAwait(false);
+ var jsonResponse = JObject.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
+ if (jsonResponse["status"].ToString() == "error") return false;
+ Client.DefaultRequestHeaders.Add("Authorization", $"Bearer {jsonResponse["access_token"]}");
+ }
+ catch(HttpRequestException)
+ {
+ return false;
+ }
+ return IsLoggedIn = true;
+ }
+ }
+}
diff --git a/ArtAPI/PixivAPI.cs b/ArtAPI/PixivAPI.cs
index c307723..5941710 100644
--- a/ArtAPI/PixivAPI.cs
+++ b/ArtAPI/PixivAPI.cs
@@ -56,11 +56,6 @@ private async Task GetArtistName(string artistID)
return JObject.Parse(response)["body"]["user_details"]["user_name"].ToString();
}
- public override async Task GetImagesAsync(string ArtistUrl)
- {
- await GetImagesAsync(new Uri(ArtistUrl)).ConfigureAwait(false);
- }
-
public override async Task GetImagesAsync(Uri artistUrl)
{
OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadPreparing));
@@ -75,6 +70,7 @@ public override async Task GetImagesAsync(Uri artistUrl)
{
await GetImagesMetadataAsync(string.Format(APIUrlWithoutLogin, artistID)).ConfigureAwait(false);
}
+ await DownloadImagesAsync().ConfigureAwait(false);
}
protected override async Task GetImagesMetadataAsync(string apiUrl)
@@ -114,7 +110,6 @@ await GetImageURLsWithoutLoginAsync(string.Format(IllustProjectUrl, illust_id))
{
OnDownloadStateChanged(new DownloadStateChangedEventArgs(State.DownloadCanceled, e.Message));
}
- await DownloadImagesAsync().ConfigureAwait(false);
}
private async Task GetImageURLsWithoutLoginAsync(string illustProject)
diff --git a/Artify/Artify.csproj b/Artify/Artify.csproj
index 2563bbc..9b65bec 100644
--- a/Artify/Artify.csproj
+++ b/Artify/Artify.csproj
@@ -7,6 +7,11 @@
assets/icons/artify.ico
+
+
+
+
+
@@ -17,7 +22,6 @@
-
@@ -26,7 +30,8 @@
-
+
+
diff --git a/Artify/Models/ArtifyModel.cs b/Artify/Models/ArtifyModel.cs
index 60df505..cfff7e1 100644
--- a/Artify/Models/ArtifyModel.cs
+++ b/Artify/Models/ArtifyModel.cs
@@ -27,13 +27,15 @@ public class ArtifyModel
{
{"general", new Regex(@"(https?://)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}(\/?[a-zA-Z0-9]*\/?)*") },
{"artstation", new Regex(@"(https://)?(www\.)?artstation\.com/[0-9a-zA-Z]+/?") },
- {"pixiv", new Regex(@"(https://)?(www\.)?pixiv\.net/[a-z]{0,6}/users/[0-9]+/?") }
+ {"pixiv", new Regex(@"(https://)?(www\.)?pixiv\.net/[a-z]{0,6}/users/[0-9]+/?") },
+ {"deviantart", new Regex(@"(https://)?(www\.)?deviantart\.com/[0-9a-zA-Z]+/?")}
};
// container for the classes
private readonly Dictionary> ArtPlatform = new Dictionary>()
{
{ "artstation", () => new ArtStationAPI() },
- { "pixiv", () => new PixivAPI() }
+ { "pixiv", () => new PixivAPI() },
+ { "deviantart", () => new DeviantArtAPI()}
};
public IRequestArt Platform
{
diff --git a/Artify/Views/MainView.xaml b/Artify/Views/MainView.xaml
index 5ef0f79..359f05b 100644
--- a/Artify/Views/MainView.xaml
+++ b/Artify/Views/MainView.xaml
@@ -94,11 +94,14 @@
@@ -117,7 +120,10 @@
+