Skip to content

Commit 9ab8caf

Browse files
committed
3.2.7 — CC API migration, clear cache button, install detection fix, bug fixes
1 parent 2463abf commit 9ab8caf

6 files changed

Lines changed: 147 additions & 50 deletions

File tree

Wauncher/Services/FriendsService.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public async Task LoadSelfProfileAsync()
133133
if (!hasSteam || string.IsNullOrWhiteSpace(Steam.recentSteamID64))
134134
return;
135135

136-
var rawSelfJson = await Api.Eddies.GetSelfInfo(Steam.recentSteamID64);
136+
var rawSelfJson = await Api.Profiles.GetSelfInfo(Steam.recentSteamID64);
137137
var self = Api.ParseSelfInfoPayload(rawSelfJson);
138138
if (self == null)
139139
return;
@@ -202,16 +202,18 @@ public async Task RefreshFriendsAsync()
202202
return;
203203
}
204204

205-
string rawFriendsJson;
206-
try
205+
if (string.IsNullOrEmpty(Steam.recentSteamID64))
207206
{
208-
rawFriendsJson = await Api.Eddies.GetFriends(Steam.recentSteamID64 ?? string.Empty);
209-
}
210-
catch (Exception ex)
211-
{
212-
ErrorLogger.LogError("FriendsService.RefreshFriendsAsync.GetFriends", ex, "Failed to get friends via SteamID64, trying SteamID2 fallback");
213-
rawFriendsJson = await Api.Eddies.GetFriendsBySteamId2(Steam.recentSteamID2 ?? string.Empty);
207+
Dispatcher.UIThread.Post(() =>
208+
{
209+
ShowNoFriendsState = false;
210+
FriendsStatus = "Sign in to Steam to see friends.";
211+
FriendsShowStatus = true;
212+
});
213+
return;
214214
}
215+
216+
var rawFriendsJson = await Api.Profiles.GetFriends(Steam.recentSteamID64);
215217
var apiFriends = Api.ParseFriendsPayload(rawFriendsJson)
216218
.OrderBy(f => f.Status == "Offline" ? 1 : 0)
217219
.ToList();

Wauncher/Services/UpdateService.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,24 @@ public UpdateService()
6060

6161
public async Task<bool> CheckForUpdatesAsync()
6262
{
63+
if (IsCheckingUpdates || IsUpdating || IsInstalling)
64+
return false;
65+
66+
// Always check for a missing game install regardless of SkipUpdates —
67+
// SkipUpdates only skips the patch check, not the install detection.
68+
string csgoExe = Path.Combine(WauncherDirectory, "csgo.exe");
69+
if (!File.Exists(csgoExe))
70+
{
71+
IsNeedingInstall = true;
72+
return true;
73+
}
74+
6375
if (ViewModels.SettingsWindowViewModel.LoadGlobal().SkipUpdates)
6476
{
6577
IsUpdateAvailable = false;
6678
return false;
6779
}
6880

69-
if (IsCheckingUpdates || IsUpdating || IsInstalling)
70-
return false;
71-
7281
IsCheckingUpdates = true;
7382
// Clear any stale error from a previous (e.g. offline) check so a successful
7483
// re-check doesn't keep showing "Can't connect to update server".
@@ -77,14 +86,6 @@ public async Task<bool> CheckForUpdatesAsync()
7786

7887
try
7988
{
80-
string csgoExe = Path.Combine(WauncherDirectory, "csgo.exe");
81-
82-
if (!File.Exists(csgoExe))
83-
{
84-
IsNeedingInstall = true;
85-
return true;
86-
}
87-
8889
var patches = await GetPatchesAsync();
8990
if (patches == null)
9091
return false;

Wauncher/Utils/Api.cs

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ public class FriendInfo : INotifyPropertyChanged
5858
public string SteamId
5959
{
6060
get => _steamId;
61-
set { _steamId = value; OnPropertyChanged(); }
61+
// Only overwrite if new value is non-empty so steamid64 written first isn't erased
62+
// by a subsequent empty "steamid" field in the same JSON object.
63+
set { if (!string.IsNullOrWhiteSpace(value)) { _steamId = value; OnPropertyChanged(); } }
6264
}
6365

6466
[JsonProperty("steamid2")]
@@ -71,6 +73,16 @@ public string? SteamId2
7173
}
7274
}
7375

76+
[JsonProperty("steamid64")]
77+
public string? SteamId64
78+
{
79+
set
80+
{
81+
if (!string.IsNullOrWhiteSpace(value) && string.IsNullOrWhiteSpace(SteamId))
82+
SteamId = value;
83+
}
84+
}
85+
7486
[JsonProperty("username")]
7587
public string Username
7688
{
@@ -164,18 +176,26 @@ public class FriendsResponse
164176
public List<FriendInfo>? Friends { get; set; }
165177
}
166178

167-
public interface IEddies
179+
public class CCFriendsResponse
168180
{
169-
[Headers("User-Agent: ClassicCounter Wauncher")]
170-
[Get("/friendsapi.php")]
171-
Task<string> GetFriends([AliasAs("steamid64")] string steamId64);
181+
[JsonProperty("response")]
182+
public List<FriendInfo>? Response { get; set; }
183+
}
184+
185+
public class CCPlayerResponse
186+
{
187+
[JsonProperty("response")]
188+
public FriendInfo? Response { get; set; }
189+
}
172190

191+
public interface IClassicCounterProfiles
192+
{
173193
[Headers("User-Agent: ClassicCounter Wauncher")]
174-
[Get("/friendsapi.php")]
175-
Task<string> GetFriendsBySteamId2([AliasAs("steamid2")] string steamId2);
194+
[Get("/friends")]
195+
Task<string> GetFriends([AliasAs("steamid64")] string steamId64);
176196

177197
[Headers("User-Agent: ClassicCounter Wauncher")]
178-
[Get("/selfinfo.php")]
198+
[Get("/player")]
179199
Task<string> GetSelfInfo([AliasAs("steamid64")] string steamId64);
180200
}
181201

@@ -204,34 +224,36 @@ private static HttpClient TimedClient(string baseUrl, int timeoutSeconds = 12) =
204224

205225
public static IGitHub GitHub = RestService.For<IGitHub>(TimedClient("https://api.github.com", 8), _settings);
206226
public static IClassicCounter ClassicCounter = RestService.For<IClassicCounter>(TimedClient("https://classiccounter.cc/api"), _settings);
207-
public static IEddies Eddies = RestService.For<IEddies>("https://eddies.cc/api", _settings);
227+
public static IClassicCounterProfiles Profiles = RestService.For<IClassicCounterProfiles>(TimedClient("https://classiccounter.cc/api/profiles"), _settings);
208228

209229
public static List<FriendInfo> ParseFriendsPayload(string? json)
210230
{
211231
if (string.IsNullOrWhiteSpace(json))
212232
return new List<FriendInfo>();
213233

234+
try
235+
{
236+
var cc = JsonConvert.DeserializeObject<CCFriendsResponse>(json);
237+
if (cc?.Response != null && cc.Response.Count > 0)
238+
return NormalizeFriends(cc.Response);
239+
}
240+
catch { }
241+
214242
try
215243
{
216244
var wrapped = JsonConvert.DeserializeObject<FriendsResponse>(json);
217245
if (wrapped?.Friends != null && wrapped.Friends.Count > 0)
218246
return NormalizeFriends(wrapped.Friends);
219247
}
220-
catch
221-
{
222-
// Fall through to array parse.
223-
}
248+
catch { }
224249

225250
try
226251
{
227252
var flat = JsonConvert.DeserializeObject<List<FriendInfo>>(json);
228253
if (flat != null)
229254
return NormalizeFriends(flat);
230255
}
231-
catch
232-
{
233-
// Ignore and return empty.
234-
}
256+
catch { }
235257

236258
return new List<FriendInfo>();
237259
}
@@ -243,29 +265,47 @@ public static List<FriendInfo> ParseFriendsPayload(string? json)
243265

244266
try
245267
{
246-
var parsed = JsonConvert.DeserializeObject<FriendInfo>(json);
247-
if (parsed == null)
248-
return null;
249-
250-
return NormalizeFriends(new[] { parsed }).FirstOrDefault();
268+
var cc = JsonConvert.DeserializeObject<CCPlayerResponse>(json);
269+
if (cc?.Response != null)
270+
return NormalizeFriends(new[] { cc.Response }).FirstOrDefault();
251271
}
252-
catch
272+
catch { }
273+
274+
try
253275
{
254-
return null;
276+
var parsed = JsonConvert.DeserializeObject<FriendInfo>(json);
277+
if (parsed != null)
278+
return NormalizeFriends(new[] { parsed }).FirstOrDefault();
255279
}
280+
catch { }
281+
282+
return null;
256283
}
257284

258285
private static List<FriendInfo> NormalizeFriends(IEnumerable<FriendInfo> friends)
259286
{
260287
var normalized = new List<FriendInfo>();
288+
var usedKeys = new HashSet<string>(StringComparer.Ordinal);
289+
261290
foreach (var f in friends)
262291
{
263292
var username = string.IsNullOrWhiteSpace(f.Username) ? "Unknown" : f.Username;
264293
var status = NormalizeStatus(f.Status);
265294

295+
// Fall back to username as identity key when the API omits steamid.
296+
// Append an index suffix to guarantee uniqueness when two friends share a username.
297+
string key = !string.IsNullOrWhiteSpace(f.SteamId) ? f.SteamId : username;
298+
if (!usedKeys.Add(key))
299+
{
300+
int n = 1;
301+
string unique;
302+
while (!usedKeys.Add(unique = $"{key}#{n}")) n++;
303+
key = unique;
304+
}
305+
266306
normalized.Add(new FriendInfo
267307
{
268-
SteamId = f.SteamId ?? string.Empty,
308+
SteamId = key,
269309
Username = username,
270310
AvatarUrl = f.AvatarUrl ?? string.Empty,
271311
Status = status

Wauncher/Utils/Download.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,8 +773,10 @@ public static void Cleanup7zFiles()
773773
try
774774
{
775775
string directory = WauncherDirectory;
776-
var files = Directory.GetFiles(directory, "*.7z", SearchOption.AllDirectories)
777-
.Concat(Directory.GetFiles(directory, "*.7z.*", SearchOption.AllDirectories))
776+
777+
// Only target ClassicCounter split archives (ClassicCounter.7z.001, etc.)
778+
// Never scan broadly — the game folder could live inside a Downloads folder.
779+
var files = Directory.GetFiles(directory, "ClassicCounter.7z*", SearchOption.TopDirectoryOnly)
778780
.Distinct(StringComparer.OrdinalIgnoreCase);
779781

780782
foreach (string file in files)
@@ -783,14 +785,16 @@ public static void Cleanup7zFiles()
783785
{
784786
File.Delete(file);
785787
if (Debug.Enabled())
786-
Terminal.Debug($"Deleted .7z file: {file}");
788+
Terminal.Debug($"Deleted archive: {file}");
787789
}
788790
catch (Exception ex)
789791
{
790792
if (Debug.Enabled())
791-
Terminal.Debug($"Failed to delete .7z file {file}: {ex.Message}");
793+
Terminal.Debug($"Failed to delete archive {file}: {ex.Message}");
792794
}
793795
}
796+
797+
Delete7zaExecutable();
794798
}
795799
catch (Exception ex)
796800
{

Wauncher/Views/Controls/SettingsPanel.axaml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@
5050
<Style Selector="Button.compactActionBtn:disabled /template/ Border#PART_Border">
5151
<Setter Property="Background" Value="#686868" />
5252
</Style>
53+
<Style Selector="Button.compactActionBtn.danger /template/ Border#PART_Border">
54+
<Setter Property="Background" Value="#A82020" />
55+
</Style>
56+
<Style Selector="Button.compactActionBtn.danger:pointerover /template/ Border#PART_Border">
57+
<Setter Property="Background" Value="#C93030" />
58+
</Style>
59+
<Style Selector="Button.compactActionBtn.danger:pressed /template/ Border#PART_Border">
60+
<Setter Property="Background" Value="#8A1A1A" />
61+
</Style>
5362
</UserControl.Styles>
5463

5564
<Grid Background="{DynamicResource AppMainBackground}" MinHeight="415">
@@ -87,7 +96,10 @@
8796
<Rectangle Grid.Row="1" Fill="{DynamicResource AppDivider}" />
8897

8998
<!-- Vertical list of settings -->
90-
<StackPanel Grid.Row="2" VerticalAlignment="Center" Margin="40,10,40,10" Spacing="0">
99+
<ScrollViewer Grid.Row="2"
100+
HorizontalScrollBarVisibility="Disabled"
101+
VerticalScrollBarVisibility="Auto">
102+
<StackPanel VerticalAlignment="Center" Margin="40,10,40,10" Spacing="0">
91103

92104
<!-- Enable In-Game Inventory -->
93105
<Grid ColumnDefinitions="*,Auto" MinHeight="44">
@@ -158,7 +170,20 @@
158170
Classes="compactActionBtn" Click="AddToSteamButton_Click" Content="Add to Steam" />
159171
</Grid>
160172

173+
<Rectangle Height="1" Fill="{DynamicResource AppDivider}" />
174+
175+
<!-- Clear Download Cache -->
176+
<Grid ColumnDefinitions="*,Auto" MinHeight="44">
177+
<StackPanel Grid.Column="0" VerticalAlignment="Center">
178+
<TextBlock FontSize="13" FontWeight="SemiBold" Foreground="{DynamicResource AppPrimaryText}" Text="Clear Download Cache" />
179+
<TextBlock FontSize="11" Foreground="{DynamicResource AppMutedText}" Text="Delete leftover .7z files if an update got stuck." Margin="0,2,0,0" />
180+
</StackPanel>
181+
<Button x:Name="ClearCacheButton" Grid.Column="1" VerticalAlignment="Center"
182+
Classes="compactActionBtn danger" Click="ClearCacheButton_Click" Content="Clear Cache" />
183+
</Grid>
184+
161185
</StackPanel>
186+
</ScrollViewer>
162187

163188
<Rectangle Grid.Row="3" Fill="{DynamicResource AppDivider}" />
164189

Wauncher/Views/Controls/SettingsPanel.axaml.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,31 @@ private async void AddToSteamButton_Click(object? sender, RoutedEventArgs e)
103103
}
104104
}
105105

106+
private async void ClearCacheButton_Click(object? sender, RoutedEventArgs e)
107+
{
108+
if (sender is not Button btn)
109+
return;
110+
111+
btn.IsEnabled = false;
112+
btn.Content = "Clearing...";
113+
114+
try
115+
{
116+
await Task.Run(DownloadManager.Cleanup7zFiles);
117+
btn.Content = "Cleared!";
118+
}
119+
catch
120+
{
121+
btn.Content = "Failed";
122+
}
123+
finally
124+
{
125+
await Task.Delay(2000);
126+
btn.Content = "Clear Cache";
127+
btn.IsEnabled = true;
128+
}
129+
}
130+
106131
private async Task RefreshSteamButtonStateAsync()
107132
{
108133
if (AddToSteamButton == null)

0 commit comments

Comments
 (0)