public static ValveAPIResponseCollection DownloadValveDefinitions(string URL, string cacheLocation) { Console.Clear(); Console.WriteLine($"Pulling Valve API data."); JsonSerializerSettings settings = new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error, }; ValveAPIResponseCollection responses = null; if (File.Exists(cacheLocation)) { Console.WriteLine($"Cached Valve data found at {cacheLocation}. Using this data."); responses = JsonConvert.DeserializeObject <ValveAPIResponseCollection>(File.ReadAllText(cacheLocation), settings); if (responses.Responses.Any(x => x.Value.IsExpired)) { Console.WriteLine("This data is stale. Deleting and refreshing."); responses = new ValveAPIResponseCollection(); } } else { Console.WriteLine($"No cached Valve data found."); responses = new ValveAPIResponseCollection(); } string baseLocation = Path.GetDirectoryName(cacheLocation); for (int i = 0; i < 100; i++) { string index = i.ToString("00"); string path = Path.Combine(baseLocation, $"ValveResponse_Set{index}.json"); if (responses.ContainsKey(i)) { Console.WriteLine($"Loading set {i} from {path}..."); File.WriteAllText(path, responses[i].JSONResult); responses[i].ParseJSON(); } else { string setURL = $"{URL}{index}/"; Console.WriteLine($"Connecting to cdn router for set {i} at {setURL}..."); //Have to use HttpWebRequest instead of WebClient because this is a URL GET rather than a specific resource link that DownloadString can grab. HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(setURL); request.Method = "GET"; string result = ""; try { using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); result = reader.ReadToEnd(); reader.Close(); dataStream.Close(); } } catch (WebException e) { if (e.Message.Contains("(400)")) { Console.WriteLine($"Set {i} does not exist. Stopping here."); //We've hit a set that doesn't exist break; } } var cdnResponse = JsonConvert.DeserializeObject <ValveAPIResponse>(result, settings); Console.WriteLine($"Successfully pulled from cdn router. Set {i} can be found at {cdnResponse.FullURL}. Downloading card data..."); using (WebClient client = new WebClient()) { result = client.DownloadString(cdnResponse.FullURL); } cdnResponse.JSONResult = result; cdnResponse.ParseJSON(); cdnResponse.RetrievalDate = DateTime.Now; Console.WriteLine($"Successfully pulled from Valve API. Caching card data to {path}..."); File.WriteAllText(path, result); Console.WriteLine("Done."); responses[i] = cdnResponse; } File.WriteAllText(cacheLocation, JsonConvert.SerializeObject(responses)); } return(responses); }
public static (Dictionary <int, WikiSet> Sets, Dictionary <int, WikiCard> Cards) ConvertValveCardsToWikiCards(ValveAPIResponseCollection api) { var sets = new Dictionary <int, WikiSet>(); var cards = new Dictionary <int, WikiCard>(); foreach (var pair in api.Responses) { sets[pair.Key] = new WikiSet(pair.Value.SetDefinition); foreach (var card in pair.Value.SetDefinition.card_list) { cards[card.card_id] = new WikiCard(card); } } return(sets, cards); }
public static void DownloadCardImages(ValveAPIResponseCollection sets, string imageLocation) { if (!Directory.Exists(imageLocation)) { Directory.CreateDirectory(imageLocation); } foreach (var pair in sets.Responses) { string set = pair.Key.ToString("00"); foreach (var card in pair.Value.SetDefinition.card_list) { foreach (var language in card.large_image.Keys) { string langDir = Path.Combine(imageLocation, "cards", language); Directory.CreateDirectory(langDir); string cardFilename = Path.Combine(langDir, $"Artifact_card_{set}_{ScrubString(card.card_name["english"])}_{card.card_id}_{language}.png"); Console.WriteLine($"Working on {cardFilename}..."); if (File.Exists(cardFilename)) { Console.WriteLine("\tSkipped."); continue; } using (WebClient client = new WebClient()) { client.DownloadFile(card.large_image[language], cardFilename); Console.WriteLine("\tDone."); } } foreach (var language in card.mini_image.Keys) { string langDir = Path.Combine(imageLocation, "icons", language); Directory.CreateDirectory(langDir); string abilityFileName = Path.Combine(langDir, $"Artifact_icon_{set}_{ScrubString(card.card_name["english"])}_{card.card_id}_{language}.png"); Console.WriteLine($"Working on {abilityFileName}..."); if (File.Exists(abilityFileName)) { Console.WriteLine("\tSkipped."); continue; } using (WebClient client = new WebClient()) { client.DownloadFile(card.mini_image[language], abilityFileName); Console.WriteLine("\tDone."); } } foreach (var language in card.ingame_image.Keys) { string langDir = Path.Combine(imageLocation, "hero_icons", language); Directory.CreateDirectory(langDir); string ingameFileName = Path.Combine(langDir, $"Artifact_heroicon_{set}_{ScrubString(card.card_name["english"])}_{card.card_id}_{language}.png"); Console.WriteLine($"Working on {ingameFileName}..."); if (File.Exists(ingameFileName)) { Console.WriteLine("\tSkipped."); continue; } using (WebClient client = new WebClient()) { client.DownloadFile(card.ingame_image[language], ingameFileName); Console.WriteLine("\tDone."); } } } } }
static void Main(string[] args) { string configLocation = Path.GetFullPath("./config.json"); Config config = LoadConfig(configLocation); string cardCache = ""; Dictionary <int, WikiSet> Sets = null; Dictionary <int, WikiCard> Cards = null; ValveAPIResponseCollection ValveData = null; CardTextCollection GameFileInfo = null; Dictionary <string, int> VOMapping = null; try { string command = null; bool exit = false; while (!exit) { switch (command) { case "valve": ValveData = DownloadValveDefinitions(config.ValveAPIBaseURL, config.ValveCacheLocation); if (Sets == null || Cards == null) { (Sets, Cards) = ConvertValveCardsToWikiCards(ValveData); } break; case "save": if (ValveData == null) { ValveData = DownloadValveDefinitions(config.ValveAPIBaseURL, config.ValveCacheLocation); } DownloadCardImages(ValveData, config.APIImagesLocation); break; case "clear": break; case "load": if (ValveData == null) { ValveData = DownloadValveDefinitions(config.ValveAPIBaseURL, config.ValveCacheLocation); } if (Sets == null || Cards == null) { (Sets, Cards) = ConvertValveCardsToWikiCards(ValveData); } VOMapping = MapCardIDsToVONames(config.ArtifactBaseDir, Sets.Keys.ToList()); ExtractGameData(config.ArtifactBaseDir, Sets.Keys.ToList(), VOMapping); break; case "merge": break; case "extract": ExtractRawCardImages(config.ArtifactBaseDir, config.GameImagesLocation, config.GameImageFormat); break; case "exit": exit = true; break; case null: break; default: Console.WriteLine("Command not recognized. Please try again."); break; } Console.WriteLine("\n\n\nPlease enter one of the following options:\n\n"); Console.WriteLine("valve - retrieve complete card definitions from the official Valve API."); Console.WriteLine("save - retrieve card images from the official Valve API that are not cached."); Console.WriteLine("clear - delete all cached card API images."); Console.WriteLine("load - read card/lore/voiceover data from game files at the configured Artifact game path."); Console.WriteLine("merge - combine card info from the game data at the configured Artifact game path with official API data."); Console.WriteLine("extract - [WARNING: MEMORY HEAVY] extract card images from the game data at the configured Artifact game path."); Console.WriteLine("upload - push all extracted game images and cached API card images to the configured wiki."); Console.WriteLine("backup - download all existing wiki card articles prior to overwriting them."); Console.WriteLine("update - edit or create all card articles with the latest and greatest card info."); Console.WriteLine("exit - exit\n"); command = Console.ReadLine().ToLower(); } } catch (Exception e) { Console.WriteLine($"\n\n\n\n\nERROR\n\nAn exception was encountered while running Artificer. Please provide the following to the maintainer of the bot:\n\n{e.ToString()}"); } Console.WriteLine("\n\n\n\n\nPress Enter to continue..."); Console.Read(); }