Skip to content

Commit

Permalink
Added Reverse Image Search
Browse files Browse the repository at this point in the history
  • Loading branch information
master117 committed Mar 30, 2018
1 parent 68cff57 commit 1565371
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.jpg
*.png

*.suo
/.vs/
Expand Down
9 changes: 9 additions & 0 deletions AnimeImageSorter/AnimeImageSorter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,26 @@
<ItemGroup>
<Compile Include="BImage.cs" />
<Compile Include="HttpRequester.cs" />
<Compile Include="Imgur.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Result.cs" />
<Compile Include="SauceNao.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="imgurApiKey.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="pass.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="sauceNaoApiKey.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="user.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down
4 changes: 1 addition & 3 deletions AnimeImageSorter/BImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ class BImage

public bool SFW = false;

public BImage(JArray jArray)
public BImage(JToken jToken)
{
var jToken = jArray[0];

charCount = (int)jToken["tag_count_character"];
charactersString = ((string)jToken["tag_string_character"]);
characters = charactersString.Split(' ').ToList();
Expand Down
24 changes: 24 additions & 0 deletions AnimeImageSorter/HttpRequester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ public static JArray GetHttpJSONJArray(string adress)
return null;
}

public static JToken GetHttpJSONJToken(string adress)
{
//first we get a Stream of the Json, for that we use a webrequest
Stream resStream = GetHttpStream(adress, null, null, DecompressionMethods.None);
//GetHttpStream may return null if we got no nice answer
if (resStream == null)
return null;

try
{
var rawJson = new StreamReader(resStream).ReadToEnd();
//turns our raw string into a key value lookup
var json = JToken.Parse(rawJson);

return json;
}
catch (FormatException e)
{
Console.WriteLine(e.StackTrace);
}

return null;
}

//This method returns a stream on the response of a RESTful webrequest
private static Stream GetHttpStream(string adress, string username, string password,
DecompressionMethods decompressionMethod)
Expand Down
32 changes: 32 additions & 0 deletions AnimeImageSorter/Imgur.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace AnimeImageSorter
{
class Imgur
{
public static string Upload(string path, string apiKey)
{
using (var w = new WebClient())
{
w.Headers.Add("Authorization: Client-ID " + apiKey);
var values = new NameValueCollection
{
{ "image", Convert.ToBase64String(File.ReadAllBytes(@path)) }
};

string response = System.Text.Encoding.UTF8.GetString(w.UploadValues("https://api.imgur.com/3/upload", values));
Console.WriteLine(response);
dynamic dynObj = JsonConvert.DeserializeObject(response);
return dynObj.data.link;
}
}
}
}
65 changes: 62 additions & 3 deletions AnimeImageSorter/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,22 @@ enum MultipleOption

static MultipleOption CurrentMultipleOption = MultipleOption.Unknown;

enum ReverseImageSearch
{
Unknown = 0,
Yes = 1,
No = 2
}

static ReverseImageSearch CurrentReverseImageSearch = ReverseImageSearch.Unknown;

//Regex used to find MD5 in filenames
private static Regex md5Regex = new Regex("^[0-9a-f]{32}$");

//SauceNao and Imgur ApiKeys
private static string sauceNaoApiKey;
private static string imgurApiKey;

static void Main(string[] args)
{
//Should rpleace this with switches
Expand Down Expand Up @@ -116,6 +129,33 @@ static void Main(string[] args)
if (key4 == "Q" || CurrentMultipleOption == MultipleOption.Unknown)
return;

// Get ReverseImageSearch Type
Console.WriteLine("\n\nReverse Image Search images not found through hashing (this is slow and needs extra steps, details in github): y(es) / n(o) / q(uit)");
string key5 = Console.ReadKey().KeyChar.ToString().ToUpper();

if (key5 == "Y")
CurrentReverseImageSearch = ReverseImageSearch.Yes;

if (key5 == "N")
CurrentReverseImageSearch = ReverseImageSearch.No;

if (key5 == "Q" || CurrentReverseImageSearch == ReverseImageSearch.Unknown)
return;

if (CurrentReverseImageSearch == ReverseImageSearch.Yes)
{
if (File.Exists("sauceNaoApiKey.txt") && File.Exists("imgurApiKey.txt"))
{
sauceNaoApiKey = File.ReadAllText("sauceNaoApiKey.txt");
imgurApiKey = File.ReadAllText("imgurApiKey.txt");
}
else
{
Console.WriteLine("\n Either sauceNaoApiKey.txt or imgurApiKey.txt missing. To fix this problem look into github. Press any key to quit.");
Console.ReadKey();
}
}

// List all files in the current folder
List<string> files = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.*", SearchOption.TopDirectoryOnly)
.Where(x => x.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase)
Expand Down Expand Up @@ -143,17 +183,36 @@ static void Main(string[] args)
string danbooruUri = "https://danbooru.donmai.us/posts.json" + "?limit=1" + "&tags=md5:" + md5;
var danbooruJson = HttpRequester.GetHttpJSONJArray(danbooruUri);

//If booru search didn't find anything, try reverse search
if (danbooruJson?.Count > 0 && CurrentReverseImageSearch == ReverseImageSearch.Yes)
{
Console.WriteLine("Uploading to imgur for check...");
string image = Imgur.Upload(file, imgurApiKey);

List<Result> results = new SauceNao(sauceNaoApiKey).Request(image);

//Remove all low similarity results
results.RemoveAll(x => (float)x.header.similarity < 90.0);

//Get danbooru id, if any high similarity result still has one
string danbooruId = results.First(x => x.data.danbooru_id != null).data.danbooru_id;

//Get JSON Data on file
danbooruUri = "https://danbooru.donmai.us/posts/" + danbooruId + ".json";
danbooruJson = new JArray() { HttpRequester.GetHttpJSONJToken(danbooruUri) };
}

//Work JSON Data
if(danbooruJson != null && danbooruJson.Count > 0)
if (danbooruJson?.Count > 0)
{
//Log
Console.WriteLine("Found file on Danbooru: " + filename);

//Create bImage object
var bImage = new BImage(danbooruJson);
var bImage = new BImage(danbooruJson[0]);

//CopyMove file
if(bImage.charCount >= 1 && CurrentSortBy == Sortby.Character
if (bImage.charCount >= 1 && CurrentSortBy == Sortby.Character
|| bImage.copyRightCount >= 1 && CurrentSortBy == Sortby.Series)
{
CopyMoveFile(file, filenameLong, bImage);
Expand Down
14 changes: 14 additions & 0 deletions AnimeImageSorter/Result.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace AnimeImageSorter
{
internal class Result
{
public dynamic header;
public dynamic data;

public Result(dynamic header, dynamic data)
{
this.header = header;
this.data = data;
}
}
}
50 changes: 50 additions & 0 deletions AnimeImageSorter/SauceNao.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace AnimeImageSorter
{
class SauceNao
{
private static string ENDPOINT = "https://saucenao.com/search.php";
private string ApiKey;

public SauceNao(string apiKey)
{
this.ApiKey = apiKey;
}

public List<Result> Request(string url)
{
WebClient webClient = new WebClient();

webClient.QueryString.Add("db", "999");
webClient.QueryString.Add("output_type", "2");
webClient.QueryString.Add("numres", "16");
webClient.QueryString.Add("api_key", ApiKey);
webClient.QueryString.Add("url", url);

List<Result> results = new List<Result>();

try
{
string response = webClient.DownloadString(ENDPOINT);
dynamic dynObj = JsonConvert.DeserializeObject(response);
foreach (var result in dynObj.results)
{
results.Add(new Result(result.header, result.data));
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

return results;
}
}
}
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,19 @@ First: Uses the first tag.

Skip: Skips these files from sorting.

### Reverse Image Search
Enables Reverse Image Search, only if booru/hash search fails:

### Notes
- You need to have saucenaoapikey.txt and imgurapikey.txt in the same folder, filled with your own matching keys.

- Very slow, every used image is uploaded.

Yes: Enables Reverse Image Search on fail.

No: disables Reverse Image Search on fail.


## Notes

This software is open source and may be distributed, modified, and used, but not sold commercially.

Expand Down

0 comments on commit 1565371

Please sign in to comment.