|
1 | | -using System.Text; |
2 | 1 | using Microsoft.Win32; |
3 | 2 | using VDFparse; |
| 3 | +using CommandLine; |
| 4 | +using System.Text.Json; |
4 | 5 |
|
5 | 6 | namespace VDFParse.Cli; |
6 | 7 |
|
| 8 | +class Options |
| 9 | +{ |
| 10 | + [Value(0, Required = true, MetaName = "file", HelpText = "The file to read from or `appinfo`/`packageinfo`.")] |
| 11 | + public string Path { get; set; } = null!; |
| 12 | + |
| 13 | + [Value(1, MetaName = "id", HelpText = "The ID of the item to query.")] |
| 14 | + public IEnumerable<uint> Ids { get; set; } = null!; |
| 15 | + |
| 16 | + [Option('i', "info", HelpText = "Write only info about the specified item or file.")] |
| 17 | + public bool Info { get; set; } |
| 18 | +} |
| 19 | + |
7 | 20 | static class Program |
8 | 21 | { |
9 | 22 | static int Main(string[] args) |
10 | 23 | { |
11 | | - Console.OutputEncoding = Encoding.UTF8; |
12 | | - switch (args.ElementAtOrDefault(0)) |
13 | | - { |
14 | | - case "-v": |
15 | | - case "--version": |
16 | | - Console.WriteLine(typeof(Program).Assembly.GetName().Version); |
17 | | - return 0; |
18 | | - case "-?": |
19 | | - case "/?": |
20 | | - case "-h": |
21 | | - case "--help": |
22 | | - case null: |
23 | | - Console.WriteLine(Translations.Get("HelpMessage"), |
24 | | - typeof(Program).Assembly.GetName().Name); |
25 | | - return 0; |
26 | | - default: |
27 | | - break; |
28 | | - } |
29 | | - switch (args[0]) |
30 | | - { |
31 | | - case "list": |
32 | | - case "info": |
33 | | - if (args.Length < 2) |
34 | | - { |
35 | | - Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments")); |
36 | | - return 4; |
37 | | - } |
38 | | - break; |
39 | | - case "json": |
40 | | - if (args.Length < 3) |
41 | | - { |
42 | | - Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments")); |
43 | | - return 4; |
44 | | - } |
45 | | - break; |
46 | | - case "query": |
47 | | - if (args.Length < 4) |
48 | | - { |
49 | | - Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments")); |
50 | | - return 4; |
51 | | - } |
52 | | - break; |
53 | | - default: |
54 | | - Console.Error.WriteLine(Translations.Get("ErrorUnknownParameter"), args[0]); |
55 | | - return 3; |
56 | | - } |
57 | | - VDFFile vdfFile = new VDFFile(); |
58 | | - string filePath; |
59 | | - if (args[1] == "appinfo" || args[1] == "packageinfo") |
| 24 | + return Parser.Default |
| 25 | + .ParseArguments<Options>(args) |
| 26 | + .MapResult(RunOptions, (_) => 1); |
| 27 | + } |
| 28 | + |
| 29 | + static int RunOptions(Options opts) |
| 30 | + { |
| 31 | + // Automatically determine path of default files |
| 32 | + if (opts.Path == "appinfo" || opts.Path == "packageinfo") |
60 | 33 | { |
61 | 34 | string? steamPath; |
62 | 35 | try |
63 | 36 | { |
64 | 37 | steamPath = GetSteamPath(); |
65 | | - Console.WriteLine(steamPath); |
66 | 38 | if (steamPath is null) |
67 | 39 | { |
68 | | - Console.Error.WriteLine(Translations.Get("ErrorCannotFindSteam")); |
69 | | - return 1; |
| 40 | + Console.Error.WriteLine("Cannot find Steam."); |
| 41 | + return 2; |
70 | 42 | } |
71 | 43 | } |
72 | 44 | catch (PlatformNotSupportedException) |
73 | 45 | { |
74 | | - Console.Error.WriteLine(Translations.Get("ErrorPlatformUnsupported")); |
75 | | - return 2; |
| 46 | + Console.Error.WriteLine("Platform unsupported for automated Steam locating."); |
| 47 | + return 3; |
76 | 48 | } |
77 | | - if (args[1] == "appinfo") |
| 49 | + if (opts.Path == "appinfo") |
78 | 50 | { |
79 | | - filePath = Path.Combine(steamPath, "appcache", "appinfo.vdf"); |
| 51 | + opts.Path = Path.Combine(steamPath, "appcache", "appinfo.vdf"); |
80 | 52 | } |
81 | 53 | else |
82 | 54 | { |
83 | | - filePath = Path.Combine(steamPath, "appcache", "packageinfo.vdf"); |
| 55 | + opts.Path = Path.Combine(steamPath, "appcache", "packageinfo.vdf"); |
84 | 56 | } |
85 | 57 | } |
86 | | - else |
87 | | - { |
88 | | - filePath = args[1]; |
89 | | - } |
90 | | - vdfFile.Read(filePath); |
| 58 | + |
| 59 | + VDFFile vdfFile; |
91 | 60 | try |
92 | 61 | { |
93 | | - vdfFile.Read(filePath); |
| 62 | + vdfFile = VDFFile.Read(opts.Path); |
94 | 63 | } |
95 | | - // TODO: Catch explicit errors |
96 | | - #pragma warning disable CA1031 |
97 | 64 | catch |
98 | 65 | { |
99 | | - Console.Error.WriteLine(Translations.Get("ErrorParsingFile"), filePath); |
100 | | - return 7; |
| 66 | + Console.Error.WriteLine($"Error while trying to parse \"{opts.Path}\""); |
| 67 | + return 4; |
101 | 68 | } |
102 | | - try |
| 69 | + |
| 70 | + // Output the right data |
| 71 | + dynamic data; |
| 72 | + if (opts.Ids is not null) |
103 | 73 | { |
104 | | - switch (args[0]) |
105 | | - { |
106 | | - case "list": |
107 | | - return List(vdfFile); |
108 | | - case "info": |
109 | | - return Info(vdfFile); |
110 | | - } |
111 | | - List<Dataset> processing; |
112 | | - if (args[2] == "*") |
113 | | - { |
114 | | - processing = vdfFile.Datasets; |
115 | | - } |
116 | | - else |
| 74 | + data = new Dictionary<uint, dynamic>(); |
| 75 | + |
| 76 | + var ids = opts.Ids.ToHashSet(); |
| 77 | + foreach (var dataset in vdfFile.Datasets) |
117 | 78 | { |
118 | | - uint id; |
119 | | - bool success = uint.TryParse(args[2], out id); |
120 | | - if (!success) |
121 | | - { |
122 | | - Console.Error.WriteLine(Translations.Get("ErrorInvalidNumber"), args[2]); |
123 | | - return 5; |
124 | | - } |
125 | | - var dataset = vdfFile.FindByID(id); |
126 | | - if (dataset == null) |
| 79 | + if (ids.Contains(dataset.Id)) |
127 | 80 | { |
128 | | - Console.Error.WriteLine(Translations.Get("ErrorNoId"), id); |
129 | | - return 6; |
| 81 | + if (opts.Info) |
| 82 | + dataset.Data.Clear(); |
| 83 | + |
| 84 | + data[dataset.Id] = dataset; |
| 85 | + ids.Remove(dataset.Id); |
130 | 86 | } |
131 | | - processing = new List<Dataset> { dataset }; |
132 | 87 | } |
133 | | - switch (args[0]) |
| 88 | + if (ids.Count != 0) |
134 | 89 | { |
135 | | - case "json": |
136 | | - #pragma warning disable CA1806 |
137 | | - int.TryParse(args.ElementAtOrDefault(4), out int indent); |
138 | | - return Json(processing, indent: 4); |
139 | | - case "query": |
140 | | - return Query(processing, args.Skip(3).ToArray()); |
| 90 | + var remaining = String.Join(", ", ids); |
| 91 | + Console.Error.WriteLine($"Could not find entries with id(s): {remaining}"); |
| 92 | + return 5; |
141 | 93 | } |
142 | 94 | } |
143 | | - // TODO: catch explicit errors |
144 | | - #pragma warning disable CA1031 |
145 | | - catch (Exception e) |
| 95 | + else if (opts.Info) |
146 | 96 | { |
147 | | - Console.Error.WriteLine(Translations.Get("ErrorUnknown"), e.Message); |
| 97 | + data = new |
| 98 | + { |
| 99 | + Path = opts.Path, |
| 100 | + EUniverse = vdfFile.EUniverse, |
| 101 | + Length = vdfFile.Datasets.Count, |
| 102 | + }; |
148 | 103 | } |
149 | | - return 9; |
150 | | - } |
151 | | - |
152 | | - static int List(VDFFile source) |
153 | | - { |
154 | | - Console.WriteLine(String.Join("\n", source.Datasets.Select(dataset => dataset.ID))); |
155 | | - return 0; |
156 | | - } |
157 | | - |
158 | | - static int Info(VDFFile source) |
159 | | - { |
160 | | - Console.WriteLine(source.Datasets.Count); |
161 | | - return 0; |
162 | | - } |
163 | | - |
164 | | - static int Json(List<Dataset> datasets, int indent) |
165 | | - { |
166 | | - foreach (var dataset in datasets) |
| 104 | + else |
167 | 105 | { |
168 | | - Console.WriteLine(dataset.Data.ToJSON(indent: indent)); |
| 106 | + data = vdfFile; |
169 | 107 | } |
170 | | - return 0; |
171 | | - } |
172 | 108 |
|
173 | | - static int Query(List<Dataset> datasets, string[] queries) |
174 | | - { |
175 | | - foreach (var dataset in datasets) |
176 | | - { |
177 | | - foreach (var query in queries) |
178 | | - { |
179 | | - Console.WriteLine(String.Join("\n", dataset.Data.Search(query))); |
180 | | - } |
181 | | - } |
| 109 | + var options = new JsonSerializerOptions(); |
| 110 | + options.Converters.Add(new BytesToBase64JsonConverter()); |
| 111 | + |
| 112 | + Console.WriteLine(JsonSerializer.Serialize(data, options)); |
182 | 113 | return 0; |
183 | 114 | } |
| 115 | + |
184 | 116 | static string? GetSteamPath() |
185 | 117 | { |
186 | 118 |
|
|
0 commit comments