MT_skins_updater.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. //Json.NET library (http://json.codeplex.com/)
  3. using Newtonsoft.Json;
  4. using System.Collections.Generic;
  5. using System.Net;
  6. using System.IO;
  7. // MT skins updater for the skins mod
  8. // Creator: Krock
  9. // License: zlib (http://www.zlib.net/zlib_license.html)
  10. namespace MT_skins_updater {
  11. class Program {
  12. static void Main(string[] args) {
  13. Console.WriteLine("Welcome to the MT skins updater!");
  14. Console.WriteLine("# Created by: Krock (2014-07-10)");
  15. Engine e = new Engine();
  16. Console.WriteLine(@"Path to the skins mod: (ex. 'E:\Minetest\mods\skinsdb\skins\')");
  17. string path = Console.ReadLine();
  18. Console.WriteLine("Start updating at page: ('0' to update everything)");
  19. int page = getInt(Console.ReadLine());
  20. e.Start(path, page);
  21. Console.WriteLine("Press any key to exit.");
  22. Console.ReadKey(false);
  23. }
  24. public static int getInt(string i) {
  25. int ret = 0;
  26. int.TryParse(i, out ret);
  27. return (ret > 0)? ret : 0;
  28. }
  29. }
  30. class Engine {
  31. string root = "http://minetest.fensta.bplaced.net";
  32. bool alternate = true; //should it use the special version of medadata saving?
  33. public void Start(string path, int page) {
  34. if (path.Length < 5) {
  35. Console.WriteLine("Too short path. STOP.");
  36. return;
  37. }
  38. if (path[path.Length - 1] != '\\') {
  39. path += '\\';
  40. }
  41. if(!Directory.Exists(path + "meta")){
  42. Console.WriteLine("Folder 'meta' not found. STOP.");
  43. return;
  44. }
  45. if(!Directory.Exists(path + "textures")){
  46. Console.WriteLine("Folder 'textures' not found. STOP.");
  47. return;
  48. }
  49. WebClient cli = new WebClient();
  50. //add useragent to identify
  51. cli.Headers.Add("User-Agent", "MT_skin_grabber 1.1");
  52. bool firstSkin = true;
  53. List<string> skin_local = new List<string>();
  54. int pages = page,
  55. updated = 0;
  56. for (; page <= pages; page++) {
  57. string contents = "";
  58. try {
  59. contents = cli.DownloadString(root + "/api/get.json.php?getlist&page=" + page);
  60. } catch(WebException e) {
  61. Console.WriteLine("Whoops! Error at page ID: " + page + ". WebClient sais: " + e.Message);
  62. Console.WriteLine("Press any key to skip this page.");
  63. Console.ReadKey(false);
  64. continue;
  65. }
  66. Data o = JsonConvert.DeserializeObject<Data>(contents);
  67. if (o.pages != pages) {
  68. pages = o.pages;
  69. }
  70. Console.WriteLine("# Page " + page + " (" + o.per_page + " skins)");
  71. for (int i = 0; i < o.skins.Length; i++) {
  72. int id = o.skins[i].id;
  73. if(o.skins[i].type != "image/png"){
  74. Console.WriteLine("Image type '" + o.skins[i].type + "' not supported at skin ID: " + id);
  75. Console.WriteLine("Press any key to continue.");
  76. Console.ReadKey(false);
  77. continue;
  78. }
  79. //eliminate special chars!
  80. o.skins[i].name = WebUtility.HtmlDecode(o.skins[i].name);
  81. o.skins[i].author = WebUtility.HtmlDecode(o.skins[i].author);
  82. //to delete old, removed skins
  83. if (firstSkin) {
  84. firstSkin = false;
  85. string[] files = Directory.GetFiles(path + "textures\\");
  86. for (int f = 0; f < files.Length; f++) {
  87. string[] filePath = stringSplitLast(files[f], '\\'),
  88. fileName = stringSplitLast(filePath[1], '.'),
  89. fileVer = stringSplitLast(fileName[0], '_');
  90. if (fileVer[1] == "" || fileVer[0] != "character") continue;
  91. int skinNr = Program.getInt(fileVer[1]);
  92. if (skinNr <= id) continue;
  93. skin_local.Add(fileName[0]);
  94. }
  95. } else skin_local.Remove("character_" + id);
  96. //get file size, only override changed
  97. FileInfo localImg = new FileInfo(path + "textures\\character_" + id + ".png");
  98. byte[] imageData = Convert.FromBase64String(o.skins[i].img);
  99. bool isDif = true;
  100. if (localImg.Exists) isDif = (Math.Abs(imageData.Length - localImg.Length) >= 3);
  101. if (isDif) {
  102. File.WriteAllBytes(localImg.FullName, imageData);
  103. imageData = null;
  104. //previews
  105. try {
  106. cli.DownloadFile(root + "/skins/1/" + id + ".png", path + "textures\\character_" + id + "_preview.png");
  107. } catch (WebException e) {
  108. Console.WriteLine("Whoops! Error at skin ID: " + id + ". WebClient sais: " + e.Message);
  109. Console.WriteLine("Press any key to continue.");
  110. Console.ReadKey(false);
  111. }
  112. } else {
  113. Console.WriteLine("[SKIP] character_" + id);
  114. continue;
  115. }
  116. string meta = "";
  117. if (!alternate) {
  118. meta = "name = \"" + o.skins[i].name + "\",\n";
  119. meta += "author = \"" + o.skins[i].author + "\",\n";
  120. meta += "comment = \"" + o.skins[i].license + '"';
  121. } else {
  122. meta = o.skins[i].name + '\n' + o.skins[i].author + '\n' + o.skins[i].license;
  123. }
  124. File.WriteAllText(path + "meta\\character_" + id + ".txt", meta);
  125. updated++;
  126. Console.WriteLine("[" + id + "] " + shorten(o.skins[i].name, 20) + "\t by: " + o.skins[i].author + "\t (" + o.skins[i].license + ")");
  127. }
  128. }
  129. foreach (string fileName in skin_local) {
  130. if(File.Exists(path + "textures\\" + fileName + ".png")) {
  131. File.Delete(path + "textures\\" + fileName + ".png");
  132. }
  133. if(File.Exists(path + "textures\\" + fileName + "_preview.png")) {
  134. File.Delete(path + "textures\\" + fileName + "_preview.png");
  135. }
  136. if(File.Exists(path + "meta\\" + fileName + ".txt")) {
  137. File.Delete(path + "meta\\" + fileName + ".txt");
  138. }
  139. Console.WriteLine("[DEL] " + fileName + " (deleted skin)");
  140. }
  141. Console.WriteLine("Done. Updated " + updated + " skins!");
  142. }
  143. string shorten(string inp, int len) {
  144. char[] shr = new char[len];
  145. for (int i = 0; i < len; i++) {
  146. if (i < inp.Length) {
  147. shr[i] = inp[i];
  148. } else shr[i] = ' ';
  149. }
  150. return new string(shr);
  151. }
  152. string[] stringSplitLast(string path, char limiter) {
  153. int found = 0;
  154. int totalLen = path.Length - 1;
  155. for (int i = totalLen; i >= 0; i--) {
  156. if (path[i] == limiter) {
  157. found = i;
  158. break;
  159. }
  160. }
  161. if (found == 0) {
  162. return new string[] { "", "" };
  163. }
  164. int len = totalLen - found;
  165. char[] str_1 = new char[found],
  166. str_2 = new char[len];
  167. for (int i = 0; i < path.Length; i++) {
  168. if (i == found) continue;
  169. if (i < found) {
  170. str_1[i] = path[i];
  171. } else {
  172. str_2[i - found - 1] = path[i];
  173. }
  174. }
  175. return new string[] { new string(str_1), new string(str_2) };
  176. }
  177. }
  178. class Data {
  179. public Skins_data[] skins;
  180. public int page, pages, per_page;
  181. }
  182. class Skins_data {
  183. public string name, author, uploaded, type, license, img;
  184. public int id, license_id;
  185. }
  186. }