Asynchronous Guilded API wrapper for Python

Overview

Welcome to guilded.py, a discord.py-esque asynchronous Python wrapper for the Guilded API. If you know discord.py, you know guilded.py.

Documentation

In the works. Fortunately, if you've used discord.py before, you'll already have a head start.

Basic Example

import guilded

client = guilded.Client()

@client.event
async def on_ready():
    print('Ready')

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    if message.content == 'ping':
        await message.channel.send('pong')

client.run('email', 'password')

For more examples, see the examples directory in this repository.

Support

Guilded.py has a support channel under its dedicated group for any questions you may have.

  1. Join the Guilded-API server
  2. Navigate to #library-list
  3. Click on the guilded.py role and click "Add me to role"
  4. You should see a new group pop up in your sidebar - you are now in the Guilded.py group
Comments
  • Added Makefile + development mode

    Added Makefile + development mode

    I went and added a Makefile for quickly putting guilded.py into development mode. I added the usage instructions to the README but the basic usage is to create your venv then run make develop.

    This allows for any changes to the library code to be reflected back in Python immediately plus make developing simpler

    opened by ThomasJRyan 4
  • MemberConverter doesn't accept user mention as argument

    MemberConverter doesn't accept user mention as argument

    Describe the bug I can't target a user using a mention when attempting to convert, only with the raw name or user ID

    To Reproduce This fails await commands.MemberConverter().convert(ctx, "@Henry") This succeeds await commands.MemberConverter().convert(ctx, "Henry")

    Expected behavior Return the user successfully

    Actual behavior Throws that it can't find the user

    wontfix 
    opened by henry232323 3
  • Embeed the bot inside a fastapi server

    Embeed the bot inside a fastapi server

    Describe the bug Start my fastapi server using uvicorn, send a "ping" in chat, bot answer with "pong", stop uvicorn server. This is the stacktrace I get.

    Ready
    INFO:     Shutting down
    INFO:     Waiting for application shutdown.
    INFO:     Application shutdown complete.
    INFO:     Finished server process [37840]
    Traceback (most recent call last):
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner
        self.run()
      File "C:\Users\xxx\IdeaProjects\onr-bot-guilded\.tox\py310\lib\site-packages\guilded\gateway.py", line 1022, in run
        f = asyncio.run_coroutine_threadsafe(coro, loop=self.ws.loop)
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\tasks.py", line 885, in run_coroutine_threadsafe
        loop.call_soon_threadsafe(callback)
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 795, in call_soon_threadsafe
        self._check_closed()
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 515, in _check_closed
        raise RuntimeError('Event loop is closed')
    RuntimeError: Event loop is closed
    python-BaseException
    Exception in thread Thread-5:
    Traceback (most recent call last):
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner
        self.run()
      File "C:\Users\xxx\IdeaProjects\onr-bot-guilded\.tox\py310\lib\site-packages\guilded\gateway.py", line 1022, in run
        f = asyncio.run_coroutine_threadsafe(coro, loop=self.ws.loop)
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\tasks.py", line 885, in run_coroutine_threadsafe
        loop.call_soon_threadsafe(callback)
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 795, in call_soon_threadsafe
        self._check_closed()
      File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 515, in _check_closed
        raise RuntimeError('Event loop is closed')
    RuntimeError: Event loop is closed
    sys:1: RuntimeWarning: coroutine 'GuildedWebSocket.ping' was never awaited
    RuntimeWarning: Enable tracemalloc to get the object allocation traceback
    
    Process finished with exit code 0
    
    

    To Reproduce

    import asyncio
    import guilded
    from fastapi import FastAPI
    
    app = FastAPI()
    client = guilded.Client()
    
    @app.on_event("startup")
    async def startup_event():
        logging.info('Starting server')
        asyncio.create_task(client.start(TOKEN))
    
    
    @client.event
    async def on_ready():
        print('Ready')
    
    @client.event
    async def on_message(message):
        if message.author == client.user:
            return
        if message.content == 'ping':
            await message.channel.send('pong!')
    
    def main():
        import uvicorn
        uvicorn.run(app="app", host="0.0.0.0", port=8080, access_log=False, workers=1)
    
    
    if __name__ == '__main__':
        main()
    

    Expected behavior I don't expect any stack trace in logs

    Actual behavior Stacktrace telling me RuntimeWarning: coroutine 'GuildedWebSocket.ping' was never awaited

    Screenshots If applicable, please attach screenshots to help explain/demonstrate the problem.

    Environment

    • OS: Windows 10
    • Python version (make sure you're using >=3.8): 3.10
    • Library version: "guilded.py" = "^1.5.0" fastapi = "^0.85.2" uvicorn = "^0.19.0"
    invalid 
    opened by NargiT 2
  • Cant send Embeds

    Cant send Embeds

    Describe the bug You cant send Embeds.

    To Reproduce Code: @bot.command() async def EmbedTest(ctx): embed = guilded.Embed(Title="Test Title", desciption="Test Description", color=0x00ff00) embed.add_field(name="Field 1", value="Field 1 Value", inline=False) await ctx.send(embed=embed)

    Screenshots image

    Code: image

    Environment

    • OS: Windows 10
    • Python version: 3.9
    • Library version: 1.0.0a0
    unconfirmed bug 
    opened by Jigsaw88 2
  • `message.author.send('some string')` not working

    `message.author.send('some string')` not working

    Describe the bug Hi, I am trying to migrate a bot from discord to guilded. The bot generates a QR code and sends it to a member of the guild. The member types $qr in a guild channel and the bot then DM's the QR code to the member. However, the bot fails to DM the member.

    To Reproduce This is the on_message event listener I am using.

    @client.event
    # Listen for an incoming message
    async def on_message(message):
        # If the author is the robot itself, then do nothing!
        if message.author == client.user:
            return
        # If the user writes $qr
        if message.content == "$qr":
            current_time = now.strftime("%H:%M:%S")
            print('\n')
            # This for loop check for all the user's DiscordID in the Database
            if str(message.author.id) in ScholarsDict:
                print("This user received his QR Code : " + message.author.name)
                print("Discord ID : " + str(message.author.id))
                print("Current time : ", current_time)
                # value with discordID
                botPlaceHolders = ScholarsDict[str(message.author.id)]
                # discordID's privateKey from the database
                accountPrivateKey = botPlaceHolders[2]
                # discordID's EthWalletAddress from the database
                accountAddress = botPlaceHolders[1]
                # Get a message from AxieInfinty
                rawMessage = getRawMessage()
                # Sign that message with accountPrivateKey
                signedMessage = getSignMessage(rawMessage, accountPrivateKey)
                # Get an accessToken by submitting the signature to AxieInfinty
                accessToken = submitSignature(signedMessage, rawMessage, accountAddress)
                # Create a QrCode with that accessToken
                qrCodePath = f"QRCode_{message.author.id}_{str(uuid.uuid4())[0:8]}.png"
                generate_qr(accessToken, qrCodePath)
    
                # Send the QrCode the the user who asked for
                await message.author.send(
                    "Tips: If the qr code wont work, please try this steps. Delete the old qr on your device, and get a "
                    "new one again, "
                    "if that doesn't work then scan the qr code with another device."
    
                    + message.author.name + "\nHere is your new QR Code to login : "
                )
                await message.author.send(file=guilded.File(qrCodePath))
                os.remove(qrCodePath)
                return ["bot_token"]
            else:
                print("This user didn't receive a QR Code because not added in SecretStorage: " + message.author.name)
                print("Guilded ID: " + str(message.author.id))
                print("Current time: ", current_time)
                return
    

    Expected behavior I expect the bot to DM the member the generated QR code

    Actual behavior I get this error instead

    Ignoring exception in on_message:
    Traceback (most recent call last):
      File "/home/kintama/Downloads/Cryptic-QR-Code-for-Guilded/venv/lib/python3.8/site-packages/guilded/client.py", line 353, in _run_event
        await coro(*args, **kwargs)
      File "Cryptic-Scholars-QR-Code-Bot.py", line 67, in on_message
        await message.author.send(
      File "/home/kintama/Downloads/Cryptic-QR-Code-for-Guilded/venv/lib/python3.8/site-packages/guilded/user.py", line 213, in general
        return await getattr(self._user, x)(*args, **kwargs)
      File "/home/kintama/Downloads/Cryptic-QR-Code-for-Guilded/venv/lib/python3.8/site-packages/guilded/abc.py", line 616, in send
        await self.create_dm()
      File "/home/kintama/Downloads/Cryptic-QR-Code-for-Guilded/venv/lib/python3.8/site-packages/guilded/abc.py", line 591, in create_dm
        data = await self._state.create_dm_channel([self.id])
    AttributeError: 'HTTPClient' object has no attribute 'create_dm_channel'
    

    Environment

    • OS: Ubuntu 20.04.4 LTS
    • Python version: 3.8.10
    • Library version: 17c058335ac664b4fcf0f584ae7456c0567a4309
    invalid 
    opened by kintama48 2
  • Wrong license message

    Wrong license message

    Wrong license message

    So in some files this include but not limited to: backoff.py, the license message is still belongs to Rapptz while LICENSE file is shay (shayypy). Is this on purpose?

    opened by TheGenocides 2
  • Automatic Building

    Automatic Building

    Ok, this thing will build and upload a package to pypi every time you push a commit to the github, This Needs 2 secrets (one called "user" where you will drop your pypi user, another is called "pass" where you need to drop your password)

    to setup a secret you should go to Settings > Secret and create it there, no one can steal your password if you store it on secrets

    opened by danilacasito 2
  • Command parser should merge user/channel mentions into a single argument

    Command parser should merge user/channel mentions into a single argument

    Currently, I have to explain to users that they need to surround a user or channel mention in quotation marks purely due to the fact that the library's command parser recognizes user/channel mentions with multiple words separated by spaces as individual arguments instead of a single argument. It would be much better if the command parser could recognize user/channel mentions toward users & channels in the bot's cache and merge them into one argument.

    wontfix 
    opened by Reapimus 1
  • BotTeamMembershipCreated websocket event causes the bot to crash on server join

    BotTeamMembershipCreated websocket event causes the bot to crash on server join

    Describe the bug When the bot tries to handle the BotTeamMembershipCreated WebSocket event, it causes a crash to occur.

    To Reproduce Have the bot join a server while it is running.

    Expected behavior The event should be handled appropriately and the bot should not crash.

    Actual behavior The bot crashes with the error "UnboundLocalError: local variable 'server' referenced before assignment"

    Environment

    • OS: Linux
    • Python version (make sure you're using >=3.8): 3.10.7
    • Library version: 1.4.0
    bug 
    opened by Reapimus 1
  • Unable to send Media

    Unable to send Media

    Describe the bug when attempting to send media to show Images or Diagrams, you are unable to send the media

    To Reproduce Attempt to send either files or attachments, via await ctx.send or await channel.send... etc

    Expected behavior Send message with a Media Attachment of a file.

    Actual behavior Message is sent without Media Attachment, and doesn't deliver an error message

    Screenshots image

    Environment

    • OS: Arch Linux 2022.06.01 (Development PC) Ubuntu Server Bionic Beaver 18.04.6 LTS (Server)
    • Python version (make sure you're using >=3.8): Python 3.10 Both Environments.
    • Library version: 1.0.0a0 (0.0.5 lacks guilded.ext)
    opened by Reedeht 1
  • Embeds not Sending

    Embeds not Sending

    Describe the bug When attempting to send embeds, that have been made similar to in discord.py, you get a series of errors related to embeds.

    To Reproduce How to reproduce is in screenshot, but it is applicable to all embed modifications

    Expected behavior Bot would send an embed with gold colouring, and a single field, with Test as a title and Test as Content.

    Actual behavior Errors sent to console, copy and paste below Ignoring exception in command test: Traceback (most recent call last): File "guilded/ext/commands/core.py", line 83, in wrapped ret = await coro(*args, **kwargs) File "PycharmProjects/Unified States/miscRW/credits.py", line 18, in test await ctx.send(embed=embed) File "guilded/abc.py", line 236, in send data = await self._state.create_channel_message(self._channel_id, File "guilded/http.py", line 1404, in request return await perform() File "guilded/http.py", line 1400, in perform raise exception(response, data) guilded.errors.BadRequest: 400 (BadRequestError): data must have required property 'content', data must have required property 'embeds', data must match a schema in anyOf

    The above exception was the direct cause of the following exception: Traceback (most recent call last): File "guilded/ext/commands/bot.py", line 421, in invoke await ctx.command.invoke(ctx) File "guilded/ext/commands/core.py", line 619, in invoke await injected(*ctx.args, **ctx.kwargs) File "guilded/ext/commands/core.py", line 92, in wrapped raise CommandInvokeError(exc) from exc guilded.ext.commands.errors.CommandInvokeError: Command raised an exception: BadRequest: 400 (BadRequestError): data must have required property 'content', data must have required property 'embeds', data must match a schema in anyOf

    Screenshots image

    Environment

    • OS: Arch Linux 2022.06.01 (Development PC) Ubuntu Server Bionic Beaver 18.04.6 LTS (Server)
    • Python version (make sure you're using >=3.8): Python 3.10 Both Environments.
    • Library version: 1.0.0a0 (0.0.5 lacks guilded.ext)
    opened by Reedeht 1
  • Event rework

    Event rework

    This issue outlines two enhancements to how events work in guilded.py. The first is the addition of more granular event control: restraining categories of events based on what your client needs. The second is a rework to how parameters are passed to event callbacks.

    Granular events

    discord.py implements a similar idea with its enable_debug_events parameter for Clients. This enhancement proposes the addition of this parameter as well as a use_discordpy_style_events parameter in order to "switch" event behavior to be more akin to discord.py. This would currently only detail event names (e.g., server_join vs. guild_join - only one or the other), but its effects are greater when considering the following change:

    Event parameters

    This change is considerably more impactful. If you are familiar with the JavaScript event system (with its Event and inheritors) then this may ring a bell for you. Instead of the following:

    async def on_message(message):
        # message is a ChatMessage
        ...
    

    you would handle events like so:

    async def on_message(event):
        # event is a MessageEvent
        message = event.message
        # message is a ChatMessage
    

    This change could also come with the decision to drop raw_ events in exchange for a more unified interface:

    async def on_message_update(event):
        before = event.before  # could be None. Such a value indicates that the message was not cached.
        after = event.after  # always a ChatMessage
    
        # To perform cache-dependent logic, the user will essentially mirror the previous internal behavior:
        if before is None:
            return
    

    This also flattens relatively convoluted events like raw_message_reaction_add and makes the whole event system function similarly. For example:

    async def on_message_reaction_add(event):
        message = event.message  # could be None, but the user will always have event.message_id
        emote = event.emote  # Emote
        # The user will also have event.channel(_id), event.created_by(_id), and event.server(_id)
    

    Guilded does not provide the rich data in its ChannelMessageReactionCreated/ChannelMessageReactionDeleted payloads that would make Reaction a better model to have here.

    This would also enable events to include miscellaneous metadata, like that which is seen in TeamMemberRemoved:

    async def on_member_remove(event):
        member = event.member  # could be None, but the user will always have event.server_id and event.user_id
        kicked = event.kicked
        banned = event.banned
    

    This removes the need for extraneous member_leave and member_kick events which are not present in the bot API.

    Conclusion

    The latter part of this issue is currently available for use as an opt-in experiment, more details here. Feel free to discuss either of these in the #development channel (see the support header) or in this issue's comments.

    enhancement 
    opened by shayypy 7
  • Implement rate limit buckets

    Implement rate limit buckets

    Guilded's rate limits are pretty vague but it is possible to improve on the current system as a library. Notably, this issue suggests implementation of rate limit buckets in order to prevent extraneous requests from being made to the same bucket while the client is rate limited.

    Partially related to this issue is the x-slowmode-cooldown header returned when the client fails to send a message to a channel with slowmode enabled. It contains the value in seconds of the slowmode setting for the channel. In this case, the bucket is the channelId.

    enhancement 
    opened by shayypy 0
A simple API Wrapper for Guilded.

Guildr A simple API Wrapper for Guilded. Frequently updated! I am not a user of Guilded, meaning I do not keep track of new Guilded updates or patches

null 2 Mar 7, 2022
🚀 An asynchronous python API wrapper meant to replace discord.py - Snappy discord api wrapper written with aiohttp & websockets

Pincer An asynchronous python API wrapper meant to replace discord.py ❗ The package is currently within the planning phase ?? Links |Join the discord

Pincer 125 Dec 26, 2022
Asynchronous Python Wrapper for the GoFile API

Asynchronous Python Wrapper for the GoFile API

Gautam Kumar 22 Aug 4, 2022
Asynchronous Python Wrapper for the Ufile API

Ufile.io Asynchronous Python Wrapper for the Ufile API (Unofficial).

Gautam Kumar 16 Aug 31, 2022
ro.py is a modern, asynchronous Python 3 wrapper for the Roblox API.

GitHub | Discord | PyPI | Documentation | Examples | License Overview Welcome to ro.py! ro.py is an asynchronous, object-oriented wrapper for the Robl

ro.py 81 Dec 26, 2022
Asynchronous Python API Wrapper for phisherman.gg

Asynchronous Python API Wrapper for phisherman.gg

Qrista Labs 4 Apr 30, 2022
Fully asynchronous trace.moe API wrapper

AioMoe Fully asynchronous trace.moe API wrapper Installation You can install the stable version from PyPI: $ pip install aiomoe Or get it from github

null 2 Jun 26, 2022
Asynchronous wrapper для Gismeteo.ru.

aiopygismeteo Асинхронная обёртка для Gismeteo.ru. Синхронная версия здесь. Установка python -m pip install -U aiopygismeteo Документация https://aiop

Almaz 6 Dec 8, 2022
Asynchronous wrapper for wttr.in weather forecast.

aiopywttr Asynchronous wrapper for wttr.in weather forecast. Synchronous version here. Installation pip install aiopywttr Example This example prints

Almaz 4 Dec 24, 2022
🖥️ Python - P1 Monitor API Asynchronous Python Client

??️ Asynchronous Python client for the P1 Monitor

Klaas Schoute 9 Dec 12, 2022
Aws-lambda-requests-wrapper - Request/Response wrapper for AWS Lambda with API Gateway

AWS Lambda Requests Wrapper Request/Response wrapper for AWS Lambda with API Gat

null 1 May 20, 2022
Python: Asynchronous client for the Tailscale API

Python: Asynchronous client for the Tailscale API Asynchronous client for the Tailscale API. About This package allows you to control and monitor Tail

Franck Nijhof 9 Nov 22, 2022
Python: Asynchronous client for the Open-Meteo API.

Python: Asynchronous client for the Open-Meteo API. Asynchronous client for the Open-Meteo API. About Open-Meteo offers free weather forecast APIs for

Franck Nijhof 11 Dec 21, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022
Python API wrapper around Trello's API

A wrapper around the Trello API written in Python. Each Trello object is represented by a corresponding Python object. The attributes of these objects

Richard Kolkovich 904 Jan 2, 2023
Async ready API wrapper for Revolt API written in Python.

Mutiny Async ready API wrapper for Revolt API written in Python. Installation Python 3.9 or higher is required To install the library, you can just ru

null 16 Mar 29, 2022
A Python API wrapper for the Twitter API!

PyTweet PyTweet is an api wrapper made for twitter using twitter's api version 2! Installation Windows py3 -m pip install PyTweet Linux python -m pip

TheFarGG 1 Nov 19, 2022
Python API wrapper library for Convex Value API

convex-value-python Python API wrapper library for Convex Value API. Further Links: Convex Value homepage @ConvexValue on Twitter JB on Twitter Authen

Aaron DeVera 2 May 11, 2022