diff --git a/ApiAccessLevel.cs b/ApiAccessLevel.cs new file mode 100644 index 0000000..dc7a386 --- /dev/null +++ b/ApiAccessLevel.cs @@ -0,0 +1,33 @@ +namespace Tiltify +{ + public enum ApiAccessLevel + { + None, + OAuth, + Public, + Private, + PublicPrivate, + } + + public static class ApiAccessPath + { + public static string GetPath(ApiAccessLevel level, ApiVersion version) + { + // V3 doesn't add access level pathing + if (version == ApiVersion.V3) + return ""; + + switch (level) + { + case ApiAccessLevel.Public: + return "/api/public"; + case ApiAccessLevel.Private: + return "/api/private"; + case ApiAccessLevel.OAuth: + case ApiAccessLevel.None: + default: + return ""; + } + } + } +} diff --git a/ApiBase.cs b/ApiBase.cs index e3e86c7..eb83793 100644 --- a/ApiBase.cs +++ b/ApiBase.cs @@ -7,9 +7,7 @@ namespace Tiltify { public class ApiBase { - internal const string BaseTiltifyAPI = "https://tiltify.com/api"; - - private readonly ApiSettings settings; + protected ApiSettings settings; private readonly IRateLimiter rateLimiter; private readonly IHttpCallHandler http; @@ -25,33 +23,60 @@ public ApiBase(ApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler this.http = http; } - protected async Task TiltifyGetAsync(string resource, ApiVersion api, List> getParams = null, string customBase = null) + public ApiVersion GetApiVersion() => settings.APIVersion; + + protected async Task TiltifyGetAsync(string resource, ApiVersion api, List> getParams = null, string customBase = null, ApiAccessLevel access = ApiAccessLevel.Public) { - var url = ConstructResourceUrl(resource, getParams, api, customBase); + var url = ConstructResourceUrl(resource, getParams, api, customBase, access); var accessToken = settings.OAuthToken; return await rateLimiter.Perform(async () => (await http.GeneralRequestAsync(url, "GET", null, api, accessToken).ConfigureAwait(false)).Value).ConfigureAwait(false); } - protected async Task TiltifyGetGenericAsync(string resource, ApiVersion api, List> getParams = null, string customBase = null) + protected async Task TiltifyGetGenericAsync(string resource, ApiVersion api, List> getParams = null, string customBase = null, ApiAccessLevel access = ApiAccessLevel.Public) { - var url = ConstructResourceUrl(resource, getParams, api, customBase); + var url = ConstructResourceUrl(resource, getParams, api, customBase, access); var accessToken = settings.OAuthToken; return await rateLimiter.Perform(async () => JsonConvert.DeserializeObject((await http.GeneralRequestAsync(url, "GET", null, api, accessToken).ConfigureAwait(false)).Value, jsonDeserializer)).ConfigureAwait(false); } - private string ConstructResourceUrl(string resource = null, List> getParams = null, ApiVersion api = ApiVersion.V3, string overrideUrl = null) + protected async Task TiltifyPostGenericAsync(string resource, ApiVersion api, List> getParams = null, string customBase = null, ApiAccessLevel access = ApiAccessLevel.Public) + { + var url = ConstructResourceUrl(resource, null, api, customBase, access); + string payload = ""; + + if (getParams != null) + { + Dictionary converted = new Dictionary(); + // Fun conversion from a KVP to a Dictionary so it can convert properly via JSONConvert + getParams.ForEach((singleKvp) => converted.Add(singleKvp.Key, singleKvp.Value)); + payload = JsonConvert.SerializeObject(converted); + } + + string accessToken = string.Empty; + if (access != ApiAccessLevel.OAuth) + accessToken = settings.OAuthToken; + + return await rateLimiter.Perform(async () => JsonConvert.DeserializeObject((await http.GeneralRequestAsync(url, "POST", payload, api, accessToken).ConfigureAwait(false)).Value, jsonDeserializer)).ConfigureAwait(false); + } + + private string ConstructResourceUrl(string resource = null, List> getParams = null, ApiVersion api = ApiVersion.Latest, string overrideUrl = null, ApiAccessLevel access = ApiAccessLevel.Public) { var url = ""; if (overrideUrl == null) { if (resource == null) throw new Exception("Cannot pass null resource with null override url"); + + string accessPath = ApiAccessPath.GetPath(access, api); switch (api) { case ApiVersion.V3: - url = $"{BaseTiltifyAPI}/v3{resource}"; + url = $"https://tiltify.com/api/v3{resource}"; + break; + case ApiVersion.V5: + url = $"https://v5api.tiltify.com{accessPath}{resource}"; break; } } @@ -59,14 +84,18 @@ private string ConstructResourceUrl(string resource = null, List Authorize(AuthGrantType grantType = AuthGrantType.ClientCredentials, ApiAccessLevel scopes = ApiAccessLevel.Public, string authCode = "") + { + List> Args = new List>(); + Args.Add(new KeyValuePair("grant_type", GrantTypeToString(grantType))); + Args.Add(new KeyValuePair("client_id", settings.ClientID)); + Args.Add(new KeyValuePair("client_secret", settings.ClientSecret)); + + if (grantType == AuthGrantType.AuthorizationCode) + { + Args.Add(new KeyValuePair("code", authCode)); + } + else if (grantType == AuthGrantType.RefreshToken) + { + Args.Add(new KeyValuePair("refresh_token", settings.RefreshToken)); + } + + // Adding the scopes + string scopeForm; + switch(scopes) + { + default: + case ApiAccessLevel.Public: + scopeForm = "public"; + break; + case ApiAccessLevel.Private: + scopeForm = "webhooks:write"; + break; + case ApiAccessLevel.PublicPrivate: + scopeForm = "public webhooks:write"; + break; + } + Args.Add(new KeyValuePair("scope", scopeForm)); + + Task authResp = TiltifyPostGenericAsync("/oauth/token", GetApiVersion(), Args, null, ApiAccessLevel.OAuth); + if (authResp.Result != null) + { + AuthorizationResponse resp = authResp.Result; + if (resp.Type == "bearer") + settings.OAuthToken = resp.AccessToken; + + if (resp.RefreshToken != null) + settings.RefreshToken = resp.RefreshToken; + } + return authResp; + } + } +} diff --git a/Campaigns.cs b/Campaigns.cs index dc13c6f..5835ce0 100644 --- a/Campaigns.cs +++ b/Campaigns.cs @@ -1,5 +1,8 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Tiltify.Models; +using System; +using System.Globalization; namespace Tiltify { @@ -9,9 +12,21 @@ public Campaigns(ApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandle { } - public Task GetCampaignDonations(int campaignId) + public Task GetCampaignDonations(int campaignId, ApiAccessLevel access = ApiAccessLevel.Public) { - return TiltifyGetGenericAsync($"/campaigns/{campaignId}/donations", ApiVersion.V3); + return TiltifyGetGenericAsync($"/campaigns/{campaignId}/donations", ApiVersion.V3, null, null, access); + } + + public Task GetCampaignDonations(string campaignId, ApiAccessLevel access = ApiAccessLevel.Public) + { + return TiltifyGetGenericAsync($"/campaigns/{campaignId}/donations", GetApiVersion(), null, null, access); + } + + public Task GetCampaignDonations(string campaignId, DateTime donationsAfter, int limit = 10, ApiAccessLevel access = ApiAccessLevel.Public) + { + List> Args = new List>(); + Args.Add(new KeyValuePair("completed_after", donationsAfter.ToString("o", CultureInfo.InvariantCulture))); + return TiltifyGetGenericAsync($"/campaigns/{campaignId}/donations?limit={limit}", GetApiVersion(), Args, null, access); } } } diff --git a/Events/OnCampaignDonationArgs.cs b/Events/OnCampaignDonationArgs.cs index ee126a0..8c13290 100644 --- a/Events/OnCampaignDonationArgs.cs +++ b/Events/OnCampaignDonationArgs.cs @@ -5,6 +5,6 @@ namespace Tiltify.Events { public class OnCampaignDonationArgs : EventArgs { - public DonationInformation Donation; + public WebSocketDonationInformation Donation; } } \ No newline at end of file diff --git a/IHttpCallHandler.cs b/IHttpCallHandler.cs index 19e3a1f..3136f2d 100644 --- a/IHttpCallHandler.cs +++ b/IHttpCallHandler.cs @@ -5,7 +5,7 @@ namespace Tiltify { public interface IHttpCallHandler { - Task> GeneralRequestAsync(string url, string method, string payload = null, ApiVersion api = ApiVersion.V3, string accessToken = null); + Task> GeneralRequestAsync(string url, string method, string payload = null, ApiVersion api = ApiVersion.Latest, string accessToken = null); Task PutBytesAsync(string url, byte[] payload); Task RequestReturnResponseCodeAsync(string url, string method, List> getParams = null); } diff --git a/Models/AuthorizationResponse.cs b/Models/AuthorizationResponse.cs new file mode 100644 index 0000000..9106912 --- /dev/null +++ b/Models/AuthorizationResponse.cs @@ -0,0 +1,25 @@ +using Newtonsoft.Json; + +namespace Tiltify.Models +{ + public class AuthorizationResponse + { + [JsonProperty(PropertyName = "access_token")] + public string AccessToken; + + [JsonProperty(PropertyName = "created_at")] + public string CreationTime; + + [JsonProperty(PropertyName = "expires_in")] + public int Expiration; +#nullable enable + [JsonProperty(PropertyName = "refresh_token")] + public string? RefreshToken; +#nullable restore + [JsonProperty(PropertyName = "scope")] + public string Scope; + + [JsonProperty(PropertyName = "token_type")] + public string Type; + } +} diff --git a/Models/DonationInformation.cs b/Models/DonationInformation.cs index bfbef52..b0ac9fd 100644 --- a/Models/DonationInformation.cs +++ b/Models/DonationInformation.cs @@ -3,28 +3,36 @@ namespace Tiltify.Models { - //{ "amount":1.0,"challenge_id":null,"comment":null,"completedAt":1650338036000,"event_id":165720,"id":5842193,"name":"Anonymous","poll_option_id":null,"reward_id":null,"updatedAt":1650338036000} + public class Money + { + [JsonProperty(PropertyName = "currency")] + public string Currency = string.Empty; + + [JsonProperty(PropertyName = "value")] + public string Value = string.Empty; + } + public class DonationInformation { [JsonProperty(PropertyName = "id")] - public int Id { get; protected set; } - [JsonProperty(PropertyName = "event_id")] - public int? CampaignId { get; protected set; } - [JsonProperty(PropertyName = "challenge_id")] - public int? ChallengeId { get; protected set; } + public string Id { get; protected set; } +#nullable enable + [JsonProperty(PropertyName = "campaign_id")] + public string? CampaignId { get; protected set; } + [JsonProperty(PropertyName = "poll_option_id")] - public int? PollOptionId { get; protected set; } + public string? PollOptionId { get; protected set; } + [JsonProperty(PropertyName = "amount")] - public double Amount { get; protected set; } - [JsonProperty(PropertyName = "name")] + public Money? Amount { get; protected set; } +#nullable restore + [JsonProperty(PropertyName = "donor_name")] public string Name { get; protected set; } - [JsonProperty(PropertyName = "comment")] + + [JsonProperty(PropertyName = "donor_comment")] public string Comment { get; protected set; } - [JsonProperty(PropertyName = "completedAt")] - public long CompletedAt { get; protected set; } - [JsonProperty(PropertyName = "reward_id")] - public int? RewardId { get; protected set; } - [JsonProperty(PropertyName = "rewardId")] - private int? RewardIdAltKey { set { RewardId = value; } } + + [JsonProperty(PropertyName = "completed_at")] + public string CompletedAt { get; protected set; } } } diff --git a/Models/GetTeamCampaignResponse.cs b/Models/GetTeamCampaignResponse.cs new file mode 100644 index 0000000..c6b5a12 --- /dev/null +++ b/Models/GetTeamCampaignResponse.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Tiltify.Models +{ + public class GetTeamCampaignResponse + { + [JsonProperty(PropertyName = "data")] + public TeamCampaignInfo Data { get; protected set; } + } +} diff --git a/Models/TeamCampaignInfo.cs b/Models/TeamCampaignInfo.cs new file mode 100644 index 0000000..4a77057 --- /dev/null +++ b/Models/TeamCampaignInfo.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; + +namespace Tiltify.Models +{ +#nullable enable + public class TeamCampaignInfo + { + [JsonProperty(PropertyName = "amount_raised")] + public Money? TeamAmountRaised { get; set; } + + [JsonProperty(PropertyName = "currency_code")] + public string CurrencyCode { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "description")] + public string? Description { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "donate_url")] + public string DonateURL { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "url")] + public string URL { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "goal")] + public Money? Goal { get; set; } + + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "status")] + public string Status { get; set; } = string.Empty; + + [JsonProperty(PropertyName = "supporting_amount_raised")] + public Money? SupportingAmountsRaised { get; set; } + + [JsonProperty(PropertyName = "total_amount_raised")] + public Money? TotalAmountRaised { get; set; } + } +#nullable restore +} diff --git a/Models/WebSocketDonationInformation.cs b/Models/WebSocketDonationInformation.cs new file mode 100644 index 0000000..8951eeb --- /dev/null +++ b/Models/WebSocketDonationInformation.cs @@ -0,0 +1,30 @@ + +using Newtonsoft.Json; + +namespace Tiltify.Models +{ + //{ "amount":1.0,"challenge_id":null,"comment":null,"completedAt":1650338036000,"event_id":165720,"id":5842193,"name":"Anonymous","poll_option_id":null,"reward_id":null,"updatedAt":1650338036000} + public class WebSocketDonationInformation + { + [JsonProperty(PropertyName = "id")] + public int Id { get; protected set; } + [JsonProperty(PropertyName = "event_id")] + public int? CampaignId { get; protected set; } + [JsonProperty(PropertyName = "challenge_id")] + public int? ChallengeId { get; protected set; } + [JsonProperty(PropertyName = "poll_option_id")] + public int? PollOptionId { get; protected set; } + [JsonProperty(PropertyName = "amount")] + public double Amount { get; protected set; } + [JsonProperty(PropertyName = "name")] + public string Name { get; protected set; } + [JsonProperty(PropertyName = "comment")] + public string Comment { get; protected set; } + [JsonProperty(PropertyName = "completedAt")] + public long CompletedAt { get; protected set; } + [JsonProperty(PropertyName = "reward_id")] + public int? RewardId { get; protected set; } + [JsonProperty(PropertyName = "rewardId")] + private int? RewardIdAltKey { set { RewardId = value; } } + } +} diff --git a/TeamCampaigns.cs b/TeamCampaigns.cs new file mode 100644 index 0000000..9a12eb2 --- /dev/null +++ b/TeamCampaigns.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Tiltify.Models; +using System; +using System.Globalization; + +namespace Tiltify +{ + public class TeamCampaigns : ApiBase + { + public TeamCampaigns(ApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http) : base(settings, rateLimiter, http) + { + } + + public Task GetCampaign(string campaignId) + { + return TiltifyGetGenericAsync($"/team_campaigns/{campaignId}/", GetApiVersion(), null, null, ApiAccessLevel.Public); + } + + public Task GetCampaignDonations(string campaignId, ApiAccessLevel access = ApiAccessLevel.Public) + { + return TiltifyGetGenericAsync($"/team_campaigns/{campaignId}/donations", GetApiVersion(), null, null, access); + } + + public Task GetCampaignDonations(string campaignId, DateTime donationsAfter, int limit = 10, ApiAccessLevel access = ApiAccessLevel.Public) + { + List> Args = new List>(); + Args.Add(new KeyValuePair("completed_after", donationsAfter.ToString("o", CultureInfo.InvariantCulture))); + return TiltifyGetGenericAsync($"/team_campaigns/{campaignId}/donations?limit={limit}", GetApiVersion(), Args, null, access); + } + } +} diff --git a/Tiltify-Client.csproj b/Tiltify-Client.csproj index db61a88..9a4cc93 100644 --- a/Tiltify-Client.csproj +++ b/Tiltify-Client.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net6.0 Tiltify_Client diff --git a/Tiltify.cs b/Tiltify.cs index 826fb4a..e0d99a7 100644 --- a/Tiltify.cs +++ b/Tiltify.cs @@ -8,7 +8,9 @@ public class Tiltify private readonly ILogger logger; public ApiSettings Settings { get; } + public Auth Auth { get; } public Campaigns Campaigns { get; } + public TeamCampaigns TeamCampaigns { get; } public Users Users { get; } /// @@ -25,7 +27,9 @@ public Tiltify(ILoggerFactory loggerFactory = null, IRateLimiter rateLimiter = n http = http ?? new TiltifyhHttpClient(loggerFactory?.CreateLogger()); Settings = settings ?? new ApiSettings(); + Auth = new Auth(settings, rateLimiter, http); Campaigns = new Campaigns(settings, rateLimiter, http); + TeamCampaigns = new TeamCampaigns(settings, rateLimiter, http); Users = new Users(settings, rateLimiter, http); } } diff --git a/TiltifyHttpClient.cs b/TiltifyHttpClient.cs index feba734..79600e8 100644 --- a/TiltifyHttpClient.cs +++ b/TiltifyHttpClient.cs @@ -35,7 +35,7 @@ public async Task PutBytesAsync(string url, byte[] payload) } public async Task> GeneralRequestAsync(string url, string method, - string payload = null, ApiVersion api = ApiVersion.V3, string accessToken = null) + string payload = null, ApiVersion api = ApiVersion.Latest, string accessToken = null) { var request = new HttpRequestMessage { @@ -43,14 +43,22 @@ public async Task> GeneralRequestAsync(string url, str Method = new HttpMethod(method) }; - if (string.IsNullOrWhiteSpace(accessToken)) - throw new InvalidCredentialException("A Client-Id and OAuth token is required to use the Tiltify API."); - request.Headers.Add(HttpRequestHeader.Accept.ToString(), "application/json"); - request.Headers.Add(HttpRequestHeader.Authorization.ToString(), $"Bearer {FormatOAuth(accessToken)}"); + if (!string.IsNullOrWhiteSpace(accessToken)) + { + request.Headers.Add(HttpRequestHeader.Authorization.ToString(), $"Bearer {FormatOAuth(accessToken)}"); + } + else if (method.ToLower() == "get") + { + // All their GET apis require an oauth token in some regard. + throw new InvalidCredentialException("A Client-Id and OAuth token is required to use the Tiltify API."); + } if (payload != null) + { request.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + request.Headers.Add(HttpRequestHeader.ContentType.ToString(), "application/json"); + } var response = await _http.SendAsync(request).ConfigureAwait(false); if (response.IsSuccessStatusCode) diff --git a/TiltifyWebSocket.cs b/TiltifyWebSocket.cs index 923e459..6a2475b 100644 --- a/TiltifyWebSocket.cs +++ b/TiltifyWebSocket.cs @@ -196,16 +196,16 @@ private void PongTimerTick(object sender, ElapsedEventArgs e) /* * Heartbeat required every 30 seconds - * JOIN: ["27","27","campaign.165613.donation","phx_join",{}] - * JOIN REPLY: ["27","27","campaign.165613.donation","phx_reply",{"response":{},"status":"ok"}] + * JOIN: ["27","27","fact.165613.donation","phx_join",{}] + * JOIN REPLY: ["27","27","fact.165613.donation","phx_reply",{"response":{},"status":"ok"}] * HEARTBEAT: [null,"32","phoenix","heartbeat",{}] * HEARTBEAT REPLY: [null,"32","phoenix","phx_reply",{"response":{},"status":"ok"}] - * LEAVE: ["27","28","campaign.165613.donation","phx_leave",{}] - * LEAVE REPLY: ["27","28","campaign.165613.donation","phx_reply",{"response":{},"status":"ok"}] - * CLOSE REPLY: ["27","27","campaign.165613.donation","phx_close",{}] - * DONATION: [null,null,"campaign.165613.donation","donation",{"amount":37.0,"challenge_id":31290,"comment":"Muensterous cheese puns! I may not be that sharp, but this is no gouda! Swiss entire idea is full of holes! Cheddar get out of here before I make a pun myself...\n((And of course, as ever and always, Trans Rights!!!))","completedAt":1649552307000,"event_id":165613,"id":5827276,"name":"N0nb1naryCode","poll_option_id":39030,"reward_id":null,"updatedAt":1649552307000}] - * DONATION: [null,null,"campaign.165613.donation","donation",{"amount":12.0,"challenge_id":31290,"comment":"Let's gooooooo! Animals in balls? Running crazy races? We need this!","completedAt":1649553051000,"event_id":165613,"id":5827305,"name":"TrainerAnade","poll_option_id":39031,"reward_id":null,"updatedAt":1649553051000}] - * DONATION: [null,null,"campaign.165613.donation","donation",{"amount":21.0,"challenge_id":31290,"comment":"Things and stuff! Trans Rights! I don't have anything clever to add!!","completedAt":1649553226000,"event_id":165613,"id":5827315,"name":"N0nb1naryCode","poll_option_id":39030,"reward_id":null,"updatedAt":1649553226000}] + * LEAVE: ["27","28","fact.165613.donation","phx_leave",{}] + * LEAVE REPLY: ["27","28","fact.165613.donation","phx_reply",{"response":{},"status":"ok"}] + * CLOSE REPLY: ["27","27","fact.165613.donation","phx_close",{}] + * DONATION: [null,null,"fact.165613.donation","donation",{"amount":37.0,"challenge_id":31290,"comment":"Muensterous cheese puns! I may not be that sharp, but this is no gouda! Swiss entire idea is full of holes! Cheddar get out of here before I make a pun myself...\n((And of course, as ever and always, Trans Rights!!!))","completedAt":1649552307000,"event_id":165613,"id":5827276,"name":"N0nb1naryCode","poll_option_id":39030,"reward_id":null,"updatedAt":1649552307000}] + * DONATION: [null,null,"fact.165613.donation","donation",{"amount":12.0,"challenge_id":31290,"comment":"Let's gooooooo! Animals in balls? Running crazy races? We need this!","completedAt":1649553051000,"event_id":165613,"id":5827305,"name":"TrainerAnade","poll_option_id":39031,"reward_id":null,"updatedAt":1649553051000}] + * DONATION: [null,null,"fact.165613.donation","donation",{"amount":21.0,"challenge_id":31290,"comment":"Things and stuff! Trans Rights! I don't have anything clever to add!!","completedAt":1649553226000,"event_id":165613,"id":5827315,"name":"N0nb1naryCode","poll_option_id":39030,"reward_id":null,"updatedAt":1649553226000}] */ /// /// Parses the message. @@ -272,9 +272,9 @@ private void ParseMessage(string message) { break; } - if ("campaign".Equals(topicParts[0]) && "donation".Equals(topicParts[2])) + if ("fact".Equals(topicParts[0]) && "donation".Equals(topicParts[2])) { - var donation = resp.Data.ToObject(); + var donation = resp.Data.ToObject(); OnCampaignDonation?.Invoke(this, new OnCampaignDonationArgs { Donation = donation }); return; } @@ -375,8 +375,8 @@ private void UnaccountedFor(string message) /// The campaign identifier. public void ListenToCampaignDonations(string campaignId) { - // campaign.165613.donation - var topic = $"campaign.{campaignId}.donation"; + // fact.165613.donation + var topic = $"fact.{campaignId}.donation"; _topicToChannelId[topic] = campaignId; ListenToTopic(topic); } diff --git a/Users.cs b/Users.cs index 3c6c3cd..ea8acb4 100644 --- a/Users.cs +++ b/Users.cs @@ -11,7 +11,19 @@ public Users(ApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler ht public Task GetUser() { - return TiltifyGetGenericAsync($"/user", ApiVersion.V3); + ApiVersion version = GetApiVersion(); + string endpointPath; + switch (version) + { + default: + case ApiVersion.V3: + endpointPath = "/user"; + break; + case ApiVersion.V5: + endpointPath = "/current-user"; + break; + } + return TiltifyGetGenericAsync(endpointPath, version); } } }