aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/models.py110
-rw-r--r--api/tests/test_users.py2
-rw-r--r--api/urls.py6
-rw-r--r--api/viewsets.py106
4 files changed, 160 insertions, 64 deletions
diff --git a/api/models.py b/api/models.py
index 3387e9be..21b5975a 100644
--- a/api/models.py
+++ b/api/models.py
@@ -60,6 +60,50 @@ class OffTopicChannelName(ModelReprMixin, models.Model):
return self.name
+class Role(ModelReprMixin, models.Model):
+ """A role on our Discord server."""
+
+ id = models.BigIntegerField( # noqa
+ primary_key=True,
+ validators=(
+ MinValueValidator(
+ limit_value=0,
+ message="Role IDs cannot be negative."
+ ),
+ ),
+ help_text="The role ID, taken from Discord."
+ )
+ name = models.CharField(
+ max_length=100,
+ help_text="The role name, taken from Discord."
+ )
+ colour = models.IntegerField(
+ validators=(
+ MinValueValidator(
+ limit_value=0,
+ message="Colour hex cannot be negative."
+ ),
+ ),
+ help_text="The integer value of the colour of this role from Discord."
+ )
+ permissions = models.IntegerField(
+ validators=(
+ MinValueValidator(
+ limit_value=0,
+ message="Role permissions cannot be negative."
+ ),
+ MaxValueValidator(
+ limit_value=2 << 32,
+ message="Role permission bitset exceeds value of having all permissions"
+ )
+ ),
+ help_text="The integer value of the permission bitset of this role from Discord."
+ )
+
+ def __str__(self):
+ return self.name
+
+
class SnakeFact(ModelReprMixin, models.Model):
"""A snake fact used by the bot's snake cog."""
@@ -126,48 +170,24 @@ class SpecialSnake(ModelReprMixin, models.Model):
return self.name
-class Role(ModelReprMixin, models.Model):
- """A role on our Discord server."""
+class Tag(ModelReprMixin, models.Model):
+ """A tag providing (hopefully) useful information."""
- id = models.BigIntegerField( # noqa
- primary_key=True,
- validators=(
- MinValueValidator(
- limit_value=0,
- message="Role IDs cannot be negative."
- ),
- ),
- help_text="The role ID, taken from Discord."
- )
- name = models.CharField(
+ title = models.CharField(
max_length=100,
- help_text="The role name, taken from Discord."
- )
- colour = models.IntegerField(
- validators=(
- MinValueValidator(
- limit_value=0,
- message="Colour hex cannot be negative."
- ),
+ help_text=(
+ "The title of this tag, shown in searches and providing "
+ "a quick overview over what this embed contains."
),
- help_text="The integer value of the colour of this role from Discord."
+ primary_key=True
)
- permissions = models.IntegerField(
- validators=(
- MinValueValidator(
- limit_value=0,
- message="Role permissions cannot be negative."
- ),
- MaxValueValidator(
- limit_value=2 << 32,
- message="Role permission bitset exceeds value of having all permissions"
- )
- ),
- help_text="The integer value of the permission bitset of this role from Discord."
+ embed = pgfields.JSONField(
+ help_text="The actual embed shown by this tag.",
+ validators=(validate_tag_embed,)
)
def __str__(self):
- return self.name
+ return self.title
class User(ModelReprMixin, models.Model):
@@ -217,26 +237,6 @@ class User(ModelReprMixin, models.Model):
return f"{self.name}#{self.discriminator}"
-class Tag(ModelReprMixin, models.Model):
- """A tag providing (hopefully) useful information."""
-
- title = models.CharField(
- max_length=100,
- help_text=(
- "The title of this tag, shown in searches and providing "
- "a quick overview over what this embed contains."
- ),
- primary_key=True
- )
- embed = pgfields.JSONField(
- help_text="The actual embed shown by this tag.",
- validators=(validate_tag_embed,)
- )
-
- def __str__(self):
- return self.title
-
-
class Infraction(ModelReprMixin, models.Model):
"""An infraction for a Discord user."""
diff --git a/api/tests/test_users.py b/api/tests/test_users.py
index 8dadcbdb..90bc3d30 100644
--- a/api/tests/test_users.py
+++ b/api/tests/test_users.py
@@ -4,7 +4,7 @@ from .base import APISubdomainTestCase
from ..models import Role, User
-class UnauthedDocumentationLinkAPITests(APISubdomainTestCase):
+class UnauthedUserAPITests(APISubdomainTestCase):
def setUp(self):
super().setUp()
self.client.force_authenticate(user=None)
diff --git a/api/urls.py b/api/urls.py
index af275381..7d6a4f7d 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -4,7 +4,7 @@ from rest_framework.routers import DefaultRouter
from .views import HealthcheckView
from .viewsets import (
DocumentationLinkViewSet, InfractionViewSet,
- OffTopicChannelNameViewSet,
+ OffTopicChannelNameViewSet, RoleViewSet,
SnakeFactViewSet, SnakeIdiomViewSet,
SnakeNameViewSet, SpecialSnakeViewSet,
TagViewSet, UserViewSet
@@ -27,6 +27,10 @@ bot_router.register(
base_name='offtopicchannelname'
)
bot_router.register(
+ 'roles',
+ RoleViewSet
+)
+bot_router.register(
'snake-facts',
SnakeFactViewSet
)
diff --git a/api/viewsets.py b/api/viewsets.py
index 2784bbad..ab62f8a7 100644
--- a/api/viewsets.py
+++ b/api/viewsets.py
@@ -14,7 +14,7 @@ from rest_framework_bulk import BulkCreateModelMixin
from .models import (
DocumentationLink, Infraction,
- OffTopicChannelName,
+ OffTopicChannelName, Role,
SnakeFact, SnakeIdiom,
SnakeName, SpecialSnake,
Tag, User
@@ -22,9 +22,10 @@ from .models import (
from .serializers import (
DocumentationLinkSerializer, ExpandedInfractionSerializer,
InfractionSerializer, OffTopicChannelNameSerializer,
- SnakeFactSerializer, SnakeIdiomSerializer,
- SnakeNameSerializer, SpecialSnakeSerializer,
- TagSerializer, UserSerializer
+ RoleSerializer, SnakeFactSerializer,
+ SnakeIdiomSerializer, SnakeNameSerializer,
+ SpecialSnakeSerializer, TagSerializer,
+ UserSerializer
)
@@ -319,6 +320,97 @@ class OffTopicChannelNameViewSet(DestroyModelMixin, ViewSet):
return Response(serialized.data)
+class RoleViewSet(ModelViewSet):
+ """
+ View providing CRUD access to the roles on our server, used
+ by the bot to keep a mirror of our server's roles on the site.
+
+ ## Routes
+ ### GET /bot/roles
+ Returns all roles in the database.
+
+ #### Response format
+ >>> [
+ ... {
+ ... 'id': 267628507062992896,
+ ... 'name': "Admins",
+ ... 'colour': 1337,
+ ... 'permissions': 8
+ ... }
+ ... ]
+
+ #### Status codes
+ - 200: returned on success
+
+ ### GET /bot/roles/<snowflake:int>
+ Gets a single role by ID.
+
+ #### Response format
+ >>> {
+ ... 'id': 267628507062992896,
+ ... 'name': "Admins",
+ ... 'colour': 1337,
+ ... 'permissions': 8
+ ... }
+
+ #### Status codes
+ - 200: returned on success
+ - 404: if a role with the given `snowflake` could not be found
+
+ ### POST /bot/roles
+ Adds a single new role.
+
+ #### Request body
+ >>> {
+ ... 'id': int,
+ ... 'name': str,
+ ... 'colour': int,
+ ... 'permissions': int,
+ ... }
+
+ #### Status codes
+ - 201: returned on success
+ - 400: if the body format is invalid
+
+ ### PUT /bot/roles/<snowflake:int>
+ Update the role with the given `snowflake`.
+ All fields in the request body are required.
+
+ #### Request body
+ >>> {
+ ... 'id': int,
+ ... 'name': str,
+ ... 'colour': int,
+ ... 'permissions': int
+ ... }
+
+ #### Status codes
+ - 200: returned on success
+ - 400: if the request body was invalid
+
+ ### PATCH /bot/roles/<snowflake:int>
+ Update the role with the given `snowflake`.
+ All fields in the request body are required.
+
+ >>> {
+ ... 'id': int,
+ ... 'name': str,
+ ... 'colour': int,
+ ... 'permissions': int
+ ... }
+
+ ### DELETE /bot/roles/<snowflake:int>
+ Deletes the role with the given `snowflake`.
+
+ #### Status codes
+ - 204: returned on success
+ - 404: if a role with the given `snowflake` does not exist
+ """
+
+ queryset = Role.objects.all()
+ serializer_class = RoleSerializer
+
+
class SnakeFactViewSet(ListModelMixin, GenericViewSet):
"""
View providing snake facts created by the Pydis community in the first code jam.
@@ -506,7 +598,7 @@ class TagViewSet(ModelViewSet):
- 201: returned on success
- 400: if one of the given fields is invalid
- ### PUT /bot/members/<title:str>
+ ### PUT /bot/tags/<title:str>
Update the tag with the given `title`.
#### Request body
@@ -524,7 +616,7 @@ class TagViewSet(ModelViewSet):
- 400: if the request body was invalid, see response body for details
- 404: if the tag with the given `title` could not be found
- ### PATCH /bot/members/<title:str>
+ ### PATCH /bot/tags/<title:str>
Update the tag with the given `title`.
#### Request body
@@ -542,7 +634,7 @@ class TagViewSet(ModelViewSet):
- 400: if the request body was invalid, see response body for details
- 404: if the tag with the given `title` could not be found
- ### DELETE /bot/members/<title:str>
+ ### DELETE /bot/tags/<title:str>
Deletes the tag with the given `title`.
#### Status codes