WIP with JSON static parsing

This commit is contained in:
Smaug123
2023-12-27 20:21:08 +00:00
parent 77ceafde0b
commit 5fd1a52bd8
17 changed files with 756 additions and 94 deletions

View File

@@ -5,8 +5,8 @@ open PureGym
type AuthArg =
| [<Unique ; CustomAppSettings "PUREGYM_BEARER_TOKEN">] Bearer_Token of string
| [<Unique>] User_Email of string
| [<Unique>] Pin of string
| [<Unique ; EqualsAssignmentOrSpaced>] User_Email of string
| [<Unique ; EqualsAssignmentOrSpaced>] Pin of string
| [<GatherUnrecognized>] Others of string
interface IArgParserTemplate with

View File

@@ -14,7 +14,7 @@ type GetTokenArg =
match s with
| GetTokenArg.Pin _ -> "Eight-digit PureGym user's PIN"
| GetTokenArg.User_Email _ -> "PureGym user's email address"
| GetTokenArg.StdIn _ -> "Read anything not specified on the command line from stdin"
| GetTokenArg.StdIn -> "Read anything not specified on the command line from stdin"
static member Parse (args : ParseResults<GetTokenArg>) : Result<UsernamePin, ArguParseException> =
let canUseStdin = args.TryGetResult(GetTokenArg.StdIn).IsSome

View File

@@ -48,9 +48,10 @@ module Fullness =
let run (args : FullnessArgs) =
task {
let! client = Api.make args.Creds
let! client = Dto.make args.Creds
let! id = GymSelector.canonicalId client args.Gym
let! attendance = client.GetGymAttendance id
let attendance = failwith ""
if args.Terse then
System.Console.WriteLine attendance.TotalPeopleInGym

View File

@@ -44,7 +44,7 @@ module LookupGym =
let run (args : LookupGymArgs) =
task {
let! client = Api.make args.Creds
let! client = Dto.make args.Creds
let! s = client.GetGym 19
System.Console.WriteLine (string<Gym> s)
return 0

View File

@@ -31,9 +31,8 @@ module MemberActivity =
let run (args : MemberActivityArgs) =
task {
let! client = Api.make args.Creds
let! client = Dto.make args.Creds
let! activity = client.GetMemberActivity ()
let activity = activity.ToMemberActivity ()
System.Console.WriteLine (string<MemberActivityThisMonth> activity)
return 0
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@@ -41,7 +41,7 @@ module Sessions =
let run (args : SessionsArgs) =
task {
let! client = Api.make args.Creds
let! client = Dto.make args.Creds
let! activity = client.GetSessions args.FromDate args.ToDate
System.Console.WriteLine (string<Sessions> activity)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
@@ -9,12 +9,15 @@
<ItemGroup>
<Compile Include="TestSurface.fs" />
<Compile Include="TestJson.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.12" />
<PackageReference Include="FsCheck" Version="2.16.6" />
<PackageReference Include="FsUnit" Version="5.6.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="NUnit" Version="3.13.3"/>
<PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2"/>
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
<PackageReference Include="coverlet.collector" Version="3.2.0"/>

273
PureGym.Test/TestJson.fs Normal file
View File

@@ -0,0 +1,273 @@
namespace PureGym.Test
open System
open System.Text.Json.Nodes
open NUnit.Framework
open FsUnitTyped
open PureGym
[<TestFixture>]
module TestJson =
let gymOpeningHoursCases =
[
"""{"openingHours": [], "isAlwaysOpen": false}""", { GymOpeningHours.OpeningHours = [] ; IsAlwaysOpen = false }
"""{"openingHours": ["something"], "isAlwaysOpen": false}""", { GymOpeningHours.OpeningHours = ["something"] ; IsAlwaysOpen = false }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymOpeningHoursCases))>]
let ``GymOpeningHours JSON parse`` (json : string, expected : GymOpeningHours) =
JsonNode.Parse json
|> GymOpeningHours.jsonParse
|> shouldEqual expected
let gymAccessOptionsCases =
List.allPairs [ true ; false ] [ true ; false ]
|> List.map (fun (a, b) ->
let s = sprintf """{"pinAccess": %b, "qrCodeAccess": %b}""" a b
s, { GymAccessOptions.PinAccess = a ; QrCodeAccess = b }
)
|> List.map TestCaseData
[<TestCaseSource (nameof(gymAccessOptionsCases))>]
let ``GymAccessOptions JSON parse`` (json : string, expected : GymAccessOptions) =
JsonNode.Parse json
|> GymAccessOptions.jsonParse
|> shouldEqual expected
let gymLocationCases =
[
"""{"latitude": 1.0, "longitude": 3.0}""", { GymLocation.Latitude = 1.0 ; Longitude = 3.0 }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymLocationCases))>]
let ``GymLocation JSON parse`` (json : string, expected : GymLocation) =
JsonNode.Parse json
|> GymLocation.jsonParse
|> shouldEqual expected
let gymAddressCases =
[
"""{"addressLine1": "", "postCode": "hi", "town": ""}""", { GymAddress.AddressLine1 = "" ; AddressLine2 = None ; AddressLine3 = None ; County = None ; Postcode = "hi" ; Town = "" }
"""{"addressLine1": "", "addressLine2": null, "postCode": "hi", "town": ""}""", { GymAddress.AddressLine1 = "" ; AddressLine2 = None ; AddressLine3 = None ; County = None ; Postcode = "hi" ; Town = "" }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymAddressCases))>]
let ``GymAddress JSON parse`` (json : string, expected : GymAddress) =
JsonNode.Parse (json, Nullable (JsonNodeOptions(PropertyNameCaseInsensitive = true)))
|> GymAddress.jsonParse
|> shouldEqual expected
let gymCases =
let ovalJson = """{"name":"London Oval","id":19,"status":2,"address":{"addressLine1":"Canterbury Court","addressLine2":"Units 4, 4A, 5 And 5A","addressLine3":"Kennington Park","town":"LONDON","county":null,"postcode":"SW9 6DE"},"phoneNumber":"+44 3444770005","emailAddress":"info.londonoval@puregym.com","staffMembers":null,"gymOpeningHours":{"isAlwaysOpen":true,"openingHours":[]},"reasonsToJoin":null,"accessOptions":{"pinAccess":true,"qrCodeAccess":true},"virtualTourUrl":null,"personalTrainersUrl":null,"webViewUrl":null,"floorPlanUrl":null,"location":{"longitude":"-0.110252","latitude":"51.480401"},"timeZone":"Europe/London","reopenDate":"2021-04-12T00:00:00+01 Europe/London"}"""
let oval =
{
Gym.Name = "London Oval"
Id = 19
Status = 2
Address =
{
AddressLine1 = "Canterbury Court"
AddressLine2 = Some "Units 4, 4A, 5 And 5A"
AddressLine3 = Some "Kennington Park"
Town = "LONDON"
County = None
Postcode = "SW9 6DE"
}
PhoneNumber = "+44 3444770005"
EmailAddress = "info.londonoval@puregym.com"
GymOpeningHours =
{
IsAlwaysOpen = true
OpeningHours = []
}
AccessOptions = { PinAccess = true ; QrCodeAccess = true }
Location = { Longitude = -0.110252 ; Latitude = 51.480401 }
TimeZone = "Europe/London"
ReopenDate = "2021-04-12T00:00:00+01 Europe/London"
}
[
ovalJson, oval
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymCases))>]
let ``Gym JSON parse`` (json : string, expected : Gym) =
JsonNode.Parse json
|> Gym.jsonParse
|> shouldEqual expected
let memberCases =
let me =
{
Id = 1234567
CompoundMemberId = "12A123456"
FirstName = "Patrick"
LastName = "Stevens"
HomeGymId = 19
HomeGymName = "London Oval"
EmailAddress = "someone@somewhere"
GymAccessPin = "00000000"
DateOfBirth = DateOnly (1994, 01, 02)
MobileNumber = "+44 1234567"
Postcode = "W1A 1AA"
MembershipName = "Corporate"
MembershipLevel = 12
SuspendedReason = 0
MemberStatus = 2
}
let meJson = """{
"id": 1234567,
"compoundMemberId": "12A123456",
"firstName": "Patrick",
"lastName": "Stevens",
"homeGymId": 19,
"homeGymName": "London Oval",
"emailAddress": "someone@somewhere",
"gymAccessPin": "00000000",
"dateofBirth": "1994-01-02",
"mobileNumber": "+44 1234567",
"postCode": "W1A 1AA",
"membershipName": "Corporate",
"membershipLevel": 12,
"suspendedReason": 0,
"memberStatus": 2
}"""
[
meJson, me
]
|> List.map TestCaseData
[<TestCaseSource (nameof memberCases)>]
let ``Member JSON parse`` (json : string, expected : Member) =
json
|> JsonNode.Parse
|> Member.jsonParse
|> shouldEqual expected
let gymAttendanceCases =
let json = """{
"description": "65",
"totalPeopleInGym": 65,
"totalPeopleInClasses": 2,
"totalPeopleSuffix": null,
"isApproximate": false,
"attendanceTime": "2023-12-27T18:54:09.5101697",
"lastRefreshed": "2023-12-27T18:54:09.5101697Z",
"lastRefreshedPeopleInClasses": "2023-12-27T18:50:26.0782286Z",
"maximumCapacity": 0
}"""
let expected =
{
Description = "65"
TotalPeopleInGym = 65
TotalPeopleInClasses = 2
TotalPeopleSuffix = None
IsApproximate = false
AttendanceTime = DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc) + TimeSpan.FromTicks 7L
LastRefreshed = DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc) + TimeSpan.FromTicks 7L
LastRefreshedPeopleInClasses = DateTime (2023, 12, 27, 18, 50, 26, 078, 228, DateTimeKind.Utc) + TimeSpan.FromTicks 6L
MaximumCapacity = 0
}
[
json, expected
]
|> List.map TestCaseData
[<TestCaseSource (nameof gymAttendanceCases)>]
let ``GymAttendance JSON parse`` (json : string, expected : GymAttendance) =
json
|> JsonNode.Parse
|> GymAttendance.jsonParse
|> shouldEqual expected
let memberActivityDtoCases =
let json = """{"totalDuration":2217,"averageDuration":48,"totalVisits":46,"totalClasses":0,"isEstimated":false,"lastRefreshed":"2023-12-27T19:00:56.0309892Z"}"""
let value = {
TotalDuration = 2217
AverageDuration = 48
TotalVisits = 46
TotalClasses = 0
IsEstimated = false
LastRefreshed = DateTime (2023, 12, 27, 19, 00, 56, 030, 989, DateTimeKind.Utc) + TimeSpan.FromTicks 2L
}
[
json, value
]
|> List.map TestCaseData
[<TestCaseSource (nameof memberActivityDtoCases)>]
let ``MemberActivityDto JSON parse`` (json : string, expected : MemberActivityDto) =
json
|> JsonNode.Parse
|> MemberActivityDto.jsonParse
|> shouldEqual expected
let sessionsCases =
let json = """{
"Summary":{"Total":{"Activities":0,"Visits":10,"Duration":445},"ThisWeek":{"Activities":0,"Visits":0,"Duration":0}},
"Visits":[
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-21T10:12:00","Duration":50,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-20T12:05:00","Duration":80,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-17T19:37:00","Duration":46,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-16T12:19:00","Duration":37,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-15T11:14:00","Duration":47,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-13T10:30:00","Duration":36,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-10T16:18:00","Duration":32,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-05T22:36:00","Duration":40,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-03T17:59:00","Duration":48,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-01T21:41:00","Duration":29,"Name":null}],
"Activities":[]}
"""
let singleVisit startTime duration =
{
IsDurationEstimated = false
Gym = {
Id = 19
Name = "London Oval"
Status = "Blocked"
}
StartTime = startTime
Duration = duration
}
let expected = {
Summary = {
Total = {
Activities = 0
Visits = 10
Duration = 445
}
ThisWeek = {
Activities = 0
Visits = 0
Duration = 0
}
}
Visits =
[
singleVisit (DateTime (2023, 12, 21, 10, 12, 00)) 50
singleVisit (DateTime (2023, 12, 20, 12, 05, 00)) 80
singleVisit (DateTime (2023, 12, 17, 19, 37, 00)) 46
singleVisit (DateTime (2023, 12, 16, 12, 19, 00)) 37
singleVisit (DateTime (2023, 12, 15, 11, 14, 00)) 47
singleVisit (DateTime (2023, 12, 13, 10, 30, 00)) 36
singleVisit (DateTime (2023, 12, 10, 16, 18, 00)) 32
singleVisit (DateTime (2023, 12, 05, 22, 36, 00)) 40
singleVisit (DateTime (2023, 12, 03, 17, 59, 00)) 48
singleVisit (DateTime (2023, 12, 01, 21, 41, 00)) 29
]
}
[
json, expected
]
|> List.map TestCaseData
[<TestCaseSource (nameof sessionsCases)>]
let ``Sessions JSON parse`` (json : string, expected : Sessions) =
json
|> fun o -> JsonNode.Parse (o, Nullable (JsonNodeOptions (PropertyNameCaseInsensitive = true)))
|> Sessions.jsonParse
|> shouldEqual expected

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}") = "MyriadPlugin", "..\MyriadPlugin\MyriadPlugin\MyriadPlugin.fsproj", "{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}"
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
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

58
PureGym/Client.fs Normal file
View File

@@ -0,0 +1,58 @@
namespace PureGym
open System
open System.Net.Http
open System.Threading.Tasks
open RestEase
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<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>
/// Get information about the PureGym human whose credentials this client is authenticated with.
[<Get "v1/member">]
abstract GetMember : unit -> 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>
/// Get information about a specific gym.
[<Get "v1/gyms/{gym_id}">]
abstract GetGym : [<Path "gym_id">] gymId : int -> Task<Gym>
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> Task<MemberActivityThisMonth>
/// 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>
// [<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
}

View File

@@ -1,12 +1,10 @@
namespace PureGym
open System
open System.Net.Http
open System.Text.Json.Serialization
open System.Threading.Tasks
open RestEase
/// Describes the opening hours of a given gym.
[<MyriadPlugin.JsonParse>]
type GymOpeningHours =
{
/// If this is true, there should be no OpeningHours (but nothing enforces that).
@@ -23,6 +21,7 @@ type GymOpeningHours =
this.OpeningHours |> String.concat ", "
/// How a human can authenticate with a gym when they physically try to enter it
[<MyriadPlugin.JsonParse>]
type GymAccessOptions =
{
/// This gym has PIN entry pads
@@ -36,28 +35,32 @@ type GymAccessOptions =
$"Pin access: %c{Char.emoji this.PinAccess}; QR code access: %c{Char.emoji this.QrCodeAccess}"
/// Where a gym is on the Earth
[<MyriadPlugin.JsonParse>]
type GymLocation =
{
/// Measured in degrees
[<JsonNumberHandling (JsonNumberHandling.AllowReadingFromString)>]
Longitude : float
/// Measured in degrees
[<JsonNumberHandling (JsonNumberHandling.AllowReadingFromString)>]
Latitude : float
}
/// The postal address of a gym
[<MyriadPlugin.JsonParse>]
type GymAddress =
{
/// E.g. "Canterbury Court"
[<JsonRequired>]
AddressLine1 : string
/// E.g. "Units 4, 4A, 5 And 5A"
AddressLine2 : string
AddressLine2 : string option
/// E.g. "Kennington Park"
AddressLine3 : string
AddressLine3 : string option
/// E.g. "LONDON"
[<JsonRequired>]
Town : string
County : string
County : string option
/// E.g. "SW9 6DE"
[<JsonRequired>]
Postcode : string
@@ -67,11 +70,11 @@ type GymAddress =
override this.ToString () =
[
yield Some this.AddressLine1
yield this.AddressLine2 |> Option.ofObj
yield this.AddressLine3 |> Option.ofObj
yield this.AddressLine2
yield this.AddressLine3
match this.County with
| null -> yield Some $"%s{this.Town} %s{this.Postcode}"
| county ->
| None -> yield Some $"%s{this.Town} %s{this.Postcode}"
| Some county ->
yield Some this.Town
yield Some $"%s{county} %s{this.Postcode}"
]
@@ -79,6 +82,7 @@ type GymAddress =
|> String.concat "\n"
/// Metadata about a physical gym
[<MyriadPlugin.JsonParse>]
type Gym =
{
// The following fields are returned but are always null
@@ -133,6 +137,7 @@ Opening hours: %s{string<GymOpeningHours> this.GymOpeningHours}
"""
/// A human member of PureGym
[<MyriadPlugin.JsonParse>]
type Member =
{
/// This member's ID. This is a fairly large number.
@@ -153,10 +158,12 @@ type Member =
/// This user's gym access pin, probably 8 digits
GymAccessPin : string
/// This user's recorded date of birth
[<JsonPropertyName "dateofBirth">]
DateOfBirth : DateOnly
/// This user's phone number, human-readable
MobileNumber : string
/// This user's registered home postcode
[<JsonPropertyName "postCode">]
Postcode : string
/// E.g. "Corporate"
MembershipName : string
@@ -166,6 +173,7 @@ type Member =
}
/// Statistics for how many people are currently at a gym
[<MyriadPlugin.JsonParse>]
type GymAttendance =
{
/// This appears always to be just equal to TotalPeopleInGym, but a string.
@@ -178,7 +186,7 @@ type GymAttendance =
[<JsonRequired>]
TotalPeopleInClasses : int
/// E.g. " or fewer"
TotalPeopleSuffix : string
TotalPeopleSuffix : string option
[<JsonRequired>]
IsApproximate : bool
/// When the query was received (I think)
@@ -195,8 +203,8 @@ type GymAttendance =
override this.ToString () =
let totalPeopleSuffix =
match this.TotalPeopleSuffix with
| null -> ""
| suffix -> suffix
| None -> ""
| Some suffix -> suffix
let capacity =
if this.MaximumCapacity = 0 then
@@ -234,6 +242,7 @@ type MemberActivityThisMonth =
}
/// Don't use this type. It's public because System.Text.Json can't do private types.
[<MyriadPlugin.JsonParse>]
type MemberActivityDto =
{
[<JsonRequired>]
@@ -260,6 +269,7 @@ type MemberActivityDto =
LastRefreshed = this.LastRefreshed
}
[<MyriadPlugin.JsonParse>]
type SessionsAggregate =
{
/// Number of gym "activities" within some query-defined time period; presumably this is like classes?
@@ -272,6 +282,7 @@ type SessionsAggregate =
}
/// The DTO for gym info returned from the Sessions endpoint.
[<MyriadPlugin.JsonParse>]
type VisitGym =
{
// Omitting Location, GymAccess, ContactInfo, TimeZone because these were all null for me
@@ -284,6 +295,7 @@ type VisitGym =
}
/// Summary of a single visit to a gym.
[<MyriadPlugin.JsonParse>]
type Visit =
{
// Omitted Name because it always was null for me
@@ -303,6 +315,7 @@ type Visit =
$"%s{this.Gym.Name}: %s{startTime} (%i{this.Duration} minutes)"
/// Aggregate statistics for gym visits across a time period.
[<MyriadPlugin.JsonParse>]
type SessionsSummary =
{
/// Aggregate stats for gym visits within the query-dependent time period.
@@ -315,6 +328,7 @@ type SessionsSummary =
override this.ToString () =
$"%i{this.Total.Visits} visits, totalling %i{this.Total.Duration} minutes"
[<MyriadPlugin.JsonParse>]
type Sessions =
{
Summary : SessionsSummary
@@ -327,55 +341,3 @@ type Sessions =
let visits = this.Visits |> Seq.map string<Visit> |> String.concat "\n"
$"%s{summary}\n%s{visits}"
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<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>
/// Get information about the PureGym human whose credentials this client is authenticated with.
[<Get "v1/member">]
abstract GetMember : unit -> 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>
/// Get information about a specific gym.
[<Get "v1/gyms/{gym_id}">]
abstract GetGym : [<Path "gym_id">] gymId : int -> Task<Gym>
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> 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>
// [<Get "v1/member/activity/history">]
// abstract GetMemberActivityAll : unit -> Task<string>
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]
module Api =
/// 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
}

321
PureGym/GeneratedDto.fs Normal file
View File

@@ -0,0 +1,321 @@
//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace PureGym
/// Module containing JSON parsing methods for the GymOpeningHours type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymOpeningHours =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
let OpeningHours =
node.["openingHours"].AsArray()
|> Seq.map (fun elt -> elt.AsValue().GetValue<string>())
|> List.ofSeq
let IsAlwaysOpen = node.["isAlwaysOpen"].AsValue().GetValue<bool>()
{ IsAlwaysOpen = IsAlwaysOpen
OpeningHours = OpeningHours }
namespace PureGym
/// Module containing JSON parsing methods for the GymAccessOptions type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAccessOptions =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
let QrCodeAccess = node.["qrCodeAccess"].AsValue().GetValue<bool>()
let PinAccess = node.["pinAccess"].AsValue().GetValue<bool>()
{ PinAccess = PinAccess
QrCodeAccess = QrCodeAccess }
namespace PureGym
/// Module containing JSON parsing methods for the GymLocation type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymLocation =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymLocation =
let Latitude =
try
node.["latitude"].AsValue().GetValue<float>()
with :? System.InvalidOperationException as exc ->
if exc.Message.Contains "cannot be converted to" then
if
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
then
node.["latitude"].AsValue().GetValue<string>() |> System.Double.Parse
else
reraise ()
else
reraise ()
let Longitude =
try
node.["longitude"].AsValue().GetValue<float>()
with :? System.InvalidOperationException as exc ->
if exc.Message.Contains "cannot be converted to" then
if
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
then
node.["longitude"].AsValue().GetValue<string>() |> System.Double.Parse
else
reraise ()
else
reraise ()
{ Longitude = Longitude
Latitude = Latitude }
namespace PureGym
/// Module containing JSON parsing methods for the GymAddress type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAddress =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAddress =
let Postcode = node.["postcode"].AsValue().GetValue<string>()
let County =
match node.["county"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let Town = node.["town"].AsValue().GetValue<string>()
let AddressLine3 =
match node.["addressLine3"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let AddressLine2 =
match node.["addressLine2"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let AddressLine1 = node.["addressLine1"].AsValue().GetValue<string>()
{ AddressLine1 = AddressLine1
AddressLine2 = AddressLine2
AddressLine3 = AddressLine3
Town = Town
County = County
Postcode = Postcode }
namespace PureGym
/// Module containing JSON parsing methods for the Gym type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Gym =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Gym =
let ReopenDate = node.["reopenDate"].AsValue().GetValue<string>()
let TimeZone = node.["timeZone"].AsValue().GetValue<string>()
let Location = GymLocation.jsonParse node.["location"]
let AccessOptions = GymAccessOptions.jsonParse node.["accessOptions"]
let GymOpeningHours = GymOpeningHours.jsonParse node.["gymOpeningHours"]
let EmailAddress = node.["emailAddress"].AsValue().GetValue<string>()
let PhoneNumber = node.["phoneNumber"].AsValue().GetValue<string>()
let Address = GymAddress.jsonParse node.["address"]
let Status = node.["status"].AsValue().GetValue<int>()
let Id = node.["id"].AsValue().GetValue<int>()
let Name = node.["name"].AsValue().GetValue<string>()
{ Name = Name
Id = Id
Status = Status
Address = Address
PhoneNumber = PhoneNumber
EmailAddress = EmailAddress
GymOpeningHours = GymOpeningHours
AccessOptions = AccessOptions
Location = Location
TimeZone = TimeZone
ReopenDate = ReopenDate }
namespace PureGym
/// Module containing JSON parsing methods for the Member type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Member =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Member =
let MemberStatus = node.["memberStatus"].AsValue().GetValue<int>()
let SuspendedReason = node.["suspendedReason"].AsValue().GetValue<int>()
let MembershipLevel = node.["membershipLevel"].AsValue().GetValue<int>()
let MembershipName = node.["membershipName"].AsValue().GetValue<string>()
let Postcode = node.["postCode"].AsValue().GetValue<string>()
let MobileNumber = node.["mobileNumber"].AsValue().GetValue<string>()
let DateOfBirth =
node.["dateofBirth"].AsValue().GetValue<string>() |> System.DateOnly.Parse
let GymAccessPin = node.["gymAccessPin"].AsValue().GetValue<string>()
let EmailAddress = node.["emailAddress"].AsValue().GetValue<string>()
let HomeGymName = node.["homeGymName"].AsValue().GetValue<string>()
let HomeGymId = node.["homeGymId"].AsValue().GetValue<int>()
let LastName = node.["lastName"].AsValue().GetValue<string>()
let FirstName = node.["firstName"].AsValue().GetValue<string>()
let CompoundMemberId = node.["compoundMemberId"].AsValue().GetValue<string>()
let Id = node.["id"].AsValue().GetValue<int>()
{ Id = Id
CompoundMemberId = CompoundMemberId
FirstName = FirstName
LastName = LastName
HomeGymId = HomeGymId
HomeGymName = HomeGymName
EmailAddress = EmailAddress
GymAccessPin = GymAccessPin
DateOfBirth = DateOfBirth
MobileNumber = MobileNumber
Postcode = Postcode
MembershipName = MembershipName
MembershipLevel = MembershipLevel
SuspendedReason = SuspendedReason
MemberStatus = MemberStatus }
namespace PureGym
/// Module containing JSON parsing methods for the GymAttendance type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAttendance =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAttendance =
let MaximumCapacity = node.["maximumCapacity"].AsValue().GetValue<int>()
let LastRefreshedPeopleInClasses =
node.["lastRefreshedPeopleInClasses"].AsValue().GetValue<string>()
|> System.DateTime.Parse
let LastRefreshed =
node.["lastRefreshed"].AsValue().GetValue<string>() |> System.DateTime.Parse
let AttendanceTime =
node.["attendanceTime"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsApproximate = node.["isApproximate"].AsValue().GetValue<bool>()
let TotalPeopleSuffix =
match node.["totalPeopleSuffix"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let TotalPeopleInClasses = node.["totalPeopleInClasses"].AsValue().GetValue<int>()
let TotalPeopleInGym = node.["totalPeopleInGym"].AsValue().GetValue<int>()
let Description = node.["description"].AsValue().GetValue<string>()
{ Description = Description
TotalPeopleInGym = TotalPeopleInGym
TotalPeopleInClasses = TotalPeopleInClasses
TotalPeopleSuffix = TotalPeopleSuffix
IsApproximate = IsApproximate
AttendanceTime = AttendanceTime
LastRefreshed = LastRefreshed
LastRefreshedPeopleInClasses = LastRefreshedPeopleInClasses
MaximumCapacity = MaximumCapacity }
namespace PureGym
/// Module containing JSON parsing methods for the MemberActivityDto type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module MemberActivityDto =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
let LastRefreshed =
node.["lastRefreshed"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsEstimated = node.["isEstimated"].AsValue().GetValue<bool>()
let TotalClasses = node.["totalClasses"].AsValue().GetValue<int>()
let TotalVisits = node.["totalVisits"].AsValue().GetValue<int>()
let AverageDuration = node.["averageDuration"].AsValue().GetValue<int>()
let TotalDuration = node.["totalDuration"].AsValue().GetValue<int>()
{ TotalDuration = TotalDuration
AverageDuration = AverageDuration
TotalVisits = TotalVisits
TotalClasses = TotalClasses
IsEstimated = IsEstimated
LastRefreshed = LastRefreshed }
namespace PureGym
/// Module containing JSON parsing methods for the SessionsAggregate type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
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>()
{ Activities = Activities
Visits = Visits
Duration = Duration }
namespace PureGym
/// Module containing JSON parsing methods for the VisitGym type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
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>()
{ Id = Id
Name = Name
Status = Status }
namespace PureGym
/// Module containing JSON parsing methods for the Visit type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
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 StartTime =
node.["startTime"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsDurationEstimated = node.["isDurationEstimated"].AsValue().GetValue<bool>()
{ IsDurationEstimated = IsDurationEstimated
StartTime = StartTime
Duration = Duration
Gym = Gym }
namespace PureGym
/// Module containing JSON parsing methods for the SessionsSummary type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
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"]
{ Total = Total; ThisWeek = ThisWeek }
namespace PureGym
/// Module containing JSON parsing methods for the Sessions type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Sessions =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Sessions =
let Visits =
node.["visits"].AsArray()
|> Seq.map (fun elt -> Visit.jsonParse elt)
|> List.ofSeq
let Summary = SessionsSummary.jsonParse node.["summary"]
{ Summary = Summary; Visits = Visits }

View File

@@ -8,17 +8,30 @@
<ItemGroup>
<Compile Include="String.fs" />
<Compile Include="Auth.fs" />
<Compile Include="Api.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" />
</ItemGroup>
<ItemGroup>
<MyriadSdkGenerator Include="/Users/patrick/Documents/GitHub/MyriadPlugin/MyriadPlugin/bin/Debug/net6.0/MyriadPlugin.dll" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="RestEase" Version="1.6.4" />
<PackageReference Update="FSharp.Core" Version="6.0.0" />
<PackageReference Update="FSharp.Core" Version="6.0.1" />
<PackageReference Include="System.Text.Json" Version="7.0.3" />
<PackageReference Include="Fastenshtein" Version="1.0.0.8" />
<PackageReference Include="Myriad.Core" Version="0.8.3" />
<PackageReference Include="Myriad.Sdk" Version="0.8.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MyriadPlugin\MyriadPlugin\MyriadPlugin.fsproj" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,3 @@
PureGym.Api inherit obj
PureGym.Api.make [static method]: PureGym.Auth -> PureGym.IPureGymApi System.Threading.Tasks.Task
PureGym.Auth inherit obj, implements PureGym.Auth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Auth System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
PureGym.Auth+Tags inherit obj
PureGym.Auth+Tags.Token [static field]: int = 1
@@ -37,6 +35,8 @@ PureGym.AuthToken.get_ExpiryTime [method]: unit -> System.DateTime option
PureGym.AuthTokenModule inherit obj
PureGym.AuthTokenModule.get [static method]: PureGym.UsernamePin -> PureGym.AuthToken System.Threading.Tasks.Task
PureGym.AuthTokenModule.ofBearerToken [static method]: string -> PureGym.AuthToken
PureGym.Dto inherit obj
PureGym.Dto.make [static method]: PureGym.Auth -> PureGym.IPureGymApi System.Threading.Tasks.Task
PureGym.Gym inherit obj, implements PureGym.Gym System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Gym System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Gym..ctor [constructor]: (string, int, int, PureGym.GymAddress, string, string, PureGym.GymOpeningHours, PureGym.GymAccessOptions, PureGym.GymLocation, string, string)
PureGym.Gym.AccessOptions [property]: [read-only] PureGym.GymAccessOptions
@@ -67,22 +67,26 @@ PureGym.GymAccessOptions.get_PinAccess [method]: unit -> bool
PureGym.GymAccessOptions.get_QrCodeAccess [method]: unit -> bool
PureGym.GymAccessOptions.PinAccess [property]: [read-only] bool
PureGym.GymAccessOptions.QrCodeAccess [property]: [read-only] bool
PureGym.GymAccessOptionsModule inherit obj
PureGym.GymAccessOptionsModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAccessOptions
PureGym.GymAddress inherit obj, implements PureGym.GymAddress System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAddress System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymAddress..ctor [constructor]: (string, string, string, string, string, string)
PureGym.GymAddress..ctor [constructor]: (string, string option, string option, string, string option, string)
PureGym.GymAddress.AddressLine1 [property]: [read-only] string
PureGym.GymAddress.AddressLine2 [property]: [read-only] string
PureGym.GymAddress.AddressLine3 [property]: [read-only] string
PureGym.GymAddress.County [property]: [read-only] string
PureGym.GymAddress.AddressLine2 [property]: [read-only] string option
PureGym.GymAddress.AddressLine3 [property]: [read-only] string option
PureGym.GymAddress.County [property]: [read-only] string option
PureGym.GymAddress.get_AddressLine1 [method]: unit -> string
PureGym.GymAddress.get_AddressLine2 [method]: unit -> string
PureGym.GymAddress.get_AddressLine3 [method]: unit -> string
PureGym.GymAddress.get_County [method]: unit -> string
PureGym.GymAddress.get_AddressLine2 [method]: unit -> string option
PureGym.GymAddress.get_AddressLine3 [method]: unit -> string option
PureGym.GymAddress.get_County [method]: unit -> string option
PureGym.GymAddress.get_Postcode [method]: unit -> string
PureGym.GymAddress.get_Town [method]: unit -> string
PureGym.GymAddress.Postcode [property]: [read-only] string
PureGym.GymAddress.Town [property]: [read-only] string
PureGym.GymAddressModule inherit obj
PureGym.GymAddressModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAddress
PureGym.GymAttendance inherit obj, implements PureGym.GymAttendance System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAttendance System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymAttendance..ctor [constructor]: (string, int, int, string, bool, System.DateTime, System.DateTime, System.DateTime, int)
PureGym.GymAttendance..ctor [constructor]: (string, int, int, string option, bool, System.DateTime, System.DateTime, System.DateTime, int)
PureGym.GymAttendance.AttendanceTime [property]: [read-only] System.DateTime
PureGym.GymAttendance.Description [property]: [read-only] string
PureGym.GymAttendance.get_AttendanceTime [method]: unit -> System.DateTime
@@ -93,26 +97,34 @@ PureGym.GymAttendance.get_LastRefreshedPeopleInClasses [method]: unit -> System.
PureGym.GymAttendance.get_MaximumCapacity [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleInClasses [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleInGym [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleSuffix [method]: unit -> string
PureGym.GymAttendance.get_TotalPeopleSuffix [method]: unit -> string option
PureGym.GymAttendance.IsApproximate [property]: [read-only] bool
PureGym.GymAttendance.LastRefreshed [property]: [read-only] System.DateTime
PureGym.GymAttendance.LastRefreshedPeopleInClasses [property]: [read-only] System.DateTime
PureGym.GymAttendance.MaximumCapacity [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleInClasses [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleInGym [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleSuffix [property]: [read-only] string
PureGym.GymAttendance.TotalPeopleSuffix [property]: [read-only] string option
PureGym.GymAttendanceModule inherit obj
PureGym.GymAttendanceModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAttendance
PureGym.GymLocation inherit obj, implements PureGym.GymLocation System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymLocation System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymLocation..ctor [constructor]: (float, float)
PureGym.GymLocation.get_Latitude [method]: unit -> float
PureGym.GymLocation.get_Longitude [method]: unit -> float
PureGym.GymLocation.Latitude [property]: [read-only] float
PureGym.GymLocation.Longitude [property]: [read-only] float
PureGym.GymLocationModule inherit obj
PureGym.GymLocationModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymLocation
PureGym.GymModule inherit obj
PureGym.GymModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Gym
PureGym.GymOpeningHours inherit obj, implements PureGym.GymOpeningHours System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymOpeningHours System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymOpeningHours..ctor [constructor]: (bool, string list)
PureGym.GymOpeningHours.get_IsAlwaysOpen [method]: unit -> bool
PureGym.GymOpeningHours.get_OpeningHours [method]: unit -> string list
PureGym.GymOpeningHours.IsAlwaysOpen [property]: [read-only] bool
PureGym.GymOpeningHours.OpeningHours [property]: [read-only] string list
PureGym.GymOpeningHoursModule inherit obj
PureGym.GymOpeningHoursModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymOpeningHours
PureGym.GymSelector inherit obj, implements PureGym.GymSelector System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymSelector System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 3 cases
PureGym.GymSelector+Id inherit PureGym.GymSelector
PureGym.GymSelector+Id.get_Item [method]: unit -> int
@@ -143,8 +155,8 @@ PureGym.IPureGymApi.GetGym [method]: int -> PureGym.Gym System.Threading.Tasks.T
PureGym.IPureGymApi.GetGymAttendance [method]: int -> PureGym.GymAttendance System.Threading.Tasks.Task
PureGym.IPureGymApi.GetGyms [method]: unit -> PureGym.Gym list System.Threading.Tasks.Task
PureGym.IPureGymApi.GetMember [method]: unit -> PureGym.Member System.Threading.Tasks.Task
PureGym.IPureGymApi.GetMemberActivity [method]: unit -> PureGym.MemberActivityDto System.Threading.Tasks.Task
PureGym.IPureGymApi.GetSessions [method]: System.DateTime -> System.DateTime -> PureGym.Sessions System.Threading.Tasks.Task
PureGym.IPureGymApi.GetMemberActivity [method]: unit -> string System.Threading.Tasks.Task
PureGym.IPureGymApi.GetSessions [method]: System.DateTime -> System.DateTime -> string System.Threading.Tasks.Task
PureGym.Member inherit obj, implements PureGym.Member System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Member System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Member..ctor [constructor]: (int, string, string, string, int, string, string, string, System.DateOnly, string, string, string, int, int, int)
PureGym.Member.CompoundMemberId [property]: [read-only] string
@@ -192,6 +204,8 @@ PureGym.MemberActivityDto.ToMemberActivity [method]: unit -> PureGym.MemberActiv
PureGym.MemberActivityDto.TotalClasses [property]: [read-only] int
PureGym.MemberActivityDto.TotalDuration [property]: [read-only] int
PureGym.MemberActivityDto.TotalVisits [property]: [read-only] int
PureGym.MemberActivityDtoModule inherit obj
PureGym.MemberActivityDtoModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.MemberActivityDto
PureGym.MemberActivityThisMonth inherit obj, implements PureGym.MemberActivityThisMonth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.MemberActivityThisMonth System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.MemberActivityThisMonth..ctor [constructor]: (int, int, int, int, bool, System.DateTime)
PureGym.MemberActivityThisMonth.AverageDurationMinutes [property]: [read-only] int
@@ -206,6 +220,8 @@ PureGym.MemberActivityThisMonth.LastRefreshed [property]: [read-only] System.Dat
PureGym.MemberActivityThisMonth.TotalClasses [property]: [read-only] int
PureGym.MemberActivityThisMonth.TotalDurationMinutes [property]: [read-only] int
PureGym.MemberActivityThisMonth.TotalVisits [property]: [read-only] int
PureGym.MemberModule inherit obj
PureGym.MemberModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Member
PureGym.Sessions inherit obj, implements PureGym.Sessions System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Sessions System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Sessions..ctor [constructor]: (PureGym.SessionsSummary, PureGym.Visit list)
PureGym.Sessions.get_Summary [method]: unit -> PureGym.SessionsSummary
@@ -220,12 +236,18 @@ PureGym.SessionsAggregate.get_Activities [method]: unit -> int
PureGym.SessionsAggregate.get_Duration [method]: unit -> int
PureGym.SessionsAggregate.get_Visits [method]: unit -> int
PureGym.SessionsAggregate.Visits [property]: [read-only] int
PureGym.SessionsAggregateModule inherit obj
PureGym.SessionsAggregateModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.SessionsAggregate
PureGym.SessionsModule inherit obj
PureGym.SessionsModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Sessions
PureGym.SessionsSummary inherit obj, implements PureGym.SessionsSummary System.IEquatable, System.Collections.IStructuralEquatable, PureGym.SessionsSummary System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.SessionsSummary..ctor [constructor]: (PureGym.SessionsAggregate, PureGym.SessionsAggregate)
PureGym.SessionsSummary.get_ThisWeek [method]: unit -> PureGym.SessionsAggregate
PureGym.SessionsSummary.get_Total [method]: unit -> PureGym.SessionsAggregate
PureGym.SessionsSummary.ThisWeek [property]: [read-only] PureGym.SessionsAggregate
PureGym.SessionsSummary.Total [property]: [read-only] PureGym.SessionsAggregate
PureGym.SessionsSummaryModule inherit obj
PureGym.SessionsSummaryModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.SessionsSummary
PureGym.UsernamePin inherit obj, implements PureGym.UsernamePin System.IEquatable, System.Collections.IStructuralEquatable, PureGym.UsernamePin System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.UsernamePin..ctor [constructor]: (string, string)
PureGym.UsernamePin.get_Pin [method]: unit -> string
@@ -249,4 +271,8 @@ PureGym.VisitGym.get_Name [method]: unit -> string
PureGym.VisitGym.get_Status [method]: unit -> string
PureGym.VisitGym.Id [property]: [read-only] int
PureGym.VisitGym.Name [property]: [read-only] string
PureGym.VisitGym.Status [property]: [read-only] string
PureGym.VisitGym.Status [property]: [read-only] string
PureGym.VisitGymModule inherit obj
PureGym.VisitGymModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.VisitGym
PureGym.VisitModule inherit obj
PureGym.VisitModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Visit

0
PureGym/myriad.toml Normal file
View File

View File

@@ -1,5 +1,5 @@
{
"version": "2.0",
"version": "3.0",
"publicReleaseRefSpec": [
"^refs/heads/main$"
],