{"id":20453505,"url":"https://github.com/interstella0/starlight-dpy","last_synced_at":"2025-04-13T03:34:10.337Z","repository":{"id":64600272,"uuid":"576830466","full_name":"InterStella0/starlight-dpy","owner":"InterStella0","description":"A utility library that she uses for discord.py","archived":false,"fork":false,"pushed_at":"2024-02-18T05:19:13.000Z","size":579,"stargazers_count":18,"open_issues_count":4,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-29T03:33:27.781Z","etag":null,"topics":["discord","discord-bot","help-command","helper","library","pagination","utility"],"latest_commit_sha":null,"homepage":"https://starlight-dpy.readthedocs.io/en/latest/","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/InterStella0.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-11T05:35:55.000Z","updated_at":"2024-04-12T09:22:32.000Z","dependencies_parsed_at":"2024-02-18T04:27:38.861Z","dependency_job_id":"39bae10f-9bb7-4cfe-b412-599900108f3f","html_url":"https://github.com/InterStella0/starlight-dpy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InterStella0%2Fstarlight-dpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InterStella0%2Fstarlight-dpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InterStella0%2Fstarlight-dpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InterStella0%2Fstarlight-dpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InterStella0","download_url":"https://codeload.github.com/InterStella0/starlight-dpy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224770449,"owners_count":17366931,"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":["discord","discord-bot","help-command","helper","library","pagination","utility"],"created_at":"2024-11-15T11:12:59.631Z","updated_at":"2024-11-15T11:13:00.369Z","avatar_url":"https://github.com/InterStella0.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# starlight-dpy\nA utility library that she uses for discord.py\n\nThis 'library' is still in pre-alpha. This is still\nactively being develop and major changes _may_ be made :3\n\nFeel free to open an issue if you found any bugs!🌷\n\n**Do not use this in production.**\n\n### Installation\n```\npip install git+https://github.com/InterStella0/starlight-dpy\n```\n\n# Help Command\n\n## Menu Help Command\n\u003cdetails\u003e\n\u003csummary\u003eEasily paginate your help command with little effort.\u003c/summary\u003e\n\n```python\nimport starlight\nimport discord\n\nfrom discord.ext import commands\n\nbot = commands.Bot(\n    command_prefix=\"??\",\n    help_command=starlight.MenuHelpCommand(\n        per_page=10,\n        accent_color=0xffcccb,\n        error_color=discord.Color.red()\n    ),\n    intents=discord.Intents.all(),\n    description=\"Demonstration bot\"\n)\n```\n**Output**\n\n![default.png](docs/images/default_menu_help.png)\n\n### Customizing\nYou can easily customize your help command by overriding `format_*` methods!\n\nFormat methods: \n- `format_command_brief(cmd: commands.Command)`\n- `format_cog_page(view: HelpMenuCog, data: List[commands.Command])`\n- `format_bot_page(view: HelpMenuBot, mapping: Dict[Optional[commands.Cog], List[commands.Command]])`\n- `format_group_detail(view: HelpMenuGroup)`\n- `format_command_detail(view: HelpMenuCommand)`\n- `format_error_detail(view: HelpMenuError)`\n\n**Note:`page` suffix meant the View inherits SimplePaginationView** \n\n**Example:**\n```python\nimport starlight\nimport discord\n\nfrom discord.ext import commands\n\nclass MyMenuHelpCommand(starlight.MenuHelpCommand):\n    async def format_bot_page(self, view, mapping):\n        return discord.Embed(\n            title=\"Help\",\n            description=\"Choose a category to display your help command!\",\n            color=self.accent_color\n        )\n\n\nbot = commands.Bot(\n    command_prefix=\"??\",\n    help_command=MyMenuHelpCommand(\n            per_page=10,\n            accent_color=0xffcccb,\n            error_color=discord.Color.red(),\n            pagination_buttons={\n                \"start_button\": discord.ui.Button(emoji=\"⏪\", row=1),\n                \"previous_button\": discord.ui.Button(emoji=\"◀️\", style=discord.ButtonStyle.blurple, row=1),\n                \"stop_button\": discord.ui.Button(emoji=\"⏹️\", style=discord.ButtonStyle.red, row=1),\n                \"next_button\": discord.ui.Button(emoji=\"▶️\", style=discord.ButtonStyle.blurple, row=1),\n                \"end_button\": discord.ui.Button(emoji=\"⏩\", row=1)\n            }\n    ),\n    intents=discord.Intents.all(),\n    description=\"Demonstration bot\"\n)\n```\n**Output**\n\n![output.png](docs/images/customize_menu_help.png)\n\u003c/details\u003e\n\n## Paginate Help Command\n\u003cdetails\u003e\n\u003csummary\u003eUses buttons for navigation.\u003c/summary\u003e\n\n```python\nimport starlight\nimport discord\n\nfrom discord.ext import commands\n\nbot = commands.Bot(\n    command_prefix=\"??\",\n    help_command=starlight.PaginateHelpCommand(),\n    intents=discord.Intents.all()\n)\n```\n\n**Output**\n\n![output.png](docs/images/default_paginate_help.png)\n\u003c/details\u003e\n\n## Help Hybrid Command\n\u003cdetails\u003e\n\u003csummary\u003eHybrid is a term to implement both text and slash command in\ndiscord.py. \u003c/summary\u003e\n\n\n### Injection\nHelpCommand was explicitly only a text command. \nFor existing HelpCommand implementation, you can\nchange it to a hybrid, you can use `starlight.convert_help_hybrid`.\n\n```python\nimport starlight\nfrom discord.ext import commands\n\nmy_help_command = commands.DefaultHelpCommand()\nhybrid_help_command = starlight.convert_help_hybrid(my_help_command)\nbot = commands.Bot(..., help_command=hybrid_help_command)\n```\nOnce you sync your command. You can now use help command in slash command.\n\n**Note:** `convert_help_hybrid` second argument is directly transfered to\nthe AppCommand parameters.\n\n\n### Inherits\nFor new implementation of helpcommand, you can directly inherits\n`starlight.HelpHybridCommand`. This will have several helpful feature\nto integrate with app command. `with_app_command` should also be\nset to True\n\n```python\nimport starlight\nfrom discord.ext import commands\n\nclass MyHelp(starlight.HelpHybridCommand):\n    async def send_bot_help(self, mapping, /) -\u003e None:\n        no_command = len([c for cog in mapping.values() for c in cog])\n        response = f'I have `{no_command:,}` commands!'\n        await self.get_destination().send(response)\n\nbot = commands.Bot(..., help_command=MyHelp(with_app_command=True))\n```\nOnce you sync your command. You can now use help command in slash command.\n\n**Output**\n\n![output.png](docs/images/hybridhelp.png)\n\n\u003c/details\u003e\n\n# Views\n\n## Inline View\n\u003cdetails\u003e\n\u003csummary\u003eA shortcut for view handling.\u003c/summary\u003e\nCreate inline view for distinct behaviours with `starlight.inline_view`.\n\n```python\nimport starlight\nimport discord\n\n@bot.command()\nasync def my_command(ctx):\n    view = discord.ui.View()\n    hi_button = discord.ui.Button(label=\"hi\")\n    view.add_item(hi_button)\n    await ctx.send(\"hi\", view=view)\n    async for interaction, item in starlight.inline_view(view):\n        if item is hi_button:\n            response = \"hi\"\n        else:\n            response = \"unknown\"\n        await interaction.response.send_message(response, ephemeral=True)\n```\nYou can specify a `discord.ui.Item` to listen for a single item.\nEffective when you're expecting only a single interaction.\n\n```python\nresult = None\nasync for interaction, item in starlight.inline_view(view, item=hi_button):\n    result = await view.get_my_result(interaction)\n    view.stop()  # ensure only a single sequence\n\nprint(\"My Result:\", result)\n```\n**Note:**\n- Interaction callbacks are sequential due to async iterator.\n- Always go for View subclasses whenever you can.\n\u003c/details\u003e\n\n## Pagination View\n\u003cdetails\u003e\n\u003csummary\u003eA simple pagination interface.\u003c/summary\u003e\n\nThis was designed to not rely on `discord.ext.menus` due to lack of support\nfor `Interaction`. Majority of code that was present in `discord.ext.menus`\nwas dedicated for Reaction which has made it not ideal to be inherited.\n\n```python\nimport starlight\nimport discord\n\nclass MyPagination(starlight.SimplePaginationView):\n    async def format_page(self, interaction, data):\n        return discord.Embed(\n            title=f\"Simple display[{self.current_page + 1}/{self.max_pages}]\",\n            description=\"\\n\".join(data)\n        )\n\n\n@bot.command()\nasync def my_command(ctx):\n    my_data = [[\"1\", \"2\", \"3\"], [\"4\", \"5\", \"6\"], [\"7\", \"8\", \"9\"]]\n    view = MyPagination(my_data, cache_page=True)\n    await view.start(ctx)\n```\n**Note: You're required to chunk your data on your own. Tips:`discord.utils.as_chunks`**\n\n*Supports `commands.Paginator` with `.from_paginator` classmethod.*\n\n**Output**\n\n![output.png](docs/images/pagination_view.png)\n\n\u003c/details\u003e\n\n## Inline Pagination\n\u003cdetails\u003e\n\u003csummary\u003ePaginating can have distinct formats which could cause boilerplate code. Which leads to the \ncreation of Inline Pagination.\u003c/summary\u003e\nIt works\nsimilarly with Inline View. With a slight change, \n`InlinePaginationItem` are yielded for you to respond it to have an\neffect to the message through `.format()` method.\n\n```python\nimport starlight\nimport discord\n\n@bot.command()\nasync def my_command(ctx):\n    my_data = [[\"1\", \"2\", \"3\"], [\"4\", \"5\", \"6\"], [\"7\", \"8\", \"9\"]]\n    view = starlight.SimplePaginationView(my_data, cache_page=True)\n    async for item in starlight.inline_pagination(view, context=ctx):\n        embed = discord.Embed(\n            title=f\"Simple display[{view.current_page + 1}/{view.max_pages}]\",\n            description=\"\\n\".join(item.data)\n        )\n        item.format(embed=embed)  # keyword arguments are passed to `Message.edit`\n```\n\nThe output of this code is the equivalent of the Pagination View example.\n\u003c/details\u003e\n\n# General Utility\n## Search\n\u003cdetails\u003e\n\u003csummary\u003eAn extended version of discord.utils.get().\u003c/summary\u003e\nHowever, it is a filter that returns\na sequence. This also supports for fuzzy matching as they are relatively\ncommon to be used within a discord bot.\n\n```python\nfrom starlight import search, Contains\n# Contains is alias of ContainsFilter class\nitems_with_my_value = search(items, my_attr=Contains('my_value'))\n\n# Equivalent of\nitems_contains_value = [item for item in items if 'my_value' in item.my_attr]\n```\n\n\u003c/details\u003e\n\n## Flatten\n\u003cdetails\u003e\n\u003csummary\u003eFlatten nested iterables.\u003c/summary\u003e\n\n```python\nfrom starlight import flatten\n\narr = [[1, 2], [3, [4, 5], 6], 7, [8]]\narr_flatten = flatten(arr)\nprint(arr_flatten)  # -\u003e [1, 2, 3, 4, 5, 6, 7, 8]\n```\n\u003c/details\u003e\n\n# Converters\n## Separator\n\u003cdetails\u003e\n\u003csummary\u003eGreedy behaviour with a separator instead of spaces as \ndelimiter.\u003c/summary\u003e\nBy default, this is set to ',' as the delimiter. It can be configured by\npassing 'separator' keyword argument.\n\n```python\nfrom starlight import star_commands\n\n@star_commands.command(bot=bot) # this is required for separators\nasync def my_command(ctx, colours: star_commands.Separator[discord.Color], *, the_rest: str):\n    await ctx.send(f\"{colours} | '{the_rest}'\")\n```\n\n**Output**\n\n![output.png](docs/images/separators_example.png)\n\n\u003c/details\u003e\n\n# References\n- [Documentation](https://starlight-dpy.readthedocs.io/en/latest/)\n- [Discord.py Docs](https://discordpy.readthedocs.io/en/stable)\n\n\n# Contributors\n[![contributors](https://contrib.rocks/image?repo=InterStella0/starlight-dpy)](https://github.com/InterStella0/starlight-dpy/graphs/contributors)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterstella0%2Fstarlight-dpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterstella0%2Fstarlight-dpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterstella0%2Fstarlight-dpy/lists"}