Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Extensions/TpkExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using HumbleKeys.Models;
using Playnite.SDK.Models;

namespace HumbleKeys.Extensions
{
public static class TpkExtensions
{
public const string SteamGameUrlMask = @"https://store.steampowered.com/app/{0}";
public const string SteamSearchUrlMask = @"https://store.steampowered.com/search/?term={0}";

public static Link MakeSteamLink(string gameKey) => new Link("Steam", string.Format(SteamGameUrlMask, gameKey));

public static Link MakeSteamLink(this Order.TpkdDict.Tpk tpk)
{
if (!string.IsNullOrEmpty(tpk.steam_app_id)) { return MakeSteamLink(tpk.steam_app_id); }

string humanName = tpk.human_name;

if (string.IsNullOrEmpty(humanName))
{
humanName = tpk.machine_name?.Replace("_steam", string.Empty).Replace("_choice", string.Empty);
}

if (string.IsNullOrEmpty(humanName)) return null;
if (humanName.EndsWith(" Steam"))
{
humanName = humanName.Remove(humanName.LastIndexOf(" Steam", StringComparison.Ordinal));
}
if (humanName.EndsWith(" DLC"))
{
humanName = humanName.Remove(humanName.LastIndexOf(" DLC", StringComparison.Ordinal));
}

return new Link("Steam", string.Format(SteamSearchUrlMask, humanName.Replace(" ", "%2B")));
}

}
}
33 changes: 7 additions & 26 deletions HumbleKeysLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls;
using HumbleKeys.Extensions;
using HumbleKeys.Models;
using HumbleKeys.Services;

Expand All @@ -19,8 +20,6 @@ public class HumbleKeysLibrary : LibraryPlugin
private static readonly ILogger logger = LogManager.GetLogger();
private const string dbImportMessageId = "humblekeyslibImportError";
private const string humblePurchaseUrlMask = @"https://www.humblebundle.com/downloads?key={0}";
private const string steamGameUrlMask = @"https://store.steampowered.com/app/{0}";
private const string steamSearchUrlMask = @"https://store.steampowered.com/search/?term={0}";
private const string REDEEMED_STR = "Key: Redeemed";
private const string UNREDEEMED_STR = "Key: Unredeemed";
private const string UNREDEEMABLE_STR = "Key: Unredeemable";
Expand Down Expand Up @@ -335,7 +334,7 @@ protected void ProcessOrders(Dictionary<string,Order> orders, IEnumerable<IGroup
}
}

bool UpdateStoreLinks(ObservableCollection<Link> links, Order.TpkdDict.Tpk tpkd, bool useDispatcher)
public bool UpdateStoreLinks(ObservableCollection<Link> links, Order.TpkdDict.Tpk tpkd, bool useDispatcher)
{
var recordChanged = false;

Expand All @@ -362,29 +361,11 @@ bool UpdateStoreLinks(ObservableCollection<Link> links, Order.TpkdDict.Tpk tpkd,
}
}

if (tpkd.key_type != "steam") return recordChanged;

Link steamGameLink;
string humanName = string.Empty;
if (!string.IsNullOrEmpty(tpkd.steam_app_id))
{
steamGameLink = MakeSteamLink(tpkd.steam_app_id);
}
else
{
humanName = tpkd.human_name;
steamGameLink = new Link("Steam", string.Format(steamSearchUrlMask, humanName.Replace(" ", "%2B")));
}

if (humanName.EndsWith(" Steam"))
{
humanName = humanName.Remove(humanName.LastIndexOf(" Steam", StringComparison.Ordinal));
}
if (humanName.EndsWith(" DLC"))
{
humanName = humanName.Remove(humanName.LastIndexOf(" DLC", StringComparison.Ordinal));
}
if (tpkd?.key_type != "steam") return recordChanged;

var steamGameLink = tpkd.MakeSteamLink();
if (steamGameLink == null) return false;

var steamLinks = links.Where((link1, i) => link1.Name == "Steam");
var steamLinksList = steamLinks.ToList();
var existingSteamLink = steamLinksList.FirstOrDefault();
Expand Down Expand Up @@ -418,6 +399,7 @@ bool UpdateStoreLinks(ObservableCollection<Link> links, Order.TpkdDict.Tpk tpkd,
}

return true;

}

Game ImportNewGame(Order.TpkdDict.Tpk tpkd, Tag groupTag = null)
Expand Down Expand Up @@ -639,7 +621,6 @@ KeyInfo GetKeyInfo(string key_type, bool needSourceId)
#region === Helper Methods ============
private static string GetGameId(Order.TpkdDict.Tpk tpk) => $"{tpk.machine_name}_{tpk.gamekey}";
private static Link MakeLink(string gameKey) => new Link("Humble Purchase URL", string.Format(humblePurchaseUrlMask, gameKey) );
private static Link MakeSteamLink(string gameKey) => new Link("Steam", string.Format(steamGameUrlMask, gameKey));
private static bool IsKeyNull(Order.TpkdDict.Tpk t) => t?.redeemed_key_val == null;
private static bool IsKeyPresent(Order.TpkdDict.Tpk t) => !IsKeyNull(t);
private static string GetOrderRedemptionTagState(Order.TpkdDict.Tpk t)
Expand Down
3 changes: 2 additions & 1 deletion HumbleKeysLibrary.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Extensions\CloneObject.cs" />
<Compile Include="Extensions\TpkExtensions.cs" />
<Compile Include="HumbleKeysLibraryClient.cs" />
<Compile Include="HumbleKeysLibrary.cs" />
<Compile Include="HumbleKeysLibrarySettings.cs" />
Expand Down Expand Up @@ -89,7 +90,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="PlayniteSDK" Version="6.9.0" />
<PackageReference Include="PlayniteSDK" Version="6.16.0" />
</ItemGroup>
<ItemGroup>
<Content Include=".github\workflows\generate_release_artifacts.yml" />
Expand Down
9 changes: 9 additions & 0 deletions HumbleKeysLibrary.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ VisualStudioVersion = 15.0.28307.572
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HumbleKeysLibrary", "HumbleKeysLibrary.csproj", "{2351B5C1-6E28-4B79-A1D9-90FDA53B5417}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HumbleKeysLibraryTest", "HumbleKeysLibraryTest\HumbleKeysLibraryTest.csproj", "{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}"
ProjectSection(ProjectDependencies) = postProject
{2351B5C1-6E28-4B79-A1D9-90FDA53B5417} = {2351B5C1-6E28-4B79-A1D9-90FDA53B5417}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -15,6 +20,10 @@ Global
{2351B5C1-6E28-4B79-A1D9-90FDA53B5417}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2351B5C1-6E28-4B79-A1D9-90FDA53B5417}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2351B5C1-6E28-4B79-A1D9-90FDA53B5417}.Release|Any CPU.Build.0 = Release|Any CPU
{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
3 changes: 3 additions & 0 deletions HumbleKeysLibrary.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DLC/@EntryIndexedValue">DLC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
Expand All @@ -12,6 +13,8 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=70345118_002D4b40_002D4ece_002D937c_002Dbbeb7a0b2e70/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue">C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe</s:String>
<s:Int64 x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsbuildVersion/@EntryValue">1048576</s:Int64>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gamekeys/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=humblebundle/@EntryIndexedValue">True</s:Boolean>
Expand Down
66 changes: 66 additions & 0 deletions HumbleKeysLibraryTest/ExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using HumbleKeys;
using HumbleKeys.Extensions;
using HumbleKeys.Models;
using NSubstitute;
using NUnit.Framework;
using Playnite.SDK;

namespace HumbleKeysLibraryTest
{
[TestFixture]
public class ExtensionTests
{
[TestCase]
public void EmptyTpk()
{
var tpk = new Order.TpkdDict.Tpk();
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Null);
}

[TestCase]
public void EmptyHumanNameCreatesValidSteamLinkViaMachineName()
{
var tpk = new Order.TpkdDict.Tpk {machine_name = "flowersanddeities_choice_steam", human_name = string.Empty};
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Not.Null);
Assert.That(link.Url, Is.EqualTo(string.Format(TpkExtensions.SteamSearchUrlMask, "flowersanddeities")));
}

[TestCase]
public void HumanNameCreatesValidSteamLinkViaHumanName()
{
var tpk = new Order.TpkdDict.Tpk {machine_name = "flowersanddeities_choice_steam", human_name = "Flowers and Deities"};
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Not.Null);
Assert.That(link.Url, Is.EqualTo(string.Format(TpkExtensions.SteamSearchUrlMask, "Flowers%2Band%2BDeities")));
}

[TestCase]
public void HumanNameDLCCreatesValidSteamLinkViaHumanName()
{
var tpk = new Order.TpkdDict.Tpk {machine_name = "flowersanddeities_choice_steam", human_name = "Flowers and Deities DLC"};
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Not.Null);
Assert.That(link.Url, Is.EqualTo(string.Format(TpkExtensions.SteamSearchUrlMask, "Flowers%2Band%2BDeities")));
}

[TestCase]
public void HumanNameSteamCreatesValidSteamLinkViaHumanName()
{
var tpk = new Order.TpkdDict.Tpk {machine_name = "flowersanddeities_choice_steam", human_name = "Flowers and Deities Steam"};
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Not.Null);
Assert.That(link.Url, Is.EqualTo(string.Format(TpkExtensions.SteamSearchUrlMask, "Flowers%2Band%2BDeities")));
}

[TestCase]
public void AppIdCreatesValidSteamLink()
{
var tpk = new Order.TpkdDict.Tpk {steam_app_id = "3816000", machine_name = "flowersanddeities_choice_steam", human_name = "Flowers and Deities"};
var link = tpk.MakeSteamLink();
Assert.That(link, Is.Not.Null);
Assert.That(link.Url, Is.EqualTo(string.Format(TpkExtensions.SteamGameUrlMask, "3816000")));
}
}
}
65 changes: 65 additions & 0 deletions HumbleKeysLibraryTest/HumbleKeysLibraryTest.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{487D0989-E9EF-4852-A4C2-FB40E1E2ABA9}</ProjectGuid>
<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HumbleKeysLibraryTest</RootNamespace>
<AssemblyName>HumbleKeysLibraryTest</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
</ItemGroup>
<ItemGroup>
<Compile Include="ExtensionTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NSubstitute" Version="6.0.0" />
<PackageReference Include="NUnit" Version="4.6.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HumbleKeysLibrary.csproj">
<Project>{2351b5c1-6e28-4b79-a1d9-90fda53b5417}</Project>
<Name>HumbleKeysLibrary</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

</Project>
35 changes: 35 additions & 0 deletions HumbleKeysLibraryTest/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("HumbleKeysLibraryTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HumbleKeysLibraryTest")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("487D0989-E9EF-4852-A4C2-FB40E1E2ABA9")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading