modifyself 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {modifyself-0.2.0 → modifyself-0.2.2}/PKG-INFO +3 -1
- {modifyself-0.2.0 → modifyself-0.2.2}/README.md +30 -30
- modifyself-0.2.2/modifyself/models/billing.py +88 -0
- modifyself-0.2.2/modifyself/models/message.py +222 -0
- modifyself-0.2.2/modifyself/models/relationship.py +47 -0
- modifyself-0.2.2/modifyself/models/settings.py +54 -0
- modifyself-0.2.2/modifyself/models/webhook.py +168 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself.egg-info/PKG-INFO +3 -1
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself.egg-info/requires.txt +2 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/pyproject.toml +34 -30
- modifyself-0.2.0/modifyself/models/billing.py +0 -0
- modifyself-0.2.0/modifyself/models/message.py +0 -180
- modifyself-0.2.0/modifyself/models/relationship.py +0 -0
- modifyself-0.2.0/modifyself/models/settings.py +0 -0
- modifyself-0.2.0/modifyself/models/webhook.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/LICENSE +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/__init__.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/activity.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/client.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/__init__.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/checks.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/cog.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/context.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/converters.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/commands/core.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/components.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/core/bitfield.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/core/enums.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/core/mixins.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/core/snowflake.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/errors.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/gateway/__init__.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/gateway/dispatcher.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/gateway/heartbeat.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/gateway/websocket.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/headers.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/http/__init__.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/http/client.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/http/ratelimit.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/http/route.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/interactions.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/__init__.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/base.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/channel.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/guild.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/member.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/models/user.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/state.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/types.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/utils.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself/voice.py +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself.egg-info/SOURCES.txt +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself.egg-info/dependency_links.txt +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/modifyself.egg-info/top_level.txt +0 -0
- {modifyself-0.2.0 → modifyself-0.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modifyself
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A clean, pythonic Discord self-bot library
|
|
5
5
|
Author-email: modifyself <modifyself@example.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,6 +16,8 @@ Requires-Dist: aiohttp>=3.8.0
|
|
|
16
16
|
Requires-Dist: plyer>=0.9
|
|
17
17
|
Requires-Dist: pillow>=10.0
|
|
18
18
|
Requires-Dist: requests>=2.28
|
|
19
|
+
Requires-Dist: PyNaCl>=1.5.0
|
|
20
|
+
Requires-Dist: opuslib>=3.0.0
|
|
19
21
|
Dynamic: license-file
|
|
20
22
|
|
|
21
23
|
# modifyself
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# modifyself
|
|
2
|
-
|
|
3
|
-
A clean, pythonic Discord self-bot library.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
pip install modifyself
|
|
8
|
-
|
|
9
|
-
## Quick Example
|
|
10
|
-
|
|
11
|
-
rom modifyself import Client, command
|
|
12
|
-
|
|
13
|
-
bot = Client(token="your_token")
|
|
14
|
-
|
|
15
|
-
@bot.command()
|
|
16
|
-
async def ping(ctx):
|
|
17
|
-
await ctx.reply("Pong!")
|
|
18
|
-
|
|
19
|
-
bot.run()
|
|
20
|
-
|
|
21
|
-
## Features
|
|
22
|
-
|
|
23
|
-
- Clean, intuitive API
|
|
24
|
-
- Command framework with cogs
|
|
25
|
-
- Automatic rate limiting
|
|
26
|
-
- Gateway event handling
|
|
27
|
-
- Full API coverage
|
|
28
|
-
|
|
29
|
-
## License
|
|
30
|
-
|
|
1
|
+
# modifyself
|
|
2
|
+
|
|
3
|
+
A clean, pythonic Discord self-bot library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
pip install modifyself
|
|
8
|
+
|
|
9
|
+
## Quick Example
|
|
10
|
+
|
|
11
|
+
rom modifyself import Client, command
|
|
12
|
+
|
|
13
|
+
bot = Client(token="your_token")
|
|
14
|
+
|
|
15
|
+
@bot.command()
|
|
16
|
+
async def ping(ctx):
|
|
17
|
+
await ctx.reply("Pong!")
|
|
18
|
+
|
|
19
|
+
bot.run()
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- Clean, intuitive API
|
|
24
|
+
- Command framework with cogs
|
|
25
|
+
- Automatic rate limiting
|
|
26
|
+
- Gateway event handling
|
|
27
|
+
- Full API coverage
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
|
|
31
31
|
MIT
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Billing models (payment sources, etc.)
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, Any
|
|
6
|
+
from .base import DiscordObject
|
|
7
|
+
|
|
8
|
+
class PaymentSource(DiscordObject):
|
|
9
|
+
"""Represents a payment source (card, PayPal, etc.)."""
|
|
10
|
+
|
|
11
|
+
__slots__ = (
|
|
12
|
+
"type",
|
|
13
|
+
"brand",
|
|
14
|
+
"last_4",
|
|
15
|
+
"expires_month",
|
|
16
|
+
"expires_year",
|
|
17
|
+
"default",
|
|
18
|
+
"invalid",
|
|
19
|
+
"billing_address",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def __init__(self, *, state, data: dict):
|
|
23
|
+
super().__init__(state=state, data=data)
|
|
24
|
+
self._update(data)
|
|
25
|
+
|
|
26
|
+
def _update(self, data: dict):
|
|
27
|
+
self.type = data.get("type")
|
|
28
|
+
self.brand = data.get("brand")
|
|
29
|
+
self.last_4 = data.get("last_4")
|
|
30
|
+
self.expires_month = data.get("expires_month")
|
|
31
|
+
self.expires_year = data.get("expires_year")
|
|
32
|
+
self.default = data.get("default", False)
|
|
33
|
+
self.invalid = data.get("invalid", False)
|
|
34
|
+
self.billing_address = data.get("billing_address")
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def is_card(self) -> bool:
|
|
38
|
+
return self.type == 1
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def is_paypal(self) -> bool:
|
|
42
|
+
return self.type == 2
|
|
43
|
+
|
|
44
|
+
def __repr__(self) -> str:
|
|
45
|
+
return f"<PaymentSource id={self.id} type={self.type} last4={self.last_4}>"
|
|
46
|
+
|
|
47
|
+
class Subscription(DiscordObject):
|
|
48
|
+
"""Represents a subscription (Nitro, etc.)."""
|
|
49
|
+
|
|
50
|
+
__slots__ = (
|
|
51
|
+
"type",
|
|
52
|
+
"plan_id",
|
|
53
|
+
"status",
|
|
54
|
+
"current_period_start",
|
|
55
|
+
"current_period_end",
|
|
56
|
+
"renewal_interval",
|
|
57
|
+
"renewal_interval_count",
|
|
58
|
+
"entitlement_id",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def __init__(self, *, state, data: dict):
|
|
62
|
+
super().__init__(state=state, data=data)
|
|
63
|
+
self._update(data)
|
|
64
|
+
|
|
65
|
+
def _update(self, data: dict):
|
|
66
|
+
self.type = data.get("type")
|
|
67
|
+
self.plan_id = data.get("plan_id")
|
|
68
|
+
self.status = data.get("status")
|
|
69
|
+
self.current_period_start = data.get("current_period_start")
|
|
70
|
+
self.current_period_end = data.get("current_period_end")
|
|
71
|
+
self.renewal_interval = data.get("renewal_interval")
|
|
72
|
+
self.renewal_interval_count = data.get("renewal_interval_count")
|
|
73
|
+
self.entitlement_id = data.get("entitlement_id")
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def is_nitro(self) -> bool:
|
|
77
|
+
return self.type == 1
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def is_nitro_classic(self) -> bool:
|
|
81
|
+
return self.type == 2
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def is_active(self) -> bool:
|
|
85
|
+
return self.status == 1
|
|
86
|
+
|
|
87
|
+
def __repr__(self) -> str:
|
|
88
|
+
return f"<Subscription id={self.id} type={self.type} status={self.status}>"
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Discord Message model.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Optional, List, Dict, Any, Union
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
|
|
8
|
+
from .base import DiscordObject
|
|
9
|
+
from .user import User
|
|
10
|
+
from .member import Member
|
|
11
|
+
from ..core.enums import MessageType
|
|
12
|
+
from ..utils import parse_time
|
|
13
|
+
from ..components import Component, ActionRow, ComponentType
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ..state import ConnectionState
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Message(DiscordObject):
|
|
20
|
+
"""Represents a Discord message."""
|
|
21
|
+
|
|
22
|
+
__slots__ = (
|
|
23
|
+
"channel_id",
|
|
24
|
+
"author",
|
|
25
|
+
"content",
|
|
26
|
+
"timestamp",
|
|
27
|
+
"edited_timestamp",
|
|
28
|
+
"tts",
|
|
29
|
+
"mention_everyone",
|
|
30
|
+
"mentions",
|
|
31
|
+
"mention_roles",
|
|
32
|
+
"attachments",
|
|
33
|
+
"embeds",
|
|
34
|
+
"reactions",
|
|
35
|
+
"pinned",
|
|
36
|
+
"type",
|
|
37
|
+
"guild_id",
|
|
38
|
+
"member",
|
|
39
|
+
"referenced_message",
|
|
40
|
+
"flags",
|
|
41
|
+
"thread",
|
|
42
|
+
"application",
|
|
43
|
+
"message_reference",
|
|
44
|
+
"interaction",
|
|
45
|
+
"components",
|
|
46
|
+
"sticker_items",
|
|
47
|
+
"position",
|
|
48
|
+
"role_subscription_data",
|
|
49
|
+
"resolved",
|
|
50
|
+
"poll",
|
|
51
|
+
"call",
|
|
52
|
+
"author",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def __init__(self, *, state: "ConnectionState", data: dict):
|
|
56
|
+
super().__init__(state=state, data=data)
|
|
57
|
+
self._update(data)
|
|
58
|
+
|
|
59
|
+
def _update(self, data: dict):
|
|
60
|
+
self.id = int(data["id"])
|
|
61
|
+
self.channel_id = int(data["channel_id"])
|
|
62
|
+
self.content = data.get("content", "")
|
|
63
|
+
self.timestamp = parse_time(data["timestamp"])
|
|
64
|
+
self.edited_timestamp = parse_time(data["edited_timestamp"]) if data.get("edited_timestamp") else None
|
|
65
|
+
self.tts = data.get("tts", False)
|
|
66
|
+
self.mention_everyone = data.get("mention_everyone", False)
|
|
67
|
+
self.mentions = [User(state=self._state, data=u) for u in data.get("mentions", [])]
|
|
68
|
+
self.mention_roles = data.get("mention_roles", [])
|
|
69
|
+
self.attachments = data.get("attachments", [])
|
|
70
|
+
self.embeds = data.get("embeds", [])
|
|
71
|
+
self.reactions = data.get("reactions", [])
|
|
72
|
+
self.pinned = data.get("pinned", False)
|
|
73
|
+
self.type = MessageType(data.get("type", 0))
|
|
74
|
+
self.guild_id = int(data["guild_id"]) if data.get("guild_id") else None
|
|
75
|
+
self.flags = data.get("flags", 0)
|
|
76
|
+
self.sticker_items = data.get("sticker_items", [])
|
|
77
|
+
self.position = data.get("position", 0)
|
|
78
|
+
self.role_subscription_data = data.get("role_subscription_data")
|
|
79
|
+
self.resolved = data.get("resolved")
|
|
80
|
+
self.poll = data.get("poll")
|
|
81
|
+
self.call = data.get("call")
|
|
82
|
+
|
|
83
|
+
# Author
|
|
84
|
+
self.author = User(state=self._state, data=data["author"])
|
|
85
|
+
|
|
86
|
+
# Member (if in guild)
|
|
87
|
+
self.member = None
|
|
88
|
+
if data.get("member"):
|
|
89
|
+
self.member = Member(state=self._state, data=data["member"], guild_id=self.guild_id)
|
|
90
|
+
|
|
91
|
+
# Referenced message
|
|
92
|
+
self.referenced_message = None
|
|
93
|
+
if data.get("referenced_message"):
|
|
94
|
+
self.referenced_message = Message(state=self._state, data=data["referenced_message"])
|
|
95
|
+
|
|
96
|
+
# Thread
|
|
97
|
+
self.thread = data.get("thread")
|
|
98
|
+
|
|
99
|
+
# Application
|
|
100
|
+
self.application = data.get("application")
|
|
101
|
+
|
|
102
|
+
# Message reference
|
|
103
|
+
self.message_reference = data.get("message_reference")
|
|
104
|
+
|
|
105
|
+
# Interaction
|
|
106
|
+
self.interaction = data.get("interaction")
|
|
107
|
+
|
|
108
|
+
# Components
|
|
109
|
+
self._components = []
|
|
110
|
+
for comp_data in data.get("components", []):
|
|
111
|
+
if comp_data.get("type") == ComponentType.ACTION_ROW:
|
|
112
|
+
row = ActionRow()
|
|
113
|
+
for child_data in comp_data.get("components", []):
|
|
114
|
+
row.components.append(Component(child_data))
|
|
115
|
+
self._components.append(row)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def jump_url(self) -> str:
|
|
119
|
+
"""The jump URL for this message."""
|
|
120
|
+
return f"https://discord.com/channels/{self.guild_id or '@me'}/{self.channel_id}/{self.id}"
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def clean_content(self) -> str:
|
|
124
|
+
"""The content of the message with mentions cleaned."""
|
|
125
|
+
content = self.content
|
|
126
|
+
for user in self.mentions:
|
|
127
|
+
content = content.replace(f"<@{user.id}>", f"@{user.name}")
|
|
128
|
+
content = content.replace(f"<@!{user.id}>", f"@{user.name}")
|
|
129
|
+
for role_id in self.mention_roles:
|
|
130
|
+
content = content.replace(f"<@&{role_id}>", f"@<role>")
|
|
131
|
+
if self.mention_everyone:
|
|
132
|
+
content = content.replace("@everyone", "@everyone")
|
|
133
|
+
content = content.replace("@here", "@here")
|
|
134
|
+
return content
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def components(self) -> List[ActionRow]:
|
|
138
|
+
"""The components in this message."""
|
|
139
|
+
return self._components
|
|
140
|
+
|
|
141
|
+
async def edit(
|
|
142
|
+
self,
|
|
143
|
+
content: Optional[str] = None,
|
|
144
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
145
|
+
components: Optional[List[ActionRow]] = None,
|
|
146
|
+
**kwargs,
|
|
147
|
+
) -> "Message":
|
|
148
|
+
"""Edit this message."""
|
|
149
|
+
payload = {}
|
|
150
|
+
if content is not None:
|
|
151
|
+
payload["content"] = content
|
|
152
|
+
if embeds is not None:
|
|
153
|
+
payload["embeds"] = embeds
|
|
154
|
+
if components is not None:
|
|
155
|
+
payload["components"] = [c.to_dict() for c in components]
|
|
156
|
+
payload.update(kwargs)
|
|
157
|
+
|
|
158
|
+
data = await self._state.http.edit_message(
|
|
159
|
+
self.channel_id,
|
|
160
|
+
self.id,
|
|
161
|
+
**payload,
|
|
162
|
+
)
|
|
163
|
+
self._update(data)
|
|
164
|
+
return self
|
|
165
|
+
|
|
166
|
+
async def delete(self) -> None:
|
|
167
|
+
"""Delete this message."""
|
|
168
|
+
await self._state.http.delete_message(self.channel_id, self.id)
|
|
169
|
+
|
|
170
|
+
async def reply(
|
|
171
|
+
self,
|
|
172
|
+
content: Optional[str] = None,
|
|
173
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
174
|
+
components: Optional[List[ActionRow]] = None,
|
|
175
|
+
**kwargs,
|
|
176
|
+
) -> "Message":
|
|
177
|
+
"""Reply to this message."""
|
|
178
|
+
payload = {
|
|
179
|
+
"message_reference": {"message_id": self.id},
|
|
180
|
+
}
|
|
181
|
+
if content is not None:
|
|
182
|
+
payload["content"] = content
|
|
183
|
+
if embeds is not None:
|
|
184
|
+
payload["embeds"] = embeds
|
|
185
|
+
if components is not None:
|
|
186
|
+
payload["components"] = [c.to_dict() for c in components]
|
|
187
|
+
payload.update(kwargs)
|
|
188
|
+
|
|
189
|
+
data = await self._state.http.send_message(
|
|
190
|
+
self.channel_id,
|
|
191
|
+
**payload,
|
|
192
|
+
)
|
|
193
|
+
return self._state._store_message(data)
|
|
194
|
+
|
|
195
|
+
async def add_reaction(self, emoji: str) -> None:
|
|
196
|
+
"""Add a reaction to this message."""
|
|
197
|
+
await self._state.http.add_reaction(self.channel_id, self.id, emoji)
|
|
198
|
+
|
|
199
|
+
async def remove_reaction(self, emoji: str) -> None:
|
|
200
|
+
"""Remove a reaction from this message."""
|
|
201
|
+
await self._state.http.remove_reaction(self.channel_id, self.id, emoji)
|
|
202
|
+
|
|
203
|
+
async def clear_reactions(self) -> None:
|
|
204
|
+
"""Clear all reactions from this message."""
|
|
205
|
+
await self._state.http.clear_reactions(self.channel_id, self.id)
|
|
206
|
+
|
|
207
|
+
async def pin(self) -> None:
|
|
208
|
+
"""Pin this message."""
|
|
209
|
+
await self._state.http.pin_message(self.channel_id, self.id)
|
|
210
|
+
|
|
211
|
+
async def unpin(self) -> None:
|
|
212
|
+
"""Unpin this message."""
|
|
213
|
+
await self._state.http.unpin_message(self.channel_id, self.id)
|
|
214
|
+
|
|
215
|
+
async def get_reaction_users(self, emoji: str, limit: int = 100) -> List[User]:
|
|
216
|
+
"""Get users who reacted with a specific emoji."""
|
|
217
|
+
# This would need to be implemented in the HTTP client
|
|
218
|
+
# For now, just return an empty list
|
|
219
|
+
return []
|
|
220
|
+
|
|
221
|
+
def __repr__(self) -> str:
|
|
222
|
+
return f"<Message id={self.id} content={self.content[:50]!r}>"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Relationship models (friends, blocks, etc.)
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, Any
|
|
6
|
+
from .base import DiscordObject
|
|
7
|
+
|
|
8
|
+
class Relationship(DiscordObject):
|
|
9
|
+
"""Represents a relationship (friend, block, etc.)."""
|
|
10
|
+
|
|
11
|
+
__slots__ = (
|
|
12
|
+
"user_id",
|
|
13
|
+
"type",
|
|
14
|
+
"nickname",
|
|
15
|
+
"since",
|
|
16
|
+
"user",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
def __init__(self, *, state, data: dict):
|
|
20
|
+
super().__init__(state=state, data=data)
|
|
21
|
+
self._update(data)
|
|
22
|
+
|
|
23
|
+
def _update(self, data: dict):
|
|
24
|
+
self.user_id = int(data.get("user_id", 0))
|
|
25
|
+
self.type = data.get("type", 0) # 1=friends, 2=blocked, 3=incoming, 4=outgoing
|
|
26
|
+
self.nickname = data.get("nickname")
|
|
27
|
+
self.since = data.get("since")
|
|
28
|
+
self.user = data.get("user")
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def is_friend(self) -> bool:
|
|
32
|
+
return self.type == 1
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def is_blocked(self) -> bool:
|
|
36
|
+
return self.type == 2
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def is_incoming_request(self) -> bool:
|
|
40
|
+
return self.type == 3
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def is_outgoing_request(self) -> bool:
|
|
44
|
+
return self.type == 4
|
|
45
|
+
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
return f"<Relationship id={self.id} type={self.type}>"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User settings models.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, Any, List
|
|
6
|
+
from .base import DiscordObject
|
|
7
|
+
|
|
8
|
+
class GuildSettings(DiscordObject):
|
|
9
|
+
"""Settings for a specific guild."""
|
|
10
|
+
|
|
11
|
+
__slots__ = (
|
|
12
|
+
"guild_id",
|
|
13
|
+
"channel_overwrites",
|
|
14
|
+
"muted",
|
|
15
|
+
"mute_config",
|
|
16
|
+
"mobile_push",
|
|
17
|
+
"message_notifications",
|
|
18
|
+
"flags",
|
|
19
|
+
"notify_highlights",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def __init__(self, *, state, data: dict):
|
|
23
|
+
super().__init__(state=state, data=data)
|
|
24
|
+
self._update(data)
|
|
25
|
+
|
|
26
|
+
def _update(self, data: dict):
|
|
27
|
+
self.guild_id = int(data.get("guild_id", 0))
|
|
28
|
+
self.channel_overwrites = data.get("channel_overwrites", {})
|
|
29
|
+
self.muted = data.get("muted", False)
|
|
30
|
+
self.mute_config = data.get("mute_config", {})
|
|
31
|
+
self.mobile_push = data.get("mobile_push", False)
|
|
32
|
+
self.message_notifications = data.get("message_notifications", 0)
|
|
33
|
+
self.flags = data.get("flags", 0)
|
|
34
|
+
self.notify_highlights = data.get("notify_highlights", {})
|
|
35
|
+
|
|
36
|
+
def __repr__(self) -> str:
|
|
37
|
+
return f"<GuildSettings guild_id={self.guild_id}>"
|
|
38
|
+
|
|
39
|
+
class UserSettings:
|
|
40
|
+
"""Container for user settings (not a model)."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, data: dict):
|
|
43
|
+
self.theme = data.get("theme", "dark")
|
|
44
|
+
self.locale = data.get("locale", "en-US")
|
|
45
|
+
self.status = data.get("status", "online")
|
|
46
|
+
self.developer_mode = data.get("developer_mode", False)
|
|
47
|
+
self.afk_timeout = data.get("afk_timeout", 600)
|
|
48
|
+
self.animate_emoji = data.get("animate_emoji", True)
|
|
49
|
+
self.animate_stickers = data.get("animate_stickers", True)
|
|
50
|
+
self.enable_tts = data.get("enable_tts", False)
|
|
51
|
+
self.guilds = data.get("guild_settings", {})
|
|
52
|
+
|
|
53
|
+
def __repr__(self) -> str:
|
|
54
|
+
return f"<UserSettings theme={self.theme} status={self.status}>"
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Discord Webhook models.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Optional, List, Dict, Any, Union
|
|
6
|
+
from .base import DiscordObject
|
|
7
|
+
from .user import User
|
|
8
|
+
from .channel import Channel
|
|
9
|
+
from ..utils import parse_time
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ..state import ConnectionState
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Webhook(DiscordObject):
|
|
16
|
+
"""Represents a Discord webhook."""
|
|
17
|
+
|
|
18
|
+
__slots__ = (
|
|
19
|
+
"type",
|
|
20
|
+
"name",
|
|
21
|
+
"avatar",
|
|
22
|
+
"channel_id",
|
|
23
|
+
"guild_id",
|
|
24
|
+
"user",
|
|
25
|
+
"token",
|
|
26
|
+
"source_guild",
|
|
27
|
+
"source_channel",
|
|
28
|
+
"url",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def __init__(self, *, state: "ConnectionState", data: dict):
|
|
32
|
+
super().__init__(state=state, data=data)
|
|
33
|
+
self._update(data)
|
|
34
|
+
|
|
35
|
+
def _update(self, data: dict):
|
|
36
|
+
self.id = int(data["id"])
|
|
37
|
+
self.type = data.get("type", 1) # 1=incoming, 2=channel follower
|
|
38
|
+
self.name = data.get("name")
|
|
39
|
+
self.avatar = data.get("avatar")
|
|
40
|
+
self.channel_id = int(data["channel_id"])
|
|
41
|
+
self.guild_id = int(data["guild_id"]) if data.get("guild_id") else None
|
|
42
|
+
self.token = data.get("token")
|
|
43
|
+
self.source_guild = data.get("source_guild")
|
|
44
|
+
self.source_channel = data.get("source_channel")
|
|
45
|
+
|
|
46
|
+
self.user = None
|
|
47
|
+
if data.get("user"):
|
|
48
|
+
self.user = User(state=self._state, data=data["user"])
|
|
49
|
+
|
|
50
|
+
self.url = data.get("url")
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def avatar_url(self) -> Optional[str]:
|
|
54
|
+
"""The URL of the webhook's avatar."""
|
|
55
|
+
if self.avatar:
|
|
56
|
+
return f"https://cdn.discordapp.com/avatars/{self.id}/{self.avatar}.png"
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def display_name(self) -> str:
|
|
61
|
+
"""The display name of the webhook."""
|
|
62
|
+
return self.name or "Unknown Webhook"
|
|
63
|
+
|
|
64
|
+
async def send(
|
|
65
|
+
self,
|
|
66
|
+
content: Optional[str] = None,
|
|
67
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
68
|
+
username: Optional[str] = None,
|
|
69
|
+
avatar_url: Optional[str] = None,
|
|
70
|
+
tts: bool = False,
|
|
71
|
+
components: Optional[List] = None,
|
|
72
|
+
**kwargs,
|
|
73
|
+
) -> Dict[str, Any]:
|
|
74
|
+
"""Send a message with this webhook."""
|
|
75
|
+
payload = {}
|
|
76
|
+
if content is not None:
|
|
77
|
+
payload["content"] = content
|
|
78
|
+
if embeds is not None:
|
|
79
|
+
payload["embeds"] = embeds
|
|
80
|
+
if username is not None:
|
|
81
|
+
payload["username"] = username
|
|
82
|
+
if avatar_url is not None:
|
|
83
|
+
payload["avatar_url"] = avatar_url
|
|
84
|
+
if tts:
|
|
85
|
+
payload["tts"] = tts
|
|
86
|
+
if components is not None:
|
|
87
|
+
payload["components"] = [c.to_dict() for c in components]
|
|
88
|
+
payload.update(kwargs)
|
|
89
|
+
|
|
90
|
+
url = f"/webhooks/{self.id}/{self.token}"
|
|
91
|
+
return await self._state.http.request(
|
|
92
|
+
method="POST",
|
|
93
|
+
url=url,
|
|
94
|
+
json=payload,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
async def edit(
|
|
98
|
+
self,
|
|
99
|
+
name: Optional[str] = None,
|
|
100
|
+
avatar: Optional[str] = None,
|
|
101
|
+
channel_id: Optional[int] = None,
|
|
102
|
+
**kwargs,
|
|
103
|
+
) -> "Webhook":
|
|
104
|
+
"""Edit this webhook."""
|
|
105
|
+
payload = {}
|
|
106
|
+
if name is not None:
|
|
107
|
+
payload["name"] = name
|
|
108
|
+
if avatar is not None:
|
|
109
|
+
payload["avatar"] = avatar
|
|
110
|
+
if channel_id is not None:
|
|
111
|
+
payload["channel_id"] = str(channel_id)
|
|
112
|
+
payload.update(kwargs)
|
|
113
|
+
|
|
114
|
+
data = await self._state.http.request(
|
|
115
|
+
method="PATCH",
|
|
116
|
+
url=f"/webhooks/{self.id}",
|
|
117
|
+
json=payload,
|
|
118
|
+
)
|
|
119
|
+
self._update(data)
|
|
120
|
+
return self
|
|
121
|
+
|
|
122
|
+
async def delete(self) -> None:
|
|
123
|
+
"""Delete this webhook."""
|
|
124
|
+
await self._state.http.request(
|
|
125
|
+
method="DELETE",
|
|
126
|
+
url=f"/webhooks/{self.id}",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def __repr__(self) -> str:
|
|
130
|
+
return f"<Webhook id={self.id} name={self.name!r}>"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class WebhookMessage:
|
|
134
|
+
"""A message sent via webhook."""
|
|
135
|
+
|
|
136
|
+
def __init__(self, data: dict):
|
|
137
|
+
self.id = int(data["id"])
|
|
138
|
+
self.channel_id = int(data["channel_id"])
|
|
139
|
+
self.content = data.get("content", "")
|
|
140
|
+
self.timestamp = parse_time(data["timestamp"])
|
|
141
|
+
self.edited_timestamp = parse_time(data["edited_timestamp"]) if data.get("edited_timestamp") else None
|
|
142
|
+
self.embeds = data.get("embeds", [])
|
|
143
|
+
self.attachments = data.get("attachments", [])
|
|
144
|
+
self.components = data.get("components", [])
|
|
145
|
+
self.flags = data.get("flags", 0)
|
|
146
|
+
self.webhook_id = int(data.get("webhook_id", 0))
|
|
147
|
+
|
|
148
|
+
async def edit(
|
|
149
|
+
self,
|
|
150
|
+
content: Optional[str] = None,
|
|
151
|
+
embeds: Optional[List[Dict[str, Any]]] = None,
|
|
152
|
+
components: Optional[List] = None,
|
|
153
|
+
**kwargs,
|
|
154
|
+
) -> "WebhookMessage":
|
|
155
|
+
"""Edit this webhook message."""
|
|
156
|
+
payload = {}
|
|
157
|
+
if content is not None:
|
|
158
|
+
payload["content"] = content
|
|
159
|
+
if embeds is not None:
|
|
160
|
+
payload["embeds"] = embeds
|
|
161
|
+
if components is not None:
|
|
162
|
+
payload["components"] = [c.to_dict() for c in components]
|
|
163
|
+
payload.update(kwargs)
|
|
164
|
+
return self
|
|
165
|
+
|
|
166
|
+
async def delete(self) -> None:
|
|
167
|
+
"""Delete this webhook message."""
|
|
168
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modifyself
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A clean, pythonic Discord self-bot library
|
|
5
5
|
Author-email: modifyself <modifyself@example.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,6 +16,8 @@ Requires-Dist: aiohttp>=3.8.0
|
|
|
16
16
|
Requires-Dist: plyer>=0.9
|
|
17
17
|
Requires-Dist: pillow>=10.0
|
|
18
18
|
Requires-Dist: requests>=2.28
|
|
19
|
+
Requires-Dist: PyNaCl>=1.5.0
|
|
20
|
+
Requires-Dist: opuslib>=3.0.0
|
|
19
21
|
Dynamic: license-file
|
|
20
22
|
|
|
21
23
|
# modifyself
|
|
@@ -1,30 +1,34 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "modifyself"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "A clean, pythonic Discord self-bot library"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license = "MIT"
|
|
11
|
-
authors = [
|
|
12
|
-
{name = "modifyself", email = "modifyself@example.com"}
|
|
13
|
-
]
|
|
14
|
-
requires-python = ">=3.9"
|
|
15
|
-
dependencies = [
|
|
16
|
-
"websockets>=10.0",
|
|
17
|
-
"wreq>=0.1.0",
|
|
18
|
-
"aiohttp>=3.8.0",
|
|
19
|
-
"plyer>=0.9",
|
|
20
|
-
"pillow>=10.0",
|
|
21
|
-
"requests>=2.28",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "modifyself"
|
|
7
|
+
version = "0.2.2"
|
|
8
|
+
description = "A clean, pythonic Discord self-bot library"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "modifyself", email = "modifyself@example.com"}
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
dependencies = [
|
|
16
|
+
"websockets>=10.0",
|
|
17
|
+
"wreq>=0.1.0",
|
|
18
|
+
"aiohttp>=3.8.0",
|
|
19
|
+
"plyer>=0.9",
|
|
20
|
+
"pillow>=10.0",
|
|
21
|
+
"requests>=2.28",
|
|
22
|
+
"PyNaCl>=1.5.0",
|
|
23
|
+
"opuslib>=3.0.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/clashings/modifyself"
|
|
28
|
+
Bug-Reports = "https://github.com/clashings/modifyself/issues"
|
|
29
|
+
Source = "https://github.com/clashings/modifyself"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
where = ["."]
|
|
33
|
+
include = ["modifyself*"]
|
|
34
|
+
exclude = ["tests*", "examples*", "docs*"]
|
|
File without changes
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Discord Message model.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
|
|
7
|
-
from .base import DiscordObject
|
|
8
|
-
from .user import User
|
|
9
|
-
from ..core.snowflake import Snowflake
|
|
10
|
-
from ..utils import parse_time
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from ..state import ConnectionState
|
|
14
|
-
from .member import Member
|
|
15
|
-
from .channel import Channel
|
|
16
|
-
from .guild import Guild
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Message(DiscordObject):
|
|
20
|
-
"""Represents a message in Discord."""
|
|
21
|
-
|
|
22
|
-
__slots__ = (
|
|
23
|
-
"channel_id",
|
|
24
|
-
"author",
|
|
25
|
-
"content",
|
|
26
|
-
"timestamp",
|
|
27
|
-
"edited_at",
|
|
28
|
-
"tts",
|
|
29
|
-
"mention_everyone",
|
|
30
|
-
"mentions",
|
|
31
|
-
"mention_roles",
|
|
32
|
-
"attachments",
|
|
33
|
-
"embeds",
|
|
34
|
-
"reactions",
|
|
35
|
-
"pinned",
|
|
36
|
-
"type",
|
|
37
|
-
"guild_id",
|
|
38
|
-
"member",
|
|
39
|
-
"referenced_message",
|
|
40
|
-
"_cs_channel",
|
|
41
|
-
"_cs_guild",
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
def __init__(self, *, state: "ConnectionState", data: dict):
|
|
45
|
-
super().__init__(state=state, data=data)
|
|
46
|
-
self._cs_channel = None
|
|
47
|
-
self._cs_guild = None
|
|
48
|
-
self._update(data)
|
|
49
|
-
|
|
50
|
-
def _update(self, data: dict):
|
|
51
|
-
self.channel_id = Snowflake(data.get("channel_id", 0))
|
|
52
|
-
author_data = data.get("author", {})
|
|
53
|
-
self.author = User(state=self._state, data=author_data)
|
|
54
|
-
self.content = data.get("content", "")
|
|
55
|
-
self.timestamp = parse_time(data["timestamp"]) if "timestamp" in data else None
|
|
56
|
-
self.edited_at = (
|
|
57
|
-
parse_time(data["edited_timestamp"]) if data.get("edited_timestamp") else None
|
|
58
|
-
)
|
|
59
|
-
self.tts = data.get("tts", False)
|
|
60
|
-
self.mention_everyone = data.get("mention_everyone", False)
|
|
61
|
-
self.mentions = [
|
|
62
|
-
User(state=self._state, data=u) for u in data.get("mentions", [])
|
|
63
|
-
]
|
|
64
|
-
self.mention_roles = [int(r) for r in data.get("mention_roles", [])]
|
|
65
|
-
self.attachments = data.get("attachments", [])
|
|
66
|
-
self.embeds = data.get("embeds", [])
|
|
67
|
-
self.reactions = data.get("reactions", [])
|
|
68
|
-
self.pinned = data.get("pinned", False)
|
|
69
|
-
self.type = data.get("type", 0)
|
|
70
|
-
self.guild_id = (
|
|
71
|
-
Snowflake(data["guild_id"]) if data.get("guild_id") else None
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# Member info if present
|
|
75
|
-
member_data = data.get("member")
|
|
76
|
-
if member_data and self.guild_id:
|
|
77
|
-
from .member import Member
|
|
78
|
-
self.member = Member(
|
|
79
|
-
state=self._state, data={**member_data, "user": author_data},
|
|
80
|
-
guild_id=self.guild_id
|
|
81
|
-
)
|
|
82
|
-
else:
|
|
83
|
-
self.member = None
|
|
84
|
-
|
|
85
|
-
# Referenced message
|
|
86
|
-
ref_data = data.get("referenced_message")
|
|
87
|
-
if ref_data:
|
|
88
|
-
self.referenced_message = Message(state=self._state, data=ref_data)
|
|
89
|
-
else:
|
|
90
|
-
self.referenced_message = None
|
|
91
|
-
|
|
92
|
-
def __repr__(self) -> str:
|
|
93
|
-
return f"<Message id={self.id} author={self.author!r} channel={self.channel_id}>"
|
|
94
|
-
|
|
95
|
-
def __str__(self) -> str:
|
|
96
|
-
return self.content
|
|
97
|
-
|
|
98
|
-
@property
|
|
99
|
-
def channel(self) -> "Channel | None":
|
|
100
|
-
if self._cs_channel is None:
|
|
101
|
-
self._cs_channel = self._state._channels.get(self.channel_id)
|
|
102
|
-
return self._cs_channel
|
|
103
|
-
|
|
104
|
-
@property
|
|
105
|
-
def guild(self) -> "Guild | None":
|
|
106
|
-
if self.guild_id is None:
|
|
107
|
-
return None
|
|
108
|
-
if self._cs_guild is None:
|
|
109
|
-
self._cs_guild = self._state._guilds.get(self.guild_id)
|
|
110
|
-
return self._cs_guild
|
|
111
|
-
|
|
112
|
-
@property
|
|
113
|
-
def jump_url(self) -> str:
|
|
114
|
-
guild_id = self.guild_id or "@me"
|
|
115
|
-
return f"https://discord.com/channels/{guild_id}/{self.channel_id}/{self.id}"
|
|
116
|
-
|
|
117
|
-
@property
|
|
118
|
-
def created_at(self):
|
|
119
|
-
return self.id.created_at
|
|
120
|
-
|
|
121
|
-
@property
|
|
122
|
-
def edited_timestamp(self):
|
|
123
|
-
return self.edited_at
|
|
124
|
-
|
|
125
|
-
@property
|
|
126
|
-
def clean_content(self) -> str:
|
|
127
|
-
"""The message content with mentions replaced with names."""
|
|
128
|
-
content = self.content
|
|
129
|
-
for user in self.mentions:
|
|
130
|
-
content = content.replace(f"<@{user.id}>", f"@{user.display_name}")
|
|
131
|
-
content = content.replace(f"<@!{user.id}>", f"@{user.display_name}")
|
|
132
|
-
return content
|
|
133
|
-
|
|
134
|
-
async def delete(self, *, delay: float | None = None):
|
|
135
|
-
"""Delete this message."""
|
|
136
|
-
if delay:
|
|
137
|
-
import asyncio
|
|
138
|
-
await asyncio.sleep(delay)
|
|
139
|
-
await self._state.http.delete_message(self.channel_id, self.id)
|
|
140
|
-
|
|
141
|
-
async def edit(self, content: str | None = None, **kwargs):
|
|
142
|
-
"""Edit this message."""
|
|
143
|
-
data = await self._state.http.edit_message(
|
|
144
|
-
self.channel_id, self.id, content, **kwargs
|
|
145
|
-
)
|
|
146
|
-
self._update(data)
|
|
147
|
-
return self
|
|
148
|
-
|
|
149
|
-
async def reply(self, content: str | None = None, **kwargs):
|
|
150
|
-
"""Reply to this message."""
|
|
151
|
-
ref = {
|
|
152
|
-
"type": 0,
|
|
153
|
-
"message_id": str(self.id),
|
|
154
|
-
"channel_id": str(self.channel_id),
|
|
155
|
-
}
|
|
156
|
-
if self.guild_id:
|
|
157
|
-
ref["guild_id"] = str(self.guild_id)
|
|
158
|
-
kwargs["message_reference"] = ref
|
|
159
|
-
data = await self._state.http.send_message(self.channel_id, content, **kwargs)
|
|
160
|
-
return self._state._store_message(data)
|
|
161
|
-
|
|
162
|
-
async def add_reaction(self, emoji: str):
|
|
163
|
-
"""Add a reaction to this message."""
|
|
164
|
-
await self._state.http.add_reaction(self.channel_id, self.id, emoji)
|
|
165
|
-
|
|
166
|
-
async def remove_reaction(self, emoji: str):
|
|
167
|
-
"""Remove a reaction from this message."""
|
|
168
|
-
await self._state.http.remove_reaction(self.channel_id, self.id, emoji)
|
|
169
|
-
|
|
170
|
-
async def clear_reactions(self):
|
|
171
|
-
"""Clear all reactions from this message."""
|
|
172
|
-
await self._state.http.clear_reactions(self.channel_id, self.id)
|
|
173
|
-
|
|
174
|
-
async def pin(self):
|
|
175
|
-
"""Pin this message."""
|
|
176
|
-
await self._state.http.pin_message(self.channel_id, self.id)
|
|
177
|
-
|
|
178
|
-
async def unpin(self):
|
|
179
|
-
"""Unpin this message."""
|
|
180
|
-
await self._state.http.unpin_message(self.channel_id, self.id)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|