public UpdatePatreonInfoJob(ILogger <UpdatePatreonInfoJob> logger, IHttpClientFactory httpClientFactory, IOptions <PatreonSettings> patreonSettings, UserManager <ApplicationUser> userManager, IRepository <PatreonToken> tokenRepository, IRepository <AccountSubscription> subscriptionRepository, IUnitOfWork unitOfWork) : base(logger) { _httpClientFactory = httpClientFactory; _userManager = userManager; _unitOfWork = unitOfWork; _tokenRepository = tokenRepository; _subscriptionRepository = subscriptionRepository; _patreonSettings = patreonSettings.Value; }
public PatreonController( IHttpContextAccessor contextAccessor, UserManager <ApplicationUser> userManager, IRepository <PatreonToken> repository, IUnitOfWork unitOfWork, ILogger <PatreonController> logger, IHttpClientFactory httpClientFactory, IOptions <PatreonSettings> patreonSettings, IOptions <AppSettings> appSettings) : base(contextAccessor, userManager, logger) { _repository = repository; _unitOfWork = unitOfWork; _httpClientFactory = httpClientFactory; _patreonSettings = patreonSettings.Value; _appSettings = appSettings.Value; }
private async Task <string> CheckSignature(PatreonSettings settings) { if (!HttpContext.Request.Headers.TryGetValue("X-Patreon-Signature", out StringValues header) || header.Count != 1) { throw new HttpResponseException() { Value = new BasicJSONErrorResult("Invalid request", "Missing X-Patreon-Signature header").ToString() }; } var actualSignature = header[0]; if (settings == null || string.IsNullOrEmpty(settings.WebhookSecret)) { throw new HttpResponseException() { Status = StatusCodes.Status500InternalServerError, Value = new BasicJSONErrorResult("Server configuration error", "Patreon webhook is not configured") .ToString() }; } var readBody = await Request.ReadBodyAsync(); var rawPayload = readBody.Buffer.ToArray(); var neededSignature = Convert.ToHexString(new HMACMD5(Encoding.UTF8.GetBytes(settings.WebhookSecret)) .ComputeHash(rawPayload)).ToLowerInvariant(); if (!SecurityHelpers.SlowEquals(neededSignature, actualSignature)) { logger.LogWarning("Patreon webhook signature didn't match expected value"); throw new HttpResponseException() { Status = StatusCodes.Status403Forbidden, Value = new BasicJSONErrorResult("Invalid signature", "Payload signature does not match expected value").ToString() }; } return(Encoding.UTF8.GetString(rawPayload)); }
public static RewardGroup ShouldBeInGroupForPatron(Patron?patron, PatreonSettings settings) { if (settings == null) { throw new ArgumentException("patreon settings is null"); } if (patron == null || patron.Suspended == true) { return(RewardGroup.None); } if (patron.RewardId == settings.VipRewardId) { return(RewardGroup.VIP); } if (patron.RewardId == settings.DevbuildsRewardId) { return(RewardGroup.DevBuild); } return(RewardGroup.None); }
/// <summary> /// Gets all patrons of the active campaign /// </summary> /// <param name="settings">Where to get the campaign from</param> /// <param name="cancellationToken">Supports canceling this while waiting</param> /// <returns>API response with all the patron objects</returns> public async Task <List <PatronMemberInfo> > GetPatrons(PatreonSettings settings, CancellationToken cancellationToken) { // ReSharper disable once StringLiteralTypo var url = $"https://www.patreon.com/api/oauth2/api/campaigns/{settings.CampaignId}/pledges?include=patron.null," + "reward&fields%5Bpledge%5D=status,currency,amount_cents,declined_since"; var result = new List <PatronMemberInfo>(); while (!string.IsNullOrEmpty(url)) { var response = await client.GetFromJsonAsync <PatreonAPIListResponse>(url, cancellationToken); if (response == null) { throw new PatreonAPIDataException("failed to deserialize response from patreon API"); } foreach (var data in response.Data) { if (data.Type != "pledge") { continue; } var patronRelationship = data.Relationships?.Patron; if (patronRelationship?.Data == null) { throw new PatreonAPIDataException("Pledge relationship to patron doesn't exist"); } var userData = response.FindIncludedObject(patronRelationship.Data.Id, patronRelationship.Data.Type); if (userData == null) { throw new PatreonAPIDataException("Failed to find pledge's related user object"); } var rewardRelationship = data.Relationships?.Reward; if (rewardRelationship == null) { throw new PatreonAPIDataException( "Pledge relationship to reward data is not included for user"); } // This happens if the user has not selected a reward // TODO: would be nice to log this problem here as we should let the patron know they need to // select a reward if (rewardRelationship.Data == null) { continue; } var rewardData = response.FindIncludedObject(rewardRelationship.Data.Id, rewardRelationship.Data.Type); if (rewardData == null) { throw new PatreonAPIDataException("Failed to find pledge's related reward object"); } result.Add(new PatronMemberInfo() { Pledge = data, User = userData, Reward = rewardData, }); } // Pagination if (response.Links != null && response.Links.TryGetValue("next", out string?nextUrl)) { url = nextUrl; } else { // No more pages time to break the loop url = null; } } return(result); }
public PatreonCreatorAPI(PatreonSettings settings) : this(settings.CreatorToken) { }