mirror of
https://github.com/rfvgyhn/min-ed-launcher.git
synced 2026-02-04 19:25:40 +00:00
@ -62,9 +62,10 @@ let private epicValues = lazy (
|
||||
let credIdProp = credType.GetProperty("ClientId")
|
||||
let credSecretProp = credType.GetProperty("ClientSecret")
|
||||
let depIdProp = optType.GetProperty("DeploymentId")
|
||||
let sandboxIdProp = optType.GetProperty("SandboxId")
|
||||
let credsProp = optType.GetProperty("ClientCredentials")
|
||||
|
||||
if methodInfo <> null && credIdProp <> null && credSecretProp <> null && depIdProp <> null && credsProp <> null then
|
||||
if methodInfo <> null && credIdProp <> null && credSecretProp <> null && depIdProp <> null && sandboxIdProp <> null && credsProp <> null then
|
||||
let eosIf = Activator.CreateInstance(eosIfType, null)
|
||||
let options = methodInfo.Invoke(eosIf, null)
|
||||
|
||||
@ -72,11 +73,12 @@ let private epicValues = lazy (
|
||||
let credentials = credsProp.GetValue(options)
|
||||
if credentials <> null then
|
||||
let depId = depIdProp.GetValue(options) :?> string
|
||||
let sandboxId = sandboxIdProp.GetValue(options) :?> string
|
||||
let cId = credIdProp.GetValue(credentials) :?> string
|
||||
let cSecret = credSecretProp.GetValue(credentials) :?> string
|
||||
|
||||
if depId <> null && cId <> null && cSecret <> null then
|
||||
Ok (cId, cSecret, depId)
|
||||
if depId <> null && sandboxId <> null && cId <> null && cSecret <> null then
|
||||
Ok (cId, cSecret, depId, sandboxId)
|
||||
else
|
||||
err "Unable to get values of IDs"
|
||||
else
|
||||
@ -104,9 +106,9 @@ let private requestToStr formValues contentHeaders (request: HttpRequestMessage)
|
||||
|
||||
let private requestToken launcherVersion (formValues: string list) : Task<Result<RefreshableToken, string>> =
|
||||
match epicValues.Force() with
|
||||
| Ok (clientId, clientSecret, dId) -> task {
|
||||
| Ok (clientId, clientSecret, depId, _) -> task {
|
||||
let formValues =
|
||||
[ $"deployment_id={dId}"
|
||||
[ $"deployment_id={depId}"
|
||||
"scope=basic_profile friends_list presence" ]
|
||||
|> List.append formValues
|
||||
use content = new StringContent(String.Join("&", formValues), Encoding.UTF8, "application/x-www-form-urlencoded")
|
||||
@ -156,6 +158,14 @@ let private generateExchangeCode token = task {
|
||||
Log.debug $"Requesting epic exchange code failed: %s{content}"
|
||||
return $"%i{int response.StatusCode}: %s{response.ReasonPhrase}" |> Error }
|
||||
|
||||
let getDeploymentId() =
|
||||
epicValues.Force()
|
||||
|> Result.map (fun (_, _, depId, _) -> depId)
|
||||
|
||||
let getSandboxId() =
|
||||
epicValues.Force()
|
||||
|> Result.map (fun (_, _, _, sandboxId) -> sandboxId)
|
||||
|
||||
let loginWithCode launcherVersion exchangeCode =
|
||||
requestToken launcherVersion [ "grant_type=exchange_code"; $"exchange_code=%s{exchangeCode}" ]
|
||||
|
||||
|
||||
@ -144,9 +144,11 @@ let createArgString vr (lang: string option) edSession machineId timestamp watch
|
||||
if lang.IsSome then "/language " + lang.Value
|
||||
match platform, product.VInfo.SteamAware with
|
||||
| Steam, true -> "/steam"
|
||||
| Epic _, _ ->
|
||||
let refresh = edSession.PlatformToken.GetRefreshToken() |> Option.defaultValue ""
|
||||
$"\"EpicToken {refresh}\""
|
||||
| Epic p, _ ->
|
||||
let refresh = edSession.PlatformToken.GetRefreshToken() |> Option.defaultValue "[none]"
|
||||
let sId = p.SandboxId |> Option.defaultValue "[none]"
|
||||
let dId = p.DeploymentId |> Option.defaultValue "[none]"
|
||||
$"\"ConfigureEpic %s{refresh} %s{sId} %s{dId}\""
|
||||
| _, _ -> ()
|
||||
match vr with
|
||||
| Vr -> "/vr"
|
||||
|
||||
@ -70,8 +70,29 @@ let applyDeviceAuth settings =
|
||||
| Cobra.CredResult.Failure msg -> return Error msg }
|
||||
| _ -> Ok settings |> Task.fromResult
|
||||
|
||||
let applyFallbackEpidIds settings =
|
||||
match settings.Platform with
|
||||
| Epic details -> result {
|
||||
let! depId =
|
||||
details.DeploymentId
|
||||
|> Option.map Ok
|
||||
|> Option.defaultWith (fun () ->
|
||||
Epic.getDeploymentId()
|
||||
|> Result.mapError (fun e -> $"Failed to get Epic deployment id: {e}")
|
||||
)
|
||||
let! sandboxId =
|
||||
details.SandboxId
|
||||
|> Option.map Ok
|
||||
|> Option.defaultWith (fun () ->
|
||||
Epic.getDeploymentId()
|
||||
|> Result.mapError (fun e -> $"Failed to get Epic sandbox id: {e}")
|
||||
)
|
||||
return { settings with Platform = Epic { details with DeploymentId = Some depId; SandboxId = Some sandboxId } }
|
||||
}
|
||||
| _ -> Ok settings
|
||||
|
||||
let private doesntEndWith (value: string) (str: string) = not (str.EndsWith(value))
|
||||
type private EpicArg = ExchangeCode of string | Type of string | AppId of string
|
||||
type private EpicArg = ExchangeCode of string | Type of string | AppId of string | SandboxId of string | DeploymentId of string
|
||||
let parseArgs defaults (findCbLaunchDir: Platform -> Result<string,string>) (argv: string[]) =
|
||||
let launcherIndex =
|
||||
argv
|
||||
@ -102,9 +123,11 @@ let parseArgs defaults (findCbLaunchDir: Platform -> Result<string,string>) (arg
|
||||
arg
|
||||
|> Option.map (fun arg ->
|
||||
match arg with
|
||||
| ExchangeCode p -> { details with ExchangeCode = p }
|
||||
| Type t -> { details with Type = t }
|
||||
| AppId id -> { details with AppId = id })
|
||||
| ExchangeCode p -> { details with ExchangeCode = p }
|
||||
| Type t -> { details with Type = t }
|
||||
| AppId id -> { details with AppId = id }
|
||||
| SandboxId id -> { details with SandboxId = Some id }
|
||||
| DeploymentId id -> { details with DeploymentId = Some id })
|
||||
|> Option.defaultValue details
|
||||
|> Epic
|
||||
|
||||
@ -133,6 +156,8 @@ let parseArgs defaults (findCbLaunchDir: Platform -> Result<string,string>) (arg
|
||||
| "-auth_password", Some password -> { s with Platform = epicArg (ExchangeCode password) }
|
||||
| "-auth_type", Some t -> { s with Platform = epicArg (Type t) }
|
||||
| "-epicapp", Some id -> { s with Platform = epicArg (AppId id) }
|
||||
| "-epicsandboxid", Some id -> { s with Platform = epicArg (SandboxId id) }
|
||||
| "-epicdeploymentid", Some id -> { s with Platform = epicArg (DeploymentId id) }
|
||||
| "/oculus", Some nonce -> { s with Platform = Oculus nonce; ForceLocal = true }
|
||||
| "/restart", PosDouble delay -> { s with Restart = delay * 1000. |> int64 |> Some }
|
||||
| "/vr", _ -> { s with DisplayMode = Vr }
|
||||
@ -261,6 +286,7 @@ let getSettings args appDir fileConfig = task {
|
||||
let! settings =
|
||||
parseArgs defaults fallbackDirs args
|
||||
|> Result.tee (fun s -> Directory.SetCurrentDirectory(s.CbLauncherDir))
|
||||
|> Result.bind applyFallbackEpidIds
|
||||
|> Result.bindTask applyDeviceAuth
|
||||
|
||||
return settings
|
||||
|
||||
@ -54,10 +54,14 @@ type SampledProgress<'T>(interval: TimeSpan, handler: 'T -> unit, finishedHandle
|
||||
type EpicDetails =
|
||||
{ ExchangeCode: string
|
||||
Type: string
|
||||
AppId: string }
|
||||
AppId: string
|
||||
SandboxId: string option
|
||||
DeploymentId: string option }
|
||||
with static member Empty = { ExchangeCode = ""
|
||||
Type = ""
|
||||
AppId = "" }
|
||||
AppId = ""
|
||||
SandboxId = None
|
||||
DeploymentId = None }
|
||||
type Credentials = { Username: string; Password: string }
|
||||
type FrontierDetails =
|
||||
{ Profile: string; Credentials: Credentials option; AuthToken: string option }
|
||||
|
||||
@ -63,19 +63,20 @@ open MinEdLauncher.Tests.Extensions
|
||||
|
||||
Expect.notStringContains actual "/steam" ""
|
||||
}
|
||||
test "Epic platform contains refresh token" {
|
||||
let get = fun () -> { RefreshableToken.Empty with RefreshToken = "asdf" }
|
||||
let token = { EdSession.Empty with PlatformToken = Expires {| Get = get; Renew = fun () -> Task.fromResult (Result.Ok()) |} }
|
||||
let actual = createArgString Vr None token "" getTimestamp false (Epic EpicDetails.Empty) hashFile product
|
||||
test "Epic platform contains refresh token, sandbox id and deployment id" {
|
||||
let getToken = fun () -> { RefreshableToken.Empty with RefreshToken = "asdf" }
|
||||
let epicDetails = { EpicDetails.Empty with SandboxId = Some "sId"; DeploymentId = Some "depId" }
|
||||
let token = { EdSession.Empty with PlatformToken = Expires {| Get = getToken; Renew = fun () -> Task.fromResult (Result.Ok()) |} }
|
||||
let actual = createArgString Vr None token "" getTimestamp false (Epic epicDetails) hashFile product
|
||||
|
||||
Expect.stringContains actual "\"EpicToken asdf\"" ""
|
||||
Expect.stringContains actual "\"ConfigureEpic asdf sId depId\"" ""
|
||||
}
|
||||
test "Non epic platform doesn't contain refresh token" {
|
||||
let get = fun () -> { RefreshableToken.Empty with RefreshToken = "asdf" }
|
||||
let token = { EdSession.Empty with PlatformToken = Expires {| Get = get; Renew = fun _ -> Task.fromResult (Result.Ok()) |} }
|
||||
let getToken = fun () -> { RefreshableToken.Empty with RefreshToken = "asdf" }
|
||||
let token = { EdSession.Empty with PlatformToken = Expires {| Get = getToken; Renew = fun _ -> Task.fromResult (Result.Ok()) |} }
|
||||
let actual = createArgString Vr None token "" getTimestamp false Dev hashFile product
|
||||
|
||||
Expect.notStringContains actual "\"EpicToken" ""
|
||||
Expect.notStringContains actual "\"ConfigureEpic" ""
|
||||
}
|
||||
test "VR mode" {
|
||||
let actual = createArgString Vr None token "" getTimestamp false Dev hashFile product
|
||||
|
||||
@ -61,6 +61,14 @@ let tests =
|
||||
let settings = parse [| "-epicapp=asdf" |]
|
||||
Expect.equal settings.Platform (Epic { EpicDetails.Empty with AppId = "asdf" }) ""
|
||||
}
|
||||
test "Matches epic sandbox id" {
|
||||
let settings = parse [| "-epicsandboxid=asdf" |]
|
||||
Expect.equal settings.Platform (Epic { EpicDetails.Empty with SandboxId = Some "asdf" }) ""
|
||||
}
|
||||
test "Matches epic deployment id" {
|
||||
let settings = parse [| "-epicdeploymentid=asdf" |]
|
||||
Expect.equal settings.Platform (Epic { EpicDetails.Empty with DeploymentId = Some "asdf" }) ""
|
||||
}
|
||||
test "Matches /oculus nonce" {
|
||||
let settings = parse [| "/oculus"; "123" |]
|
||||
Expect.equal settings.Platform (Oculus "123") ""
|
||||
|
||||
Reference in New Issue
Block a user