Guest User

Untitled

a guest
Nov 12th, 2022
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.49 KB | None | 0 0
  1. using System.Text.Json;
  2. using System.Text.Json.Serialization;
  3. using System.Text.RegularExpressions;
  4. using System.Web;
  5. using System.Xml.Serialization;
  6.  
  7. public static class Scheduler
  8. {
  9.     public static void Process<T>(IEnumerable<T> ie, int delay, Func<T, Task<bool>> job)
  10.     {
  11.         const int concurrency = 4;
  12.  
  13.         var count = 0;
  14.         var total = ie.Count();
  15.  
  16.         var mutex = new object();
  17.         void ReportProgress(int current)
  18.         {
  19.             lock (mutex)
  20.             {
  21.                 if (current == count)
  22.                 {
  23.                     var progress = Math.Round((float)current / total * 100, 2);
  24.                     Console.WriteLine($"{current}/{total}: {progress}%");
  25.                 }
  26.             }
  27.         }
  28.  
  29.         Parallel.ForEach(ie, new ParallelOptions() { MaxDegreeOfParallelism = concurrency }, x =>
  30.         {
  31.             var didWork = true;
  32.             try
  33.             {
  34.                 didWork = job(x).GetAwaiter().GetResult();
  35.             }
  36.             catch (Exception _)
  37.             {
  38.                 Console.WriteLine($"Task failed :(");
  39.             }
  40.             finally
  41.             {
  42.                 ReportProgress(Interlocked.Increment(ref count));
  43.                 if (didWork) Thread.Sleep(delay);
  44.             }
  45.         });
  46.     }
  47. }
  48.  
  49. public struct Post
  50. {
  51.     public string URL;
  52.     public string Filename;
  53.     public IEnumerable<string> Tags;
  54. }
  55. public interface IBooru
  56. {
  57.     public string ConstructURL(int page, int limit, IEnumerable<string> tags);
  58.     public Task<IEnumerable<Post>> GetPosts(int page, int limit, IEnumerable<string> tags);
  59. }
  60.  
  61. public class Gelbooru : IBooru
  62. {
  63.     public class DataContract
  64.     {
  65.         [XmlRoot(ElementName = "post")]
  66.         public class Post
  67.         {
  68.             [XmlElement(ElementName = "tags")]
  69.             public string Tags { get; set; }
  70.  
  71.             [XmlElement(ElementName = "file_url")]
  72.             public string File_url { get; set; }
  73.         }
  74.  
  75.         [XmlRoot(ElementName = "posts")]
  76.         public class Posts
  77.         {
  78.             [XmlElement(ElementName = "post")]
  79.             public List<Post>? Post { get; set; }
  80.  
  81.             [XmlAttribute(AttributeName = "limit")]
  82.             public int Limit { get; set; }
  83.  
  84.             [XmlAttribute(AttributeName = "offset")]
  85.             public int Offset { get; set; }
  86.  
  87.             [XmlAttribute(AttributeName = "count")]
  88.             public int Count { get; set; }
  89.         }
  90.     }
  91.  
  92.     private HttpClient _hc = new HttpClient();
  93.     private XmlSerializer _xml = new XmlSerializer(typeof(DataContract.Posts));
  94.  
  95.     public Gelbooru(HttpClient hc)
  96.     {
  97.         _hc = hc;
  98.     }
  99.  
  100.     public string ConstructURL(int page, int limit, IEnumerable<string> tags)
  101.     {
  102.         var encodedTags = HttpUtility.UrlEncode(string.Join(" ", tags));
  103.         return $"https://gelbooru.com/index.php?page=dapi&s=post&q=index&limit={limit}&pid={page}&tags={encodedTags}";
  104.     }
  105.  
  106.     public async Task<IEnumerable<Post>> GetPosts(int page, int limit, IEnumerable<string> tags)
  107.     {
  108.         var get = await _hc.GetAsync(ConstructURL(page, limit, tags));
  109.         var content = await get.Content.ReadAsStringAsync();
  110.         using (var sr = new StringReader(content))
  111.             return ((DataContract.Posts?)_xml.Deserialize(sr)).Post.Select(x => new Post() { URL = x.File_url, Tags = x.Tags.Split(" ") });
  112.     }
  113. }
  114. public class Danbooru : IBooru
  115. {
  116.     public class DataContract
  117.     {
  118.         public class Post
  119.         {
  120.             [JsonPropertyName("tag_string")]
  121.  
  122.             public string Tags { get; set; }
  123.             [JsonPropertyName("tag_string_general")]
  124.             public string TagsGeneral { get; set; }
  125.  
  126.             [JsonPropertyName("file_url")]
  127.             public string File_url { get; set; }
  128.         }
  129.     }
  130.  
  131.     private HttpClient _hc = new HttpClient();
  132.  
  133.     public Danbooru(HttpClient hc)
  134.     {
  135.         _hc = hc;
  136.     }
  137.  
  138.     public string ConstructURL(int page, int limit, IEnumerable<string> tags)
  139.     {
  140.         var encodedTags = HttpUtility.UrlEncode(string.Join(" ", tags));
  141.         return $"https://danbooru.donmai.us/posts.json?limit={limit}&page={page}&tags={encodedTags}";
  142.     }
  143.  
  144.     public async Task<IEnumerable<Post>> GetPosts(int page, int limit, IEnumerable<string> tags)
  145.     {
  146.         var get = await _hc.GetAsync(ConstructURL(page, limit, tags));
  147.         var content = await get.Content.ReadAsStringAsync();
  148.         return JsonSerializer.Deserialize<DataContract.Post[]>(content)
  149.             .Select(x => new Post() {
  150.                 URL = x.File_url,
  151.                 Tags = x.Tags.Split(" "),
  152.                 Filename = x.File_url?.Split("/")?.Last()
  153.             });
  154.     }
  155. }
  156.  
  157. public class Entrypoint
  158. {
  159.     static void RemoveCaptionsForDeleted(string directory)
  160.     {
  161.         var extensions = new[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg" };
  162.         foreach (var f in new DirectoryInfo(directory).GetFiles("*.txt"))
  163.         {
  164.             var extensionless = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f.FullName));
  165.  
  166.             var exists = false;
  167.             foreach (var ext in extensions)
  168.                 if (File.Exists(Path.Combine(directory, extensionless + ext)))
  169.                     exists = true;
  170.             if (!exists)
  171.                 File.Delete(f.FullName);
  172.         }
  173.     }
  174.  
  175.     static void CopyCaptionsForProcessed(string captionsDir, string processedDir)
  176.     {
  177.         var extensions = new[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg" };
  178.         foreach (var f in new DirectoryInfo(processedDir).GetFiles("*.png"))
  179.         {
  180.             var match = Regex.Match(f.Name, @"\d+-\d+-([^\.]+)\.png");
  181.             if (!match.Success) continue;
  182.             var origName = match.Groups[1];
  183.             var origCaptions = Path.Combine(captionsDir, origName + ".txt");
  184.             if (File.Exists(origCaptions))
  185.                 File.Copy(origCaptions, Path.Combine(processedDir, Path.GetFileNameWithoutExtension(f.Name) + ".txt"), true);
  186.         }
  187.     }
  188.  
  189.     static void DumpUniqueCaptions(string captionsDir)
  190.     {
  191.         var allCaptions = new HashSet<string>();
  192.         foreach (var f in new DirectoryInfo(captionsDir).GetFiles("*.txt"))
  193.         {
  194.             var captions = File.ReadAllText(f.FullName).Split(", ");
  195.             foreach (var caption in captions)
  196.                 allCaptions.Add(caption);
  197.         }
  198.         File.WriteAllLines("captions.txt", allCaptions);
  199.     }
  200.  
  201.     static void FilterCaptions(string captionsDir)
  202.     {
  203.         var allCaptions = File.ReadAllLines("captions.txt");
  204.         foreach (var f in new DirectoryInfo(captionsDir).GetFiles("*.txt"))
  205.         {
  206.             var captions = File.ReadAllText(f.FullName).Split(", ");
  207.             var filtered = captions
  208.                 .Intersect(allCaptions)
  209.                 .Select(x => PoorMansTagCleaner(x))
  210.                 .ToArray();
  211.             File.WriteAllText(f.FullName, string.Join(", ", filtered));
  212.         }
  213.  
  214.     }
  215.  
  216.     static string PoorMansTagCleaner(string tag)
  217.     {
  218.         return tag
  219.             .Replace("_", " ")
  220.             .Replace("\\(", "(").Replace("\\)", ")")
  221.             .Replace("(", "\\(").Replace(")", "\\)");
  222.     }
  223.  
  224.     private static HttpClient _hc = new HttpClient();
  225.  
  226.     public static void Main(string[] args)
  227.     {
  228.         const string output_dir = "OUT";
  229.         if (!Directory.Exists(output_dir))
  230.             Directory.CreateDirectory(output_dir);
  231.  
  232.         //DumpUniqueCaptions(@"X:\1");
  233.         //FilterCaptions(@"X:\1");
  234.         //CopyCaptionsForProcessed(
  235.         //    @"X:\1",
  236.         //    @"X:\2"
  237.         //    );
  238.         //foreach (var t in new DirectoryInfo(@"X:\1").GetFiles("*.txt"))
  239.         //{
  240.         //    var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(t.FullName));
  241.         //    File.Move(t.FullName, Path.Combine(t.Directory.FullName, name + ".txt"));
  242.         //}
  243.  
  244.         //FilterCaptions(@"X:\1");
  245.         //RemoveCaptionsForDeleted(@"X:\1");
  246.         //return;
  247.  
  248.         var tags = new[] { "midna", "some_other_tag" };
  249.         var mre = new ManualResetEvent(false);
  250.  
  251.         IBooru booru = new Danbooru(_hc);
  252.  
  253.         Task.Factory.StartNew(async () =>
  254.         {
  255.             var page = 0;
  256.             var postsPerPage = 20;
  257.  
  258.             while(true)
  259.             {
  260.                 Console.WriteLine($"Fetching page {page + 1}");
  261.                 var posts = await booru.GetPosts(page, postsPerPage, tags);
  262.                 Scheduler.Process(posts, 2000, async post =>
  263.                 {
  264.                     var didWork = false;
  265.                     var imagePath = Path.Combine(output_dir, post.Filename);
  266.                     if (!File.Exists(imagePath))
  267.                     {
  268.                         didWork = true;
  269.                         var data = await _hc.GetByteArrayAsync(post.URL);
  270.                         File.WriteAllBytes(imagePath, data);
  271.                     }
  272.                     var tagPath = Path.Combine(output_dir, $"{Path.GetFileNameWithoutExtension(post.Filename)}.txt");
  273.                     if (!File.Exists(tagPath))
  274.                     {
  275.                         File.WriteAllText(tagPath, string.Join(", ", post.Tags.Select(PoorMansTagCleaner)));
  276.                     }
  277.                     return didWork;
  278.                 });
  279.  
  280.                 if (posts.Count() != postsPerPage)
  281.                     break;
  282.  
  283.                 await Task.Delay(2000);
  284.                 page++;
  285.             }
  286.            
  287.             mre.Set();
  288.         });
  289.         mre.WaitOne();
  290.     }
  291.  
  292. }
Add Comment
Please, Sign In to add comment