Skip to content

Commit

Permalink
implement localized pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
th0mk committed Jan 5, 2025
1 parent d078b01 commit 12e8b18
Show file tree
Hide file tree
Showing 12 changed files with 3,167 additions and 19 deletions.
12 changes: 7 additions & 5 deletions src/FMBot.Bot/Builders/StaticBuilders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ public async Task<ResponseModel> SupporterButtons(
ContextModel context,
bool expandWithPerks,
bool showExpandButton,
bool publicResponse = false)
bool publicResponse = false,
string userLocale = null)
{
var response = new ResponseModel
{
Expand Down Expand Up @@ -162,10 +163,11 @@ public async Task<ResponseModel> SupporterButtons(
}
else
{
response.Embed.AddField("Monthly - $3.99",
"-# $3.99 per month", true);
response.Embed.AddField("Yearly - $23.99",
"-# $1.99 per month - Saves 50%", true);
var pricing = await this._supporterService.GetPricing(userLocale);
response.Embed.AddField($"Monthly - {pricing.MonthlyPriceString}",
$"-# {pricing.MonthlySubText}", true);
response.Embed.AddField($"Yearly - {pricing.YearlyPriceString}",
$"-# {pricing.YearlySubText}", true);

response.Components = new ComponentBuilder()
.WithButton("Get monthly",
Expand Down
32 changes: 30 additions & 2 deletions src/FMBot.Bot/Services/SupporterService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Serilog;
using Shared.Domain.Enums;
using Shared.Domain.Models;
using Web.InternalApi;
using StringExtensions = FMBot.Bot.Extensions.StringExtensions;
Expand Down Expand Up @@ -471,6 +472,18 @@ public async Task<StripeSupporter> GetStripeSupporter(ulong discordUserId)
.FirstOrDefaultAsync(f => f.PurchaserDiscordUserId == discordUserId);
}

public async Task<StripePricing> GetPricing(string userLocale)
{
await using var db = await this._contextFactory.CreateDbContextAsync();

var prices = await db.StripePricing
.Where(w => w.Type == StripeSupporterType.Supporter)
.ToListAsync();

return prices.FirstOrDefault(f => userLocale != null && f.Locales.Any(a => a == userLocale)) ??
prices.First(p => p.Default);
}

public async Task<OpenCollectiveUser> GetOpenCollectiveSupporter(string openCollectiveId)
{
var openCollectiveSupporters = await this._openCollectiveService.GetOpenCollectiveOverview();
Expand Down Expand Up @@ -1423,6 +1436,14 @@ public async Task<int> GetActiveDiscordSupporterCountAsync()
.CountAsync(c => c.Expired != true && c.SubscriptionType == SubscriptionType.Discord);
}

public async Task<int> GetActiveStripeSupporterCountAsync()
{
await using var db = await this._contextFactory.CreateDbContextAsync();
return await db.Supporters
.AsQueryable()
.CountAsync(c => c.Expired != true && c.SubscriptionType == SubscriptionType.Stripe);
}

public async Task<IReadOnlyList<Supporter>> GetAllSupporters()
{
await using var db = await this._contextFactory.CreateDbContextAsync();
Expand All @@ -1434,20 +1455,27 @@ public async Task<IReadOnlyList<Supporter>> GetAllSupporters()
}

public async Task<string> GetSupporterCheckoutLink(ulong discordUserId, string lastFmUserName, string type,
StripeSupporter existingStripeSupporter = null)
StripePricing pricing, StripeSupporter existingStripeSupporter = null)
{
var existingStripeCustomerId = "";
if (existingStripeSupporter != null)
{
existingStripeCustomerId = existingStripeSupporter.StripeCustomerId;
}

var priceId = pricing.MonthlyPriceId;
if (type.Equals("yearly", StringComparison.OrdinalIgnoreCase))
{
priceId = pricing.YearlyPriceId;
}

var url = await this._supporterLinkService.GetCheckoutLinkAsync(new CreateLinkOptions
{
DiscordUserId = (long)discordUserId,
LastFmUserName = lastFmUserName,
Type = type,
ExistingCustomerId = existingStripeCustomerId
ExistingCustomerId = existingStripeCustomerId,
PriceId = priceId
});

return url?.CheckoutLink;
Expand Down
1 change: 1 addition & 0 deletions src/FMBot.Bot/Services/TimerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ public async Task UpdateMetrics()

Statistics.ActiveSupporterCount.Set(await this._supporterService.GetActiveSupporterCountAsync());
Statistics.ActiveDiscordSupporterCount.Set(await this._supporterService.GetActiveDiscordSupporterCountAsync());
Statistics.ActiveStripeSupporterCount.Set(await this._supporterService.GetActiveStripeSupporterCountAsync());

Statistics.OneDayActiveUserCount.Set(await this._userService.GetTotalActiveUserCountAsync(1));
Statistics.SevenDayActiveUserCount.Set(await this._userService.GetTotalActiveUserCountAsync(7));
Expand Down
13 changes: 8 additions & 5 deletions src/FMBot.Bot/SlashCommands/StaticSlashCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using FMBot.Bot.Resources;
using FMBot.Bot.Services;
using FMBot.Domain.Models;
using Humanizer.DateTimeHumanizeStrategy;

namespace FMBot.Bot.SlashCommands;

Expand Down Expand Up @@ -53,7 +54,7 @@ public async Task GetSupporterAsync()
{
var contextUser = await this._userService.GetUserSettingsAsync(this.Context.User);
var response = await this._staticBuilders.SupporterButtons(new ContextModel(this.Context, contextUser),
false, true);
false, true, userLocale: this.Context.Interaction.UserLocale);

await this.Context.SendResponse(this.Interactivity, response, ephemeral: true);
this.Context.LogCommandUsed(response.CommandResponse);
Expand All @@ -77,7 +78,7 @@ public async Task SupporterButtons(string newResponse, string expandWithPerks, s
{
var contextUser = await this._userService.GetUserSettingsAsync(this.Context.User);
var response = await this._staticBuilders.SupporterButtons(new ContextModel(this.Context, contextUser),
expandWithPerks == "true", showExpandButton == "true");
expandWithPerks == "true", showExpandButton == "true", userLocale: this.Context.Interaction.UserLocale);

if (newResponse == "true")
{
Expand Down Expand Up @@ -109,8 +110,10 @@ public async Task GetSupporterLink(string type)
var contextUser = await this._userService.GetUserSettingsAsync(this.Context.User);
var existingStripeSupporter = await this._supporterService.GetStripeSupporter(contextUser.DiscordUserId);

var pricing = await this._supporterService.GetPricing(this.Context.Interaction.UserLocale);

var link = await this._supporterService.GetSupporterCheckoutLink(this.Context.User.Id,
contextUser.UserNameLastFM, type, existingStripeSupporter);
contextUser.UserNameLastFM, type, pricing, existingStripeSupporter);

var components = new ComponentBuilder().WithButton($"Complete purchase", style: ButtonStyle.Link, url: link,
emote: Emoji.Parse("⭐"));
Expand All @@ -121,11 +124,11 @@ public async Task GetSupporterLink(string type)
description.AppendLine($"**Click the unique link below to purchase supporter!**");
if (type == "yearly")
{
description.AppendLine("-# $23.99 — Yearly");
description.AppendLine($"-# {pricing.YearlySummary}");
}
else
{
description.AppendLine("-# $3.99 — Monthly");
description.AppendLine($"-# {pricing.MonthlySummary}");
}

if (SupporterService.IsSupporter(contextUser.UserType))
Expand Down
5 changes: 4 additions & 1 deletion src/FMBot.Domain/Statistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static class Statistics
LabelNames = new[] { "method" }
});

public static readonly Counter LastfmAuthorizedApiCalls = Metrics
public static readonly Counter LastfmAuthorizedApiCalls = Metrics
.CreateCounter("lastfm_authorized_api_calls", "Amount of authorized last.fm API calls",
new CounterConfiguration
{
Expand Down Expand Up @@ -145,6 +145,9 @@ public static class Statistics
public static readonly Gauge ActiveDiscordSupporterCount = Metrics
.CreateGauge("bot_active_discord_supporter_count", "Total count of all active Discord supporters in the database");

public static readonly Gauge ActiveStripeSupporterCount = Metrics
.CreateGauge("bot_active_stripe_supporter_count", "Total count of all active Stripe supporters in the database");


public static readonly Gauge OneDayActiveUserCount = Metrics
.CreateGauge("bot_active_users_count_1d", "Total count of users who've used the bot in the last day");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<Compile Remove="Properties\**" />
<EmbeddedResource Remove="Properties\**" />
<None Remove="Properties\**" />
<Compile Remove="Migrations\20250105161525_AddStripeLocalPricing.cs" />
<Compile Remove="Migrations\20250105161525_AddStripeLocalPricing.Designer.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
Expand Down
11 changes: 11 additions & 0 deletions src/FMBot.Persistence.EntityFrameWork/FMBotDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class FMBotDbContext : DbContext
public virtual DbSet<Supporter> Supporters { get; set; }

public virtual DbSet<StripeSupporter> StripeSupporters { get; set; }
public virtual DbSet<StripePricing> StripePricing { get; set; }

public virtual DbSet<DiscogsRelease> DiscogsReleases { get; set; }
public virtual DbSet<UserDiscogsReleases> UserDiscogsReleases { get; set; }
Expand Down Expand Up @@ -186,6 +187,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.HasKey(e => e.Id);
});

modelBuilder.Entity<StripePricing>(entity =>
{
entity.HasKey(e => e.Id);

entity.Property(e => e.Locales)
.HasConversion(
v => string.Join(',', v),
v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));
});

modelBuilder.Entity<BottedUser>(entity =>
{
entity.HasKey(e => e.BottedUserId);
Expand Down
Loading

0 comments on commit 12e8b18

Please sign in to comment.