disagreement 0.3.0b1__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. disagreement/__init__.py +2 -4
  2. disagreement/audio.py +25 -5
  3. disagreement/cache.py +12 -3
  4. disagreement/caching.py +15 -14
  5. disagreement/client.py +86 -52
  6. disagreement/enums.py +10 -3
  7. disagreement/error_handler.py +5 -1
  8. disagreement/errors.py +1341 -3
  9. disagreement/event_dispatcher.py +1 -3
  10. disagreement/ext/__init__.py +1 -0
  11. disagreement/ext/app_commands/__init__.py +0 -2
  12. disagreement/ext/app_commands/commands.py +0 -2
  13. disagreement/ext/app_commands/context.py +0 -2
  14. disagreement/ext/app_commands/converters.py +2 -4
  15. disagreement/ext/app_commands/decorators.py +5 -7
  16. disagreement/ext/app_commands/handler.py +1 -3
  17. disagreement/ext/app_commands/hybrid.py +0 -2
  18. disagreement/ext/commands/__init__.py +0 -2
  19. disagreement/ext/commands/cog.py +0 -2
  20. disagreement/ext/commands/converters.py +16 -5
  21. disagreement/ext/commands/core.py +52 -14
  22. disagreement/ext/commands/decorators.py +3 -7
  23. disagreement/ext/commands/errors.py +0 -2
  24. disagreement/ext/commands/help.py +0 -2
  25. disagreement/ext/commands/view.py +1 -3
  26. disagreement/gateway.py +27 -25
  27. disagreement/http.py +264 -22
  28. disagreement/interactions.py +0 -2
  29. disagreement/models.py +199 -105
  30. disagreement/shard_manager.py +0 -2
  31. disagreement/ui/view.py +2 -2
  32. disagreement/voice_client.py +20 -1
  33. {disagreement-0.3.0b1.dist-info → disagreement-0.4.0.dist-info}/METADATA +32 -6
  34. disagreement-0.4.0.dist-info/RECORD +55 -0
  35. disagreement-0.3.0b1.dist-info/RECORD +0 -55
  36. {disagreement-0.3.0b1.dist-info → disagreement-0.4.0.dist-info}/WHEEL +0 -0
  37. {disagreement-0.3.0b1.dist-info → disagreement-0.4.0.dist-info}/licenses/LICENSE +0 -0
  38. {disagreement-0.3.0b1.dist-info → disagreement-0.4.0.dist-info}/top_level.txt +0 -0
disagreement/http.py CHANGED
@@ -1,5 +1,3 @@
1
- # disagreement/http.py
2
-
3
1
  """
4
2
  HTTP client for interacting with the Discord REST API.
5
3
  """
@@ -11,12 +9,7 @@ import json
11
9
  from urllib.parse import quote
12
10
  from typing import Optional, Dict, Any, Union, TYPE_CHECKING, List
13
11
 
14
- from .errors import (
15
- HTTPException,
16
- RateLimitError,
17
- AuthenticationError,
18
- DisagreementException,
19
- )
12
+ from .errors import * # Import all custom exceptions
20
13
  from . import __version__ # For User-Agent
21
14
  from .rate_limiter import RateLimiter
22
15
  from .interactions import InteractionResponsePayload
@@ -31,6 +24,232 @@ API_BASE_URL = "https://discord.com/api/v10" # Using API v10
31
24
 
32
25
  logger = logging.getLogger(__name__)
33
26
 
27
+ DISCORD_ERROR_CODE_TO_EXCEPTION = {
28
+ 0: GeneralError,
29
+ 10001: UnknownAccount,
30
+ 10002: UnknownApplication,
31
+ 10003: UnknownChannel,
32
+ 10004: UnknownGuild,
33
+ 10005: UnknownIntegration,
34
+ 10006: UnknownInvite,
35
+ 10007: UnknownMember,
36
+ 10008: UnknownMessage,
37
+ 10009: UnknownPermissionOverwrite,
38
+ 10010: UnknownProvider,
39
+ 10011: UnknownRole,
40
+ 10012: UnknownToken,
41
+ 10013: UnknownUser,
42
+ 10014: UnknownEmoji,
43
+ 10015: UnknownWebhook,
44
+ 10016: UnknownWebhookService,
45
+ 10020: UnknownSession,
46
+ 10021: UnknownAsset,
47
+ 10026: UnknownBan,
48
+ 10027: UnknownSKU,
49
+ 10028: UnknownStoreListing,
50
+ 10029: UnknownEntitlement,
51
+ 10030: UnknownBuild,
52
+ 10031: UnknownLobby,
53
+ 10032: UnknownBranch,
54
+ 10033: UnknownStoreDirectoryLayout,
55
+ 10036: UnknownRedistributable,
56
+ 10038: UnknownGiftCode,
57
+ 10049: UnknownStream,
58
+ 10050: UnknownPremiumServerSubscribeCooldown,
59
+ 10057: UnknownGuildTemplate,
60
+ 10059: UnknownDiscoverableServerCategory,
61
+ 10060: UnknownSticker,
62
+ 10061: UnknownStickerPack,
63
+ 10062: UnknownInteraction,
64
+ 10063: UnknownApplicationCommand,
65
+ 10065: UnknownVoiceState,
66
+ 10066: UnknownApplicationCommandPermissions,
67
+ 10067: UnknownStageInstance,
68
+ 10068: UnknownGuildMemberVerificationForm,
69
+ 10069: UnknownGuildWelcomeScreen,
70
+ 10070: UnknownGuildScheduledEvent,
71
+ 10071: UnknownGuildScheduledEventUser,
72
+ 10087: UnknownTag,
73
+ 10097: UnknownSound,
74
+ 20001: BotsCannotUseThisEndpoint,
75
+ 20002: OnlyBotsCanUseThisEndpoint,
76
+ 20009: ExplicitContentCannotBeSentToTheDesiredRecipients,
77
+ 20012: NotAuthorizedToPerformThisActionOnThisApplication,
78
+ 20016: ActionCannotBePerformedDueToSlowmodeRateLimit,
79
+ 20018: OnlyTheOwnerOfThisAccountCanPerformThisAction,
80
+ 20022: MessageCannotBeEditedDueToAnnouncementRateLimits,
81
+ 20024: UnderMinimumAge,
82
+ 20028: ChannelHitWriteRateLimit,
83
+ 20029: ServerHitWriteRateLimit,
84
+ 20031: DisallowedWordsInStageTopicOrNames,
85
+ 20035: GuildPremiumSubscriptionLevelTooLow,
86
+ 30001: MaximumNumberOfGuildsReached,
87
+ 30002: MaximumNumberOfFriendsReached,
88
+ 30003: MaximumNumberOfPinsReached,
89
+ 30004: MaximumNumberOfRecipientsReached,
90
+ 30005: MaximumNumberOfGuildRolesReached,
91
+ 30007: MaximumNumberOfWebhooksReached,
92
+ 30008: MaximumNumberOfEmojisReached,
93
+ 30010: MaximumNumberOfReactionsReached,
94
+ 30011: MaximumNumberOfGroupDMsReached,
95
+ 30013: MaximumNumberOfGuildChannelsReached,
96
+ 30015: MaximumNumberOfAttachmentsInAMessageReached,
97
+ 30016: MaximumNumberOfInvitesReached,
98
+ 30018: MaximumNumberOfAnimatedEmojisReached,
99
+ 30019: MaximumNumberOfServerMembersReached,
100
+ 30030: MaximumNumberOfServerCategoriesReached,
101
+ 30031: GuildAlreadyHasATemplate,
102
+ 30032: MaximumNumberOfApplicationCommandsReached,
103
+ 30033: MaximumNumberOfThreadParticipantsReached,
104
+ 30034: MaximumNumberOfDailyApplicationCommandCreatesReached,
105
+ 30035: MaximumNumberOfBansForNonGuildMembersExceeded,
106
+ 30037: MaximumNumberOfBansFetchesReached,
107
+ 30038: MaximumNumberOfUncompletedGuildScheduledEventsReached,
108
+ 30039: MaximumNumberOfStickersReached,
109
+ 30040: MaximumNumberOfPruneRequestsReached,
110
+ 30042: MaximumNumberOfGuildWidgetSettingsUpdatesReached,
111
+ 30045: MaximumNumberOfSoundboardSoundsReached,
112
+ 30046: MaximumNumberOfEditsToMessagesOlderThan1HourReached,
113
+ 30047: MaximumNumberOfPinnedThreadsInAForumChannelReached,
114
+ 30048: MaximumNumberOfTagsInAForumChannelReached,
115
+ 30052: BitrateIsTooHighForChannelOfThisType,
116
+ 30056: MaximumNumberOfPremiumEmojisReached,
117
+ 30058: MaximumNumberOfWebhooksPerGuildReached,
118
+ 30061: MaximumNumberOfChannelPermissionOverwritesReached,
119
+ 30062: TheChannelsForThisGuildAreTooLarge,
120
+ 40001: Unauthorized,
121
+ 40002: YouNeedToVerifyYourAccount,
122
+ 40003: YouAreOpeningDirectMessagesTooFast,
123
+ 40004: SendMessagesHasBeenTemporarilyDisabled,
124
+ 40005: RequestEntityTooLarge,
125
+ 40006: ThisFeatureHasBeenTemporarilyDisabledServerSide,
126
+ 40007: TheUserIsBannedFromThisGuild,
127
+ 40012: ConnectionHasBeenRevoked,
128
+ 40018: OnlyConsumableSKUsCanBeConsumed,
129
+ 40019: YouCanOnlyDeleteSandboxEntitlements,
130
+ 40032: TargetUserIsNotConnectedToVoice,
131
+ 40033: ThisMessageHasAlreadyBeenCrossposted,
132
+ 40041: AnApplicationCommandWithThatNameAlreadyExists,
133
+ 40043: ApplicationInteractionFailedToSend,
134
+ 40058: CannotSendAMessageInAForumChannel,
135
+ 40060: InteractionHasAlreadyBeenAcknowledged,
136
+ 40061: TagNamesMustBeUnique,
137
+ 40062: ServiceResourceIsBeingRateLimited,
138
+ 40066: ThereAreNoTagsAvailableThatCanBeSetByNonModerators,
139
+ 40067: ATagIsRequiredToCreateAForumPostInThisChannel,
140
+ 40074: AnEntitlementHasAlreadyBeenGrantedForThisResource,
141
+ 40094: ThisInteractionHasHitTheMaximumNumberOfFollowUpMessages,
142
+ 40333: CloudflareIsBlockingYourRequest,
143
+ 50001: MissingAccess,
144
+ 50002: InvalidAccountType,
145
+ 50003: CannotExecuteActionOnADMChannel,
146
+ 50004: GuildWidgetDisabled,
147
+ 50005: CannotEditAMessageAuthoredByAnotherUser,
148
+ 50006: CannotSendAnEmptyMessage,
149
+ 50007: CannotSendMessagesToThisUser,
150
+ 50008: CannotSendMessagesInANonTextChannel,
151
+ 50009: ChannelVerificationLevelIsTooHighForYouToGainAccess,
152
+ 50010: OAuth2ApplicationDoesNotHaveABot,
153
+ 50011: OAuth2ApplicationLimitReached,
154
+ 50012: InvalidOAuth2State,
155
+ 50013: YouLackPermissionsToPerformThatAction,
156
+ 50014: InvalidAuthenticationTokenProvided,
157
+ 50015: NoteWasTooLong,
158
+ 50016: ProvidedTooFewOrTooManyMessagesToDelete,
159
+ 50017: InvalidMFALevel,
160
+ 50019: AMessageCanOnlyBePinnedToTheChannelItWasSentIn,
161
+ 50020: InviteCodeWasEitherInvalidOrTaken,
162
+ 50021: CannotExecuteActionOnASystemMessage,
163
+ 50024: CannotExecuteActionOnThisChannelType,
164
+ 50025: InvalidOAuth2AccessTokenProvided,
165
+ 50026: MissingRequiredOAuth2Scope,
166
+ 50027: InvalidWebhookTokenProvided,
167
+ 50028: InvalidRole,
168
+ 50033: InvalidRecipients,
169
+ 50034: AMessageProvidedWasTooOldToBulkDelete,
170
+ 50035: InvalidFormBody,
171
+ 50036: AnInviteWasAcceptedToAGuildTheApplicationBotIsNotIn,
172
+ 50039: InvalidActivityAction,
173
+ 50041: InvalidAPIVersionProvided,
174
+ 50045: FileUploadedExceedsTheMaximumSize,
175
+ 50046: InvalidFileUploaded,
176
+ 50054: CannotSelfRedeemThisGift,
177
+ 50055: InvalidGuild,
178
+ 50057: InvalidSKU,
179
+ 50067: InvalidRequestOrigin,
180
+ 50068: InvalidMessageType,
181
+ 50070: PaymentSourceRequiredToRedeemGift,
182
+ 50073: CannotModifyASystemWebhook,
183
+ 50074: CannotDeleteAChannelRequiredForCommunityGuilds,
184
+ 50080: CannotEditStickersWithinAMessage,
185
+ 50081: InvalidStickerSent,
186
+ 50083: TriedToPerformAnOperationOnAnArchivedThread,
187
+ 50085: InvalidThreadNotificationSettings,
188
+ 50086: BeforeValueIsEarlierThanTheThreadCreationDate,
189
+ 50087: CommunityServerChannelsMustBeTextChannels,
190
+ 50091: TheEntityTypeOfTheEventIsDifferentFromTheEntityYouAreTryingToStartTheEventFor,
191
+ 50095: ThisServerIsNotAvailableInYourLocation,
192
+ 50097: ThisServerNeedsMonetizationEnabledInOrderToPerformThisAction,
193
+ 50101: ThisServerNeedsMoreBoostsToPerformThisAction,
194
+ 50109: TheRequestBodyContainsInvalidJSON,
195
+ 50110: TheProvidedFileIsInvalid,
196
+ 50123: TheProvidedFileTypeIsInvalid,
197
+ 50124: TheProvidedFileDurationExceedsMaximumOf52Seconds,
198
+ 50131: OwnerCannotBePendingMember,
199
+ 50132: OwnershipCannotBeTransferredToABotUser,
200
+ 50138: FailedToResizeAssetBelowTheMaximumSize,
201
+ 50144: CannotMixSubscriptionAndNonSubscriptionRolesForAnEmoji,
202
+ 50145: CannotConvertBetweenPremiumEmojiAndNormalEmoji,
203
+ 50146: UploadedFileNotFound,
204
+ 50151: TheSpecifiedEmojiIsInvalid,
205
+ 50159: VoiceMessagesDoNotSupportAdditionalContent,
206
+ 50160: VoiceMessagesMustHaveASingleAudioAttachment,
207
+ 50161: VoiceMessagesMustHaveSupportingMetadata,
208
+ 50162: VoiceMessagesCannotBeEdited,
209
+ 50163: CannotDeleteGuildSubscriptionIntegration,
210
+ 50173: YouCannotSendVoiceMessagesInThisChannel,
211
+ 50178: TheUserAccountMustFirstBeVerified,
212
+ 50192: TheProvidedFileDoesNotHaveAValidDuration,
213
+ 50600: YouDoNotHavePermissionToSendThisSticker,
214
+ 60003: TwoFactorIsRequiredForThisOperation,
215
+ 80004: NoUsersWithDiscordTagExist,
216
+ 90001: ReactionWasBlocked,
217
+ 90002: UserCannotUseBurstReactions,
218
+ 110001: ApplicationNotYetAvailable,
219
+ 130000: APIResourceIsCurrentlyOverloaded,
220
+ 150006: TheStageIsAlreadyOpen,
221
+ 160002: CannotReplyWithoutPermissionToReadMessageHistory,
222
+ 160004: AThreadHasAlreadyBeenCreatedForThisMessage,
223
+ 160005: ThreadIsLocked,
224
+ 160006: MaximumNumberOfActiveThreadsReached,
225
+ 160007: MaximumNumberOfActiveAnnouncementThreadsReached,
226
+ 170001: InvalidJSONForUploadedLottieFile,
227
+ 170002: UploadedLottiesCannotContainRasterizedImages,
228
+ 170003: StickerMaximumFramerateExceeded,
229
+ 170004: StickerFrameCountExceedsMaximumOf1000Frames,
230
+ 170005: LottieAnimationMaximumDimensionsExceeded,
231
+ 170006: StickerFrameRateIsEitherTooSmallOrTooLarge,
232
+ 170007: StickerAnimationDurationExceedsMaximumOf5Seconds,
233
+ 180000: CannotUpdateAFinishedEvent,
234
+ 180002: FailedToCreateStageNeededForStageEvent,
235
+ 200000: MessageWasBlockedByAutomaticModeration,
236
+ 200001: TitleWasBlockedByAutomaticModeration,
237
+ 220001: WebhooksPostedToForumChannelsMustHaveAThreadNameOrThreadId,
238
+ 220002: WebhooksPostedToForumChannelsCannotHaveBothAThreadNameAndThreadId,
239
+ 220003: WebhooksCanOnlyCreateThreadsInForumChannels,
240
+ 220004: WebhookServicesCannotBeUsedInForumChannels,
241
+ 240000: MessageBlockedByHarmfulLinksFilter,
242
+ 350000: CannotEnableOnboardingRequirementsAreNotMet,
243
+ 350001: CannotUpdateOnboardingWhileBelowRequirements,
244
+ 500000: FailedToBanUsers,
245
+ 520000: PollVotingBlocked,
246
+ 520001: PollExpired,
247
+ 520002: InvalidChannelTypeForPollCreation,
248
+ 520003: CannotEditAPollMessage,
249
+ 520004: CannotUseAnEmojiIncludedWithThePoll,
250
+ 520006: CannotExpireANonPollMessage,
251
+ }
252
+
34
253
 
35
254
  class HTTPClient:
36
255
  """Handles HTTP requests to the Discord API."""
@@ -208,6 +427,17 @@ class HTTPClient:
208
427
  discord_error_code = (
209
428
  data.get("code") if isinstance(data, dict) else None
210
429
  )
430
+
431
+ if discord_error_code in DISCORD_ERROR_CODE_TO_EXCEPTION:
432
+ exc_class = DISCORD_ERROR_CODE_TO_EXCEPTION[discord_error_code]
433
+ raise exc_class(
434
+ response,
435
+ f"API Error on {method} {endpoint}: {error_text}",
436
+ status=response.status,
437
+ text=error_text,
438
+ error_code=discord_error_code,
439
+ )
440
+
211
441
  raise HTTPException(
212
442
  response,
213
443
  f"API Error on {method} {endpoint}: {error_text}",
@@ -215,8 +445,6 @@ class HTTPClient:
215
445
  text=error_text,
216
446
  error_code=discord_error_code,
217
447
  )
218
-
219
- # Should not be reached if retries are exhausted by RateLimitError
220
448
  raise DisagreementException(
221
449
  f"Failed request to {method} {endpoint} after multiple retries."
222
450
  )
@@ -369,18 +597,18 @@ class HTTPClient:
369
597
  )
370
598
 
371
599
  async def delete_user_reaction(
372
- self,
373
- channel_id: "Snowflake",
374
- message_id: "Snowflake",
375
- emoji: str,
376
- user_id: "Snowflake",
377
- ) -> None:
378
- """Removes another user's reaction from a message."""
379
- encoded = quote(emoji)
380
- await self.request(
381
- "DELETE",
382
- f"/channels/{channel_id}/messages/{message_id}/reactions/{encoded}/{user_id}",
383
- )
600
+ self,
601
+ channel_id: "Snowflake",
602
+ message_id: "Snowflake",
603
+ emoji: str,
604
+ user_id: "Snowflake",
605
+ ) -> None:
606
+ """Removes another user's reaction from a message."""
607
+ encoded = quote(emoji)
608
+ await self.request(
609
+ "DELETE",
610
+ f"/channels/{channel_id}/messages/{message_id}/reactions/{encoded}/{user_id}",
611
+ )
384
612
 
385
613
  async def get_reactions(
386
614
  self, channel_id: "Snowflake", message_id: "Snowflake", emoji: str
@@ -678,6 +906,20 @@ class HTTPClient:
678
906
  """Fetches a guild object for a given guild ID."""
679
907
  return await self.request("GET", f"/guilds/{guild_id}")
680
908
 
909
+ async def get_guild_widget(self, guild_id: "Snowflake") -> Dict[str, Any]:
910
+ """Fetches the guild widget settings."""
911
+
912
+ return await self.request("GET", f"/guilds/{guild_id}/widget")
913
+
914
+ async def edit_guild_widget(
915
+ self, guild_id: "Snowflake", payload: Dict[str, Any]
916
+ ) -> Dict[str, Any]:
917
+ """Edits the guild widget settings."""
918
+
919
+ return await self.request(
920
+ "PATCH", f"/guilds/{guild_id}/widget", payload=payload
921
+ )
922
+
681
923
  async def get_guild_templates(self, guild_id: "Snowflake") -> List[Dict[str, Any]]:
682
924
  """Fetches all templates for the given guild."""
683
925
  return await self.request("GET", f"/guilds/{guild_id}/templates")
@@ -1,5 +1,3 @@
1
- # disagreement/interactions.py
2
-
3
1
  """
4
2
  Data models for Discord Interaction objects.
5
3
  """