Skip to content

Commit 3a43db0

Browse files
authored
Merge branch 'master' into state-rewrite
Signed-off-by: VincentRPS <[email protected]>
2 parents b689c54 + 32ef1c8 commit 3a43db0

File tree

20 files changed

+632
-200
lines changed

20 files changed

+632
-200
lines changed

CHANGELOG.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ These changes are available on the `master` branch, but have not yet been releas
4949
([#2579](https://github.com/Pycord-Development/pycord/pull/2579))
5050
- Added new `Subscription` object and related methods/events.
5151
([#2564](https://github.com/Pycord-Development/pycord/pull/2564))
52+
- Added `Message.forward_to`, `Message.snapshots`, and other related attributes.
53+
([#2598](https://github.com/Pycord-Development/pycord/pull/2598))
5254
- Added the ability to change the API's base URL with `Route.API_BASE_URL`.
5355
([#2714](https://github.com/Pycord-Development/pycord/pull/2714))
5456
- Added the ability to pass a `datetime.time` object to `format_dt`
@@ -99,14 +101,16 @@ These changes are available on the `master` branch, but have not yet been releas
99101
([#2564](https://github.com/Pycord-Development/pycord/pull/2564))
100102
- Fixed `Subscription.renewal_sku_ids` not accepting `None` from the received payload.
101103
([#2709](https://github.com/Pycord-Development/pycord/pull/2709))
102-
- Fixed `ForumChannel.edit` allowing `default_reaction_emoji` to be `None`
104+
- Fixed `ForumChannel.edit` allowing `default_reaction_emoji` to be `None`.
103105
([#2739](https://github.com/Pycord-Development/pycord/pull/2739))
104106
- Fixed missing `None` type hints in `Select.__init__`.
105-
([#2746])(https://github.com/Pycord-Development/pycord/pull/2746)
107+
([#2746](https://github.com/Pycord-Development/pycord/pull/2746))
106108
- Updated `valid_locales` to support `in` and `es-419`.
107-
([#2767])(https://github.com/Pycord-Development/pycord/pull/2767)
109+
([#2767](https://github.com/Pycord-Development/pycord/pull/2767))
108110
- Fixed `Webhook.edit` not working with `attachments=[]`.
109-
([#2779])(https://github.com/Pycord-Development/pycord/pull/2779)
111+
([#2779](https://github.com/Pycord-Development/pycord/pull/2779))
112+
- Fixed GIF-based `Sticker` returning the wrong `url`.
113+
([#2781](https://github.com/Pycord-Development/pycord/pull/2781))
110114

111115
### Changed
112116

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ include README.rst
22
include LICENSE
33
include requirements.txt
44
include discord/bin/*.dll
5+
include discord/banner.txt
6+
include discord/ibanner.txt
57
include discord/py.typed
68

79
prune .github

discord/abc.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,9 +1497,9 @@ async def send(
14971497
.. versionadded:: 1.4
14981498
14991499
reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, :class:`~discord.PartialMessage`]
1500-
A reference to the :class:`~discord.Message` to which you are replying, this can be created using
1501-
:meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. You can control
1502-
whether this mentions the author of the referenced message using the
1500+
A reference to the :class:`~discord.Message` being replied to or forwarded. This can be created using
1501+
:meth:`~discord.Message.to_reference`.
1502+
When replying, you can control whether this mentions the author of the referenced message using the
15031503
:attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions`` or by
15041504
setting ``mention_author``.
15051505
@@ -1589,9 +1589,19 @@ async def send(
15891589
allowed_mentions = allowed_mentions or AllowedMentions().to_dict()
15901590
allowed_mentions["replied_user"] = bool(mention_author)
15911591

1592+
_reference = None
15921593
if reference is not None:
15931594
try:
1594-
reference = reference.to_message_reference_dict()
1595+
_reference = reference.to_message_reference_dict()
1596+
from .message import MessageReference
1597+
1598+
if not isinstance(reference, MessageReference):
1599+
utils.warn_deprecated(
1600+
f"Passing {type(reference).__name__} to reference",
1601+
"MessageReference",
1602+
"2.7",
1603+
"3.0",
1604+
)
15951605
except AttributeError:
15961606
raise InvalidArgument(
15971607
"reference parameter must be Message, MessageReference, or"
@@ -1641,7 +1651,7 @@ async def send(
16411651
nonce=nonce,
16421652
enforce_nonce=enforce_nonce,
16431653
allowed_mentions=allowed_mentions,
1644-
message_reference=reference,
1654+
message_reference=_reference,
16451655
stickers=stickers,
16461656
components=components,
16471657
flags=flags.value,
@@ -1660,7 +1670,7 @@ async def send(
16601670
nonce=nonce,
16611671
enforce_nonce=enforce_nonce,
16621672
allowed_mentions=allowed_mentions,
1663-
message_reference=reference,
1673+
message_reference=_reference,
16641674
stickers=stickers,
16651675
components=components,
16661676
flags=flags.value,

discord/banner.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
3+
${bold_white} ${reset} ${blue} ````'````````````````````````'`
4+
${bold_white} ${reset} ${bold_blue} `. `-
5+
${bold_white} O88888${reset} ${yellow}'' _
6+
${bold_white}u@@@@@@@@@@@BG! O@@@@8${reset} ${bold_yellow}_ ${reset}${bold_white}:oQ@@@@@@#Rr${reset}${bold_yellow} `-
7+
${bold_white}u@@@@@@@@@@@@@@O. O@@@@8${reset} ${red}- ${reset}${bold_white}k@@@@#dWQ@@@@D`${reset}${red} .
8+
${bold_white}u@@@@@` 'I@@@@@a`O9999r V6996u ,LaEQQQDUv. :}P$QQ8OI?. V9999L_H8Qc !y0QQRY.O@@@@8${reset} ${bold_red}- ${reset}${bold_white}Vkkk} E@@@@:${reset}${bold_red} .
9+
${bold_white}u@@@@@` :@@@@@R I@@@@Q` ^@@@@@" -M@@@@@@@@@@@q ,Q@@@@@@@@@@@V` O@@@@Q#@@@G-0@@@@@@@##@@@@8${reset} ${purple}- ${reset}${bold_white}-m3HQ@@@0r${reset}${purple} .
10+
${bold_white}u@@@@@}iYz#@@@@@) `$@@@@} O@@@@j -B@@@@Q \@@@T ,#@@@@K_`=#@@@@q O@@@@@8]*);E@@@@@V::V@@@@@8${reset} ${bold_purple}- ${reset}${bold_white}:@@@@@#$z;${reset}${bold_purple} .
11+
${bold_white}u@@@@@@@@@@@@@O! ,#@@@B.*@@@@0` L@@@@@ T@@@@@` y@@@@@: O@@@@Q` @@@@@H G@@@@8${reset} ${black}- ${reset}${bold_white}```=D@@@@P${reset}${black} .
12+
${bold_white}u@@@@@6OOOMj]! x@@@@}9@@@#! x@@@@@ }@@@@@. U@@@@@, O@@@@$ #@@@@b d@@@@8${reset} ${bold_black}- ${reset}${bold_white},####0~` :6@@@@8${reset}${bold_black} .
13+
${bold_white}u@@@@@` K@@@#@@@@x `0@@@@# /@@| .Q@@@@0r~Y@@@@@w O@@@@$ P@@@@@OxxO@@@@@8${reset} ${blue}- ${reset}${bold_white}c#@@@@@@@@@@@Q=${reset}${blue} .
14+
${bold_white}u@@@@@` `#@@@@@@g `c@@@@@@@@@@#T `M@@@@@@@@@@#) O@@@@$ `z@@@@@@@QQ@@@@8${reset} ${bold_blue}_ ${reset}${bold_white}`rz0QBBB8bV:${reset}${bold_blue} `-
15+
${bold_white}=yyyyV x@@@@@#: `~YI5MWIx! `^}m5MGwx: |yyyyv `*w33y~ )yyyyx${reset} ${yellow}.` -
16+
${bold_white}=gEB@@@@#r ${reset} ${bold_yellow} '. .`
17+
${bold_white}`g@@@@@#X_ ${reset} ${blue} '`````'''''''''''''''''''````'`
18+
${bold_white}`-":_`

discord/banners.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import datetime
2+
import importlib.resources
3+
import logging
4+
import logging.config
5+
import os
6+
import platform
7+
import string
8+
import sys
9+
import time
10+
import warnings
11+
from typing import Sequence
12+
from . import __version__
13+
14+
import colorlog
15+
import colorlog.escape_codes
16+
17+
__all__: Sequence[str] = ('start_logging', 'print_banner')
18+
19+
20+
day_prefixes: dict[int, str] = {
21+
1: 'st',
22+
2: 'nd',
23+
3: 'rd',
24+
4: 'th',
25+
5: 'th',
26+
6: 'th',
27+
7: 'th',
28+
8: 'th',
29+
9: 'th',
30+
0: 'th',
31+
}
32+
33+
34+
def start_logging(flavor: None | int | str | dict, debug: bool = False):
35+
if len(logging.root.handlers) != 0:
36+
return # the user is most likely using logging.basicConfig, or is being spearheaded by something else.
37+
38+
if flavor is None:
39+
flavor = logging.DEBUG if debug else logging.INFO
40+
41+
if isinstance(flavor, dict):
42+
logging.config.dictConfig(flavor)
43+
44+
if flavor.get('handler'):
45+
return
46+
47+
flavor = None
48+
49+
# things that will never be logged.
50+
logging.logThreads = None
51+
logging.logProcesses = None
52+
53+
colorlog.basicConfig(
54+
level=flavor,
55+
format='%(log_color)s%(bold)s%(levelname)-1.1s%(thin)s %(asctime)23.23s %(bold)s%(name)s: '
56+
'%(thin)s%(message)s%(reset)s',
57+
stream=sys.stderr,
58+
log_colors={
59+
'DEBUG': 'cyan',
60+
'INFO': 'green',
61+
'WARNING': 'yellow',
62+
'ERROR': 'red',
63+
'CRITICAL': 'red, bg_white',
64+
},
65+
)
66+
warnings.simplefilter('always', DeprecationWarning)
67+
logging.captureWarnings(True)
68+
69+
70+
def get_day_prefix(num: int) -> str:
71+
n = str(num)
72+
return day_prefixes[int(n[len(n) - 1])]
73+
74+
75+
def print_banner(
76+
bot_name: str = 'A bot',
77+
module: str | None = 'pycord',
78+
):
79+
banners = importlib.resources.files(module)
80+
81+
for trav in banners.iterdir():
82+
if trav.name == 'banner.txt':
83+
banner = trav.read_text()
84+
elif trav.name == 'ibanner.txt':
85+
info_banner = trav.read_text()
86+
87+
today = datetime.date.today()
88+
89+
args = {
90+
# the # prefix only works on Windows, and the - prefix only works on linux/unix systems
91+
'current_time': today.strftime(f'%B the %#d{get_day_prefix(today.day)} of %Y')
92+
if os.name == 'nt'
93+
else today.strftime(f'%B the %-d{get_day_prefix(today.day)} of %Y'),
94+
'py_version': platform.python_version(),
95+
'botname': bot_name,
96+
'version': __version__
97+
}
98+
args |= colorlog.escape_codes.escape_codes
99+
100+
sys.stdout.write(string.Template(banner).safe_substitute(args))
101+
sys.stdout.write(string.Template(info_banner).safe_substitute(args))
102+
sys.stdout.flush()
103+
time.sleep(0.162) # sleep for a bit to prevent overfill.

discord/channel.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3418,6 +3418,9 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage:
34183418

34193419
return PartialMessage(channel=self, id=message_id)
34203420

3421+
def __repr__(self) -> str:
3422+
return f"<PartialMessageable id={self.id} type={self.type!r}>"
3423+
34213424

34223425
def _guild_channel_factory(channel_type: int):
34233426
value = try_enum(ChannelType, channel_type)

discord/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
import aiohttp
3737

38+
from discord.banners import print_banner, start_logging
39+
3840
from . import utils
3941
from .activity import ActivityTypes, BaseActivity, create_activity
4042
from .appinfo import AppInfo, PartialAppInfo
@@ -224,6 +226,9 @@ def __init__(
224226
loop: asyncio.AbstractEventLoop | None = None,
225227
**options: Any,
226228
):
229+
self._flavor = options.get("flavor", logging.INFO)
230+
self._debug = options.get("debug", False)
231+
self._banner_module = options.get("banner_module")
227232
# self.ws is set in the connect method
228233
self.ws: DiscordWebSocket = None # type: ignore
229234
self.loop: asyncio.AbstractEventLoop = (
@@ -601,6 +606,9 @@ async def login(self, token: str) -> None:
601606
data = await self.http.static_login(token.strip())
602607
self._connection.user = ClientUser(state=self._connection, data=data)
603608

609+
print_banner(bot_name=self._connection.user.display_name, module=self._banner_module or 'discord')
610+
start_logging(self._flavor, debug=self._debug)
611+
604612
async def connect(self, *, reconnect: bool = True) -> None:
605613
"""|coro|
606614

discord/enums.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
"EntitlementOwnerType",
7777
"IntegrationType",
7878
"InteractionContextType",
79-
"ApplicationCommandPermissionType"
79+
"ApplicationCommandPermissionType",
80+
"PollLayoutType",
81+
"MessageReferenceType",
8082
)
8183

8284

@@ -267,6 +269,12 @@ class MessageType(Enum):
267269
stage_raise_hand = 30
268270
stage_topic = 31
269271
guild_application_premium_subscription = 32
272+
guild_incident_alert_mode_enabled = 36
273+
guild_incident_alert_mode_disabled = 37
274+
guild_incident_report_raid = 38
275+
guild_incident_report_false_alarm = 39
276+
purchase_notification = 44
277+
poll_result = 46
270278

271279

272280
class VoiceRegion(Enum):
@@ -1056,6 +1064,13 @@ class PollLayoutType(Enum):
10561064
default = 1
10571065

10581066

1067+
class MessageReferenceType(Enum):
1068+
"""The type of the message reference object"""
1069+
1070+
default = 0
1071+
forward = 1
1072+
1073+
10591074
class SubscriptionStatus(Enum):
10601075
"""The status of a subscription."""
10611076

discord/ext/commands/context.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,9 @@ async def send_help(self, *args: Any) -> Any:
403403
@discord.utils.copy_doc(Message.reply)
404404
async def reply(self, content: str | None = None, **kwargs: Any) -> Message:
405405
return await self.message.reply(content, **kwargs)
406+
407+
@discord.utils.copy_doc(Message.forward_to)
408+
async def forward_to(
409+
self, channel: discord.abc.Messageable, **kwargs: Any
410+
) -> Message:
411+
return await self.message.forward_to(channel, **kwargs)

discord/flags.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,14 @@ def is_voice_message(self):
411411
"""
412412
return 8192
413413

414+
@flag_value
415+
def has_snapshot(self):
416+
""":class:`bool`: Returns ``True`` if this message has a snapshot from message forwarding.
417+
418+
.. versionadded:: 2.7
419+
"""
420+
return 1 << 14
421+
414422

415423
@fill_with_flags()
416424
class PublicUserFlags(BaseFlags):

0 commit comments

Comments
 (0)