Closed Gouvernathor closed 1 year ago
Hello! Thanks for the issue. If this is a general help question, for a faster response consider joining the official Discord Server
Else if you have an issue with the library please wait for someone to help you here.
Making API calls requires a PartialUser object. This is due to the underlying state being different for api calls vs irc calls. As such, we include a .user function on PartialChatter which will fetch the User. If you wish to save on API calls, use Client.create_user to get a PartialUser. On Context, send is a special case because Context is a Messagable. We do not provide API state on the context object.
So, if I'm following correctly : the Context and Bot(/Client) classes provide IRC features, but not API ? And you need to create a User to target it with an API call ?
It would seem more easy to use, to me, that the class you use the method on is the one who sends the API thing, rather than the one receiving it. To send a mail, I use a letter and provide it with the address of the target house, I don't use the house and sign my identity at the bottom, if that makes sense.
I would see it more user-friendly if the self
, the Bot, had a send
and a announcement
methods (having whatever names), which you would pass a target (a channel, a user... a messageable I guess, sort of) and things specific to the method : a message, the optional color for announcements, a user for a ban...
And it would use the credentials passed to the Bot in the first place, even though as I understand it the credentials management would not be the same in the two cases under the hood.
Context is used solely for chat and command usage, as per similar (huge) async OOP and stateful libraries. From your comments I assume you are new to these style of libraries and design.
The Client and therefore Bot class, by inheritance, to do have API access.
There are Client level API calls and then there are User specific API calls which are made via a Partial / User object.
Ultimately keeping all functions that involve a User specifically makes more sense being a method of said User object, as this is how OOP is intended.
I don't see how doing Bot.chat_announcement(target, token, mod_id, colour, msg)
is any better than User.chat_announcement(token, mod_id, colour)
The User object already contains the target ID and the announcement method is being sent to said User.
It also allows you to follow up with other methods much easier and responses.
It sounds like you would prefer to use as raw to the spec lib as possible.
It wouldn't be Bot.chat_announcement(target, token, mod_id, colour, msg)
though, since token
and mod_id
would be managed by the Bot internally. That's the point, since they can't be in the User class anyway.
It would be Bot.chat_announcement(target, msg [, color])
, which is simpler than User.chat_announcement(token, mod_id, msg [, color])
(you forgot the msg). The Bot is already there as self
, as opposed to the token and mod_id you have to seek somewhere else in your data, and the User is still required and only changes place.
It seems to me that the Bot can manage token
, since we pass it when creating the Bot and it takes a single one. As per the mod_id
, I tried using self.user_id
and it worked 🤷
Also, you're saying that there are two kinds of API calls, Client ones and User ones. That may be true under the hood, but I don't think it should necessarily be visible to the user. If I'm using a Client anyway (and I don't think you can use twitchio without using a Bot object, can you ?), then I don't care what category the API call I'm using belongs to.
That solution would not work for instances where the bot is VIP instead of mod and you pass the command invoker's ID as the mod id instead. Not everyone wants a bot to be a moderator in their channel.
Also rate limiting is on a per token basis, so if you are in a huge amount of channels then allowing users / devs to use the invoker, broadcaster token to not hit API rate limits.
If you feel this strongly then you could always start your own lib with your own design or use an alternative solution.
I think I can simply do it as a Bot subclass on my end, but the reason it could work badly interests me. If my Bot is VIP and not mod, why would the User method work and the Bot method would not ? The bot would receive the command/trigger, and order the human broadcaster's user account (or another account) to send the announcement ?
Proof of concept :
class Bot(commands.Bot):
def __init__(self, token, *args, **kwargs):
super().__init__(token, *args, **kwargs)
self._token = token
async def chat_announcement(self, target, message, color="primary"):
return await target.chat_announcement(self._token, self.user_id, message, color)
Also I'm not saying it should replace the User methods, or that they should be removed.
You seem to have the concept that the api side revolves around a single token. That is an IRC only thing, there is no singular token for the API. As such, this design is not possible.
It would be handy if there were methods for native twitch commands (such as /announce) at the same location as
send
(so, in Contexts for example), and which would not require being passed the token and user_id a second time. Announcement for example (however you want to call the method, like Helix says or rather like the command) would takemessage
and the optionalcolor
, and that would be it.