Skip to content

Commit

Permalink
better default account stuff, epicovt support, offline mode and dry r…
Browse files Browse the repository at this point in the history
…un option
  • Loading branch information
InvoxiPlayGames committed Jul 21, 2023
1 parent 9f00228 commit f30d736
Show file tree
Hide file tree
Showing 11 changed files with 427 additions and 193 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Build

on:
push:
branches: [ "master" ]

jobs:
build:
strategy:
matrix:
rid: [win-x64, osx-arm64, linux-x64]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Build
run: dotnet build -c Release -r ${{ matrix.rid }}
- name: Publish
run: dotnet publish -c Release -r ${{ matrix.rid }} --no-build
- name: Upload
uses: actions/upload-artifact@v3
with:
name: EricLauncher-${{ matrix.rid }}
path: bin/Release/net7.0/${{ matrix.rid }}/publish/
57 changes: 0 additions & 57 deletions EASAccount.cs

This file was deleted.

76 changes: 0 additions & 76 deletions EASLogin.cs

This file was deleted.

90 changes: 90 additions & 0 deletions EpicAccount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;

namespace EricLauncher
{
class EpicAccount
{
private const string EXCHANGE_API_URL = "/account/api/oauth/exchange";
private const string VERIFY_API_URL = "/account/api/oauth/verify";

public string? AccountId;
public string? DisplayName;
public string AccessToken;
public DateTime AccessExpiry;
public string RefreshToken;
public DateTime RefreshExpiry;

private HttpClient HTTPClient;

public EpicAccount(EpicLoginResponse login)
{
AccessToken = login.access_token!;
RefreshToken = login.refresh_token!;
AccessExpiry = login.expires_at!;
RefreshExpiry = login.refresh_expires_at!;
AccountId = login.account_id!;
DisplayName = login.displayName;

HTTPClient = new();
HTTPClient.BaseAddress = new Uri(EpicLogin.ACCOUNTS_API_BASE);
HTTPClient.DefaultRequestHeaders.Accept.Clear();
HTTPClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HTTPClient.DefaultRequestHeaders.Add("Authorization", login.token_type + " " + login.access_token);
}

public EpicAccount(StoredAccountInfo info)
{
if (info.AccessToken == null || info.RefreshToken == null)
throw new Exception("Stored account info doesn't have access or refresh token");

if (info.AccountId != null)
AccountId = info.AccountId;
if (info.DisplayName != null)
DisplayName = info.DisplayName;
AccessToken = info.AccessToken;
RefreshToken = info.RefreshToken;
AccessExpiry = info.AccessExpiry;
RefreshExpiry = info.RefreshExpiry;

HTTPClient = new();
HTTPClient.BaseAddress = new Uri(EpicLogin.ACCOUNTS_API_BASE);
HTTPClient.DefaultRequestHeaders.Accept.Clear();
HTTPClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HTTPClient.DefaultRequestHeaders.Add("Authorization", "bearer " + info.AccessToken);
}

public async Task<string> GetExchangeCode()
{
EpicExchangeResponse? resp = await HTTPClient.GetFromJsonAsync<EpicExchangeResponse>(EXCHANGE_API_URL);
return resp!.code!;
}

public async Task<bool> VerifyToken()
{
HttpResponseMessage resp = await HTTPClient.GetAsync(VERIFY_API_URL);
if (!resp.IsSuccessStatusCode)
return false;
EpicVerifyResponse? verify_response = await resp.Content.ReadFromJsonAsync<EpicVerifyResponse>();
// if the token is expiring soon, why bother amirite
return verify_response!.expires_in > 60;
}

public StoredAccountInfo MakeStoredAccountInfo()
{
StoredAccountInfo info = new StoredAccountInfo();
info.AccountId = AccountId;
info.RefreshExpiry = RefreshExpiry;
info.RefreshToken = RefreshToken;
info.AccessExpiry = AccessExpiry;
info.AccessToken = AccessToken;
info.DisplayName = DisplayName;
return info;
}
}
}
23 changes: 20 additions & 3 deletions EASClasses.cs → EpicClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace EricLauncher
{
public class EASLoginResponse
public class EpicLoginResponse
{
public string? access_token { get; set; }
public int expires_in { get; set; }
Expand All @@ -27,14 +27,14 @@ public class EASLoginResponse
public string? application_id { get; set; }
}

public class EASExchangeResponse
public class EpicExchangeResponse
{
public int expiresInSeconds { get; set; }
public string? code { get; set; }
public string? creatingClientId { get; set; }
}

public class EASError
public class EpicError
{
public string? errorCode { get; set; }
public string? errorMessage { get; set; }
Expand All @@ -46,4 +46,21 @@ public class EASError
public string? error { get; set; }
}

public class EpicVerifyResponse
{
public string? token { get; set; }
public string? session_id { get; set; }
public string? token_type { get; set; }
public string? client_id { get; set; }
public bool internal_client { get; set; }
public string? client_service { get; set; }
public string? account_id { get; set; }
public int expires_in { get; set; }
public DateTime expires_at { get; set; }
public string? auth_method { get; set; }
public string? display_name { get; set; }
public string? app { get; set; }
public string? in_app_id { get; set; }
public string? device_id { get; set; }
}
}
50 changes: 50 additions & 0 deletions EpicEcom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;

namespace EricLauncher
{
class EpicEcomToken
{
public string? token { get; set; }
}

class EpicEcom
{
public const string API_BASE = "https://ecommerceintegration-public-service-ecomprod02.ol.epicgames.com";

private const string OWT_API_TEMPLATE = "/ecommerceintegration/api/public/platforms/EPIC/identities/{0}/ownershipToken";

private EpicAccount Account;
private HttpClient HTTPClient;

public EpicEcom(EpicAccount account)
{
Account = account;

HTTPClient = new();
HTTPClient.BaseAddress = new Uri(API_BASE);
HTTPClient.DefaultRequestHeaders.Accept.Clear();
HTTPClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HTTPClient.DefaultRequestHeaders.Add("Authorization", "bearer " + account.AccessToken!);
}

public async Task<string?> GetOwnershipToken(string catalog_namespace, string catalog_item_id)
{
string formatted_url = string.Format(OWT_API_TEMPLATE, Account.AccountId!);
HttpResponseMessage resp = await HTTPClient.PostAsync(formatted_url, new StringContent($"nsCatalogItemId={catalog_namespace}:{catalog_item_id}", Encoding.UTF8, "application/x-www-form-urlencoded"));
if (!resp.IsSuccessStatusCode)
{
EpicError? error_response = await resp.Content.ReadFromJsonAsync<EpicError>();
Console.WriteLine($"Failed to fetch ownership token: '{error_response!.errorMessage}' ({error_response!.errorCode})");
return null;
}
EpicEcomToken? ecom_response = await resp.Content.ReadFromJsonAsync<EpicEcomToken>();
return ecom_response!.token;
}
}
}
Loading

0 comments on commit f30d736

Please sign in to comment.