Instrumentation
This commit is contained in:
		
							parent
							
								
									542adbf9a7
								
							
						
					
					
						commit
						694cab3e49
					
				
							
								
								
									
										79
									
								
								Bot/Analytics.fs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								Bot/Analytics.fs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					module Degenz.Analytics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					open Mixpanel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let private mix = MixpanelClient(GuildEnvironment.tokenMixpanel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let private track eventName id data =
 | 
				
			||||||
 | 
					    let map =
 | 
				
			||||||
 | 
					        [ "distinct_id" , box id
 | 
				
			||||||
 | 
					          "guild_id" , box GuildEnvironment.guildId
 | 
				
			||||||
 | 
					          "env" , box GuildEnvironment.environment  ]
 | 
				
			||||||
 | 
					    mix.TrackAsync(eventName, data @ map |> dict) |> Async.AwaitTask |> Async.Ignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let invitedUserEntered inviteCode inviterId inviteeId inviterName inviteeName =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , inviterName
 | 
				
			||||||
 | 
					        "invite_code" , inviteCode
 | 
				
			||||||
 | 
					        "invitee_id" , inviteeId
 | 
				
			||||||
 | 
					        "invitee_name" , inviteeName
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Invited User Entered" inviterId data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let invitedUserAccepted inviteCode inviterId inviteeId inviterName inviteeName =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , inviterName
 | 
				
			||||||
 | 
					        "invite_code" , inviteCode
 | 
				
			||||||
 | 
					        "invitee_id" , inviteeId
 | 
				
			||||||
 | 
					        "invitee_name" , inviteeName
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Invited User Accepted" inviterId data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let recruitCommand origin id name channelId channelName =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "origin" , origin
 | 
				
			||||||
 | 
					        "channel_id" , channelId
 | 
				
			||||||
 | 
					        "channel_name" , channelName
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruit Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let recruitLinkButton inviteCode id name channelId channelName =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "invite_code" , inviteCode
 | 
				
			||||||
 | 
					        "channel_id" , channelId
 | 
				
			||||||
 | 
					        "channel_name" , channelName
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruited Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let recruitedCommand totalUsers id name channelId channelName =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "total_users_at_the_time" , totalUsers
 | 
				
			||||||
 | 
					        "channel_id" , channelId
 | 
				
			||||||
 | 
					        "channel_name" , channelName
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruited Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let whiteListButton availability id name =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "availability" , availability
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruited Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let whiteListPurchased amount id name =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "purchase_amount" , amount
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruited Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let trainingDojoStep step id name =
 | 
				
			||||||
 | 
					    let data = [
 | 
				
			||||||
 | 
					        "user_display_name" , name
 | 
				
			||||||
 | 
					        "step" , step
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    track "Recruited Command Invoked" id data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6,13 +6,10 @@ open DSharpPlus
 | 
				
			|||||||
open DSharpPlus.SlashCommands
 | 
					open DSharpPlus.SlashCommands
 | 
				
			||||||
open Degenz
 | 
					open Degenz
 | 
				
			||||||
open Emzi0767.Utilities
 | 
					open Emzi0767.Utilities
 | 
				
			||||||
open Mixpanel
 | 
					 | 
				
			||||||
//open Degenz.SlotMachine
 | 
					//open Degenz.SlotMachine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
 | 
					type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let mix = MixpanelClient("SOMETOKEN")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let guild = GuildEnvironment.guildId
 | 
					let guild = GuildEnvironment.guildId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let hackerBattleConfig = DiscordConfiguration()
 | 
					let hackerBattleConfig = DiscordConfiguration()
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@
 | 
				
			|||||||
        <Compile Include="GameTypes.fs" />
 | 
					        <Compile Include="GameTypes.fs" />
 | 
				
			||||||
        <Compile Include="GameHelpers.fs" />
 | 
					        <Compile Include="GameHelpers.fs" />
 | 
				
			||||||
        <Compile Include="DbService.fs" />
 | 
					        <Compile Include="DbService.fs" />
 | 
				
			||||||
 | 
					        <Compile Include="Analytics.fs" />
 | 
				
			||||||
        <Compile Include="PlayerInteractions.fs" />
 | 
					        <Compile Include="PlayerInteractions.fs" />
 | 
				
			||||||
        <Compile Include="InviteTracker.fs" />
 | 
					        <Compile Include="InviteTracker.fs" />
 | 
				
			||||||
        <Compile Include="XP.fs" />
 | 
					        <Compile Include="XP.fs" />
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,7 @@ let handleTrainerStep1 (ctx : IDiscordContext) =
 | 
				
			|||||||
               .AsEphemeral(true)
 | 
					               .AsEphemeral(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
 | 
					        do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
 | 
				
			||||||
 | 
					        do! Analytics.trainingDojoStep "LFG" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    } |> Async.StartAsTask :> Task
 | 
					    } |> Async.StartAsTask :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let defend (ctx : IDiscordContext) =
 | 
					let defend (ctx : IDiscordContext) =
 | 
				
			||||||
@ -79,6 +80,7 @@ let defend (ctx : IDiscordContext) =
 | 
				
			|||||||
        let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname
 | 
					        let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname
 | 
				
			||||||
        let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ Shield defaultShield ] ; Name = name } true
 | 
					        let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ Shield defaultShield ] ; Name = name } true
 | 
				
			||||||
        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
					        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
				
			||||||
 | 
					        do! Analytics.trainingDojoStep "DefendCommand" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    } |> Async.StartAsTask :> Task
 | 
					    } |> Async.StartAsTask :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleDefenseMsg hackId = {
 | 
					let handleDefenseMsg hackId = {
 | 
				
			||||||
@ -104,6 +106,7 @@ let handleDefense (ctx : IDiscordContext) =
 | 
				
			|||||||
        do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!"
 | 
					        do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!"
 | 
				
			||||||
        do! Async.Sleep 1500
 | 
					        do! Async.Sleep 1500
 | 
				
			||||||
        do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Item.Name)
 | 
					        do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Item.Name)
 | 
				
			||||||
 | 
					        do! Analytics.trainingDojoStep "ShieldActivated" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    } |> Async.StartAsTask :> Task
 | 
					    } |> Async.StartAsTask :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleTrainerStep3 (ctx : IDiscordContext) =
 | 
					let handleTrainerStep3 (ctx : IDiscordContext) =
 | 
				
			||||||
@ -117,6 +120,7 @@ let handleTrainerStep3 (ctx : IDiscordContext) =
 | 
				
			|||||||
                 + $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Item.Name}`")
 | 
					                 + $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Item.Name}`")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
 | 
					        do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
 | 
				
			||||||
 | 
					        do! Analytics.trainingDojoStep "LetsHack" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    } |> Async.StartAsTask :> Task
 | 
					    } |> Async.StartAsTask :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
					let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
				
			||||||
@ -138,6 +142,7 @@ let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
				
			|||||||
                   .AsEphemeral(true)
 | 
					                   .AsEphemeral(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            do! ctx.FollowUp(builder) |> Async.AwaitTask
 | 
					            do! ctx.FollowUp(builder) |> Async.AwaitTask
 | 
				
			||||||
 | 
					            do! Analytics.trainingDojoStep "HackCommand" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    } |> Async.StartAsTask :> Task
 | 
					    } |> Async.StartAsTask :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleHack (ctx : IDiscordContext) =
 | 
					let handleHack (ctx : IDiscordContext) =
 | 
				
			||||||
@ -153,7 +158,8 @@ let handleHack (ctx : IDiscordContext) =
 | 
				
			|||||||
               + "When you **HACK** other Degenz, you **TAKE** their 💰$GBT.\n"
 | 
					               + "When you **HACK** other Degenz, you **TAKE** their 💰$GBT.\n"
 | 
				
			||||||
               + "But remember, hacks take time to recover, so use them wisely.")
 | 
					               + "But remember, hacks take time to recover, so use them wisely.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! Async.Sleep 2000
 | 
					        do! Analytics.trainingDojoStep "HackActivated" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
 | 
					        do! Async.Sleep 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let message =
 | 
					        let message =
 | 
				
			||||||
            $"""
 | 
					            $"""
 | 
				
			||||||
@ -181,6 +187,7 @@ type the `/arsenal` command NOW"""
 | 
				
			|||||||
            do! ctx.GetDiscordMember().GrantRoleAsync(role) |> Async.AwaitTask
 | 
					            do! ctx.GetDiscordMember().GrantRoleAsync(role) |> Async.AwaitTask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            do! sendFollowUpMessage ctx ($"Your training is now complete. If you want to buy more **HACKS & SHIELDS**, go to the <#{GuildEnvironment.channelArmory}> and type the `/buy-hack` and `/buy-shield` commands!")
 | 
					            do! sendFollowUpMessage ctx ($"Your training is now complete. If you want to buy more **HACKS & SHIELDS**, go to the <#{GuildEnvironment.channelArmory}> and type the `/buy-hack` and `/buy-shield` commands!")
 | 
				
			||||||
 | 
					            do! Analytics.trainingDojoStep "CompletedNoGifts" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleArsenal (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async {
 | 
					let handleArsenal (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async {
 | 
				
			||||||
@ -235,6 +242,7 @@ let handleArsenal (ctx : IDiscordContext) = PlayerInteractions.executePlayerActi
 | 
				
			|||||||
        do! Async.Sleep 1000
 | 
					        do! Async.Sleep 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! sendFollowUpMessage ctx $"Now get out of there and go hack other Degenz in the <#{GuildEnvironment.channelBattle}> channel!"
 | 
					        do! sendFollowUpMessage ctx $"Now get out of there and go hack other Degenz in the <#{GuildEnvironment.channelBattle}> channel!"
 | 
				
			||||||
 | 
					        do! Analytics.trainingDojoStep "CompletedWithGifts" (ctx.GetDiscordMember().Id) (ctx.GetDiscordMember().Username)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
					        let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
				
			||||||
        do! ctx.GetDiscordMember().RevokeRoleAsync(role) |> Async.AwaitTask
 | 
					        do! ctx.GetDiscordMember().RevokeRoleAsync(role) |> Async.AwaitTask
 | 
				
			||||||
 | 
				
			|||||||
@ -15,11 +15,13 @@ let getId str = getVar str |> uint64
 | 
				
			|||||||
let connectionString = (getVar "DATABASE_URL").Replace("postgresql://", "postgres://").Replace("?sslmode=require", "")
 | 
					let connectionString = (getVar "DATABASE_URL").Replace("postgresql://", "postgres://").Replace("?sslmode=require", "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let guildId = getId "DISCORD_GUILD"
 | 
					let guildId = getId "DISCORD_GUILD"
 | 
				
			||||||
 | 
					let environment = getVar "ENVIRONMENT"
 | 
				
			||||||
let tokenPlayerInteractions = getVar "TOKEN_PLAYER_INTERACTIONS"
 | 
					let tokenPlayerInteractions = getVar "TOKEN_PLAYER_INTERACTIONS"
 | 
				
			||||||
let tokenSteal = getVar "TOKEN_STEAL"
 | 
					let tokenSteal = getVar "TOKEN_STEAL"
 | 
				
			||||||
let tokenHackerBattle = getVar "TOKEN_HACKER_BATTLE"
 | 
					let tokenHackerBattle = getVar "TOKEN_HACKER_BATTLE"
 | 
				
			||||||
let tokenStore = getVar "TOKEN_STORE"
 | 
					let tokenStore = getVar "TOKEN_STORE"
 | 
				
			||||||
let tokenInviter = getVar "TOKEN_INVITER"
 | 
					let tokenInviter = getVar "TOKEN_INVITER"
 | 
				
			||||||
 | 
					let tokenMixpanel = getVar "TOKEN_MIXPANEL"
 | 
				
			||||||
let channelEventsHackerBattle = getId "CHANNEL_EVENTS_HACKER_BATTLE"
 | 
					let channelEventsHackerBattle = getId "CHANNEL_EVENTS_HACKER_BATTLE"
 | 
				
			||||||
let channelTraining = getId "CHANNEL_TRAINING"
 | 
					let channelTraining = getId "CHANNEL_TRAINING"
 | 
				
			||||||
let channelArmory = getId "CHANNEL_ARMORY"
 | 
					let channelArmory = getId "CHANNEL_ARMORY"
 | 
				
			||||||
 | 
				
			|||||||
@ -199,7 +199,7 @@ let guildInviteEmbed =
 | 
				
			|||||||
    let button = DiscordButtonComponent(ButtonStyle.Success, $"CreateGuildInvite", $"GET MY UNIQUE LINK") :> DiscordComponent
 | 
					    let button = DiscordButtonComponent(ButtonStyle.Success, $"CreateGuildInvite", $"GET MY UNIQUE LINK") :> DiscordComponent
 | 
				
			||||||
    builder.AddComponents [| button |]
 | 
					    builder.AddComponents [| button |]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let private showInviteMessage (ctx : IDiscordContext) =
 | 
					let private showInviteMessage (ctx : IDiscordContext) origin =
 | 
				
			||||||
    task {
 | 
					    task {
 | 
				
			||||||
        let builder = DiscordInteractionResponseBuilder().AsEphemeral(true)
 | 
					        let builder = DiscordInteractionResponseBuilder().AsEphemeral(true)
 | 
				
			||||||
        do! ctx.Respond(InteractionResponseType.DeferredChannelMessageWithSource, builder)
 | 
					        do! ctx.Respond(InteractionResponseType.DeferredChannelMessageWithSource, builder)
 | 
				
			||||||
@ -216,6 +216,7 @@ let private showInviteMessage (ctx : IDiscordContext) =
 | 
				
			|||||||
You must **COMPLETE YOUR TRAINING FIRST!** Then you can `/recruit`...
 | 
					You must **COMPLETE YOUR TRAINING FIRST!** Then you can `/recruit`...
 | 
				
			||||||
Go to <#{GuildEnvironment.channelTraining}> now to become a **HACKER**!
 | 
					Go to <#{GuildEnvironment.channelTraining}> now to become a **HACKER**!
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					            do! Analytics.recruitCommand origin player.DiscordId (ctx.GetDiscordMember().Username) (ctx.GetChannel().Id) (ctx.GetChannel().Name)
 | 
				
			||||||
        | None ->
 | 
					        | None ->
 | 
				
			||||||
            do! sendFollowUpMessage ctx $"You're not in the game! Go to <#{GuildEnvironment.channelShelters}> NOW to get assigned a private bunk, and **JOIN THE GAME!**"
 | 
					            do! sendFollowUpMessage ctx $"You're not in the game! Go to <#{GuildEnvironment.channelShelters}> NOW to get assigned a private bunk, and **JOIN THE GAME!**"
 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
@ -259,6 +260,9 @@ let private getInvitedUsersForId (ctx : IDiscordContext) = task {
 | 
				
			|||||||
            .AsEphemeral(true)
 | 
					            .AsEphemeral(true)
 | 
				
			||||||
            .WithContent(str)
 | 
					            .WithContent(str)
 | 
				
			||||||
    do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, msg)
 | 
					    do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, msg)
 | 
				
			||||||
 | 
					    let user = ctx.GetDiscordMember()
 | 
				
			||||||
 | 
					    let channel = ctx.GetChannel()
 | 
				
			||||||
 | 
					    do! Analytics.recruitedCommand total user.Id user.Username channel.Id channel.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let clearInvites (ctx : IDiscordContext) = task {
 | 
					let clearInvites (ctx : IDiscordContext) = task {
 | 
				
			||||||
@ -281,6 +285,7 @@ let private processNewUser (eventArgs : GuildMemberAddEventArgs) =
 | 
				
			|||||||
             match result with
 | 
					             match result with
 | 
				
			||||||
             | Some (_,count) ->
 | 
					             | Some (_,count) ->
 | 
				
			||||||
                 if invite.Uses > count then
 | 
					                 if invite.Uses > count then
 | 
				
			||||||
 | 
					                     do! Analytics.invitedUserEntered invite.Code invite.Inviter.Id eventArgs.Member.Id invite.Inviter.Username eventArgs.Member.Username
 | 
				
			||||||
                     do! addInvitedUser eventArgs.Member.Id invite.Code invite.Uses |> Async.Ignore
 | 
					                     do! addInvitedUser eventArgs.Member.Id invite.Code invite.Uses |> Async.Ignore
 | 
				
			||||||
             | None -> ()
 | 
					             | None -> ()
 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
@ -291,36 +296,23 @@ let acceptInvite (ctx : IDiscordContext) (invitedPlayer : PlayerData) =
 | 
				
			|||||||
        | false ->
 | 
					        | false ->
 | 
				
			||||||
            let! _ = markInvitedAccepted invitedPlayer.DiscordId |> Async.Ignore
 | 
					            let! _ = markInvitedAccepted invitedPlayer.DiscordId |> Async.Ignore
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
                let! inviter = getInviteFromInvitedUser invitedPlayer.DiscordId
 | 
					                let! invite = getInviteFromInvitedUser invitedPlayer.DiscordId
 | 
				
			||||||
                let! player = DbService.tryFindPlayer inviter.Inviter
 | 
					                let! player = DbService.tryFindPlayer invite.Inviter
 | 
				
			||||||
                match player with
 | 
					                match player with
 | 
				
			||||||
                | Some player ->
 | 
					                | Some player ->
 | 
				
			||||||
                    do! DbService.updatePlayerCurrency (int InviteRewardAmount) player |> Async.Ignore
 | 
					                    do! DbService.updatePlayerCurrency (int InviteRewardAmount) player |> Async.Ignore
 | 
				
			||||||
                    let builder = DiscordMessageBuilder()
 | 
					                    let builder = DiscordMessageBuilder()
 | 
				
			||||||
                    builder.WithContent($"{invitedPlayer.Name} was recruited to the server. <@{player.DiscordId}> just earned {InviteRewardAmount} 💰$GBT for their efforts!") |> ignore
 | 
					                    builder.WithContent($"{invitedPlayer.Name} was recruited and is now a Degen. <@{player.DiscordId}> just earned {InviteRewardAmount} 💰$GBT for their efforts!") |> ignore
 | 
				
			||||||
                    let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
 | 
					                    let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
 | 
				
			||||||
                    do! channel.SendMessageAsync(builder)
 | 
					                    do! channel.SendMessageAsync(builder)
 | 
				
			||||||
                        |> Async.AwaitTask
 | 
					                        |> Async.AwaitTask
 | 
				
			||||||
                        |> Async.Ignore
 | 
					                        |> Async.Ignore
 | 
				
			||||||
 | 
					                    do! Analytics.invitedUserAccepted invite.Code player.DiscordId invitedPlayer.DiscordId player.Name invitedPlayer.Name
 | 
				
			||||||
                | None -> return ()
 | 
					                | None -> return ()
 | 
				
			||||||
            with _ -> ()
 | 
					            with _ -> ()
 | 
				
			||||||
        | true -> return ()
 | 
					        | true -> return ()
 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If we do it like this then there's an obvious exploit where the user can come and go as many times and it will keep
 | 
					 | 
				
			||||||
// rewarding GBT.
 | 
					 | 
				
			||||||
//let handleGuildMemberRemoved _ (eventArgs : GuildMemberRemoveEventArgs) =
 | 
					 | 
				
			||||||
//    task {
 | 
					 | 
				
			||||||
//        do! removeInvitedUser eventArgs.Member.Id
 | 
					 | 
				
			||||||
//    } :> Task
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//Degenz Game
 | 
					 | 
				
			||||||
//Mint Date: April 2022
 | 
					 | 
				
			||||||
//Supply: 3,333
 | 
					 | 
				
			||||||
//Price: 1.984 $SOL
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//Your NFT will be your In-Game Character that provides you with unique traits, and abilities in game.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let sendInitialEmbed (client : DiscordClient)  =
 | 
					let sendInitialEmbed (client : DiscordClient)  =
 | 
				
			||||||
    async {
 | 
					    async {
 | 
				
			||||||
        try
 | 
					        try
 | 
				
			||||||
@ -435,7 +427,8 @@ let handleGimmeWhitelist (ctx : IDiscordContext) =
 | 
				
			|||||||
        let recruitBtn = DiscordButtonComponent(ButtonStyle.Danger, $"ShowRecruitmentEmbed", $"Recruit Now") :> DiscordComponent
 | 
					        let recruitBtn = DiscordButtonComponent(ButtonStyle.Danger, $"ShowRecruitmentEmbed", $"Recruit Now") :> DiscordComponent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let builder = DiscordFollowupMessageBuilder().AsEphemeral(true)
 | 
					        let builder = DiscordFollowupMessageBuilder().AsEphemeral(true)
 | 
				
			||||||
        match! tryGrantWhitelist ctx with
 | 
					        let! availability = tryGrantWhitelist ctx
 | 
				
			||||||
 | 
					        match availability with
 | 
				
			||||||
        | NotAHacker -> whitelistEmbed.Description <- notAHackerMsg
 | 
					        | NotAHacker -> whitelistEmbed.Description <- notAHackerMsg
 | 
				
			||||||
        | NotInGame -> whitelistEmbed.Description <- notInGameMsg
 | 
					        | NotInGame -> whitelistEmbed.Description <- notInGameMsg
 | 
				
			||||||
        | AlreadyWhitelisted ->
 | 
					        | AlreadyWhitelisted ->
 | 
				
			||||||
@ -455,6 +448,13 @@ let handleGimmeWhitelist (ctx : IDiscordContext) =
 | 
				
			|||||||
            whitelistEmbed.Description <- canBuyWhitelistMsg
 | 
					            whitelistEmbed.Description <- canBuyWhitelistMsg
 | 
				
			||||||
        builder.AddEmbed(whitelistEmbed) |> ignore
 | 
					        builder.AddEmbed(whitelistEmbed) |> ignore
 | 
				
			||||||
        do! ctx.FollowUp(builder)
 | 
					        do! ctx.FollowUp(builder)
 | 
				
			||||||
 | 
					        let availabilityStr =
 | 
				
			||||||
 | 
					            match availability with
 | 
				
			||||||
 | 
					            | NotEnoughGBT _ -> "NotEnoughGBT"
 | 
				
			||||||
 | 
					            | Granted _ -> "Granted"
 | 
				
			||||||
 | 
					            | _ -> string availability
 | 
				
			||||||
 | 
					        let user = ctx.GetDiscordMember()
 | 
				
			||||||
 | 
					        do! Analytics.whiteListButton availabilityStr user.Id user.Username
 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let buyWhitelistMsg = $"""
 | 
					let buyWhitelistMsg = $"""
 | 
				
			||||||
@ -476,10 +476,18 @@ let handleBuyWhitelist (ctx : IDiscordContext) =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let builder = DiscordFollowupMessageBuilder().AsEphemeral(true)
 | 
					        let builder = DiscordFollowupMessageBuilder().AsEphemeral(true)
 | 
				
			||||||
        match! tryGrantWhitelist ctx with
 | 
					        match! tryGrantWhitelist ctx with
 | 
				
			||||||
        | NotAHacker -> builder.Content <- $"You are somehow not a hacker anymore, what exactly are you doing?"
 | 
					        | NotAHacker ->
 | 
				
			||||||
        | NotInGame -> builder.Content <- $"You somehow have left the game, what exactly are you doing?"
 | 
					            builder.Content <- $"You are somehow not a hacker anymore, what exactly are you doing?"
 | 
				
			||||||
        | AlreadyWhitelisted -> builder.Content <- "🎉 You're already WHITELISTED!"
 | 
					            do! ctx.FollowUp(builder)
 | 
				
			||||||
        | NotEnoughGBT _ -> builder.Content <- $"You somehow do not have enough $GBT, what exactly are you doing?"
 | 
					        | NotInGame ->
 | 
				
			||||||
 | 
					            builder.Content <- $"You somehow have left the game, what exactly are you doing?"
 | 
				
			||||||
 | 
					            do! ctx.FollowUp(builder)
 | 
				
			||||||
 | 
					        | AlreadyWhitelisted ->
 | 
				
			||||||
 | 
					            builder.Content <- "🎉 You're already WHITELISTED!"
 | 
				
			||||||
 | 
					            do! ctx.FollowUp(builder)
 | 
				
			||||||
 | 
					        | NotEnoughGBT _ ->
 | 
				
			||||||
 | 
					            builder.Content <- $"You somehow do not have enough $GBT, what exactly are you doing?"
 | 
				
			||||||
 | 
					            do! ctx.FollowUp(builder)
 | 
				
			||||||
        | Granted player ->
 | 
					        | Granted player ->
 | 
				
			||||||
            let embed = DiscordEmbedBuilder()
 | 
					            let embed = DiscordEmbedBuilder()
 | 
				
			||||||
            embed.Description <- buyWhitelistMsg
 | 
					            embed.Description <- buyWhitelistMsg
 | 
				
			||||||
@ -491,6 +499,7 @@ let handleBuyWhitelist (ctx : IDiscordContext) =
 | 
				
			|||||||
            do! ctx.GetDiscordMember().GrantRoleAsync(role)
 | 
					            do! ctx.GetDiscordMember().GrantRoleAsync(role)
 | 
				
			||||||
            let! _ = DbService.updatePlayerCurrency -WhitelistPrice player
 | 
					            let! _ = DbService.updatePlayerCurrency -WhitelistPrice player
 | 
				
			||||||
            builder.AddEmbed(embed) |> ignore
 | 
					            builder.AddEmbed(embed) |> ignore
 | 
				
			||||||
 | 
					            do! ctx.FollowUp(builder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Send message to hall of privacy
 | 
					            // Send message to hall of privacy
 | 
				
			||||||
            let builder = DiscordMessageBuilder()
 | 
					            let builder = DiscordMessageBuilder()
 | 
				
			||||||
@ -499,8 +508,9 @@ let handleBuyWhitelist (ctx : IDiscordContext) =
 | 
				
			|||||||
            do! channel.SendMessageAsync(builder)
 | 
					            do! channel.SendMessageAsync(builder)
 | 
				
			||||||
                |> Async.AwaitTask
 | 
					                |> Async.AwaitTask
 | 
				
			||||||
                |> Async.Ignore
 | 
					                |> Async.Ignore
 | 
				
			||||||
 | 
					            let user = ctx.GetDiscordMember()
 | 
				
			||||||
 | 
					            do! Analytics.whiteListPurchased WhitelistPrice user.Id user.Username
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! ctx.FollowUp(builder)
 | 
					 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleCreateInvite (ctx : IDiscordContext) =
 | 
					let handleCreateInvite (ctx : IDiscordContext) =
 | 
				
			||||||
@ -532,6 +542,7 @@ let handleCreateInvite (ctx : IDiscordContext) =
 | 
				
			|||||||
                .AsEphemeral(true)
 | 
					                .AsEphemeral(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! ctx.FollowUp(msg)
 | 
					        do! ctx.FollowUp(msg)
 | 
				
			||||||
 | 
					        do! Analytics.recruitLinkButton code user.Id user.Username (ctx.GetChannel().Id) (ctx.GetChannel().Name)
 | 
				
			||||||
    } :> Task
 | 
					    } :> Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleButtonEvent  (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
 | 
					let handleButtonEvent  (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
 | 
				
			||||||
@ -540,7 +551,7 @@ let handleButtonEvent  (_ : DiscordClient) (event : ComponentInteractionCreateEv
 | 
				
			|||||||
    | id when id.StartsWith("GimmeWhitelist")  -> handleGimmeWhitelist eventCtx
 | 
					    | id when id.StartsWith("GimmeWhitelist")  -> handleGimmeWhitelist eventCtx
 | 
				
			||||||
    | id when id.StartsWith("BuyWhitelist")  -> handleBuyWhitelist eventCtx
 | 
					    | id when id.StartsWith("BuyWhitelist")  -> handleBuyWhitelist eventCtx
 | 
				
			||||||
    | id when id.StartsWith("CreateGuildInvite")  -> handleCreateInvite eventCtx
 | 
					    | id when id.StartsWith("CreateGuildInvite")  -> handleCreateInvite eventCtx
 | 
				
			||||||
    | id when id.StartsWith("ShowRecruitmentEmbed")  -> showInviteMessage eventCtx
 | 
					    | id when id.StartsWith("ShowRecruitmentEmbed")  -> showInviteMessage eventCtx "RecruitButton"
 | 
				
			||||||
    | _ ->
 | 
					    | _ ->
 | 
				
			||||||
        task {
 | 
					        task {
 | 
				
			||||||
            let builder = DiscordInteractionResponseBuilder()
 | 
					            let builder = DiscordInteractionResponseBuilder()
 | 
				
			||||||
@ -561,7 +572,7 @@ type Inviter() =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    [<SlashCommand("recruit", "Recruit another user to this discord and earn rewards")>]
 | 
					    [<SlashCommand("recruit", "Recruit another user to this discord and earn rewards")>]
 | 
				
			||||||
    member this.CreateInvite (ctx : InteractionContext) =
 | 
					    member this.CreateInvite (ctx : InteractionContext) =
 | 
				
			||||||
        showInviteMessage (DiscordInteractionContext ctx)
 | 
					        showInviteMessage (DiscordInteractionContext ctx) "RecruitCommand"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [<SlashCommand("recruited", "Get total invites from a specific user")>]
 | 
					    [<SlashCommand("recruited", "Get total invites from a specific user")>]
 | 
				
			||||||
    member this.ListInvitedPeople (ctx : InteractionContext) =
 | 
					    member this.ListInvitedPeople (ctx : InteractionContext) =
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user