Use updated WoofWare plugins

This commit is contained in:
Smaug123
2023-12-28 19:54:08 +00:00
parent 6fb9e6e591
commit d7b078e8d6
8 changed files with 259 additions and 58 deletions

View File

@@ -17,8 +17,8 @@ type SessionsArgsFragment =
type SessionsArgs =
{
Creds : Auth
FromDate : DateTime
ToDate : DateTime
FromDate : DateOnly
ToDate : DateOnly
}
static member Parse
@@ -31,8 +31,8 @@ type SessionsArgs =
{
Creds = auth
FromDate = DateTime.Parse fromDate
ToDate = DateTime.Parse toDate
FromDate = DateOnly.Parse fromDate
ToDate = DateOnly.Parse toDate
}
|> Ok
@@ -42,7 +42,7 @@ module Sessions =
let run (args : SessionsArgs) =
task {
let! client = Dto.make args.Creds
let! activity = client.GetSessions args.FromDate args.ToDate
let! activity = client.GetSessions (args.FromDate, args.ToDate)
System.Console.WriteLine (string<Sessions> activity)
return 0

View File

@@ -6,6 +6,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PureGym.App", "PureGym.App\
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PureGym.Test", "PureGym.Test\PureGym.Test.fsproj", "{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.Myriad.Plugins", "..\WoofWare.Myriad\WoofWare.Myriad.Plugins\WoofWare.Myriad.Plugins.fsproj", "{ECA6B986-ED3A-4CC0-B37E-8E928C9DB9B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.Build.0 = Release|Any CPU
{ECA6B986-ED3A-4CC0-B37E-8E928C9DB9B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECA6B986-ED3A-4CC0-B37E-8E928C9DB9B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECA6B986-ED3A-4CC0-B37E-8E928C9DB9B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECA6B986-ED3A-4CC0-B37E-8E928C9DB9B3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

27
PureGym/Api.fs Normal file
View File

@@ -0,0 +1,27 @@
namespace PureGym
open System
open System.Net.Http
open System.Threading.Tasks
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]
module Dto =
/// Create a REST client, authenticated as the specified user.
let make (auth : Auth) : IPureGymApi Task =
task {
let! token =
match auth with
| Auth.Token t -> Task.FromResult<_> t
| Auth.User cred -> AuthToken.get cred
let client = new HttpClient ()
client.BaseAddress <- Uri "https://capi.puregym.com/api"
client.DefaultRequestHeaders.Authorization <-
Headers.AuthenticationHeaderValue ("Bearer", token.AccessToken)
client.DefaultRequestHeaders.Add ("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")
return PureGymApi.make client
}

View File

@@ -2,57 +2,38 @@ namespace PureGym
open System
open System.Net.Http
open System.Threading
open System.Threading.Tasks
open RestEase
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<WoofWare.Myriad.Plugins.HttpClient>]
[<Header("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")>]
type IPureGymApi =
/// Get the complete list of all gyms known to PureGym.
[<Get "v1/gyms/">]
abstract GetGyms : unit -> Task<Gym list>
abstract GetGyms : ?ct : CancellationToken -> Task<Gym list>
/// Get information about the PureGym human whose credentials this client is authenticated with.
[<Get "v1/member">]
abstract GetMember : unit -> Task<Member>
abstract GetMember : ?ct : CancellationToken -> Task<Member>
/// Get information about how full the given gym currently is. The gym ID can be found from `GetGyms`.
[<Get "v1/gyms/{gym_id}/attendance">]
abstract GetGymAttendance : [<Path "gym_id">] gymId : int -> Task<GymAttendance>
abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance>
/// Get information about a specific gym.
[<Get "v1/gyms/{gym_id}">]
abstract GetGym : [<Path "gym_id">] gymId : int -> Task<Gym>
abstract GetGym : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<Gym>
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> Task<MemberActivityDto>
abstract GetMemberActivity : ?ct : CancellationToken -> Task<MemberActivityDto>
/// Get information about the individual visits to all PureGyms the currently-authenticated PureGym human has made.
[<Get "v2/gymSessions/member">]
abstract GetSessions : [<Query>] fromDate : DateTime -> [<Query>] toDate : DateTime -> Task<Sessions>
abstract GetSessions :
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
// [<Get "v1/member/activity/history">]
// abstract GetMemberActivityAll : unit -> Task<string>
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]
module Dto =
/// Create a REST client, authenticated as the specified user.
let make (auth : Auth) : IPureGymApi Task =
task {
let! token =
match auth with
| Auth.Token t -> Task.FromResult<_> t
| Auth.User cred -> AuthToken.get cred
let client = new HttpClient ()
client.BaseAddress <- Uri "https://capi.puregym.com/api"
client.DefaultRequestHeaders.Authorization <-
Headers.AuthenticationHeaderValue ("Bearer", token.AccessToken)
client.DefaultRequestHeaders.Add ("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")
return RestClient.For<IPureGymApi> client
}
// abstract GetMemberActivityAll : ?ct: CancellationToken -> Task<string>

View File

@@ -274,10 +274,13 @@ type SessionsAggregate =
{
/// Number of gym "activities" within some query-defined time period; presumably this is like classes?
/// It's always 0 for me.
[<JsonPropertyName "Activities">]
Activities : int
/// Number of visits to the gym within some query-defined time period.
[<JsonPropertyName "Visits">]
Visits : int
/// In minutes: total time spent in gym during the query-defined time period.
[<JsonPropertyName "Duration">]
Duration : int
}
@@ -287,10 +290,13 @@ type VisitGym =
{
// Omitting Location, GymAccess, ContactInfo, TimeZone because these were all null for me
/// The PureGym ID of this gym, e.g. 19
[<JsonPropertyName "Id">]
Id : int
/// E.g. "London Oval", the canonical name of this gym
[<JsonPropertyName "Name">]
Name : string
/// For some reason this always seems to be "Blocked"
[<JsonPropertyName "Status">]
Status : string
}
@@ -300,12 +306,16 @@ type Visit =
{
// Omitted Name because it always was null for me
/// Whether the Duration field is estimated.
[<JsonPropertyName "IsDurationEstimated">]
IsDurationEstimated : bool
/// When the visit began.
[<JsonPropertyName "StartTime">]
StartTime : DateTime
/// In minutes.
[<JsonPropertyName "Duration">]
Duration : int
/// Which gym was visited
[<JsonPropertyName "Gym">]
Gym : VisitGym
}
@@ -319,8 +329,10 @@ type Visit =
type SessionsSummary =
{
/// Aggregate stats for gym visits within the query-dependent time period.
[<JsonPropertyName "Total">]
Total : SessionsAggregate
/// Aggregate stats for gym visits "this week", whatever that means to PureGym.
[<JsonPropertyName "ThisWeek">]
ThisWeek : SessionsAggregate
}
@@ -330,7 +342,9 @@ type SessionsSummary =
[<WoofWare.Myriad.Plugins.JsonParse>]
type Sessions =
{
[<JsonPropertyName "Summary">]
Summary : SessionsSummary
[<JsonPropertyName "Visits">]
Visits : Visit list
}

169
PureGym/GeneratedClient.fs Normal file
View File

@@ -0,0 +1,169 @@
//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace PureGym
open System
open System.Net.Http
open System.Threading
open System.Threading.Tasks
open RestEase
/// Module for constructing a REST client.
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module PureGymApi =
/// Create a REST client.
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
{ new IPureGymApi with
member _.GetGyms (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/gyms/")
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return node.AsArray () |> Seq.map (fun elt -> Gym.jsonParse elt) |> List.ofSeq
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetMember (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/member")
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return Member.jsonParse node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetGymAttendance (gymId : int, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri =
System.Uri (
client.BaseAddress.ToString ()
+ "/v1/gyms/{gym_id}/attendance".Replace ("{gym_id}", gymId.ToString ())
)
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return GymAttendance.jsonParse node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetGym (gymId : int, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri =
System.Uri (
client.BaseAddress.ToString ()
+ "/v1/gyms/{gym_id}".Replace ("{gym_id}", gymId.ToString ())
)
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return Gym.jsonParse node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetMemberActivity (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/member/activity")
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return MemberActivityDto.jsonParse node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetSessions (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri =
System.Uri (
client.BaseAddress.ToString ()
+ ("/v2/gymSessions/member"
+ "?fromDate="
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
+ "&toDate="
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode))
)
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! node =
System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct)
|> Async.AwaitTask
return Sessions.jsonParse node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
}

View File

@@ -266,9 +266,9 @@ namespace PureGym
module SessionsAggregate =
/// Parse from a JSON node.
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
let Duration = node.["duration"].AsValue().GetValue<int> ()
let Visits = node.["visits"].AsValue().GetValue<int> ()
let Activities = node.["activities"].AsValue().GetValue<int> ()
let Duration = node.["Duration"].AsValue().GetValue<int> ()
let Visits = node.["Visits"].AsValue().GetValue<int> ()
let Activities = node.["Activities"].AsValue().GetValue<int> ()
{
Activities = Activities
@@ -283,9 +283,9 @@ namespace PureGym
module VisitGym =
/// Parse from a JSON node.
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
let Status = node.["status"].AsValue().GetValue<string> ()
let Name = node.["name"].AsValue().GetValue<string> ()
let Id = node.["id"].AsValue().GetValue<int> ()
let Status = node.["Status"].AsValue().GetValue<string> ()
let Name = node.["Name"].AsValue().GetValue<string> ()
let Id = node.["Id"].AsValue().GetValue<int> ()
{
Id = Id
@@ -300,13 +300,13 @@ namespace PureGym
module Visit =
/// Parse from a JSON node.
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
let Gym = VisitGym.jsonParse node.["gym"]
let Duration = node.["duration"].AsValue().GetValue<int> ()
let Gym = VisitGym.jsonParse node.["Gym"]
let Duration = node.["Duration"].AsValue().GetValue<int> ()
let StartTime =
node.["startTime"].AsValue().GetValue<string> () |> System.DateTime.Parse
node.["StartTime"].AsValue().GetValue<string> () |> System.DateTime.Parse
let IsDurationEstimated = node.["isDurationEstimated"].AsValue().GetValue<bool> ()
let IsDurationEstimated = node.["IsDurationEstimated"].AsValue().GetValue<bool> ()
{
IsDurationEstimated = IsDurationEstimated
@@ -322,8 +322,8 @@ namespace PureGym
module SessionsSummary =
/// Parse from a JSON node.
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
let ThisWeek = SessionsAggregate.jsonParse node.["thisWeek"]
let Total = SessionsAggregate.jsonParse node.["total"]
let ThisWeek = SessionsAggregate.jsonParse node.["ThisWeek"]
let Total = SessionsAggregate.jsonParse node.["Total"]
{
Total = Total
@@ -338,11 +338,11 @@ module Sessions =
/// Parse from a JSON node.
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
let Visits =
node.["visits"].AsArray ()
node.["Visits"].AsArray ()
|> Seq.map (fun elt -> Visit.jsonParse elt)
|> List.ofSeq
let Summary = SessionsSummary.jsonParse node.["summary"]
let Summary = SessionsSummary.jsonParse node.["Summary"]
{
Summary = Summary

View File

@@ -5,23 +5,27 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarnOn>FS3559</WarnOn>
<WoofWareMyriadPluginVersion>1.0.4</WoofWareMyriadPluginVersion>
<WoofWareMyriadPluginVersion>1.1.1</WoofWareMyriadPluginVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="String.fs" />
<Compile Include="Auth.fs" />
<Compile Include="Dto.fs" />
<Compile Include="String.fs" />
<Compile Include="Auth.fs" />
<Compile Include="Dto.fs" />
<Compile Include="GeneratedDto.fs"> <!--1-->
<MyriadFile>Dto.fs</MyriadFile> <!--2-->
</Compile>
<Compile Include="Client.fs" />
<Compile Include="GymSelector.fs" />
<EmbeddedResource Include="SurfaceBaseline.txt" />
<EmbeddedResource Include="version.json" />
<Compile Include="GeneratedClient.fs">
<MyriadFile>Client.fs</MyriadFile> <!--2-->
</Compile>
<Compile Include="Api.fs" />
<Compile Include="GymSelector.fs" />
<EmbeddedResource Include="SurfaceBaseline.txt" />
<EmbeddedResource Include="version.json" />
</ItemGroup>
<ItemGroup>
<MyriadSdkGenerator Include="$(NuGetPackageRoot)/woofware.myriad.plugins/$(WoofWareMyriadPluginVersion)/lib/net6.0/WoofWare.Myriad.Plugins.dll" />
</ItemGroup>
@@ -29,7 +33,7 @@
<ItemGroup>
<PackageReference Include="RestEase" Version="1.6.4" />
<PackageReference Update="FSharp.Core" Version="6.0.1" />
<PackageReference Include="System.Text.Json" Version="7.0.3" />
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<PackageReference Include="Fastenshtein" Version="1.0.0.8" />
<PackageReference Include="Myriad.Core" Version="0.8.3" />
<PackageReference Include="Myriad.Sdk" Version="0.8.3" />