Ejemplo n.º 1
0
        public async Task AddCachedImageAsync(R4UCard card)
        {
            try
            {
                var imgURL = card.Images.Last();
                Log.Information("Caching [{serial}]: {imgURL}", card.Serial, imgURL);
                //using (System.IO.Stream netStream = await imgURL.WithImageHeaders().GetStreamAsync()) // card.GetImageStreamAsync())
                var bytes = await imgURL.WithImageHeaders().GetAsync().WithRetries(10).ReceiveBytes();

                using (Image img = Image.Load(bytes))
                {
                    var imageDirectoryPath = Path.Get(_IMAGE_CACHE_PATH);
                    if (!imageDirectoryPath.Exists)
                    {
                        imageDirectoryPath.CreateDirectory();
                    }
                    if (img.Width > img.Height)
                    {
                        Log.Debug("Rotating Image as it's Cached...");
                        img.Mutate(ctx => ctx.Rotate(RotateMode.Rotate90));
                    }
                    img.Metadata.ExifProfile ??= new ExifProfile();
                    img.Metadata.ExifProfile.SetValue(SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifTag.Copyright, card.Images.Last().Authority);
                    var savePath = Path.Get(_IMAGE_CACHE_PATH).Combine($"{card.Serial.Replace('-', '_').AsFileNameFriendly()}.jpg");
                    savePath.Open(img.SaveAsJpeg, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite);
                }
            } catch (InvalidOperationException e) when(e.Message == "Sequence contains no elements")
            {
                Log.Warning("Cannot be cached as no image URLs were found: {serial}", card.Serial);
            }
        }
Ejemplo n.º 2
0
        private async Task <R4UCard> ParseOriginalCard(WikiCardContext context, WikiSetContext setContext)
        {
            var card         = new R4UCard();
            var mainInfoBox  = context.MainInfoBox;
            var extraInfoBox = context.ExtraInfoBox;

            card.Name    = new MultiLanguageString();
            card.Name.JP = mainInfoBox.GetValueOrDefault("kanji", mainInfoBox["name"]);
            card.Name.EN = mainInfoBox["name"];
            card.Type    = TranslateType(mainInfoBox["card type"]);
            card.Set     = setContext.Set;
            if (card.Type == CardType.Character)
            {
                card.Cost   = int.Parse(mainInfoBox["cost"]);
                card.ATK    = int.Parse(mainInfoBox["atk"]);
                card.DEF    = int.Parse(mainInfoBox["def"]);
                card.Traits = await ParseTraits(context.RawMainInfoBox["trait"], setContext);
            }
            if (extraInfoBox.TryGetValue("card flavor(s)", out var flavor))
            {
                card.Flavor    = new MultiLanguageString();
                card.Flavor.EN = flavor;
            }
            if (extraInfoBox.TryGetValue("card abilities", out var abilities))
            {
                card.Effect = TranslateEffect(abilities);
                card.Color  = InferFromEffect(card.Effect);
            }
            else
            {
                // Assumed. All Partner cards do not have effects, and vanilla cards have [Relaxing]
                card.Color = CardColor.Red;
            }
            return(card);
        }
Ejemplo n.º 3
0
        private async Task <R4UCard> AddImageFromConsole(R4UCard card, InspectionOptions options)
        {
            var modifiedCard = card.Clone();

            Log.Information("Please enter a new image URL: ");
            var newURIString = Console.ReadLine();

            try
            {
                Log.Information("Validating URL...");
                var newURI = new Uri(newURIString);
                Log.Information("Looks good; validating image... (will not check if the image itself is correct!)");
                using (Image img = Image.Load(await newURI.WithImageHeaders().GetStreamAsync()))
                {
                    Log.Information("Image can be loaded. Is the ratio reasonable?");
                    var aspectRatio        = (img.Width * 1.0d) / img.Height;
                    var flooredAspectRatio = Math.Floor(aspectRatio * 100);
                    if (flooredAspectRatio < 70 || flooredAspectRatio > 72)
                    {
                        Log.Information("Image Ratio ({aspectRatio}) isn't correct (it must be approx. 0.71428571428); Failed inspection.", aspectRatio);
                        return(null);
                    }
                    else
                    {
                        if (img.Width < 400)
                        {
                            Log.Warning("The image is of low quality; this may not be good for exporting purposes. Continue? [Y/N] (Default is N)");
                            if (!ConsoleUtils.Prompted(options.IsNonInteractive, options.NoWarning))
                            {
                                return(null);
                            }
                        }
                        modifiedCard.Images.Add(newURI);
                        Log.Information("All preliminary tests passed. Modified {card}.", card.Serial);
                    }
                }
            }
            catch (UnknownImageFormatException)
            {
                Log.Error("The URL does not point to a valid image. Inspection failed.");
                return(null);
            }
            catch (Exception e)
            {
                Log.Error("{e}", e);
                return(null);
            }
            return(modifiedCard);
        }
        private async Task <R4UCard> Process(R4UCard card)
        {
            if (!HasMissingInformation(card))
            {
                return(card);
            }
            var updatedCard = card.Clone();
            var url         = rebirthURLPrefix
                              .SetQueryParam("cardno", updatedCard.Serial.Replace("+", "+")) //
            ;

            Log.Debug("Opening Link: {url}", url);
            var document = await url.WithReferrer("https://rebirth-fy.com/cardlist/").GetHTMLAsync();

            var flavorJPText        = document.QuerySelector(".cardlist-flavor").GetInnerText();
            var rulesTextJPText     = document.QuerySelector(".cardlist-free").GetInnerText().Trim();
            var imageLink           = document.QuerySelector(".cardlist-img").FindChild <IHtmlImageElement>().Source;
            var rulesTextEnumerable = effectMatcher.Matches(rulesTextJPText);

            Log.Information("Flavor JP: {jp}", flavorJPText);
            Log.Information("Rules Text JP: {jp}", rulesTextJPText);
            if (!String.IsNullOrWhiteSpace(flavorJPText))
            {
                updatedCard.Flavor ??= new MultiLanguageString();
                updatedCard.Flavor.JP = flavorJPText;
            }
            updatedCard.Effect = rulesTextEnumerable.Select((m, i) =>
            {
                var result = card.Effect[i].Clone();
                result.JP  = m.Value;
                return(result);
            }).ToArray();
            updatedCard.Images.Add(new Uri(imageLink));
            Log.Information("After editing: {@card}", updatedCard);
            return(updatedCard);
        }
 private bool HasMissingInformation(R4UCard card)
 {
     return((card?.Effect?.Any(mls => mls.JP == null) ?? false) || (card?.Name.JP == null) || (card?.Traits?.Any(mls => mls.JP == null) ?? false) || ((card.Images?.Count ?? 0) < 1));
 }
Ejemplo n.º 6
0
        private IEnumerable <R4UCard> CreateBaseCards(IHtmlParagraphElement paragraph, Dictionary <string, R4UReleaseSet> setMap)
        {
            List <R4UCard> cards = new List <R4UCard>();

            cards.Add(new R4UCard());

            var card    = cards.First();
            var content = paragraph.InnerHtml;
            var text    = paragraph.GetInnerText();
            var cursor  = text.AsSpanCursor();

            // var space = " ";

            // Format: <Serial> <Rarity> <JP Name with Spaces> <strong>English Name with Spaces</strong><br>
            if (TryGetExceptionalSerialRarityName(cursor.CurrentLine.ToString(), out var exceptionalResults))
            {
                cards = exceptionalResults.Select(res =>
                {
                    var card    = new R4UCard();
                    card.Serial = res.Serial;
                    card.Rarity = res.Rarity;
                    card.Name   = res.Name;
                    return(card);
                }).ToList();
                if (cards.Count < 1)
                {
                    yield break;
                }
                card = cards.First();
            }
            else if (serialRarityJPNameMatcher.IsMatch(content))
            {
                var firstLineMatch = serialRarityJPNameMatcher.Match(content);
                card.Serial  = firstLineMatch.Groups[1].Value.Trim();
                card.Rarity  = firstLineMatch.Groups[2].Value.Trim();
                card.Name    = new MultiLanguageString();
                card.Name.JP = rubyMatcher.Replace(firstLineMatch.Groups[3].Value, "").Trim(); // TODO: Resolve <ruby>永<rt>えい</rt>遠<rt>えん</rt></ruby>の<ruby>巫<rt>み</rt>女<rt>こ</rt></ruby> <ruby>霊<rt>れい</rt>夢<rt>む</rt></ruby>
                card.Name.EN = firstLineMatch.Groups[4].Value.Trim();
            }
            else
            {
                throw new NotImplementedException($"The serial/rarity/JP Name line cannot be parsed. Here's the offending line: {cursor.CurrentLine.ToString()}");
            }

            var releaseID = releaseIDMatcher.Match(card.Serial).Groups[1].Value;

            card.Set = setMap.GetValueOrDefault(releaseID, null) ?? CreateTemporarySet(releaseID);

            // Format: Cost <Cost> / <Series Name> / <Traits>
            cursor.Next();
            var secondLine = cursor.CurrentLine.ToString();

            if (costSeriesTraitMatcher.IsMatch(secondLine))
            {
                card.Type = CardType.Character;
                var secondLineMatch = costSeriesTraitMatcher.Match(cursor.CurrentLine.ToString());
                card.Cost   = int.Parse(secondLineMatch.Groups[1].Value);
                card.Traits = secondLineMatch.Groups[3].Value //
                              .Split(" – ")                   //
                              .Select(str => str.Trim())      //
                              .Select(t => new MultiLanguageString()
                {
                    EN = t
                })                                                     //
                              .ToList();

                cursor.Next();
                card.ATK = cursor.CurrentLine
                           .Slice("ATK ".Length)
                           .AsParsed <int>(int.TryParse);

                cursor.Next();
                string defLine = cursor.CurrentLine.ToString();
                card.DEF = cursor.CurrentLine
                           .Slice("DEF ".Length)
                           .AsParsed <int>(int.TryParse);

                Regex flavorTextMatcher = new Regex(@"" + defLine + @"<br><em>(.+)</em><br>");
                if (flavorTextMatcher.IsMatch(content))
                {
                    cursor.Next();
                    card.Flavor    = new MultiLanguageString();
                    card.Flavor.EN = cursor.CurrentLine.ToString(); // flavorTextMatcher.Match(content).Groups[1].Value;
                }
            }
            else if (seriesRebirthMatcher.IsMatch(secondLine))
            {
                card.Type = CardType.Rebirth;
                var rebirthLine = secondLine;

                Regex flavorTextMatcher = new Regex(@"" + rebirthLine + @"<br><em>(.+)</em><br>");
                if (flavorTextMatcher.IsMatch(content))
                {
                    cursor.Next();
                    card.Flavor    = new MultiLanguageString();
                    card.Flavor.EN = cursor.CurrentLine.ToString(); // flavorTextMatcher.Match(content).Groups[1].Value;
                }
            }
            else
            {
                card.Type  = CardType.Partner;
                card.Color = CardColor.Red;
            }

            if (card.Color != CardColor.Red)
            {
                List <MultiLanguageString> effects = new List <MultiLanguageString>();
                while (cursor.Next())
                {
                    Log.Information("Adding Effect: {eff}", cursor.CurrentLine.ToString());
                    effects.Add(new MultiLanguageString()
                    {
                        EN = cursor.CurrentLine.ToString()
                    });
                }
                effects     = Compress(effects);
                card.Effect = effects.ToArray();
                card.Color  = CardUtils.InferFromEffect(card.Effect);
            }

            yield return(card);

            foreach (var dupCard in cards.Skip(1))
            {
                var detailedDupCard = card.Clone();
                detailedDupCard.Serial = dupCard.Serial;
                detailedDupCard.Rarity = dupCard.Rarity;
                detailedDupCard.Name   = dupCard.Name;
                yield return(detailedDupCard);
            }
        }