Skip to content

Commit

Permalink
Merge pull request #20 from sushi-chaaaan/docs/#12-examples
Browse files Browse the repository at this point in the history
Add examples
  • Loading branch information
sushichan044 authored Oct 11, 2023
2 parents 7a8d356 + b384c34 commit 963120d
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 5 deletions.
16 changes: 11 additions & 5 deletions examples/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

import discord
from discord.ext import commands
from ductile import State, View, ViewObject
from ductile.controller import MessageableController
from ductile.state import State
from ductile.ui import Button
from ductile.view import View, ViewObject


class Bot(commands.Bot):
Expand Down Expand Up @@ -45,6 +44,11 @@ async def handle_decrement(interaction: discord.Interaction) -> None:
await interaction.response.defer()
self.count.set_state(lambda x: x - 1)

async def handle_reset(interaction: discord.Interaction) -> None:
await interaction.response.defer()
# also you can pass new value to State.set_state.
self.count.set_state(0)

async def stop(interaction: discord.Interaction) -> None:
await interaction.response.defer()
# stop the view. this will cause View.wait to return.
Expand All @@ -55,9 +59,11 @@ async def stop(interaction: discord.Interaction) -> None:
embeds=[e],
components=[
# components are fully typed with TypedDict.
Button("+1", style={"color": "grey"}, on_click=handle_increment),
Button("-1", style={"color": "grey"}, on_click=handle_decrement),
Button("stop", style={"color": "red"}, on_click=stop),
Button("+1", style={"color": "blurple"}, on_click=handle_increment),
Button("-1", style={"color": "blurple"}, on_click=handle_decrement),
# you can set style with conditional expression.
Button("reset", style={"color": "grey", "disabled": self.count.get_state() == 0}, on_click=handle_reset),
Button("stop", style={"color": "red", "row": 1}, on_click=stop),
],
)

Expand Down
108 changes: 108 additions & 0 deletions examples/confirm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# This example requires the 'message_content' privileged intent to function.


import asyncio

import discord
from discord.ext import commands
from ductile import State, View, ViewObject
from ductile.controller import InteractionController, MessageableController
from ductile.ui import Button


class Bot(commands.Bot):
def __init__(self) -> None:
super().__init__(command_prefix="!", intents=discord.Intents.all())

async def on_ready(self) -> None:
print(f"Logged in as {self.user}") # noqa: T201
print("Ready!") # noqa: T201


class ConfirmView(View):
def __init__(self) -> None:
super().__init__()
self.approved = State[bool | None](None, self)

def render(self) -> ViewObject:
async def handle_approve(interaction: discord.Interaction) -> None:
await interaction.response.defer()
self.approved.set_state(True) # noqa: FBT003
self.stop()

async def handle_deny(interaction: discord.Interaction) -> None:
await interaction.response.defer()
self.approved.set_state(False) # noqa: FBT003
self.stop()

return ViewObject(
embeds=[discord.Embed(title="Confirm", description="Are you sure?")],
components=[
Button("yes", style={"color": "green", "disabled": self.approved() is not None}, on_click=handle_approve),
Button("no", style={"color": "red", "disabled": self.approved() is not None}, on_click=handle_deny),
],
)

async def on_timeout(self) -> None:
print("Timed out") # noqa: T201
self.approved.set_state(False) # noqa: FBT003
self.stop()


class SomeBreakingView(View):
def __init__(self) -> None:
super().__init__()
# you can set state value type with generic type annotation.
self.approved = State[bool | None](None, self)

def render(self) -> ViewObject:
e = discord.Embed(
title="Some Breaking View",
description="With great power comes great responsibility.",
)
e.add_field(name="Approved", value="Not selected yet" if self.approved() is None else self.approved())

async def handle_execute(interaction: discord.Interaction) -> None:
await interaction.response.send_message("Executing...")
await interaction.edit_original_response(content="Executed!")

async def wait_for_confirm(interaction: discord.Interaction) -> None:
await interaction.response.defer()
# you can set timeout in Controller constructor.
# View.on_timeout will be called when the timeout expires.
view = ConfirmView()
controller = InteractionController(view, interaction=interaction, timeout=60, ephemeral=True)
await controller.send()
await controller.wait()
# This sleep is workaround. see details at https://github.com/sushi-chaaaan/ductile-ui/issues/23
await asyncio.sleep(3.0)
self.approved.set_state(view.approved())

return ViewObject(
embeds=[e],
components=[
Button(
"execute",
style={"color": "green", "disabled": self.approved() is not True},
on_click=handle_execute,
),
Button(
"confirm",
style={"color": "grey", "disabled": self.approved() is not None},
on_click=wait_for_confirm,
),
],
)


bot = Bot()


@bot.command(name="breaking")
async def send_counter(ctx: commands.Context) -> None:
controller = MessageableController(SomeBreakingView(), messageable=ctx.channel)
await controller.send()
await controller.wait()


bot.run("MY_COOL_BOT_TOKEN")

0 comments on commit 963120d

Please sign in to comment.