Skip to main content

An Declarative UI Kit for discord.py

Project description

https://static.pepy.tech/personalized-badge/discord-ext-ui?period=month&units=international_system&left_color=black&right_color=orange&left_text=Downloads PyPI version info PyPI supported Python versions

このパッケージはdiscord.uiの拡張です。

なぜdiscord-ext-uiを使うのか?

discord-ext-uiは、SwiftUIに似た宣言的Viewシステム・Combineシステムを搭載しています。

これにより、MVVMなどのアーキテクチャを実装したり、送信した後のボタンの編集が容易になります。

MVVMアーキテクチャを採用する利点

まずMVVMとは、各クラスが公開インスタンス変数を管理することによって、画面状態の管理を安全に行うことのできるModel View ViewModelと呼ばれるアーキテクチャの略称です。

MVVMにおいてコンポーネントの設計はView、ViewModel、Modelにわけられ、それぞれ別の役割を担います。

https://qiita.com/yuutetu/items/ea175b73e1dbbfd355db

詳しくはこちらなどの記事を参考にしてください。

MVVMにより、ロジック部分と画面への描画部分、およびDiscordへの通信部分が分けられるため、ロジックに対するテストが書きやすく、結果として品質の高いコードを維持することができます。

discord-ext-uiを採用する利点

  1. メッセージの更新を明示的に行う必要がなくなる

例として、ボタンを使ってカウントを増やしたり減らしたりできるような機能を実装するとしましょう。

MVVMを用いらずに実装する場合、ボタンの押下時に内部状態が変更された際にその状態を反映してメッセージの更新を行う処理を明示的に記述する必要があります。

対して、discord-ext-uiでは、 statepublished といった変数のラッパーを提供します。このラッパーを使用することで、メンバ変数の変更に応じてメッセージの更新を明示的に書く必要がなくなります。

また、ボタンが押されたときに実行される関数を宣言的に設定できるので、forループ等の複雑な処理を行うことも可能です。

  1. ボタンを使った時の処理が書きやすい

discord.py 2.0からボタンの対応が始まりましたが、discord.py標準のボタン対応の仕組みでは、途中でボタンの変更などがし辛いなどの問題があります。

discord-ext-uiを使えば、自動で更新する際にボタンの変更も可能なので、インスタンス変数の値に応じた無効化・有効化や、ペジネーション等の内部状態に応じたボタンの変更処理も簡単に実装することができます。

View

Viewは body という名前のメソッドを実装しなければなりません。 body メソッドはdiscord-ext-uiの Message を返却する必要があります。 ライブラリは body メソッドをメッセージを作成/更新する際に毎回呼び出し、その結果を用いてDiscord APIを呼び出します。 View クラスは start メソッドを持っていて、これにチャンネルを渡すことでメッセージの作成が行われます。

State

stateはViewのプロパティとして振る舞います。 Viewのクラス変数として定義したあと、値を代入してください。

View上のstateを更新するとメッセージの更新が行われます。つまり、ライブラリによって、 body メソッドが呼び出され、その結果を用いてDiscord上のメッセージが更新されます。

ObservedObjectとPublished

これはMVVMに関連した概念です。MVVMを用いないのであればこの節は読まなくても良いかもしれません。 ObservableObject を継承したViewModelをViewのインスタンス変数とすると、 ObservableObjectのpublished propertyにした値が変更されたとき、Viewに変更を通知して、Viewが自動で更新されます。

Example

from discord.ext.ui import Component, Button, View, ObservableObject, published, Message
from discord.ext import commands
import discord
import os

client = discord.Client()


class SampleViewModel(ObservableObject):
    num = published('num')

    def __init__(self, bot):
        super().__init__(bot)
        self.num = 0

    def countup(self):
        self.num += 1

    def countdown(self):
        self.num -= 1


class SampleView(View):
    def __init__(self, bot):
        super().__init__(bot)
        self.view_model = SampleViewModel(bot)

    async def add_reaction(self):
        await self.get_message().add_reaction("\U0001f44d")

    async def body(self):
        return Message(
            content=f"test! {self.view_model.num}",
            component=Component(items=[
                [
                    Button("+1")
                        .on_click(lambda x: self.view_model.countup())
                        .style(discord.ButtonStyle.blurple),

                    Button("-1")
                        .on_click(lambda x: self.view_model.countdown())
                        .style(discord.ButtonStyle.blurple)
                ]
            ])
        )


@client.event
async def on_message(message):
    if message.content != "!test":
        return
    await SampleView(client).start(message.channel)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

discord_ext_ui-2.1.1-py3-none-any.whl (16.9 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page