diff --git a/docs/supportedsites.md b/docs/supportedsites.md
index a480697a..325acd29 100644
--- a/docs/supportedsites.md
+++ b/docs/supportedsites.md
@@ -1,7 +1,6 @@
# Supported Sites
-
Consider all listed sites to potentially be NSFW.
@@ -209,7 +208,7 @@ Consider all listed sites to potentially be NSFW.
| Discord |
https://discord.com/ |
- Channels, DMs, Servers |
+ Channels, DMs, Messages, Servers |
|
diff --git a/gallery_dl/extractor/discord.py b/gallery_dl/extractor/discord.py
index 5a4305f4..6a5fcc9e 100644
--- a/gallery_dl/extractor/discord.py
+++ b/gallery_dl/extractor/discord.py
@@ -244,6 +244,23 @@ class DiscordChannelExtractor(DiscordExtractor):
return self.extract_channel(channel_id)
+class DiscordMessageExtractor(DiscordExtractor):
+ subcategory = "message"
+ pattern = BASE_PATTERN + r"/channels/(\d+)/(\d+)/(\d+)/?$"
+ example = "https://discord.com/channels/1234567890/9876543210/2468013579"
+
+ def items(self):
+ server_id, channel_id, message_id = self.groups
+
+ self.build_server_and_channels(server_id)
+
+ if channel_id not in self.server_channels_metadata:
+ self.parse_channel(self.api.get_channel(channel_id))
+
+ return self.extract_message(
+ self.api.get_message(channel_id, message_id))
+
+
class DiscordServerExtractor(DiscordExtractor):
subcategory = "server"
pattern = BASE_PATTERN + r"/channels/(\d+)/?$"
@@ -264,13 +281,29 @@ class DiscordDirectMessagesExtractor(DiscordExtractor):
subcategory = "direct-messages"
directory_fmt = ("{category}", "Direct Messages",
"{channel_id}_{recipients:J,}")
- pattern = BASE_PATTERN + r"/channels/@me/(\d+)"
+ pattern = BASE_PATTERN + r"/channels/@me/(\d+)/?$"
example = "https://discord.com/channels/@me/1234567890"
def items(self):
return self.extract_channel(self.groups[0])
+class DiscordDirectMessageExtractor(DiscordExtractor):
+ subcategory = "direct-message"
+ directory_fmt = ("{category}", "Direct Messages",
+ "{channel_id}_{recipients:J,}")
+ pattern = BASE_PATTERN + r"/channels/@me/(\d+)/(\d+)/?$"
+ example = "https://discord.com/channels/@me/1234567890/9876543210"
+
+ def items(self):
+ channel_id, message_id = self.groups
+
+ self.parse_channel(self.api.get_channel(channel_id))
+
+ return self.extract_message(
+ self.api.get_message(channel_id, message_id))
+
+
class DiscordAPI():
"""Interface for the Discord API v10
@@ -325,6 +358,13 @@ class DiscordAPI():
return self._pagination(_method, MESSAGES_BATCH)
+ def get_message(self, channel_id, message_id):
+ """Get message information"""
+ return self._call("/channels/" + channel_id + "/messages", {
+ "limit": 1,
+ "around": message_id
+ })[0]
+
def _call(self, endpoint, params=None):
url = self.root + endpoint
try:
diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py
index 9f916081..faa5c603 100755
--- a/scripts/supportedsites.py
+++ b/scripts/supportedsites.py
@@ -243,6 +243,7 @@ SUBCATEGORY_MAP = {
},
"discord": {
"direct-messages": "DMs",
+ "direct-message" : "",
},
"fanbox": {
"supporting": "Supported User Feed",
diff --git a/test/results/discord.py b/test/results/discord.py
index 90b7c3f4..5b2350db 100644
--- a/test/results/discord.py
+++ b/test/results/discord.py
@@ -8,6 +8,18 @@ from gallery_dl.extractor import discord
__tests__ = (
+{
+ "#url" : "https://discord.com/channels/302094807046684672/1306706528786583623/1306706528786583623",
+ "#category": ("", "discord", "message"),
+ "#class" : discord.DiscordMessageExtractor,
+},
+
+{
+ "#url" : "https://discord.com/channels/@me/1306706528786583623/1306706528786583623",
+ "#category": ("", "discord", "direct-message"),
+ "#class" : discord.DiscordDirectMessageExtractor,
+},
+
{
"#url" : "https://discord.com/channels/302094807046684672/1306705919916249098",
"#category": ("", "discord", "channel"),