diff --git a/Bot/Admin.fs b/Bot/Admin.fs index 53d7fc4..dbead26 100644 --- a/Bot/Admin.fs +++ b/Bot/Admin.fs @@ -7,7 +7,6 @@ open DSharpPlus open DSharpPlus.Entities open DSharpPlus.EventArgs open DSharpPlus.SlashCommands -open DSharpPlus.SlashCommands.Attributes open Degenz.Messaging open Npgsql.FSharp @@ -37,10 +36,11 @@ let sendEmbed embed (ctx : IDiscordContext) = do! Messaging.sendSimpleResponse ctx "Sent!" } :> Task -let getAllReactions (msg : DiscordMessage) = +let getAllReactions (msg : DiscordMessage) (ctx : IDiscordContext) : Task = task { let mutable listOfUsers = ResizeArray(512) + let mutable emojiCount = 0 for reaction in msg.Reactions do let mutable count = 0 for r in 0..reaction.Count / 100 do @@ -50,25 +50,36 @@ let getAllReactions (msg : DiscordMessage) = else msg.GetReactionsAsync(reaction.Emoji, 100) |> Async.AwaitTask |> Async.RunSynchronously listOfUsers.AddRange(rs) - printfn $"Emoji {reaction.Emoji.Name} - {reaction.Count} - Total users: {rs.Count} - Page {count}" count <- count + 1 - do! Async.Sleep 2000 + let builder = DiscordFollowupMessageBuilder().AsEphemeral(true) + builder.Content <- $"Reading {emojiCount + 1} out of {msg.Reactions.Count}: {reaction.Emoji.Name} with {reaction.Count} reactions" + do! ctx.FollowUp builder + do! Async.Sleep 1800 + emojiCount <- emojiCount + 1 - return - listOfUsers - |> List.ofSeq - |> List.map (fun (user : DiscordUser) -> - {| Id = user.Id ; FullName = $"{user.Username}#{user.Discriminator}" |}) - |> List.distinctBy (fun u -> u.Id) - |> List.map (fun user -> $"{user.Id},{user.FullName}") - |> String.concat "\n" - |> (+) "Discord Id Num,Username\n" + return listOfUsers } +let getCsvFromUsersList users = + users + |> List.ofSeq + |> List.map (fun (user : DiscordUser) -> + {| Id = user.Id ; FullName = $"{user.Username}#{user.Discriminator}" |}) + |> List.distinctBy (fun u -> u.Id) + |> List.map (fun user -> $"{user.Id},{user.FullName}") + |> String.concat "\n" + |> (+) "Discord Id Num,Username\n" + +let getCsvFromTotalInvites (users : {| Username : string ; DiscordId : uint64 ; TotalInvites : int |} seq) = + users + |> Seq.map (fun user -> $"{user.DiscordId},{user.Username},{user.TotalInvites}") + |> String.concat "\n" + |> (+) "Discord Id Num,Username,Total Invites\n" + let getUserInvites userIds = GuildEnvironment.connectionString |> Sql.connect - |> Sql.parameters [ "dids" , Sql.stringArray (userIds |> List.toArray) ] + |> Sql.parameters [ "dids" , Sql.stringArray (userIds |> Seq.toArray) ] |> Sql.query """ SELECT usr.display_name, inviter, count(invite_id) AS total_invites FROM invite JOIN invited_user iu ON invite.id = iu.invite_id @@ -77,19 +88,19 @@ let getUserInvites userIds = GROUP BY inviter, usr.display_name ORDER BY total_invites DESC; """ - |> Sql.executeAsync (fun read -> {| Username = read.string "display_name" ; DiscordId = read.string "discord_id" |> uint64 ; TotalInvites = read.int "total_invites" |}) + |> Sql.executeAsync (fun read -> {| Username = read.string "display_name" ; DiscordId = read.string "inviter" |> uint64 ; TotalInvites = read.int "total_invites" |}) |> Async.AwaitTask - -let getMessageReactions (channel : DiscordChannel) (message : string) (ctx : IDiscordContext) = +let getUsersFromMessageReactions (channel : DiscordChannel) (message : string) (ctx : IDiscordContext) = task { do! Messaging.defer ctx let ( result , mId ) = UInt64.TryParse(message) if result then let! msg = channel.GetMessageAsync(message |> uint64) |> Async.AwaitTask - let! reactions = getAllReactions msg - let builder = DiscordFollowupMessageBuilder() - use ms = new MemoryStream(Text.Encoding.ASCII.GetBytes(reactions)) :> Stream + let! reactions = getAllReactions msg ctx + let csv = getCsvFromUsersList reactions + let builder = DiscordFollowupMessageBuilder().AsEphemeral(true) + use ms = new MemoryStream(Text.Encoding.ASCII.GetBytes(csv)) :> Stream let dict = Collections.Generic.Dictionary() dict.Add("users.csv", ms) builder.AddFiles(dict) |> ignore @@ -98,16 +109,19 @@ let getMessageReactions (channel : DiscordChannel) (message : string) (ctx : IDi do! Messaging.sendSimpleResponse ctx $"The message ID provided was not a valid: {message}" } :> Task -//let getUserInvitesTable (channel : DiscordChannel) (message : string) (ctx : IDiscordContext) = -let getUserInvitesTable (ctx : IDiscordContext) = +let getUserInvitesFromReactions (channel : DiscordChannel) (message : string) (ctx : IDiscordContext) = task { do! Messaging.defer ctx - printfn $"Trying this out" + let! msg = channel.GetMessageAsync(message |> uint64) |> Async.AwaitTask + let! users = getAllReactions msg ctx try - let! invites = getUserInvites [ "90588624566886400" ; "822834227467780136" ] - printfn $"Total Invites? \n{invites}" - let builder = DiscordFollowupMessageBuilder() - builder.Content <- $"%A{invites}" + let! invites = getUserInvites (users |> Seq.map (fun u -> string u.Id)) + let csv = getCsvFromTotalInvites (invites) + let builder = DiscordFollowupMessageBuilder().AsEphemeral(true) + use ms = new MemoryStream(Text.Encoding.ASCII.GetBytes(csv)) :> Stream + let dict = Collections.Generic.Dictionary() + dict.Add("users.csv", ms) + builder.AddFiles(dict) |> ignore do! ctx.FollowUp(builder) with ex -> printfn $"exception {ex.Message}" @@ -139,10 +153,12 @@ type AdminBot() = member this.GetMessageReactions (ctx : InteractionContext, [] channel : DiscordChannel, [] messageId : string) = - enforceAdmin (DiscordInteractionContext ctx) (getMessageReactions channel messageId) + enforceAdmin (DiscordInteractionContext ctx) (getUsersFromMessageReactions channel messageId) [] - member this.GetInvitesTable (ctx : InteractionContext) = - enforceAdmin (DiscordInteractionContext ctx) getUserInvitesTable + member this.GetInvitesFromReactedMessages (ctx : InteractionContext, + [] channel : DiscordChannel, + [] messageId : string) = + enforceAdmin (DiscordInteractionContext ctx) (getUserInvitesFromReactions channel messageId)