Skip to content

Commit

Permalink
Add experimental method for importing EA App games
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkeye116477 committed Nov 19, 2024
1 parent 5a6e5c6 commit 1faea1d
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 12 deletions.
23 changes: 22 additions & 1 deletion src/LegendaryGameInstaller.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ private async void LegendaryGameInstallerUC_Loaded(object sender, RoutedEventArg
Directory.CreateDirectory(cacheInfoPath);
}

var eaAppGames = new List<string>();
var ubisoftOnlyGames = new List<string>();
var ubisoftRecommendedGames = new List<string>();
var downloadItemsAlreadyAdded = new List<string>();
Expand Down Expand Up @@ -244,6 +245,15 @@ private async void LegendaryGameInstallerUC_Loaded(object sender, RoutedEventArg
App_name = installData.gameID,
};
manifest = await LegendaryLauncher.GetGameInfo(gameData);
if (manifest.Game != null)
{
if (!manifest.Game.External_activation.IsNullOrEmpty() && (manifest.Game.External_activation.ToLower() == "origin" || manifest.Game.External_activation.ToLower() == "the ea app"))
{
eaAppGames.Add(installData.name);
MultiInstallData.Remove(installData);
continue;
}
}
if (manifest != null && manifest.Manifest != null && manifest.Game != null && !manifest.errorDisplayed)
{
Dictionary<string, LegendarySDLInfo> extraContentInfo = await LegendaryLauncher.GetExtraContentInfo(installData);
Expand Down Expand Up @@ -447,6 +457,18 @@ private async void LegendaryGameInstallerUC_Loaded(object sender, RoutedEventArg
GamesBrd.Visibility = Visibility.Visible;
}

if (eaAppGames.Count > 0)
{
if (eaAppGames.Count == 1)
{
playniteAPI.Dialogs.ShowErrorMessage(string.Format(ResourceProvider.GetString(LOC.Legendary3P_PlayniteGameInstallError), ResourceProvider.GetString(LOC.LegendaryRequiredInstallViaThirdPartyLauncherError).Format("EA App", eaAppGames[0])));
}
else
{
string eaAppGamesCombined = string.Join(", ", eaAppGames.Select(item => item.ToString()));
playniteAPI.Dialogs.ShowErrorMessage(ResourceProvider.GetString(LOC.LegendaryRequiredInstallViaThirdPartyLauncherErrorOther).Format("EA App", eaAppGamesCombined));
}
}
if (ubisoftOnlyGames.Count > 0)
{
if (ubisoftOnlyGames.Count == 1)
Expand All @@ -458,7 +480,6 @@ private async void LegendaryGameInstallerUC_Loaded(object sender, RoutedEventArg
string ubisoftOnlyGamesCombined = string.Join(", ", ubisoftOnlyGames.Select(item => item.ToString()));
playniteAPI.Dialogs.ShowErrorMessage(ResourceProvider.GetString(LOC.LegendaryRequiredInstallViaThirdPartyLauncherErrorOther).Format("Ubisoft Connect", ubisoftOnlyGamesCombined));
}

}
if (ubisoftRecommendedGames.Count > 0)
{
Expand Down
4 changes: 2 additions & 2 deletions src/LegendaryLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ public static async Task<Dictionary<string, LegendarySDLInfo>> GetExtraContentIn
{
return extraContentInfo;
}
if (manifest.Manifest.Install_tags.Count > 1)
if (manifest.Manifest != null && manifest.Manifest.Install_tags.Count > 1)
{
var cacheSDLPath = LegendaryLibrary.Instance.GetCachePath("sdlcache");
if (!Directory.Exists(cacheSDLPath))
Expand Down Expand Up @@ -589,7 +589,7 @@ public static async Task<Dictionary<string, LegendarySDLInfo>> GetExtraContentIn
}
}
}
if (manifest.Game.Owned_dlc.Count > 0)
if (manifest.Game != null && manifest.Game.Owned_dlc.Count > 0)
{
foreach (var dlc in manifest.Game.Owned_dlc.OrderBy(obj => obj.Title))
{
Expand Down
18 changes: 16 additions & 2 deletions src/LegendaryLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ internal async Task<List<GameMetadata>> GetLibraryGames(CancellationToken cancel
Logger.Warn("Found no assets on Epic accounts.");
}

if (GetSettings().ImportEALauncherGames)
{
var ignoreList = new List<string>();
foreach (var gameAsset in assets.Where(a => a.@namespace != "ue"))
{
ignoreList.Add(gameAsset.appName);
}
var nonAssets = await accountApi.GetLibraryItems(ignoreList);
assets.AddRange(nonAssets);
}

var playtimeItems = await accountApi.GetPlaytimeItems();
foreach (var gameAsset in assets.Where(a => a.@namespace != "ue"))
{
Expand All @@ -165,9 +176,12 @@ internal async Task<List<GameMetadata>> GetLibraryGames(CancellationToken cancel
continue;
}

if ((catalogItem?.customAttributes?.ThirdPartyManagedApp != null) && (catalogItem?.customAttributes?.ThirdPartyManagedApp.value.ToLower() == "the ea app"))
if (!GetSettings().ImportEALauncherGames)
{
continue;
if ((catalogItem?.customAttributes?.ThirdPartyManagedApp != null) && (catalogItem?.customAttributes?.ThirdPartyManagedApp.value.ToLower() == "the ea app" || catalogItem?.customAttributes?.ThirdPartyManagedApp.value.ToLower() == "origin"))
{
continue;
}
}

if (!GetSettings().ImportUbisoftLauncherGames)
Expand Down
1 change: 1 addition & 0 deletions src/LegendaryLibrary.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
<Compile Include="Models\LegendaryGameInfo.cs" />
<Compile Include="Models\LegendaryMetadata.cs" />
<Compile Include="Models\LegendarySDLInfo.cs" />
<Compile Include="Models\LibraryItemsResponse.cs" />
<Compile Include="Models\OverlayVersion.cs" />
<Compile Include="Models\Prerequisite.cs" />
<Compile Include="Models\UpdateInfo.cs" />
Expand Down
4 changes: 4 additions & 0 deletions src/LegendaryLibrarySettingsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
IsChecked="{Binding Settings.ImportUbisoftLauncherGames}"
Content="Ubisoft Connect" ContentStringFormat="{DynamicResource LOCLegendaryImportThirdPartyLauncherGames}" Margin="0,10,0,0" Click="ImportUbisoftLauncherGamesChk_Click" IsEnabled="{Binding IsChecked, ElementName=EpicImportUninstalledChk}" />

<CheckBox DockPanel.Dock="Top" Name="ImportEALauncherGamesChk"
IsChecked="{Binding Settings.ImportEALauncherGames}"
Content="EA App" ContentStringFormat="{DynamicResource LOCLegendaryImportThirdPartyLauncherGames}" Margin="0,10,0,0" IsEnabled="{Binding IsChecked, ElementName=EpicImportUninstalledChk}" Click="ImportEALauncherGamesChk_Click" />

<StackPanel Orientation="Horizontal"
DockPanel.Dock="Top" Margin="0,15,5,5" HorizontalAlignment="Left">
<ToggleButton HorizontalAlignment="Left" Name="LoginBtn" Content="{DynamicResource LOCLegendary3P_EpicAuthenticateLabel}" IsEnabled="False" Click="LoginBtn_Click" IsChecked="False"/>
Expand Down
8 changes: 8 additions & 0 deletions src/LegendaryLibrarySettingsView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -637,5 +637,13 @@ private void ImportUbisoftLauncherGamesChk_Click(object sender, RoutedEventArgs
playniteAPI.Dialogs.ShowMessage(ResourceProvider.GetString(LOC.LegendaryThirdPartyLauncherImportWarn).Format("Ubisoft Connect"), "", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}

private void ImportEALauncherGamesChk_Click(object sender, RoutedEventArgs e)
{
if (ImportEALauncherGamesChk.IsChecked == true)
{
playniteAPI.Dialogs.ShowMessage(ResourceProvider.GetString(LOC.LegendaryThirdPartyLauncherImportWarn).Format("EA App"), "", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}
}
1 change: 1 addition & 0 deletions src/LegendaryLibrarySettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class LegendaryLibrarySettings
public bool ConnectAccount { get; set; } = false;
public bool ImportUninstalledGames { get; set; } = false;
public bool ImportUbisoftLauncherGames { get; set; } = false;
public bool ImportEALauncherGames { get; set; } = false;
public string SelectedLauncherPath { get; set; } = "";
public string GamesInstallationPath { get; set; } = "";
public bool LaunchOffline { get; set; } = false;
Expand Down
9 changes: 2 additions & 7 deletions src/Models/AssetsResponse.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LegendaryLibraryNS.Models
namespace LegendaryLibraryNS.Models
{
public class Asset
{
Expand All @@ -14,5 +8,6 @@ public class Asset
public string catalogItemId;
public string @namespace;
public string assetId;
public string sandboxType;
}
}
1 change: 1 addition & 0 deletions src/Models/LegendaryGameInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class Game
public string Cloud_save_folder { get; set; }
public bool Is_dlc { get; set; }
public List<Owned_Dlc> Owned_dlc { get; set; } = new List<Owned_Dlc>();
public string External_activation { get; set; } = "";
}

public class Owned_Dlc
Expand Down
16 changes: 16 additions & 0 deletions src/Models/LibraryItemsResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;

namespace LegendaryLibraryNS.Models
{
public class LibraryItemsResponse
{
public Responsemetadata responseMetadata { get; set; } = new Responsemetadata();
public List<Asset> records { get; set; }

public class Responsemetadata
{
public string nextCursor { get; set; }
public string stateToken { get; set; }
}
}
}
30 changes: 30 additions & 0 deletions src/Services/EpicAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -37,6 +38,7 @@ public class EpicAccountClient
private readonly string assetsUrl = @"";
private readonly string catalogUrl = @"";
private readonly string playtimeUrl = @"";
private readonly string libraryItemsUrl = @"";
private const string authEncodedString = "MzRhMDJjZjhmNDQxNGUyOWIxNTkyMTg3NmRhMzZmOWE6ZGFhZmJjY2M3Mzc3NDUwMzlkZmZlNTNkOTRmYzc2Y2Y=";
private const string userAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Vivaldi/5.5.2805.50";

Expand All @@ -46,6 +48,7 @@ public EpicAccountClient(IPlayniteAPI api)
tokensPath = LegendaryLauncher.TokensPath;
var oauthUrlMask = @"https://{0}/account/api/oauth/token";
var accountUrlMask = @"https://{0}/account/api/public/account/";
var libraryItemsUrlMask = @"https://{0}/library/api/public/items?includeMetadata=true";
var assetsUrlMask = @"https://{0}/launcher/api/public/assets/Windows?label=Live";
var catalogUrlMask = @"https://{0}/catalog/api/shared/namespace/";
var playtimeUrlMask = @"https://{0}/library/api/public/playtime/account/{1}/all";
Expand All @@ -59,6 +62,7 @@ public EpicAccountClient(IPlayniteAPI api)
assetsUrl = string.Format(assetsUrlMask, "launcher-public-service-prod06.ol.epicgames.com");
catalogUrl = string.Format(catalogUrlMask, "catalog-public-service-prod06.ol.epicgames.com");
playtimeUrl = string.Format(playtimeUrlMask, "library-service.live.use1a.on.epicgames.com", "{0}");
libraryItemsUrl = string.Format(libraryItemsUrlMask, "library-service.live.use1a.on.epicgames.com");
}
}

Expand Down Expand Up @@ -195,6 +199,32 @@ public async Task<List<Asset>> GetAssets()
return response.Item2;
}


public async Task<List<Asset>> GetLibraryItems(List<string> ignoreList)
{
if (!await GetIsUserLoggedIn())
{
throw new Exception("User is not authenticated.");
}

var response = await InvokeRequest<LibraryItemsResponse>(libraryItemsUrl, LoadTokens());
var assets = new List<Asset>();
assets.AddRange(response.Item2.records);
while (response.Item2.responseMetadata.nextCursor != null)
{
response = await InvokeRequest<LibraryItemsResponse>($"{libraryItemsUrl}?includeMetadata=true&cursor={response.Item2.responseMetadata.nextCursor}", LoadTokens());
assets.AddRange(response.Item2.records);
}
foreach (var asset in assets.ToList())
{
if (asset.appName.IsNullOrEmpty() || ignoreList.Contains(asset.appName) || asset.sandboxType == "PRIVATE")
{
assets.Remove(asset);
}
}
return assets;
}

public async Task<List<PlaytimeItem>> GetPlaytimeItems()
{
if (!await GetIsUserLoggedIn())
Expand Down

0 comments on commit 1faea1d

Please sign in to comment.