Skip to content

Commit cbb17da

Browse files
authored
Merge pull request #2737 from wabbajack-tools/4.0.0.3
4.0.0.3
2 parents ea84222 + 372935f commit cbb17da

File tree

12 files changed

+119
-56
lines changed

12 files changed

+119
-56
lines changed

Diff for: CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
### Changelog
22

3+
#### Version - 4.0.0.3 - 3/20/2025
4+
* Fixed the open logs folder button not actually opening the logs folder on a failed installation
5+
* Fixed the missing manual report incorrectly listing Nexus files
6+
* The missing manual report will now be generated with clickable links to the Wabbajack downloads folder
7+
* Added MEGA anonymous login feature
8+
* This was previously available in older Wabbajack 3.7 versions, but it broke due to MEGA introducing a new security feature to protect against bots.
9+
* I was looking at fixing this up so the anonymous login would work again, but to my surprise it worked straight away without making any changes.
10+
* Thus, both the option to use an account and the option to use the anonymous login have now been made available within the MEGA login menu.
11+
* Adjusted wording of 'failed to download' to 'failed to source' in the description for a failed download installation error, since certain files (game files) aren't actually downloaded
12+
13+
314
#### Version - 4.0.0.2 - 3/19/2025
415
* Fixed an issue where previous installation paths might not be remembered correctly
516
* From this version onwards, Wabbajack will additionally remember previous installations by .wabbajack filename instead of only by the full install path being the same

Diff for: Wabbajack.App.Wpf/LoginManagers/Icons/mega-text.png

13.7 KB
Loading

Diff for: Wabbajack.App.Wpf/LoginManagers/MegaLoginManager.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public MegaLoginManager(ILogger<MegaLoginManager> logger, ITokenProvider<MegaTok
6969
});
7070

7171
MessageBus.Current.Listen<LoggedIntoMega>()
72-
.Subscribe(async (loggedIntoMega) => await UpdateToken(loggedIntoMega.Login))
72+
.Subscribe(async (loggedIntoMega) => await UpdateToken(loggedIntoMega?.Login))
7373
.DisposeWith(CompositeDisposable);
7474

7575
LoggedIn = _token.HaveToken();
@@ -97,7 +97,6 @@ private void StartLogin()
9797

9898
private async Task UpdateToken(AuthInfos login)
9999
{
100-
MegaToken token = null;
101100
try
102101
{
103102
await _token.SetToken(new MegaToken() { Login = login });

Diff for: Wabbajack.App.Wpf/Util/InstallResultHelper.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static string GetDescription(this InstallResult result)
2727
InstallResult.Errored => "The modlist installation has failed because of an unknown error. Check the log for more information.",
2828
InstallResult.GameMissing => "The modlist installation has failed because the game could not be found. Please make sure a valid copy of the game is installed.",
2929
InstallResult.GameInvalid => "The modlist installation has failed because not all required game files could be found. Verify all game files are present and retry installation.",
30-
InstallResult.DownloadFailed => "The modlist installation has failed because one or more required files could not be downloaded. Try manually placing these files in the downloads directory.",
30+
InstallResult.DownloadFailed => "The modlist installation has failed because one or more required files could not be sourced. Try manually sourcing these files below.",
3131
InstallResult.NotEnoughSpace => "The modlist installation has failed because not enough free space was available on the disk. Please free up enough space and retry the installation.",
3232
_ => ""
3333
};

Diff for: Wabbajack.App.Wpf/ViewModels/Installers/InstallationVM.cs

+19-13
Original file line numberDiff line numberDiff line change
@@ -723,29 +723,30 @@ private void ShowMissingManualReport(Archive[] toArray)
723723
{
724724
_logger.LogInformation("Writing Manual helper report");
725725
var report = Installer.DownloadLocation.TargetPath.Combine("MissingManuals.html");
726+
var downloadsPath = Installer.DownloadLocation.TargetPath;
726727
{
727728
using var writer = new StreamWriter(report.Open(FileMode.Create, FileAccess.Write, FileShare.None));
728729
writer.Write("<html><head><title>Missing Files</title></head><body>");
729730
writer.Write("<h1>Missing Files</h1>");
730731
writer.Write(
731-
"<p>Wabbajack was unable to download the following files automatically. Please take manual action on the following files. You might find more information on these files in the modlist readme and/or Discord server.</p>");
732+
"<p>Wabbajack was unable to source the following files automatically. Please take manual action on the following files. You might find more information on these files in the modlist readme and/or Discord server.</p>");
732733
foreach (var archive in toArray)
733734
{
734735
switch (archive.State)
735736
{
736737
case Manual manual:
737-
writer.Write($"<h3>{archive.Name}</h1>");
738+
writer.Write($"<h3>{archive.Name} (Manual)</h3>");
738739
writer.Write($"<p>{manual.Prompt}</p>");
739-
writer.Write($"<p>Put this file inside your Wabbajack downloads folder.</p>");
740+
writer.Write($"<p>Put this file inside <a href='{Installer.DownloadLocation.TargetPath}'>your Wabbajack downloads folder.</a></p>");
740741
writer.Write($"<p>Download URL: <a href=\"{manual.Url}\">{manual.Url}</a></p>");
741742
break;
742743
case MediaFire mediaFire:
743-
writer.Write($"<h3>{archive.Name}</h1>");
744-
writer.Write($"<p>Put this file inside your Wabbajack downloads folder.</p>");
744+
writer.Write($"<h3>{archive.Name} (MediaFire)</h3>");
745+
writer.Write($"<p>Put this file inside <a href='{Installer.DownloadLocation.TargetPath}'>your Wabbajack downloads folder.</a></p>");
745746
writer.Write($"<p>Download URL: <a href=\"{mediaFire.Url}\">{mediaFire.Url}</a></p>");
746747
break;
747748
case GameFileSource gameFile:
748-
writer.Write($"<h3>{archive.Name}</h3>");
749+
writer.Write($"<h3>{archive.Name} (Game File)</h3>");
749750
if(archive.Name.Contains("CreationKit"))
750751
{
751752
writer.Write($"<p>This modlist requires the Creation Kit to function.</p>");
@@ -778,23 +779,28 @@ private void ShowMissingManualReport(Archive[] toArray)
778779
break;
779780

780781
case Mega mega:
781-
writer.Write($"<h3>MEGA: {archive.Name}</h3>");
782-
writer.Write($"<p>Please <a href='{mega.Url.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside the Wabbajack downloads directory.</p>");
782+
writer.Write($"<h3>{archive.Name} (MEGA)</h3>");
783+
writer.Write($"<p>Please <a href='{mega.Url.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside <a href='{Installer.DownloadLocation.TargetPath}'>the Wabbajack downloads directory.</a></p>");
783784
break;
784785

785786
case IPS4OAuth2 ips4:
786-
writer.Write($"<h3>IPS4OAuth2: {ips4.Name}</h3>");
787-
writer.Write($"<p>Please <a href='{ips4.LinkUrl.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside the Wabbajack downloads directory.</p>");
787+
writer.Write($"<h3>{ips4.Name} (IPS4OAuth2)</h3>");
788+
writer.Write($"<p>Please <a href='{ips4.LinkUrl.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside <a href='{Installer.DownloadLocation.TargetPath}'>the Wabbajack downloads directory.</a></p>");
788789
break;
789790

790791
case GoogleDrive gd:
791-
writer.Write($"<h3>Google Drive ID: {gd.Id}</h3>");
792-
writer.Write($"<p>Please <a href='{gd.GetUri().ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside the Wabbajack downloads directory.</p>");
792+
writer.Write($"<h3>Google Drive: {gd.Id}</h3>");
793+
writer.Write($"<p>Please <a href='{gd.GetUri().ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside <a href='{Installer.DownloadLocation.TargetPath}'>the Wabbajack downloads directory.</a></p>");
793794
break;
794795

795796
case Http http:
796797
writer.Write($"<h3>Direct download: {http.PrimaryKeyString}</h3>");
797-
writer.Write($"<p>Please <a href='{http.Url.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside the Wabbajack downloads directory.</p>");
798+
writer.Write($"<p>Please <a href='{http.Url.ToString()}' target='_blank'>click here to download this file</a>, then manually place it inside <a href='{Installer.DownloadLocation.TargetPath}'>the Wabbajack downloads directory.</a></p>");
799+
break;
800+
801+
case Nexus nexus:
802+
writer.Write($"<h3>{nexus.Description} (NexusMods)");
803+
writer.Write($"<p>Please <a href='{nexus.LinkUrl}' target='_blank'>click here to download this file</a>, then manually place it inside <a href='{Installer.DownloadLocation.TargetPath}'>the Wabbajack downloads directory.</a></p>");
798804
break;
799805

800806
default:

Diff for: Wabbajack.App.Wpf/ViewModels/Interventions/MegaLoginVM.cs

+19-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class MegaLoginVM : ViewModel
2929

3030
public ICommand CloseCommand { get; }
3131
public ICommand LoginCommand { get; }
32+
public ICommand LoginAnonymouslyCommand { get; }
3233

3334
[Reactive] public double UploadProgress { get; set; }
3435
[Reactive] public string FileUrl { get; set; }
@@ -53,19 +54,26 @@ public MegaLoginVM(ILogger<MegaLoginVM> logger, MegaTokenProvider tokenProvider,
5354
ShowFloatingWindow.Send(FloatingScreenType.None);
5455
});
5556

56-
LoginCommand = ReactiveCommand.Create(async () =>
57+
LoginCommand = ReactiveCommand.Create(async (bool anonymous) =>
5758
{
5859
TriedLoggingIn = true;
5960
LoggingIn = true;
60-
// Since the login task can gets stuck on a failed login, cancel the login task if it hasn't returned after 10s
61+
// Since the login task can gets stuck on a failed login, cancel the login task if it hasn't returned after 30s
6162
using var tokenSource = new CancellationTokenSource();
6263
tokenSource.CancelAfter(TimeSpan.FromSeconds(30));
63-
Task<(AuthInfos Auth, LogonSessionToken Login)> loginTask = DoLogin(tokenSource.Token);
6464
try
6565
{
66-
var loginDetails = await loginTask;
66+
if (anonymous)
67+
{
68+
await DoLoginAnonymously(tokenSource.Token);
69+
LoggedIntoMega.Send(null);
70+
}
71+
else
72+
{
73+
var (auth, loginToken) = await DoLogin(tokenSource.Token);
74+
LoggedIntoMega.Send(auth);
75+
}
6776
LoginSuccessful = true;
68-
LoggedIntoMega.Send(loginDetails.Auth);
6977

7078
// To show the user they're logged in before closing
7179
await Task.Delay(500);
@@ -85,6 +93,8 @@ public MegaLoginVM(ILogger<MegaLoginVM> logger, MegaTokenProvider tokenProvider,
8593
}
8694
}, this.WhenAnyValue(vm => vm.LoggingIn, loggingIn => !loggingIn));
8795

96+
LoginAnonymouslyCommand = ReactiveCommand.Create(() => LoginCommand.Execute(true), this.WhenAnyValue(vm => vm.LoggingIn, loggingIn => !loggingIn));
97+
8898
this.WhenActivated(disposables =>
8999
{
90100
TriedLoggingIn = false;
@@ -98,4 +108,8 @@ public MegaLoginVM(ILogger<MegaLoginVM> logger, MegaTokenProvider tokenProvider,
98108
var auth = await _apiClient.GenerateAuthInfosAsync(Email, Password).WaitAsync(token);
99109
return (auth, await _apiClient.LoginAsync(auth).WaitAsync(token));
100110
}
111+
private async Task DoLoginAnonymously(CancellationToken token)
112+
{
113+
await _apiClient.LoginAnonymousAsync().WaitAsync(token);
114+
}
101115
}

Diff for: Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public InstallationView()
101101
break;
102102

103103
default:
104-
StoppedButton.Command = ViewModel.OpenInstallFolderCommand;
104+
StoppedButton.Command = ViewModel.OpenLogFolderCommand;
105105
StoppedButton.Icon = Symbol.FolderOpen;
106106
StoppedButton.Text = "Open Logs Folder";
107107
break;

Diff for: Wabbajack.App.Wpf/Views/Interventions/MegaLoginView.xaml

+56-31
Original file line numberDiff line numberDiff line change
@@ -34,46 +34,71 @@
3434
<ic:SymbolIcon Symbol="Dismiss" FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Right" />
3535
</Button>
3636

37-
<Image x:Name="MegaImage" Grid.Row="2" Source="pack://application:,,,/LoginManagers/Icons/mega.png" Width="64" Height="64" />
38-
<Grid Grid.Row="4" VerticalAlignment="Center" Width="{Binding Converter={StaticResource MathConverter}, ConverterParameter=x/3, ElementName=AuthorFiles, Path=ActualWidth}">
39-
<Grid.RowDefinitions>
40-
<RowDefinition Height="Auto" />
41-
<RowDefinition Height="4" />
42-
<RowDefinition Height="Auto" />
43-
<RowDefinition Height="16" />
44-
<RowDefinition Height="Auto" />
45-
<RowDefinition Height="4" />
46-
<RowDefinition Height="Auto" />
47-
<RowDefinition Height="16" />
48-
<RowDefinition Height="Auto" />
49-
<RowDefinition Height="16" />
50-
<RowDefinition Height="Auto" />
51-
</Grid.RowDefinitions>
52-
<TextBlock Text="E-mail" Grid.Row="0" />
53-
<TextBox Grid.Row="2" mahapps:TextBoxHelper.Watermark="Enter e-mail..." Text="{Binding Email}" />
54-
<TextBlock Text="Password" Grid.Row="4" />
55-
<PasswordBox x:Name="PasswordBox" Grid.Row="6" PasswordChanged="PasswordBox_PasswordChanged" />
56-
<local:WJButton x:Name="LoginButton" Grid.Row="8" Text="Login" Icon="PersonArrowRight" Width="Auto" ButtonStyle="Color" />
57-
<Border x:Name="StatusBorder" Grid.Row="10" Padding="12" Background="{StaticResource PrimaryBrush}" CornerRadius="8">
58-
<Grid x:Name="StatusGrid">
59-
<Grid.ColumnDefinitions>
60-
<ColumnDefinition Width="Auto" />
61-
<ColumnDefinition Width="*" />
62-
<ColumnDefinition Width="Auto" />
63-
</Grid.ColumnDefinitions>
64-
<ic:SymbolIcon x:Name="StatusIcon"
37+
<Image x:Name="MegaImage" Grid.Row="2" Source="pack://application:,,,/LoginManagers/Icons/mega-text.png" Width="Auto" Height="64" />
38+
<Grid Grid.Row="4" VerticalAlignment="Center">
39+
<Grid.ColumnDefinitions>
40+
<ColumnDefinition Width="*" />
41+
<ColumnDefinition Width="Auto" />
42+
<ColumnDefinition Width="Auto" />
43+
<ColumnDefinition Width="Auto" />
44+
<ColumnDefinition Width="*" />
45+
</Grid.ColumnDefinitions>
46+
47+
<Grid Grid.Column="1" Width="{Binding Converter={StaticResource MathConverter}, ConverterParameter=x/3, ElementName=AuthorFiles, Path=ActualWidth}">
48+
<Grid.RowDefinitions>
49+
<RowDefinition Height="Auto" />
50+
<RowDefinition Height="4" />
51+
<RowDefinition Height="Auto" />
52+
<RowDefinition Height="16" />
53+
<RowDefinition Height="Auto" />
54+
<RowDefinition Height="4" />
55+
<RowDefinition Height="Auto" />
56+
<RowDefinition Height="16" />
57+
<RowDefinition Height="Auto" />
58+
<RowDefinition Height="16" />
59+
<RowDefinition Height="Auto" />
60+
<RowDefinition Height="8" />
61+
<RowDefinition Height="Auto" />
62+
</Grid.RowDefinitions>
63+
64+
<!-- Normal login -->
65+
<TextBlock Text="E-mail" Grid.Row="0" />
66+
<TextBox Grid.Row="2" mahapps:TextBoxHelper.Watermark="Enter e-mail..." Text="{Binding Email}" />
67+
<TextBlock Text="Password" Grid.Row="4" />
68+
<PasswordBox x:Name="PasswordBox" Grid.Row="6" PasswordChanged="PasswordBox_PasswordChanged" />
69+
<local:WJButton x:Name="LoginButton" Grid.Row="8" Text="Login" Icon="PersonArrowRight" Width="Auto" ButtonStyle="Color" />
70+
<Border x:Name="StatusBorder" Grid.Row="10" Padding="12" Background="{StaticResource PrimaryBrush}" CornerRadius="8">
71+
<Grid x:Name="StatusGrid">
72+
<Grid.ColumnDefinitions>
73+
<ColumnDefinition Width="Auto" />
74+
<ColumnDefinition Width="*" />
75+
<ColumnDefinition Width="Auto" />
76+
</Grid.ColumnDefinitions>
77+
<ic:SymbolIcon x:Name="StatusIcon"
6578
Grid.Column="0"
6679
Symbol="ArrowCounterclockwise"
6780
FontSize="24"
6881
Foreground="{StaticResource DarkBackgroundBrush}"
6982
VerticalAlignment="Center" />
70-
<TextBlock x:Name="StatusText"
83+
<TextBlock x:Name="StatusText"
7184
Grid.Column="2"
7285
Text="Logging in..."
7386
Foreground="{StaticResource DarkBackgroundBrush}"
7487
VerticalAlignment="Center"/>
75-
</Grid>
76-
</Border>
88+
</Grid>
89+
</Border>
90+
<TextBlock Grid.Row="12" Foreground="{StaticResource ForegroundBrush}" Opacity="0.66" >
91+
<ic:SymbolIcon Width="13" Height="13" FontSize="14" Symbol="Warning" VerticalAlignment="Center" Margin="0, 4, 2, 0" />
92+
<Run Text="Please note that 2FA logins will not work as they are currently unsupported." BaselineAlignment="Center" />
93+
</TextBlock>
94+
</Grid>
95+
96+
<TextBlock Grid.Column="2" Padding="16, 0, 16, 0" FontSize="24" VerticalAlignment="Center" Text="or..." Foreground="{StaticResource DisabledButtonForeground}" />
97+
98+
<Grid Grid.Column="3" Width="{Binding Converter={StaticResource MathConverter}, ConverterParameter=x/3, ElementName=AuthorFiles, Path=ActualWidth}">
99+
<!-- Normal login -->
100+
<local:WJButton x:Name="LoginAnonymouslyButton" Text="Login anonymously" Icon="PersonArrowRight" Width="Auto" ButtonStyle="Color" />
101+
</Grid>
77102
</Grid>
78103
</Grid>
79104
</Border>

Diff for: Wabbajack.App.Wpf/Views/Interventions/MegaLoginView.xaml.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public MegaLoginView()
1919
{
2020
InitializeComponent();
2121

22-
MegaImage.Source = BitmapFrame.Create(typeof(MegaLoginManager).Assembly.GetManifestResourceStream("Wabbajack.App.Wpf.LoginManagers.Icons.mega.png")!);
22+
MegaImage.Source = BitmapFrame.Create(typeof(MegaLoginManager).Assembly.GetManifestResourceStream("Wabbajack.App.Wpf.LoginManagers.Icons.mega-text.png")!);
2323

2424
this.WhenActivated(disposables =>
2525
{
@@ -30,6 +30,9 @@ public MegaLoginView()
3030
this.BindCommand(ViewModel, vm => vm.LoginCommand, v => v.LoginButton)
3131
.DisposeWith(disposables);
3232

33+
this.BindCommand(ViewModel, vm => vm.LoginAnonymouslyCommand, v => v.LoginAnonymouslyButton)
34+
.DisposeWith(disposables);
35+
3336
ViewModel.WhenAnyValue(vm => vm.LoginSuccessful)
3437
.Subscribe(success =>
3538
{

0 commit comments

Comments
 (0)