{"id":15045006,"url":"https://github.com/discordsuperutils/discord-super-utils","last_synced_at":"2025-04-02T12:13:05.633Z","repository":{"id":41990136,"uuid":"380633430","full_name":"discordsuperutils/discord-super-utils","owner":"discordsuperutils","description":"A modern python module including many useful features that make discord bot programming extremely easy.","archived":false,"fork":false,"pushed_at":"2022-10-03T23:16:23.000Z","size":3513,"stargazers_count":118,"open_issues_count":1,"forks_count":28,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-23T07:38:29.180Z","etag":null,"topics":["database","discord","discord-api","discord-bot","discord-js","discord-py","discord-py-bot","leveling","levelingbotdiscord","mongodb","musicbotdiscord","postgresql","python","rank","sqlite"],"latest_commit_sha":null,"homepage":"https://discord-super-utils.gitbook.io/discord-super-utils/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/discordsuperutils.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-27T02:21:07.000Z","updated_at":"2025-03-19T20:44:03.000Z","dependencies_parsed_at":"2022-07-16T19:16:11.647Z","dependency_job_id":null,"html_url":"https://github.com/discordsuperutils/discord-super-utils","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/discordsuperutils%2Fdiscord-super-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/discordsuperutils%2Fdiscord-super-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/discordsuperutils%2Fdiscord-super-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/discordsuperutils%2Fdiscord-super-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/discordsuperutils","download_url":"https://codeload.github.com/discordsuperutils/discord-super-utils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246811311,"owners_count":20837752,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","discord","discord-api","discord-bot","discord-js","discord-py","discord-py-bot","leveling","levelingbotdiscord","mongodb","musicbotdiscord","postgresql","python","rank","sqlite"],"created_at":"2024-09-24T20:51:20.630Z","updated_at":"2025-04-02T12:13:05.593Z","avatar_url":"https://github.com/discordsuperutils.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ediscord-super-utils\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://codefactor.io/repository/github/discordsuperutils/discord-super-utils/\"\u003e\u003cimg src=\"https://img.shields.io/codefactor/grade/github/discordsuperutils/discord-super-utils?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://discord.gg/zhwcpTBBeC\"\u003e\u003cimg src=\"https://img.shields.io/discord/863388828734586880?logo=discord\u0026color=blue\u0026style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://pepy.tech/project/discordsuperutils\"\u003e\u003cimg src=\"https://img.shields.io/pypi/dm/discordSuperUtils?color=green\u0026style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/discordSuperUtils/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/discordSuperUtils?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"\"\u003e\u003cimg src=\"https://img.shields.io/pypi/l/discordSuperUtils?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/psf/black\"\u003e\u003cimg src=\"https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square\"\u003e\n    \u003cbr/\u003e\n  \u003ca href=\"https://discord-super-utils.gitbook.io/discord-super-utils/\"\u003eDocumentation\u003c/a\u003e\n  \u003ca href=\"https://discordsuperutils.readthedocs.io/en/latest/\"\u003eSecondary Documentation\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n   A modern python module including many useful features that make discord bot programming extremely easy.\n    \u003cbr/\u003e\n   \u003cb\u003eThe documentation is not done. if you have any questions, feel free to ask them in our \u003ca href=\"https://discord.gg/zhwcpTBBeC\"\u003ediscord server.\u003c/a\u003e\u003c/b\u003e\n\u003c/p\u003e\n\nFeatures\n-------------\n\n\n- Very easy to use and user-friendly.\n- Object Oriented.\n- Modern Leveling Manager.\n- Modern Music/Audio playing manager. [Lavalink and FFmpeg support]\n- Modern Async Database Manager (SQLite, MongoDB, PostgreSQL, MySQL, MariaDB).\n- Modern Paginator.\n- Modern Reaction Manager.\n- Modern Economy Manager.\n- Modern Image Manager (PIL).\n- Modern Invite Tracker.\n- Modern Command Hinter.\n- Modern FiveM Server Parser.\n- Modern Birthday Manager.\n- Modern Prefix Manager.\n- Includes easy to use convertors.\n- Modern spotify client that is optimized for player fetching.\n- Modern Punishment Manager (Kick, Ban, Infractions, Mutes)\n- Modern Template Manager.\n- Modern CogManager that supports usage of managers in discord cogs.\n- Modern MessageFilter and AntiSpam.\n- Customizable ModMail Manager\n- Modern Youtube client that is optimized for player fetching.\n- And many more!\n(MORE COMING SOON!)\n\nInstallation\n--------------\n\nInstalling discordSuperUtils is very easy.\n\n```sh\npython -m pip install discordSuperUtils\n```\n\nExamples\n--------------\n\n### Leveling Example (With Role Manager) ###\n\n```py\nimport discord\nfrom discord.ext import commands\n\nimport discordSuperUtils\n\nbot = commands.Bot(command_prefix=\"-\", intents=discord.Intents.all())\nLevelingManager = discordSuperUtils.LevelingManager(bot, award_role=True)\nImageManager = (\n    discordSuperUtils.ImageManager()\n)  # LevelingManager uses ImageManager to create the rank command.\n\n\n@bot.event\nasync def on_ready():\n    database = discordSuperUtils.DatabaseManager.connect(...)\n    await LevelingManager.connect_to_database(database, [\"xp\", \"roles\", \"role_list\"])\n\n    print(\"Leveling manager is ready.\", bot.user)\n\n\n@LevelingManager.event()\nasync def on_level_up(message, member_data, roles):\n    await message.reply(\n        f\"You are now level {await member_data.level()}\"\n        + (f\", you have received the {roles[0]}\" f\" role.\" if roles else \"\")\n    )\n\n\n@bot.command()\nasync def rank(ctx):\n    member_data = await LevelingManager.get_account(ctx.author)\n\n    if not member_data:\n        await ctx.send(f\"I am still creating your account! please wait a few seconds.\")\n        return\n\n    guild_leaderboard = await LevelingManager.get_leaderboard(ctx.guild)\n    member = [x for x in guild_leaderboard if x.member == ctx.author.id]\n\n    image = await ImageManager.create_leveling_profile(\n        ctx.author,\n        member_data,\n        discordSuperUtils.Backgrounds.GALAXY,\n        (127, 255, 0),\n        guild_leaderboard.index(member[0]) + 1 if member else -1,\n        outline=5,\n    )\n    await ctx.send(file=image)\n\n\n@bot.command()\nasync def set_roles(ctx, interval: int, *roles: discord.Role):\n    await LevelingManager.set_interval(ctx.guild, interval)\n    await LevelingManager.set_roles(ctx.guild, roles)\n\n    await ctx.send(\n        f\"Successfully set the interval to {interval} and role list to {', '.join(role.name for role in roles)}\"\n    )\n\n\n@bot.command()\nasync def leaderboard(ctx):\n    guild_leaderboard = await LevelingManager.get_leaderboard(ctx.guild)\n    formatted_leaderboard = [\n        f\"Member: {x.member}, XP: {await x.xp()}\" for x in guild_leaderboard\n    ]\n\n    await discordSuperUtils.PageManager(\n        ctx,\n        discordSuperUtils.generate_embeds(\n            formatted_leaderboard,\n            title=\"Leveling Leaderboard\",\n            fields=25,\n            description=f\"Leaderboard of {ctx.guild}\",\n        ),\n    ).run()\n\n\nbot.run(\"token\")\n```\n\n![Leveling Manager Example](https://media.giphy.com/media/ey1Iv2HlYYLPy0bm9p/giphy.gif)\n\n### Playing Example ### \n\n```py\nfrom math import floor\n\nfrom discord.ext import commands\n\nimport discordSuperUtils\nfrom discordSuperUtils import MusicManager\nimport discord\n\nclient_id = \"\"\nclient_secret = \"\"\n\nbot = commands.Bot(command_prefix=\"-\", intents=discord.Intents.all())\n# MusicManager = MusicManager(bot, spotify_support=False)\n\n\nMusicManager = MusicManager(\n    bot, client_id=client_id, client_secret=client_secret, spotify_support=True\n)\n\n\n# if using spotify support use this instead ^^^\n\n\n@MusicManager.event()\nasync def on_music_error(ctx, error):\n    raise error  # add your error handling here! Errors are listed in the documentation.\n\n\n@MusicManager.event()\nasync def on_queue_end(ctx):\n    print(f\"The queue has ended in {ctx}\")\n    # You could wait and check activity, etc...\n\n\n@MusicManager.event()\nasync def on_inactivity_disconnect(ctx):\n    print(f\"I have left {ctx} due to inactivity..\")\n\n\n@MusicManager.event()\nasync def on_play(ctx, player):\n    await ctx.send(f\"Playing {player}\")\n\n\n@bot.event\nasync def on_ready():\n    # database = discordSuperUtils.DatabaseManager.connect(...)\n    # await MusicManager.connect_to_database(database, [\"playlists\"])\n\n    print(\"Music manager is ready.\", bot.user)\n\n\n@bot.command()\nasync def leave(ctx):\n    if await MusicManager.leave(ctx):\n        await ctx.send(\"Left Voice Channel\")\n\n\n@bot.command()\nasync def np(ctx):\n    if player := await MusicManager.now_playing(ctx):\n        duration_played = await MusicManager.get_player_played_duration(ctx, player)\n        # You can format it, of course.\n\n        await ctx.send(\n            f\"Currently playing: {player}, \\n\"\n            f\"Duration: {duration_played}/{player.duration}\"\n        )\n\n\n@bot.command()\nasync def join(ctx):\n    if await MusicManager.join(ctx):\n        await ctx.send(\"Joined Voice Channel\")\n\n\n@bot.group(invoke_without_command=True)\nasync def playlists(ctx, user: discord.User):\n    user_playlists = await MusicManager.get_user_playlists(user)\n\n    formatted_playlists = [\n        f\"ID: '{user_playlist.id}'\\nTitle: '{user_playlist.playlist.title}'\\nTotal Songs: {len(user_playlist.playlist.songs)}\"\n        for user_playlist in user_playlists\n    ]\n\n    embeds = discordSuperUtils.generate_embeds(\n        formatted_playlists,\n        f\"Playlists of {user}\",\n        f\"Shows {user.mention}'s playlists.\",\n        25,\n        string_format=\"{}\",\n    )\n\n    page_manager = discordSuperUtils.PageManager(ctx, embeds, public=True)\n    await page_manager.run()\n\n\n@playlists.command()\nasync def add(ctx, url: str):\n    added_playlist = await MusicManager.add_playlist(ctx.author, url)\n\n    if not added_playlist:\n        await ctx.send(\"Playlist URL not found!\")\n        return\n\n    await ctx.send(f\"Playlist added with ID {added_playlist.id}\")\n\n\n@playlists.command()\nasync def play(ctx, playlist_id: str):\n    # This command is just an example, and not something you should do.\n    # The saved playlist system is supposed to provide fast, easy and simple playing, and the user should not look for\n    # the right playlist id before playing, as that defeats the whole point.\n    # Instead of playing using a playlist id, I recommend playing using indexes.\n    # Please, if you are playing using indexes, find the playlist id you need by getting all the user's playlists\n    # and then finding the id from there.\n    # Find the user's playlists using MusicManager.get_user_playlists(ctx.author, partial=True).\n    # Make sure partial is True to speed up the fetching progress (incase you want to access the playlist data,\n    # you can set it to False, of course).\n    # Using these playlists, find the id the user wants, and play it (or whatever else you want to do with it).\n    # Be creative!\n\n    user_playlist = await MusicManager.get_playlist(ctx.author, playlist_id)\n\n    if not user_playlist:\n        await ctx.send(\"That playlist does not exist!\")\n        return\n\n    if not ctx.voice_client or not ctx.voice_client.is_connected():\n        await MusicManager.join(ctx)\n\n    async with ctx.typing():\n        players = await MusicManager.create_playlist_players(\n            user_playlist.playlist, ctx.author\n        )\n\n    if players:\n        if await MusicManager.queue_add(\n            players=players, ctx=ctx\n        ) and not await MusicManager.play(ctx):\n            await ctx.send(f\"Added playlist {user_playlist.playlist.title}\")\n\n    else:\n        await ctx.send(\"Query not found.\")\n\n\n@playlists.command()\nasync def remove(ctx, playlist_id: str):\n    user_playlist = await MusicManager.get_playlist(ctx.author, playlist_id)\n\n    if not user_playlist:\n        await ctx.send(f\"Playlist with id {playlist_id} is not found.\")\n        return\n\n    await user_playlist.delete()\n    await ctx.send(f\"Playlist {user_playlist.playlist.title} has been deleted\")\n\n\n@bot.command()\nasync def play(ctx, *, query: str):\n    if not ctx.voice_client or not ctx.voice_client.is_connected():\n        await MusicManager.join(ctx)\n\n    async with ctx.typing():\n        players = await MusicManager.create_player(query, ctx.author)\n\n    if players:\n        if await MusicManager.queue_add(\n            players=players, ctx=ctx\n        ) and not await MusicManager.play(ctx):\n            await ctx.send(\"Added to queue\")\n\n    else:\n        await ctx.send(\"Query not found.\")\n\n\n@bot.command()\nasync def lyrics(ctx, query: str = None):\n    if response := await MusicManager.lyrics(ctx, query):\n        title, author, query_lyrics = response\n\n        splitted = query_lyrics.split(\"\\n\")\n        res = []\n        current = \"\"\n        for i, split in enumerate(splitted):\n            if len(splitted) \u003c= i + 1 or len(current) + len(splitted[i + 1]) \u003e 1024:\n                res.append(current)\n                current = \"\"\n                continue\n            current += split + \"\\n\"\n\n        page_manager = discordSuperUtils.PageManager(\n            ctx,\n            [\n                discord.Embed(\n                    title=f\"Lyrics for '{title}' by '{author}', (Page {i + 1}/{len(res)})\",\n                    description=x,\n                )\n                for i, x in enumerate(res)\n            ],\n            public=True,\n        )\n        await page_manager.run()\n    else:\n        await ctx.send(\"No lyrics found.\")\n\n\n@bot.command()\nasync def pause(ctx):\n    if await MusicManager.pause(ctx):\n        await ctx.send(\"Player paused.\")\n\n\n@bot.command()\nasync def resume(ctx):\n    if await MusicManager.resume(ctx):\n        await ctx.send(\"Player resumed.\")\n\n\n@bot.command()\nasync def volume(ctx, volume: int):\n    await MusicManager.volume(ctx, volume)\n\n\n@bot.command()\nasync def loop(ctx):\n    is_loop = await MusicManager.loop(ctx)\n\n    if is_loop is not None:\n        await ctx.send(f\"Looping toggled to {is_loop}\")\n\n\n@bot.command()\nasync def shuffle(ctx):\n    is_shuffle = await MusicManager.shuffle(ctx)\n\n    if is_shuffle is not None:\n        await ctx.send(f\"Shuffle toggled to {is_shuffle}\")\n\n\n@bot.command()\nasync def autoplay(ctx):\n    is_autoplay = await MusicManager.autoplay(ctx)\n\n    if is_autoplay is not None:\n        await ctx.send(f\"Autoplay toggled to {is_autoplay}\")\n\n\n@bot.command()\nasync def queueloop(ctx):\n    is_loop = await MusicManager.queueloop(ctx)\n\n    if is_loop is not None:\n        await ctx.send(f\"Queue looping toggled to {is_loop}\")\n\n\n@bot.command()\nasync def complete_queue(ctx):\n    if ctx_queue := await MusicManager.get_queue(ctx):\n        formatted_queue = [\n            f\"Title: '{x.title}'\\nRequester: {x.requester and x.requester.mention}\\n\"\n            f\"Position: {i - ctx_queue.pos}\"\n            for i, x in enumerate(ctx_queue.queue)\n        ]\n\n        num_of_fields = 25\n\n        embeds = discordSuperUtils.generate_embeds(\n            formatted_queue,\n            \"Complete Song Queue\",\n            \"Shows the complete song queue.\",\n            num_of_fields,\n            string_format=\"{}\",\n        )\n\n        page_manager = discordSuperUtils.PageManager(\n            ctx, embeds, public=True, index=floor(ctx_queue.pos / 25)\n        )\n        await page_manager.run()\n\n\n@bot.command()\nasync def goto(ctx, position: int):\n    if ctx_queue := await MusicManager.get_queue(ctx):\n        new_pos = ctx_queue.pos + position\n        if not 0 \u003c= new_pos \u003c len(ctx_queue.queue):\n            await ctx.send(\"Position is out of bounds.\")\n            return\n\n        await MusicManager.goto(ctx, new_pos)\n        await ctx.send(f\"Moved to position {position}\")\n\n\n@bot.command()\nasync def history(ctx):\n    if ctx_queue := await MusicManager.get_queue(ctx):\n        formatted_history = [\n            f\"Title: '{x.title}'\\nRequester: {x.requester and x.requester.mention}\"\n            for x in ctx_queue.history\n        ]\n\n        embeds = discordSuperUtils.generate_embeds(\n            formatted_history,\n            \"Song History\",\n            \"Shows all played songs\",\n            25,\n            string_format=\"{}\",\n        )\n\n        page_manager = discordSuperUtils.PageManager(ctx, embeds, public=True)\n        await page_manager.run()\n\n\n@bot.command()\nasync def skip(ctx, index: int = None):\n    await MusicManager.skip(ctx, index)\n\n\n@bot.command()\nasync def queue(ctx):\n    if ctx_queue := await MusicManager.get_queue(ctx):\n        formatted_queue = [\n            f\"Title: '{x.title}\\nRequester: {x.requester and x.requester.mention}\"\n            for x in ctx_queue.queue[ctx_queue.pos + 1 :]\n        ]\n\n        embeds = discordSuperUtils.generate_embeds(\n            formatted_queue,\n            \"Queue\",\n            f\"Now Playing: {await MusicManager.now_playing(ctx)}\",\n            25,\n            string_format=\"{}\",\n        )\n\n        page_manager = discordSuperUtils.PageManager(ctx, embeds, public=True)\n        await page_manager.run()\n\n\n@bot.command()\nasync def rewind(ctx, index: int = None):\n    await MusicManager.previous(ctx, index, no_autoplay=True)\n\n\n@bot.command()\nasync def ls(ctx):\n    if queue := await MusicManager.get_queue(ctx):\n        loop = queue.loop\n        loop_status = None\n\n        if loop == discordSuperUtils.Loops.LOOP:\n            loop_status = \"Looping enabled.\"\n\n        elif loop == discordSuperUtils.Loops.QUEUE_LOOP:\n            loop_status = \"Queue looping enabled.\"\n\n        elif loop == discordSuperUtils.Loops.NO_LOOP:\n            loop_status = \"No loop enabled.\"\n\n        if loop_status:\n            await ctx.send(loop_status)\n\n\n@bot.command()\nasync def move(ctx, player_index: int, index: int):\n    await MusicManager.move(ctx, player_index, index)\n\n\nbot.run(\"token\")\n```\n\n![MusicManager Example](https://media.giphy.com/media/SF6K0zIVHl6RCQ0Aqk/giphy.gif)\n\nMore examples are listed in the examples folder.\n\nKnown Issues\n--------------\n\n- Removing an animated emoji wont be recognized as a reaction role, as it shows up as not animated for some reason, breaking the reaction matcher. (Discord API Related)\n\nSupport\n--------------\n\n- **[Support Server](https://discord.gg/zhwcpTBBeC)**\n- **[Documentation](https://discord-super-utils.gitbook.io/discord-super-utils/)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiscordsuperutils%2Fdiscord-super-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdiscordsuperutils%2Fdiscord-super-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiscordsuperutils%2Fdiscord-super-utils/lists"}