The code:

using Discord;
using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Common.Attributes;
using NadekoBot.Core.Services;
using NadekoBot.Extensions;
using NadekoBot.Modules.CustomReactions.Services;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NadekoBot.Modules.CustomReactions
{
    public class CustomReactions : NadekoTopLevelModule<CustomReactionsService>
    {
        private readonly IBotCredentials _creds;
        private readonly DbService _db;
        private readonly DiscordSocketClient _client;

        public CustomReactions(IBotCredentials creds, DbService db,
            DiscordSocketClient client)
        {
            _creds = creds;
            _db = db;
            _client = client;
        }

        private bool AdminInGuildOrOwnerInDm() => (ctx.Guild == null && _creds.IsOwner(ctx.User))
                || (ctx.Guild != null && ((IGuildUser)ctx.User).GuildPermissions.Administrator);

        [NadekoCommand, Usage, Description, Aliases]
        public async Task AddCustReact(string key, [Leftover] string message)
        {
            var channel = ctx.Channel as ITextChannel;
            if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
                return;

            if (!AdminInGuildOrOwnerInDm())
            {
                await ReplyErrorLocalizedAsync("insuff_perms").ConfigureAwait(false);
                return;
            }

            var cr = await _service.AddCustomReaction(ctx.Guild?.Id, key, message);

            await ctx.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
                .WithTitle(GetText("new_cust_react"))
                .WithDescription($"#{cr.Id}")
                .AddField(efb => efb.WithName(GetText("trigger")).WithValue(key))
                .AddField(efb => efb.WithName(GetText("response")).WithValue(message.Length > 1024 ? GetText("redacted_too_long") : message))
                ).ConfigureAwait(false);
        }

        [NadekoCommand, Usage, Description, Aliases]
        public async Task EditCustReact(int id, [Leftover] string message)
        {
            var channel = ctx.Channel as ITextChannel;
            if (string.IsNullOrWhiteSpace(message) || id < 0)
                return;

            if ((channel == null && !_creds.IsOwner(ctx.User)) || (channel != null && !((IGuildUser)ctx.User).GuildPermissions.Administrator))
            {
                await ReplyErrorLocalizedAsync("insuff_perms").ConfigureAwait(false);
                return;
            }

            var cr = await _service.EditCustomReaction(ctx.Guild?.Id, id, message).ConfigureAwait(false);
            if (cr != null)
            {
                await ctx.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
                    .WithTitle(GetText("edited_cust_react"))
                    .WithDescription($"#{id}")
                    .AddField(efb => efb.WithName(GetText("trigger")).WithValue(cr.Trigger))
                    .AddField(efb => efb.WithName(GetText("response")).WithValue(message.Length > 1024 ? GetText("redacted_too_long") : message))
                    ).ConfigureAwait(false);
            }
            else
            {
                await ReplyErrorLocalizedAsync("edit_fail").ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        [Priority(1)]
        public async Task ListCustReact(int page = 1)
        {
            if (--page < 0 || page > 999)
                return;

            var customReactions = _service.GetCustomReactions(ctx.Guild?.Id);

            if (customReactions == null || !customReactions.Any())
            {
                await ReplyErrorLocalizedAsync("no_found").ConfigureAwait(false);
                return;
            }

            await ctx.SendPaginatedConfirmAsync(page, curPage =>
                new EmbedBuilder().WithOkColor()
                    .WithTitle(GetText("name"))
                    .WithDescription(string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
                                                    .Skip(curPage * 20)
                                                    .Take(20)
                                                    .Select(cr =>
                                                    {
                                                        var str = $"`#{cr.Id}` {cr.Trigger}";
                                                        if (cr.AutoDeleteTrigger)
                                                        {
                                                            str = "?" + str;
                                                        }
                                                        if (cr.DmResponse)
                                                        {
                                                            str = "?" + str;
                                                        }
                                                        var reactions = cr.GetReactions();
                                                        if(reactions.Any())
                                                        {
                                                            str = str + " // " + string.Join(" ", reactions);
                                                        }

                                                        return str;
                                                    }))), customReactions.Count(), 20)
                                .ConfigureAwait(false);
        }

        public enum All
        {
            All
        }

        [NadekoCommand, Usage, Description, Aliases]
        [Priority(0)]
        public async Task ListCustReact(All _)
        {
            var customReactions = _service.GetCustomReactions(ctx.Guild?.Id);

            if (customReactions == null || !customReactions.Any())
            {
                await ReplyErrorLocalizedAsync("no_found").ConfigureAwait(false);
                return;
            }

            using (var txtStream = await customReactions.GroupBy(cr => cr.Trigger)
                                                        .OrderBy(cr => cr.Key)
                                                        .Select(cr => new { Trigger = cr.Key, Responses = cr.Select(y => new { id = y.Id, text = y.Response }).ToList() })
                                                        .ToJson()
                                                        .ToStream()
                                                        .ConfigureAwait(false))
            {

                if (ctx.Guild == null) // its a private one, just send back
                    await ctx.Channel.SendFileAsync(txtStream, "customreactions.txt", GetText("list_all")).ConfigureAwait(false);
                else
                    await ((IGuildUser)ctx.User).SendFileAsync(txtStream, "customreactions.txt", GetText("list_all"), false).ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        public async Task ListCustReactG(int page = 1)
        {
            if (--page < 0 || page > 9999)
                return;
            var customReactions = _service.GetCustomReactions(ctx.Guild?.Id);

            if (customReactions == null || !customReactions.Any())
            {
                await ReplyErrorLocalizedAsync("no_found").ConfigureAwait(false);
            }
            else
            {
                var ordered = customReactions
                    .GroupBy(cr => cr.Trigger)
                    .OrderBy(cr => cr.Key)
                    .ToList();

                await ctx.SendPaginatedConfirmAsync(page, (curPage) =>
                    new EmbedBuilder().WithOkColor()
                        .WithTitle(GetText("name"))
                        .WithDescription(string.Join("\r\n", ordered
                                                         .Skip(curPage * 20)
                                                         .Take(20)
                                                         .Select(cr => $"**{cr.Key.Trim().ToLowerInvariant()}** `x{cr.Count()}`"))),
                    ordered.Count, 20).ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        public async Task ShowCustReact(int id)
        {
            var found = _service.GetCustomReaction(ctx.Guild?.Id, id);

            if (found == null)
            {
                await ReplyErrorLocalizedAsync("no_found_id").ConfigureAwait(false);
                return;
            }
            else
            {
                await ctx.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
                    .WithDescription($"#{id}")
                    .AddField(efb => efb.WithName(GetText("trigger")).WithValue(found.Trigger.TrimTo(1024)))
                    .AddField(efb => efb.WithName(GetText("response")).WithValue((found.Response + "\n```css\n" + found.Response).TrimTo(1020) + "```"))
                    ).ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        public async Task DelCustReact(int id)
        {
            if (!AdminInGuildOrOwnerInDm())
            {
                await ReplyErrorLocalizedAsync("insuff_perms").ConfigureAwait(false);
                return;
            }

            var cr = await _service.DeleteCustomReactionAsync(ctx.Guild?.Id, id);

            if (cr != null)
            {
                await ctx.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
                    .WithTitle(GetText("deleted"))
                    .WithDescription("#" + cr.Id)
                    .AddField(efb => efb.WithName(GetText("trigger")).WithValue(cr.Trigger.TrimTo(1024)))
                    .AddField(efb => efb.WithName(GetText("response")).WithValue(cr.Response.TrimTo(1024)))).ConfigureAwait(false);
            }
            else
            {
                await ReplyErrorLocalizedAsync("no_found_id").ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        public async Task CrReact(int id, params string[] emojiStrs)
        {
            if (!AdminInGuildOrOwnerInDm())
            {
                await ReplyErrorLocalizedAsync("insuff_perms").ConfigureAwait(false);
                return;
            }

            var cr = _service.GetCustomReaction(Context.Guild?.Id, id);
            if (cr is null)
            {
                await ReplyErrorLocalizedAsync("no_found").ConfigureAwait(false);
                return;
            }

            if (emojiStrs.Length == 0)
            {
                await _service.ResetCRReactions(ctx.Guild?.Id, id);
                await ReplyConfirmLocalizedAsync("crr_reset", Format.Bold(id.ToString())).ConfigureAwait(false);
                return;
            }

            List<string> succ = new List<string>();
            foreach (var emojiStr in emojiStrs)
            {

                var emote = emojiStr.ToIEmote();

                // i should try adding these emojis right away to the message, to make sure the bot can react with these emojis. If it fails, skip that emoji
                try
                {
                    await Context.Message.AddReactionAsync(emote).ConfigureAwait(false);
                    await Task.Delay(100).ConfigureAwait(false);
                    succ.Add(emojiStr);

                    if (succ.Count >= 3)
                        break;
                }
                catch { }
            }

            if(succ.Count == 0)
            {
                await ReplyErrorLocalizedAsync("invalid_emojis").ConfigureAwait(false);
                return;
            }

            await _service.SetCrReactions(ctx.Guild?.Id, id, succ);


            await ReplyConfirmLocalizedAsync("crr_set", Format.Bold(id.ToString()), string.Join(", ", succ.Select(x => x.ToString()))).ConfigureAwait(false);

        }

        [NadekoCommand, Usage, Description, Aliases]
        public Task CrCa(int id)
            => InternalCrEdit(id, CustomReactionsService.CrField.ContainsAnywhere);

        [NadekoCommand, Usage, Description, Aliases]
        public Task CrDm(int id)
            => InternalCrEdit(id, CustomReactionsService.CrField.DmResponse);

        [NadekoCommand, Usage, Description, Aliases]
        public Task CrAd(int id)
            => InternalCrEdit(id, CustomReactionsService.CrField.AutoDelete);

        [NadekoCommand, Usage, Description, Aliases]
        [OwnerOnly]
        public Task CrsReload()
        {
            _service.TriggerReloadCustomReactions();

            return ctx.Channel.SendConfirmAsync("?");
        }

        private async Task InternalCrEdit(int id, CustomReactionsService.CrField option)
        {
            var cr = _service.GetCustomReaction(ctx.Guild?.Id, id);
            if (!AdminInGuildOrOwnerInDm())
            {
                await ReplyErrorLocalizedAsync("insuff_perms").ConfigureAwait(false);
                return;
            }
            var (success, newVal) = await _service.ToggleCrOptionAsync(id, option).ConfigureAwait(false);
            if (!success)
            {
                await ReplyErrorLocalizedAsync("no_found_id").ConfigureAwait(false);
                return;
            }

            if (newVal)
            {
                await ReplyConfirmLocalizedAsync("option_enabled", Format.Code(option.ToString()), Format.Code(id.ToString())).ConfigureAwait(false);
            }
            else
            {
                await ReplyConfirmLocalizedAsync("option_disabled", Format.Code(option.ToString()), Format.Code(id.ToString())).ConfigureAwait(false);
            }
        }

        [NadekoCommand, Usage, Description, Aliases]
        [RequireContext(ContextType.Guild)]
        [UserPerm(GuildPerm.Administrator)]
        public async Task CrClear()
        {
            if (await PromptUserConfirmAsync(new EmbedBuilder()
                .WithTitle("Custom reaction clear")
                .WithDescription("This will delete all custom reactions on this server.")).ConfigureAwait(false))
            {
                var count = _service.ClearCustomReactions(ctx.Guild.Id);
                await ReplyConfirmLocalizedAsync("cleared", count).ConfigureAwait(false);
            }
        }
    }
}

Recommended Answers

All 3 Replies

Let's skip all that and read https://nadekobot.readthedocs.io/en/latest/guides/osx-guide/

Now back to your question. In conversions you work such in a few ways:

  1. Line by line.
  2. The whole enchilada. That is, you know what the app does and you write a new app that does that.

In closing I doubt only the above code is all that would be needed to convert this to Python. I take it you know that.

commented: I have the bot set up,,I just wanted to see the code in python +0

To see the code in Python you would have to rewrite it in Python. I see I noted the two usual methods. The app you noted would not be a trivial conversion so only those that need it would do so.

commented: is there websites or apps you reccomend for converting/translating the code +0

No. In your example the conversion does not look trivial. Try.

  1. Fiverr.com and similar to outsource the conversion.
  2. Go to this bot's source page and ask the authors if they have tried such.
  3. https://www.google.com/search?&q=c%23+python+convertor finds such but I have doubts it will result in a working bot for Discord and if it will be readable afterwards.

This seems like a lot of work just to see the code in Python.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.