Code Monkey home page Code Monkey logo

honeycomb's People

Contributors

anheledir avatar dependabot[bot] avatar samantatarun avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

samantatarun

honeycomb's Issues

Move setting the client activity into its own service.

https://api.github.com/Anheledir/Honeycomb/blob/74644b27c94c273c2f926019155b9a95f8dd712f/BaseBotService/Notifications/ActivityHandler.cs#L14

using BaseBotService.Messages;
using Discord.WebSocket;

namespace BaseBotService.Notifications;
public class ActivityHandler : INotificationHandler<ClientReadyNotification>
{
    private readonly DiscordSocketClient _client;

    public ActivityHandler(DiscordSocketClient client)
    {
        _client = client;
    }

    // TODO: Move this into its own service.
    public async Task Handle(ClientReadyNotification notification, CancellationToken cancellationToken)
    {
        await _client.SetActivityAsync(new Game("the world burn", ActivityType.Watching));
        await _client.SetStatusAsync(UserStatus.Online);
    }
}

Group-Pictures with Slot-Reservation

An artist can create a new slot-based Group-Event: A drawing with a certain theme and multiple possible spots where users can have their OCs placed.

On creation the artist must setup the event:

  • Title
  • Preview-Image with numbered spots
  • How many spots are available (min 1)
  • Conditions of participation
  • Roles that are allowed to participate (each can have an individual starting date, e.g. to have higher tiers get their slots first)
  • Starting date of the event
  • Ending date of the event
  • Must slots get confirmed? (y/n)
  • How many slots can each user reserve? (min 1)
  • Is the list of participants public? (y/n)

Eligible users can reserve one slot at a time. They must confirm reading the conditions of participation, then can enter a short note for the selected slot (or choose an OC from their Character-References). If the artist has activated confirmations, the slot is reserved and must get confirmed first (e.g. when waiting for payment). Otherwise or when getting confirmed the state is changed to taken. Other users can only select slots that are neither reserved nor taken.

If the artist decided that the list of participants is public, everyone can see the following list. If it's not public, everyone beside the artist can just see the slot-numbers and their status (open, reserved, taken):

  • Number of the slot
  • User who got it
  • OC name
  • Status (🟢 open, 🟡 reserved, 🔴 taken)

Users can cancel their slot again as long as the end-date of the event isn't reached.

Birthday gifts from Artists

Allow artists to get a reminder of upcoming birthdays up to 14 days ahead.

They can add a new commission for a gift by just pressing a button. That commission is automatically set to "Secret" and is hidden on public lists.

Once finished they can choose to publish the drawing on the user's birthday automatically as a present.

Add Application Insights to the bot

For our bot, some useful statistics that we could monitor include:

  • Message volume: Track the number of messages sent and received by the bot, as well as any errors or exceptions that occur when processing messages.

  • User engagement: Track the number of active users, the frequency of user interactions, and other engagement metrics to understand how users are interacting with the bot.

  • Performance metrics: Monitor server response times, latency, and other performance metrics to ensure that the bot is responding quickly and efficiently to user requests.

  • Error and exception tracking: Log any errors or exceptions that occur in our bot's code, along with contextual data such as the user and server that triggered the error.

By using Application Insights to monitor these metrics, we can gain valuable insights into how users are interacting with our bot, identify performance bottlenecks and errors, and optimize the bot's behavior for the best user experience.

We should utilize the Serilog.Sinks.ApplicationInsights to send log messages automatically to Application Insights, too.

Add MediatR to cleanup the code and improve the architecture

MediatR is an open-source library developed by Jimmy Bogard that simplifies communication between components within a .NET application, following the principles of the Mediator pattern. It is used to promote loose coupling between components, reduce dependencies, and improve overall application maintainability and testability.

The primary use of MediatR is to manage and handle in-process messaging, such as requests and notifications, within an application. It is particularly useful in applications built using the CQRS (Command Query Responsibility Segregation) pattern, where commands and queries are separated for better organization and scalability.

Rename _clientEvents to _discordEvents

https://api.github.com/Anheledir/Honeycomb/blob/3086e0aa5de82b3821ec1e225ecaa193e1bfeb19/BaseBotService/Program.cs#L25

        // Load instances from DI
        var _client = ServiceProvider.GetRequiredService<DiscordSocketClient>();
        var _environment = ServiceProvider.GetRequiredService<IEnvironmentService>();
        // TODO: Rename _clientEvents to _discordEvents
        var _clientEvents = ServiceProvider.GetRequiredService<DiscordEvents>();
        var _handler = ServiceProvider.GetRequiredService<InteractionService>();

No error-message when the bot has no permissions to send a DM to a user

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  • Only allow friends to send you DM on discord
  • Use the /user config command, which tries to send a DM

Expected behavior
If no DM can be send to the user for missing permissions, it should tell him in a channel-message.
Maybe try a fallback with an ephemeral-message instead. 💡

Move this into its own service.

https://api.github.com/Anheledir/Honeycomb/blob/9668069cd0d7da2d5b174db66bbc0854ad8c09ec/BaseBotService/Interactions/ActivityHandler.cs#L15

using BaseBotService.Core.Messages;
using Discord.WebSocket;

namespace BaseBotService.Interactions;
public class ActivityHandler : INotificationHandler<ClientReadyNotification>
{
    private readonly DiscordSocketClient _client;

    public ActivityHandler(DiscordSocketClient client)
    {
        _client = client;
    }

#pragma warning disable S1135
    // TODO: Move this into its own service.
    public async Task Handle(ClientReadyNotification notification, CancellationToken cancellationToken)
    {
        await _client.SetActivityAsync(new Game("the world burn", ActivityType.Watching));
        await _client.SetStatusAsync(UserStatus.Online);
    }
}

Activity Tracking Feature

Objective: Enable server-owners to activate activity tracking for their servers to gather statistics on user activity and engagement, without invading privacy or causing significant overhead.

Use-Cases:

  1. Server-owners want to determine the most active days and times on their servers to make informed decisions about when to post announcements, artwork, or other content.
  2. Server-owners want to identify the most popular channels on their servers to optimize server organization and user experience.
  3. Server-owners want to understand the roles that different users play in driving conversations, such as conversation starters, active participants, or passive observers.
  4. Server-owners want a lightweight solution that doesn't consume too many resources or cause performance issues, even on large servers.

Concept:

  1. Data Collection:

    • The bot will listen to user-presence events, such as joining or leaving voice channels, to track online presence.
    • The bot will listen to message events to track user activity in text channels. The bot will only record metadata, such as message sender, channel, timestamp, and whether the message is a reply or a new conversation starter (based on the reply status or time since the last message in the channel).
    • The bot will not store the content of messages for privacy reasons.
  2. Data Aggregation:

    • Data will be aggregated on a daily and hourly basis, taking into account server timezone settings.
    • User activity will be grouped into categories: conversation starters, active participants, and passive observers.
    • Channel activity will be aggregated to show which channels are the most popular.
  3. Data Retention and Deletion:

    • Aggregated data will be stored for a configurable period (e.g., 30 days), and older data will be automatically deleted.
    • Server-owners can request data deletion at any time, and the bot will comply.
  4. Data Presentation:

    • Server-owners can access the activity statistics via a dashboard or command-line interface, depending on their preference.
    • The interface will display data in easily digestible formats, such as graphs and tables.
    • Server-owners can filter data by user, channel, or time range to gain more specific insights.
  5. Permission Management:

    • The bot will require minimal permissions, such as "Read Message History," "View Channels," and "Read Message Content" (only to identify conversation starters and participants without storing the content).
    • Server-owners can restrict the bot's access to specific channels if desired.
  6. Scalability:

    • The bot will utilize efficient data structures and algorithms to minimize resource consumption and ensure smooth performance on large servers.
    • The use of LightDB and a Docker container on .NET 7 in Azure will help maintain low resource usage and easy scaling.

Replace DiscordSocketClient with DiscordShardedClient

In Discord, a shard is a separate instance of a bot that connects to a subset of Discord's servers. Discord uses sharding to distribute the load of a bot across multiple connections, allowing it to scale to support a large number of servers and users.

The Discord.NET library provides built-in support for sharding, making it easy to create and manage shards for your bot.

To activate this feature we need to set the ShardCount property on our DiscordSocketConfig object to the number of shards we want to use. Discord recommends using a shard count of 1,000 servers per shard, up to a maximum of 10,000 servers.

We then need to replace the currently used DiscordSocketClient by the DiscordShardedClient instead.

Also the token ID, total shard count and the individual shard-id should be configurable with environment variables.

It is possible to use sharding in combination with running your bot in multiple instances of Azure App Services. Here's one approach you can take:

  1. Deploy your bot to multiple instances of Azure App Services. Each instance should be configured to run a separate instance of your bot.
  2. In your bot's code, initialize each instance of the bot with a different shard ID. You can use the Environment.GetEnvironmentVariable method to get the instance's shard ID from an environment variable.
var config = new DiscordSocketConfig
{
    Token = "your_bot_token",
    ShardId = int.Parse(Environment.GetEnvironmentVariable("SHARD_ID")),
    ShardCount = int.Parse(Environment.GetEnvironmentVariable("SHARD_COUNT")),
};
var client = new DiscordShardedClient(config);
  1. Set the ShardCount property to the total number of shards that your bot will use across all instances.
  2. Use a load balancer such as Azure Traffic Manager to distribute incoming requests across your bot instances. You can configure the load balancer to use a round-robin or weighted round-robin algorithm to evenly distribute traffic across instances.
  3. When an instance of the bot receives a request, it will process events for its assigned shard ID. The load balancer ensures that events are distributed across all instances in a balanced way.
  4. By using this approach, we can scale the bot to support a large number of servers and users while still maintaining high availability and performance.

Add your Patreon profile to your artist profile

As artist you can connect your bot profile to your Patreon-Account and also link your patreon tiers to roles on the server.

  • Show the amount of patrons in your profile
  • Link to your patron site
  • Link Patreon tiers to server roles
  • Get the list of your Patreon members with their pledge level and their Discord-Account for automatic role assignment
  • Add a possibility to add automatic loyalty points with each payment based on the pledge level

API-Documentation: https://docs.patreon.com/#user-v2

Sample code:

using System;
using System.Collections.Generic;
using System.Net.Http;
using Newtonsoft.Json;

class Program
{
    static async System.Threading.Tasks.Task Main(string[] args)
    {
        // Replace the placeholders with your actual values
        string campaignId = "your_campaign_id";
        string accessToken = "your_access_token";

        // Define the endpoint URL and headers
        string endpoint = $"https://www.patreon.com/api/oauth2/v2/campaigns/{campaignId}/members";
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");

        // Send the API request
        HttpResponseMessage response = await client.GetAsync(endpoint);

        // Parse the response JSON to extract the member data
        string responseContent = await response.Content.ReadAsStringAsync();
        dynamic jsonResponse = JsonConvert.DeserializeObject(responseContent);
        List<dynamic> members = jsonResponse.data.ToObject<List<dynamic>>();

        // Print the member data
        foreach (dynamic member in members)
        {
            decimal pledgeAmount = member.attributes.currently_entitled_amount_cents / 100.0m;
            string discordId = member.attributes.discord_id;
            Console.WriteLine($"Discord ID: {discordId}, Pledge Amount: ${pledgeAmount}");
        }
    }
}

Allow users to configure their birthday

The user can set his birthday with a bot-command, the year being optional.
He can also select if every server he has in common with the bot is allowed to share that info or if he only wants to allow it for specifically selected servers. There should also be a button to allow the user to delete that information again.

The birthday (and age, if the year was set) is visible in the users profile (currenty the user-info command) if he allowed it for the specific server.

[i18n] Move URL to localization resource

https://api.github.com/Anheledir/Honeycomb/blob/04b6a2ac0d8478d70e2c2722c8ef2d6eaf099305/BaseBotService/Modules/BotModule.cs#L18

using BaseBotService.Attributes;
using Discord;
using Discord.Interactions;

namespace BaseBotService.Modules;

[Group("bot", "The main bot information module of Honeycomb.")]
[EnabledInDm(true)]
public class BotModule : BaseModule
{
    [SlashCommand("about", "Returns information like runtime and current version of this Honeycomb bot instance.")]
    public async Task InfoCommandAsync()
    {
        // Create embedded message with bot information
        var response = GetEmbedBuilder()
            .WithTitle(AssemblyService.Name)
            .WithThumbnailUrl(BotUser.GetAvatarUrl())
            .WithUrl("https://honeycombs.cloud/") // TODO(i18n): Move URL to localization resource
            .WithDescription($"Honeycomb is a Discord bot designed to provide artists with some useful functions to enhance their experience on Discord. With its features, artists can create a portfolio, display random entries from it, manage a commission price list, and keep track of their commission queue. The bot is released under the MIT license on GitHub.")
            .WithFields(
                new EmbedFieldBuilder()
                .WithName("Uptime")

Small issues with new user-info

Describe the bug

  • On using /user-info the last active time seems to be one hour ahead. Maybe not saved as UTC?
  • When a date is not available it shows the MinValue instead of a text like "n/a" or "unknown"
  • the timestamps should also show a relative time span like "5 years ago" for example
  • hide permissions by default and only show them with an optional parameter

Venting Module

An administrator has to configure a server-channel as "vent"-channel.
A user can then use a command to open a modal dialog where he can enter his venting message.

The message will be posted by the bot in the vent-channel anonymously. The message and its author will not be saved, but a hashed version of the author-id will be saved. This hashed ID cannot be used to identify a user. But if a message violates the server-rules, another user can report the message or a moderator can delete it (either directly or after a user reported it).

On deleting the message, the moderator can select the option to block the author of the message. As the user-id is unknown, only the hashed ID will be added to a block-list. Whenever a user wants to use the vent-command again, his user-id will be hashed again and checked if its present in the block-list. If yes, he gets a hidden message about the reason and cannot use the vent-feature.

An administrator can use a command to delete all entries on the block-list older than x days.

Optional features:

  • Make the bot create the channel itself with correct permission settings and pinning a description of the feature and how to use it to it.
  • Send the author a DM with a special password, which they can use to delete the message for a certain amount of time (e.g. 24h). The bot then changes the message text to a note, that the author redacted the message again.

!! Important !!
At no point the author of a specific vent-message should be logged and only the hashed user-id must be saved along with the message.

Add a command to show all upcoming birthdays on a server

Show the next 10 upcoming birthdays and add pagination for one year into the future.
Allow moderators to define a "Birthday" role and a certain time-of-day. Those with a birthday get said role on their birthday and at the configured time a notification is send to the server. Customizing of the message not yet necessary, will be done at a later date.

Manage artists loyalty points

  • a command only for artists to see a list with all users showing their total points, also with a search by name
  • a command to add or remove points for a single user or everyone with a specific role, notifying the users with a DM about it, and the artist being able to enter a short description (like “Patreon Membership 03/2023”, “Commission for 123€”, …)
  • the ability for users to retrieve their current balance
  • a command to show all transactions for your own points (history of all adding or substracting) and for artists to show this for every user
  • Being able to setup regular automatic transactions for users with a certain role (like everyone with @Tier3 gets 10 points on the 3rd of each month)
  • artists can give their loyalty points a custom name and icon/emoji
  • a top-10 list of users with the most coins (not current balance but all gains of the past without any spendings - so basically a list of the all-time top-supporters)

Add a database for persistances

Current preference is SQLite, as it needs not many resources and should be enough for the bot.
Also, part of this ticket is to make sure, that the database is not overwritten when publishing an updated version via docker! It must be configurable where the database-file should be persisted (e.g. by an environmental variable).

Create the base solution and projects

Create a new solution with projects for the bot, some libraries and the most basic dependencies to login to Discord.
Add the configuration for adding app secrets.
Configure a Docker Build Script to run and deploy the solution as a container.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.