Add guild channel creation methods (#102)

This commit is contained in:
Slipstream 2025-06-15 18:49:51 -06:00 committed by GitHub
parent 2586d3cd0d
commit a335ed972c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 196 additions and 0 deletions

View File

@ -711,6 +711,22 @@ class HTTPClient:
"""Fetches a channel by ID."""
return await self.request("GET", f"/channels/{channel_id}")
async def create_guild_channel(
self,
guild_id: "Snowflake",
payload: Dict[str, Any],
reason: Optional[str] = None,
) -> Dict[str, Any]:
"""Creates a new channel in the specified guild."""
headers = {"X-Audit-Log-Reason": reason} if reason else None
return await self.request(
"POST",
f"/guilds/{guild_id}/channels",
payload=payload,
custom_headers=headers,
)
async def get_channel_invites(
self, channel_id: "Snowflake"
) -> List[Dict[str, Any]]:

View File

@ -1378,6 +1378,60 @@ class Guild:
self.id, days=days, compute_count=compute_count
)
async def create_text_channel(
self,
name: str,
*,
reason: Optional[str] = None,
**options: Any,
) -> "TextChannel":
"""|coro| Create a new text channel in this guild."""
payload: Dict[str, Any] = {"name": name, "type": ChannelType.GUILD_TEXT.value}
payload.update(options)
data = await self._client._http.create_guild_channel(
self.id, payload, reason=reason
)
return cast("TextChannel", self._client.parse_channel(data))
async def create_voice_channel(
self,
name: str,
*,
reason: Optional[str] = None,
**options: Any,
) -> "VoiceChannel":
"""|coro| Create a new voice channel in this guild."""
payload: Dict[str, Any] = {
"name": name,
"type": ChannelType.GUILD_VOICE.value,
}
payload.update(options)
data = await self._client._http.create_guild_channel(
self.id, payload, reason=reason
)
return cast("VoiceChannel", self._client.parse_channel(data))
async def create_category(
self,
name: str,
*,
reason: Optional[str] = None,
**options: Any,
) -> "CategoryChannel":
"""|coro| Create a new category channel in this guild."""
payload: Dict[str, Any] = {
"name": name,
"type": ChannelType.GUILD_CATEGORY.value,
}
payload.update(options)
data = await self._client._http.create_guild_channel(
self.id, payload, reason=reason
)
return cast("CategoryChannel", self._client.parse_channel(data))
class Channel:
"""Base class for Discord channels."""

View File

@ -0,0 +1,126 @@
import pytest
from types import SimpleNamespace
from unittest.mock import AsyncMock
from disagreement.http import HTTPClient
from disagreement.client import Client
from disagreement.models import Guild, TextChannel, VoiceChannel, CategoryChannel
from disagreement.enums import (
VerificationLevel,
MessageNotificationLevel,
ExplicitContentFilterLevel,
MFALevel,
GuildNSFWLevel,
PremiumTier,
ChannelType,
)
def _guild_data():
return {
"id": "1",
"name": "g",
"owner_id": "1",
"afk_timeout": 60,
"verification_level": VerificationLevel.NONE.value,
"default_message_notifications": MessageNotificationLevel.ALL_MESSAGES.value,
"explicit_content_filter": ExplicitContentFilterLevel.DISABLED.value,
"roles": [],
"emojis": [],
"features": [],
"mfa_level": MFALevel.NONE.value,
"system_channel_flags": 0,
"premium_tier": PremiumTier.NONE.value,
"nsfw_level": GuildNSFWLevel.DEFAULT.value,
}
@pytest.mark.asyncio
async def test_http_create_guild_channel_calls_request():
http = HTTPClient(token="t")
http.request = AsyncMock(return_value={})
payload = {"name": "chan", "type": ChannelType.GUILD_TEXT.value}
await http.create_guild_channel("1", payload, reason="r")
http.request.assert_called_once_with(
"POST",
"/guilds/1/channels",
payload=payload,
custom_headers={"X-Audit-Log-Reason": "r"},
)
@pytest.mark.asyncio
async def test_guild_create_text_channel_returns_channel():
http = SimpleNamespace(
create_guild_channel=AsyncMock(
return_value={
"id": "10",
"type": ChannelType.GUILD_TEXT.value,
"guild_id": "1",
"permission_overwrites": [],
}
)
)
client = Client(token="t")
client._http = http
guild = Guild(_guild_data(), client_instance=client)
channel = await guild.create_text_channel("general")
http.create_guild_channel.assert_awaited_once_with(
"1", {"name": "general", "type": ChannelType.GUILD_TEXT.value}, reason=None
)
assert isinstance(channel, TextChannel)
assert client._channels.get("10") is channel
@pytest.mark.asyncio
async def test_guild_create_voice_channel_returns_channel():
http = SimpleNamespace(
create_guild_channel=AsyncMock(
return_value={
"id": "11",
"type": ChannelType.GUILD_VOICE.value,
"guild_id": "1",
"permission_overwrites": [],
}
)
)
client = Client(token="t")
client._http = http
guild = Guild(_guild_data(), client_instance=client)
channel = await guild.create_voice_channel("Voice")
http.create_guild_channel.assert_awaited_once_with(
"1", {"name": "Voice", "type": ChannelType.GUILD_VOICE.value}, reason=None
)
assert isinstance(channel, VoiceChannel)
assert client._channels.get("11") is channel
@pytest.mark.asyncio
async def test_guild_create_category_returns_channel():
http = SimpleNamespace(
create_guild_channel=AsyncMock(
return_value={
"id": "12",
"type": ChannelType.GUILD_CATEGORY.value,
"guild_id": "1",
"permission_overwrites": [],
}
)
)
client = Client(token="t")
client._http = http
guild = Guild(_guild_data(), client_instance=client)
channel = await guild.create_category("Cat")
http.create_guild_channel.assert_awaited_once_with(
"1", {"name": "Cat", "type": ChannelType.GUILD_CATEGORY.value}, reason=None
)
assert isinstance(channel, CategoryChannel)
assert client._channels.get("12") is channel