summaryrefslogtreecommitdiff
path: root/src/SMAPI.Web/Framework/LogParsing/Models/LogModInfo.cs
blob: 557f08ff9d783e4c7848b9407ffc224cbdea6bb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Diagnostics.CodeAnalysis;
using StardewModdingAPI.Toolkit;

namespace StardewModdingAPI.Web.Framework.LogParsing.Models
{
    /// <summary>Metadata about a mod or content pack in the log.</summary>
    public class LogModInfo
    {
        /*********
        ** Private fields
        *********/
        /// <summary>The parsed mod version, if valid.</summary>
        private Lazy<ISemanticVersion?> ParsedVersionImpl;


        /*********
        ** Accessors
        *********/
        /// <summary>The mod name.</summary>
        public string Name { get; }

        /// <summary>The mod author.</summary>
        public string Author { get; }

        /// <summary>The mod version.</summary>
        public string Version { get; private set; }

        /// <summary>The mod description.</summary>
        public string Description { get; }

        /// <summary>The update version.</summary>
        public string? UpdateVersion { get; private set; }

        /// <summary>The update link.</summary>
        public string? UpdateLink { get; private set; }

        /// <summary>The name of the mod for which this is a content pack (if applicable).</summary>
        public string? ContentPackFor { get; }

        /// <summary>The number of errors logged by this mod.</summary>
        public int Errors { get; set; }

        /// <summary>Whether the mod was loaded into the game.</summary>
        public bool Loaded { get; }

        /// <summary>Whether the mod has an update available.</summary>
        [MemberNotNullWhen(true, nameof(LogModInfo.UpdateVersion), nameof(LogModInfo.UpdateLink))]
        public bool HasUpdate => this.UpdateVersion != null && this.Version != this.UpdateVersion;

        /// <summary>Whether this is an actual mod (rather than a special entry for SMAPI or the game itself).</summary>
        public bool IsMod { get; }

        /// <summary>Whether this is a C# code mod.</summary>
        public bool IsCodeMod { get; }

        /// <summary>Whether this is a content pack for another mod.</summary>
        [MemberNotNullWhen(true, nameof(LogModInfo.ContentPackFor))]
        public bool IsContentPack { get; }


        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="name">The mod name.</param>
        /// <param name="author">The mod author.</param>
        /// <param name="version">The mod version.</param>
        /// <param name="description">The mod description.</param>
        /// <param name="updateVersion">The update version.</param>
        /// <param name="updateLink">The update link.</param>
        /// <param name="contentPackFor">The name of the mod for which this is a content pack (if applicable).</param>
        /// <param name="errors">The number of errors logged by this mod.</param>
        /// <param name="loaded">Whether the mod was loaded into the game.</param>
        /// <param name="isMod">Whether this is an actual mod (instead of a special entry for SMAPI or the game).</param>
        public LogModInfo(string name, string author, string version, string description, string? updateVersion = null, string? updateLink = null, string? contentPackFor = null, int errors = 0, bool loaded = true, bool isMod = true)
        {
            this.Name = name;
            this.Author = author;
            this.Description = description;
            this.UpdateVersion = updateVersion;
            this.UpdateLink = updateLink;
            this.ContentPackFor = contentPackFor;
            this.Errors = errors;
            this.Loaded = loaded;

            if (isMod)
            {
                this.IsMod = true;
                this.IsContentPack = !string.IsNullOrWhiteSpace(this.ContentPackFor);
                this.IsCodeMod = !this.IsContentPack;
            }

            this.OverrideVersion(version);
        }

        /// <summary>Add an update alert for this mod.</summary>
        /// <param name="updateVersion">The update version.</param>
        /// <param name="updateLink">The update link.</param>
        public void SetUpdate(string updateVersion, string updateLink)
        {
            this.UpdateVersion = updateVersion;
            this.UpdateLink = updateLink;
        }

        /// <summary>Override the version number, for cases like SMAPI itself where the version is only known later during parsing.</summary>
        /// <param name="version">The new mod version.</param>
        [MemberNotNull(nameof(LogModInfo.Version), nameof(LogModInfo.ParsedVersionImpl))]
        public void OverrideVersion(string version)
        {
            this.Version = version;
            this.ParsedVersionImpl = new Lazy<ISemanticVersion?>(this.ParseVersion);
        }

        /// <summary>Get the semantic version for this mod, if it's valid.</summary>
        public ISemanticVersion? GetParsedVersion()
        {
            return this.ParsedVersionImpl.Value;
        }


        /*********
        ** Private methods
        *********/
        /// <summary>Get the semantic version for this mod, if it's valid.</summary>
        public ISemanticVersion? ParseVersion()
        {
            return !string.IsNullOrWhiteSpace(this.Version) && SemanticVersion.TryParse(this.Version, out ISemanticVersion? version)
                ? version
                : null;
        }
    }
}