├── CHANGELOG.MD
├── OculusLibrary
├── Resources
│ └── oculusicon.png
├── extension.yaml
├── OS
│ ├── IPathNormaliser.cs
│ ├── WMODrive.cs
│ ├── IWindowsManagementObjectQueryProvider.cs
│ ├── IRegistryValueProvider.cs
│ ├── WMODriveQueryProvider.cs
│ ├── RegistryValueProvider.cs
│ └── PathNormaliser.cs
├── packages.config
├── DataExtraction
│ ├── IOculusPathSniffer.cs
│ ├── OculusWebsiteAggregateRating.cs
│ ├── OculusWebsiteJson.cs
│ ├── OculusWebsiteScraper.cs
│ └── OculusPathSniffer.cs
├── ManifestParseException.cs
├── OculusManifest.cs
├── Properties
│ └── AssemblyInfo.cs
├── OculusLibrary.csproj
└── OculusLibraryPlugin.cs
├── README.md
├── .github
└── workflows
│ ├── main.yml
│ └── release.yml
├── OculusLibrary.Tests
├── Properties
│ └── AssemblyInfo.cs
├── packages.config
├── OculusWebsiteParserTests.cs
├── PathNormaliserTests.cs
├── OculusLibrary.Tests.csproj
└── demo1.html
├── OculusLibrary.sln
├── .gitattributes
└── .gitignore
/CHANGELOG.MD:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v1.0.0
4 |
5 | Initial Release
--------------------------------------------------------------------------------
/OculusLibrary/Resources/oculusicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shawson/Playnite-OculusLibrary/HEAD/OculusLibrary/Resources/oculusicon.png
--------------------------------------------------------------------------------
/OculusLibrary/extension.yaml:
--------------------------------------------------------------------------------
1 | Name: Oculus Library Importer
2 | Author: Shaw Young
3 | Version: 1.0.0
4 | Module: OculusLibrary.dll
5 | Type: GameLibrary
6 | Icon: Resources\oculusicon.png
--------------------------------------------------------------------------------
/OculusLibrary/OS/IPathNormaliser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace OculusLibrary.OS
4 | {
5 | public interface IPathNormaliser: IDisposable
6 | {
7 | string Normalise(string path);
8 | }
9 | }
--------------------------------------------------------------------------------
/OculusLibrary/OS/WMODrive.cs:
--------------------------------------------------------------------------------
1 | namespace OculusLibrary.OS
2 | {
3 | public class WMODrive
4 | {
5 | public string DeviceId { get; set; }
6 | public string DriveLetter { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/OculusLibrary/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/OculusLibrary/DataExtraction/IOculusPathSniffer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace OculusLibrary.DataExtraction
4 | {
5 | public interface IOculusPathSniffer
6 | {
7 | List GetOculusLibraryLocations();
8 | }
9 | }
--------------------------------------------------------------------------------
/OculusLibrary/DataExtraction/OculusWebsiteAggregateRating.cs:
--------------------------------------------------------------------------------
1 | namespace OculusLibrary.DataExtraction
2 | {
3 | public class OculusWebsiteAggregateRating {
4 | public int RatingCount { get; set; }
5 | public decimal RatingValue { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/OculusLibrary/OS/IWindowsManagementObjectQueryProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Management;
3 |
4 | namespace OculusLibrary.OS
5 | {
6 | public interface IWMODriveQueryProvider
7 | {
8 | List GetDriveData();
9 | }
10 | }
--------------------------------------------------------------------------------
/OculusLibrary/DataExtraction/OculusWebsiteJson.cs:
--------------------------------------------------------------------------------
1 | namespace OculusLibrary.DataExtraction
2 | {
3 | public class OculusWebsiteJson
4 | {
5 | public string Name { get; set; }
6 | public string Description { get; set; }
7 | public OculusWebsiteAggregateRating AggregateRating { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/OculusLibrary/OS/IRegistryValueProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Microsoft.Win32;
3 |
4 | namespace OculusLibrary.OS
5 | {
6 | public interface IRegistryValueProvider
7 | {
8 | List GetSubKeysForPath(RegistryView platform, RegistryHive hive, string path);
9 | string GetValueForPath(RegistryView platform, RegistryHive hive, string path, string keyName);
10 | }
11 | }
--------------------------------------------------------------------------------
/OculusLibrary/ManifestParseException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace OculusLibrary
4 | {
5 | [Serializable]
6 | public class ManifestParseException : Exception
7 | {
8 | public ManifestParseException() { }
9 | public ManifestParseException(string message) : base(message) { }
10 | public ManifestParseException(string message, Exception inner) : base(message, inner) { }
11 | protected ManifestParseException(
12 | System.Runtime.Serialization.SerializationInfo info,
13 | System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
14 | }
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Playnite-OculusLibrary
2 |
3 | 
4 | 
5 |
6 | Plugin for Playnite to add support for importing games from the Oculus store.
7 |
8 | ## Installation ##
9 |
10 | Download the latest release zip file and extract to your Playnite/Extensions folder.
11 |
12 | ## Configuration ##
13 |
14 | Currently, none. The plugin should pickup the installation location from the Windows registry and automatically scan for your installed games.
15 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 |
6 | name: CI
7 |
8 | jobs:
9 | build:
10 | runs-on: [windows-2019]
11 | steps:
12 | - name: checkout
13 | uses: actions/checkout@v1
14 |
15 | - name: Setup Nuget.exe
16 | uses: warrenbuckley/Setup-Nuget@v1
17 |
18 | - name: Nuget Restore
19 | run: nuget restore .\OculusLibrary.sln
20 |
21 | - name: Build (DotNET4.6.2)
22 | run: |
23 | cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\"
24 | .\MSBuild.exe $Env:GITHUB_WORKSPACE\OculusLibrary.sln -p:Configuration=Release -restore
25 |
--------------------------------------------------------------------------------
/OculusLibrary.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("OculusLibrary.Tests")]
6 | [assembly: AssemblyDescription("")]
7 | [assembly: AssemblyConfiguration("")]
8 | [assembly: AssemblyCompany("")]
9 | [assembly: AssemblyProduct("OculusLibrary.Tests")]
10 | [assembly: AssemblyCopyright("Copyright © 2019")]
11 | [assembly: AssemblyTrademark("")]
12 | [assembly: AssemblyCulture("")]
13 |
14 | [assembly: ComVisible(false)]
15 |
16 | [assembly: Guid("0017fa7b-c646-4e68-bd18-9026c4c2b9e2")]
17 |
18 | // [assembly: AssemblyVersion("1.0.*")]
19 | [assembly: AssemblyVersion("1.0.0.0")]
20 | [assembly: AssemblyFileVersion("1.0.0.0")]
21 |
--------------------------------------------------------------------------------
/OculusLibrary.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/OculusLibrary/OS/WMODriveQueryProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Management;
3 |
4 | namespace OculusLibrary.OS
5 | {
6 | public class WMODriveQueryProvider : IWMODriveQueryProvider
7 | {
8 | public List GetDriveData()
9 | {
10 | var result = new List();
11 | ManagementObjectSearcher ms = new ManagementObjectSearcher("Select DeviceId, DriveLetter from Win32_Volume");
12 |
13 | foreach(var o in ms.Get())
14 | {
15 | result.Add(new WMODrive {
16 | DeviceId = o["DeviceId"]?.ToString() ?? string.Empty,
17 | DriveLetter = o["DriveLetter"]?.ToString() ?? string.Empty
18 | });
19 | }
20 |
21 | return result;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/OculusLibrary/OculusManifest.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 |
4 | namespace OculusLibrary
5 | {
6 | internal class OculusManifest
7 | {
8 | public string AppId { get; set; }
9 | public string LaunchFile { get; set; }
10 | public string LaunchParameters { get; set; }
11 | public string CanonicalName { get; set; }
12 |
13 | public static OculusManifest Parse(string json)
14 | {
15 | if (string.IsNullOrWhiteSpace(json))
16 | {
17 | throw new ArgumentException("JSON string cannot be null and empty");
18 | }
19 |
20 | var manifest = JsonConvert.DeserializeObject(json);
21 |
22 | if (manifest == null)
23 | {
24 | throw new ManifestParseException("Could not deserialise json");
25 | }
26 |
27 | manifest.LaunchFile = manifest?.LaunchFile?.Replace("/", @"\");
28 |
29 | return manifest;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/OculusLibrary/OS/RegistryValueProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace OculusLibrary.OS
9 | {
10 | public class RegistryValueProvider : IRegistryValueProvider
11 | {
12 | public RegistryValueProvider() { }
13 |
14 | public List GetSubKeysForPath(
15 | RegistryView platform,
16 | RegistryHive hive,
17 | string path)
18 | {
19 | RegistryKey rootKey = RegistryKey.OpenBaseKey(hive, platform);
20 |
21 | return rootKey
22 | .OpenSubKey(path)
23 | .GetSubKeyNames()
24 | .ToList();
25 | }
26 |
27 | public string GetValueForPath(
28 | RegistryView platform,
29 | RegistryHive hive,
30 | string path,
31 | string keyName)
32 | {
33 | RegistryKey rootKey = RegistryKey.OpenBaseKey(hive, platform);
34 |
35 | return rootKey
36 | .OpenSubKey(path)
37 | .GetValue(keyName)
38 | .ToString();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/OculusLibrary.Tests/OculusWebsiteParserTests.cs:
--------------------------------------------------------------------------------
1 | using NSubstitute;
2 | using NUnit.Framework;
3 | using OculusLibrary.DataExtraction;
4 | using Playnite.SDK;
5 | using System.IO;
6 |
7 | namespace OculusLibrary.Tests
8 | {
9 | public class OculusWebsiteParserTests
10 | {
11 | private IWebView fakeWebView;
12 | private OculusWebsiteScraper subject;
13 |
14 | [SetUp]
15 | public void Setup()
16 | {
17 | var testHtml = File.ReadAllText($"{TestContext.CurrentContext.TestDirectory}\\demo1.html");
18 |
19 | fakeWebView = Substitute.For();
20 |
21 | fakeWebView.GetPageSource()
22 | .Returns(testHtml);
23 |
24 | var fakeLogger = Substitute.For();
25 |
26 | subject = new OculusWebsiteScraper(fakeLogger);
27 | }
28 |
29 | [TearDown]
30 | public void TearDown() {
31 | fakeWebView = null;
32 | subject = null;
33 | }
34 |
35 | [Test]
36 | public void Game_Name_Correctly_Extracted()
37 | {
38 | var result = subject.ScrapeDataForApplicationId(fakeWebView, "123");
39 |
40 | Assert.AreEqual("Test Game", result.Name);
41 | }
42 |
43 | [Test]
44 | public void Game_Description_Correctly_Extracted()
45 | {
46 | var result = subject.ScrapeDataForApplicationId(fakeWebView, "123");
47 |
48 | Assert.AreEqual("This is a test description", result.Description);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/OculusLibrary/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OculusLibrary")]
9 | [assembly: AssemblyDescription("Playnite Library provider for Oculus")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Shaw Young")]
12 | [assembly: AssemblyProduct("OculusLibrary")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("499d6789-da1d-44b8-9cf3-7ec07666fd6a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/OculusLibrary.Tests/PathNormaliserTests.cs:
--------------------------------------------------------------------------------
1 | using NSubstitute;
2 | using NUnit.Framework;
3 | using OculusLibrary.OS;
4 | using System.Collections.Generic;
5 |
6 | namespace OculusLibrary.Tests
7 | {
8 | public class PathNormaliserTests
9 | {
10 | [Test]
11 | public void Get_Drive_Letter_From_DeviceId()
12 | {
13 | var path = @"\\?\Volume{a0bf4e34-c90f-4005-815c-9a5a485e40ad}\Oculus\Software";
14 |
15 | var fakeWMOProvider = Substitute.For();
16 | fakeWMOProvider.GetDriveData().Returns(new List {
17 | new WMODrive {
18 | DeviceId = @"\\?\Volume{DCBDB210-C414-409E-B108-C2BFA7395E1F}\",
19 | DriveLetter = "X:"
20 | },
21 | new WMODrive {
22 | DeviceId = @"\\?\Volume{DCBDB210-C414-409E-B108-C2BFA7395E1F}\",
23 | DriveLetter = ""
24 | },
25 | new WMODrive {
26 | DeviceId = @"\\?\Volume{a0bf4e34-c90f-4005-815c-9a5a485e40ad}\",
27 | DriveLetter = "D:"
28 | },
29 | new WMODrive {
30 | DeviceId = @"\\?\Volume{ECBDB210-D414-509E-B108-C2BFA7395E1F}\",
31 | DriveLetter = "C:"
32 | },
33 | });
34 |
35 | using (var subject = new PathNormaliser(fakeWMOProvider))
36 | {
37 | var normalisedPath = subject.Normalise(path);
38 | Assert.AreEqual(@"D:\Oculus\Software", normalisedPath);
39 | }
40 |
41 |
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
5 |
6 | name: Release Build
7 |
8 | jobs:
9 | build:
10 | runs-on: [windows-2019]
11 | steps:
12 | - name: checkout
13 | uses: actions/checkout@v1
14 |
15 | - name: Setup Nuget.exe
16 | uses: warrenbuckley/Setup-Nuget@v1
17 |
18 | - name: Nuget Restore
19 | run: nuget restore .\OculusLibrary.sln
20 |
21 | - name: Build (DotNET4.6.2)
22 | run: |
23 | cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\"
24 | .\MSBuild.exe $Env:GITHUB_WORKSPACE\OculusLibrary.sln -p:Configuration=Release -restore
25 |
26 | - name: Zip Build artifacts
27 | run: |
28 | Compress-Archive -Path $Env:GITHUB_WORKSPACE\OculusLibrary\bin\Release\* -DestinationPath $Env:GITHUB_WORKSPACE\Oculus.zip
29 |
30 | - name: Create Release
31 | id: create_release
32 | uses: actions/create-release@v1
33 | env:
34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
35 | with:
36 | tag_name: ${{ github.ref }}
37 | release_name: Release ${{ github.ref }}
38 | body: |
39 | Changes in this Release
40 | - First Change
41 | - Second Change
42 | draft: false
43 | prerelease: false
44 |
45 | - name: Upload Release Asset
46 | id: upload-release-asset
47 | uses: actions/upload-release-asset@v1.0.1
48 | env:
49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50 | with:
51 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
52 | asset_path: .\Oculus.zip
53 | asset_name: Oculus.zip
54 | asset_content_type: application/zip
--------------------------------------------------------------------------------
/OculusLibrary/DataExtraction/OculusWebsiteScraper.cs:
--------------------------------------------------------------------------------
1 | using Playnite.SDK;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 | using System.Threading.Tasks;
9 | using System.Web.Script.Serialization;
10 |
11 | namespace OculusLibrary.DataExtraction
12 | {
13 | public class OculusWebsiteScraper
14 | {
15 | private readonly JavaScriptSerializer serialiser;
16 | private readonly ILogger logger;
17 |
18 | public OculusWebsiteScraper(ILogger logger)
19 | {
20 | serialiser = new JavaScriptSerializer();
21 | this.logger = logger;
22 | }
23 |
24 | public OculusWebsiteJson ScrapeDataForApplicationId(IWebView view, string appId)
25 | {
26 | logger.Debug($"Trying to scrape {appId}");
27 |
28 | // robo recall 1081190428622821
29 | try
30 | {
31 | view.NavigateAndWait($"https://www.oculus.com/experiences/rift/{appId}/");
32 | var source = view.GetPageSource();
33 |
34 | // get the json block from the source which contains the games meta data
35 |
36 | Regex regex = new Regex(@"
12 |
13 |
14 |
15 |
16 |
17 |