Skip to content

Commit

Permalink
Add Epic achievements #121
Browse files Browse the repository at this point in the history
  • Loading branch information
Lacro59 committed Oct 24, 2021
1 parent 54c1914 commit e3046ae
Show file tree
Hide file tree
Showing 12 changed files with 499 additions and 8 deletions.
269 changes: 269 additions & 0 deletions source/Clients/EpicAchievements.cs
@@ -0,0 +1,269 @@
using CommonPlayniteShared.Common;
using CommonPlayniteShared.PluginLibrary.EpicLibrary;
using CommonPlayniteShared.PluginLibrary.EpicLibrary.Services;
using CommonPluginsShared;
using CommonPluginsShared.Models;
using Playnite.SDK.Data;
using Playnite.SDK.Models;
using SuccessStory.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace SuccessStory.Clients
{
class EpicAchievements : GenericAchievements
{
protected static EpicAccountClient _EpicAPI;
internal static EpicAccountClient EpicAPI
{
get
{
if (_EpicAPI == null)
{
_EpicAPI = new EpicAccountClient(
PluginDatabase.PlayniteApi,
PluginDatabase.Paths.PluginUserDataPath + "\\..\\00000002-DBD1-46C6-B5D0-B1BA559D10E4\\tokens.json"
);
}
return _EpicAPI;
}

set
{
_EpicAPI = value;
}
}

private const string UrlAchievements = @"https://www.epicgames.com/store/{0}/achievements/{1}";


public EpicAchievements() : base("Epic", CodeLang.GetGogLang(PluginDatabase.PlayniteApi.ApplicationSettings.Language))
{

}


public override GameAchievements GetAchievements(Game game)
{
GameAchievements gameAchievements = SuccessStory.PluginDatabase.GetDefault(game);
List<Achievements> AllAchievements = new List<Achievements>();


string Url = string.Empty;
string ResultWeb = string.Empty;


if (IsConnected())
{
try
{
var tokens = EpicAPI.loadTokens();

string ProductSlug = GetProductSlug(game.Name);
Url = string.Format(UrlAchievements, LocalLang, ProductSlug);

ResultWeb = Web.DownloadStringData(Url, tokens.access_token).GetAwaiter().GetResult();
}
catch (Exception ex)
{
if (ex.Message.Contains("404"))
{
logger.Warn($"Error 404 for {game.Name}");
}
else
{
ShowNotificationPluginError(ex);
}

return gameAchievements;
}

if (ResultWeb != string.Empty && !ResultWeb.Contains("<span>404</span>", StringComparison.InvariantCultureIgnoreCase))
{
try
{
int indexStart = ResultWeb.IndexOf("window.__REACT_QUERY_INITIAL_QUERIES__ =");
int indexEnd = ResultWeb.IndexOf("window.server_rendered");

int length = ResultWeb.Length
- (indexStart + "window.__REACT_QUERY_INITIAL_QUERIES__ =".Length)
- (ResultWeb.Length - indexEnd);


string JsonDataString = ResultWeb.Substring(
indexStart + "window.__REACT_QUERY_INITIAL_QUERIES__ =".Length,
length
);


indexEnd = JsonDataString.IndexOf(";");
length = JsonDataString.Length - (JsonDataString.Length - indexEnd);
JsonDataString = JsonDataString.Substring(0, length);


EpicData epicData = Serialization.FromJson<EpicData>(JsonDataString);


// Achievements data
var achievemenstData = epicData.queries
.Where(x => (Serialization.ToJson(x.state.data)).Contains("\"achievements\":[{\"achievement\"", StringComparison.InvariantCultureIgnoreCase))
.FirstOrDefault();

EpicAchievementsData epicAchievementsData = Serialization.FromJson<EpicAchievementsData>(Serialization.ToJson(achievemenstData.state.data));

if (epicAchievementsData != null && epicAchievementsData.Achievement.productAchievementsRecordBySandbox.achievements?.Count > 0)
{
foreach (var ach in epicAchievementsData.Achievement.productAchievementsRecordBySandbox.achievements)
{
Achievements temp = new Achievements
{
ApiName = ach.achievement.name,
Name = ach.achievement.unlockedDisplayName,
Description = ach.achievement.unlockedDescription,
UrlUnlocked = ach.achievement.unlockedIconLink,
UrlLocked = ach.achievement.lockedIconLink,
DateUnlocked = default(DateTime),
Percent = ach.achievement.rarity.percent
};

AllAchievements.Add(temp);
}
}

// Owned achievement
var achievemenstOwnedData = epicData.queries
.Where(x => (Serialization.ToJson(x.state.data)).Contains("\"playerAchievements\":[{\"playerAchievement\"", StringComparison.InvariantCultureIgnoreCase))
.FirstOrDefault();

if (achievemenstOwnedData != null)
{
EpicAchievementsOwnedData epicAchievementsOwnedData = Serialization.FromJson<EpicAchievementsOwnedData>(Serialization.ToJson(achievemenstOwnedData.state.data));

if (epicAchievementsOwnedData != null && epicAchievementsOwnedData.PlayerAchievement.playerAchievementGameRecordsBySandbox.records.FirstOrDefault()?.playerAchievements?.Count() > 0)
{
foreach (var ach in epicAchievementsOwnedData.PlayerAchievement.playerAchievementGameRecordsBySandbox.records.FirstOrDefault().playerAchievements)
{
var owned = AllAchievements.Find(x => x.ApiName == ach.playerAchievement.achievementName);
if (owned != null)
{
owned.DateUnlocked = ach.playerAchievement.unlockDate;
}
else
{
}
}
}
}
}
catch (Exception ex)
{
ShowNotificationPluginError(ex);
return gameAchievements;
}
}
else
{
logger.Warn($"Error 404 for {game.Name}");
}
}
else
{
ShowNotificationPluginNoAuthenticate(resources.GetString("LOCSuccessStoryNotificationsGogNoAuthenticate"));
}


gameAchievements.Items = AllAchievements;


// Set source link
if (gameAchievements.HasAchivements)
{
gameAchievements.SourcesLink = new SourceLink
{
GameName = gameAchievements.Name,
Name = "Epic",
Url = Url
};
}


return gameAchievements;
}


#region Configuration
public override bool ValidateConfiguration()
{
if (PlayniteTools.IsDisabledPlaynitePlugins("EpicLibrary"))
{
ShowNotificationPluginDisable(resources.GetString("LOCSuccessStoryNotificationsEpicDisabled"));
return false;
}
else
{
if (CachedConfigurationValidationResult == null)
{
CachedConfigurationValidationResult = IsConnected();

if (!(bool)CachedConfigurationValidationResult)
{
ShowNotificationPluginNoAuthenticate(resources.GetString("LOCSuccessStoryNotificationsEpicNoAuthenticate"));
}
}
else if (!(bool)CachedConfigurationValidationResult)
{
ShowNotificationPluginErrorMessage();
}

return (bool)CachedConfigurationValidationResult;
}
}


public override bool IsConnected()
{
if (CachedIsConnectedResult == null)
{
CachedIsConnectedResult = EpicAPI.GetIsUserLoggedIn();
}

return (bool)CachedIsConnectedResult;
}

public override bool EnabledInSettings()
{
return PluginDatabase.PluginSettings.Settings.EnableEpic;
}
#endregion


#region Epic
private string GetProductSlug(string Name)
{
string ProductSlug = string.Empty;

using (var client = new WebStoreClient())
{
var catalogs = client.QuerySearch(Name).GetAwaiter().GetResult();
if (catalogs.HasItems())
{
var catalog = catalogs.FirstOrDefault(a => a.title.Equals(Name, StringComparison.InvariantCultureIgnoreCase));
if (catalog == null)
{
catalog = catalogs[0];
}

ProductSlug = catalog.productSlug;
}
}

return ProductSlug;
}
#endregion
}
}
5 changes: 4 additions & 1 deletion source/Localization/LocSource.xaml
Expand Up @@ -44,7 +44,9 @@
<sys:String x:Key="LOCSuccessStoryNotificationsBattleNetNoAuthenticate">Battle.net user is not authenticated</sys:String>
<sys:String x:Key="LOCSuccessStoryNotificationsBattleNetNoAuthenticateOverwatch">Battle.net Overwatch user is not authenticated</sys:String>
<sys:String x:Key="LOCSuccessStoryNotificationsBattleNetNoAuthenticateSc2">Battle.net StarCraft II user is not authenticated</sys:String>

<sys:String x:Key="LOCSuccessStoryNotificationsEpicDisabled">Epic is enabled in SuccessStory but the library extension has been disabled in Playnite</sys:String>
<sys:String x:Key="LOCSuccessStoryNotificationsEpicNoAuthenticate">Epic user is not authenticated</sys:String>

<!-- SuccessStoreGameSelection -->

<sys:String x:Key="LOCSuccessStoryAchievementsCount">Achievements count</sys:String>
Expand All @@ -65,6 +67,7 @@
<sys:String x:Key="LOCSuccessStoryEnablePSN">Enable PSN achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableSteam">Enable Steam achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableGog">Enable GOG achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableEpic">Enable Epic achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableOrigin">Enable Origin achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableXbox">Enable Xbox achievements</sys:String>
<sys:String x:Key="LOCSuccessStoryEnableRetroAchievements">Enable RetroAchievements achievements</sys:String>
Expand Down
5 changes: 5 additions & 0 deletions source/Models/Achievements.cs
Expand Up @@ -270,6 +270,11 @@ private string GetNameFromUrl(string url)
string NameFromUrl = string.Empty;
List<string> urlSplited = url.Split('/').ToList();

if (url.IndexOf("epicgames.com") > -1)
{
NameFromUrl = "epic_" + Name.Replace(" ", "") + "_" + url.Substring(url.Length - 4).Replace(".png", string.Empty);
}

if (url.IndexOf(".playstation.") > -1)
{
NameFromUrl = "playstation_" + Name.Replace(" ", "") + "_" + url.Substring(url.Length - 4).Replace(".png", string.Empty);
Expand Down
71 changes: 71 additions & 0 deletions source/Models/EpicAchievementsData.cs
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuccessStory.Models
{
public class EpicAchievementsData
{
public AchievementEpic Achievement { get; set; }
}

public class PlatinumRarity
{
public int percent { get; set; }
}

public class Tier
{
public string name { get; set; }
public string hexColor { get; set; }
public int min { get; set; }
public int max { get; set; }
}

public class Rarity
{
public int percent { get; set; }
}

public class Achievement3
{
public string sandboxId { get; set; }
public string deploymentId { get; set; }
public string name { get; set; }
public bool hidden { get; set; }
public string unlockedDisplayName { get; set; }
public string lockedDisplayName { get; set; }
public string unlockedDescription { get; set; }
public string lockedDescription { get; set; }
public string unlockedIconId { get; set; }
public string lockedIconId { get; set; }
public int XP { get; set; }
public string flavorText { get; set; }
public string unlockedIconLink { get; set; }
public string lockedIconLink { get; set; }
public Tier tier { get; set; }
public Rarity rarity { get; set; }
}

public class Achievement2
{
public Achievement3 achievement { get; set; }
}

public class ProductAchievementsRecordBySandbox
{
public string productId { get; set; }
public string sandboxId { get; set; }
public int totalAchievements { get; set; }
public int totalProductXP { get; set; }
public PlatinumRarity platinumRarity { get; set; }
public List<Achievement2> achievements { get; set; }
}

public class AchievementEpic
{
public ProductAchievementsRecordBySandbox productAchievementsRecordBySandbox { get; set; }
}
}

0 comments on commit e3046ae

Please sign in to comment.