Added SubChannels backend
SubChannels are target discord channels for subscriptions to send their content into.
This commit is contained in:
parent
1e7ce34df6
commit
14167e05be
@ -4,7 +4,7 @@ import logging
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.home.models import Subscription, SavedGuilds
|
||||
from apps.home.models import SubChannel, Subscription, SavedGuilds
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -108,15 +108,21 @@ class DynamicModelSerializer(serializers.ModelSerializer):
|
||||
abstract = True
|
||||
|
||||
|
||||
class SubChannelSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for SubChannel Model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = SubChannel
|
||||
fields = ("id", "channel_id", "subscription")
|
||||
|
||||
|
||||
class SubscriptionSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the Subscription Model.
|
||||
"""
|
||||
|
||||
# image = serializers.ImageField(required=False)
|
||||
# server = serializers.CharField()
|
||||
# targets = SubscriptionTargetSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = Subscription
|
||||
fields = ("id", "name", "url", "guild_id", "channels_count", "creation_datetime", "extra_notes", "active")
|
||||
|
@ -4,6 +4,8 @@ from django.urls import path, include
|
||||
from rest_framework.authtoken.views import obtain_auth_token
|
||||
|
||||
from .views import (
|
||||
SubChannel_ListView,
|
||||
SubChannel_DetailView,
|
||||
Subscription_ListView,
|
||||
Subscription_DetailView,
|
||||
SavedGuild_ListView,
|
||||
@ -15,6 +17,11 @@ urlpatterns = [
|
||||
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
|
||||
path("api-token-auth/", obtain_auth_token),
|
||||
|
||||
path("subchannel/", include([
|
||||
path("", SubChannel_ListView.as_view(), name="subchannel"),
|
||||
path("<str:pk>/", SubChannel_DetailView.as_view(), name="subchannel-detail")
|
||||
])),
|
||||
|
||||
path("subscription/", include([
|
||||
path("", Subscription_ListView.as_view(), name="subscription"),
|
||||
path("<str:pk>/", Subscription_DetailView.as_view(), name="subscription-detail")
|
||||
|
@ -11,8 +11,9 @@ from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
|
||||
from rest_framework.parsers import MultiPartParser, FormParser
|
||||
|
||||
from apps.home.models import Subscription, SavedGuilds
|
||||
from apps.home.models import SubChannel, Subscription, SavedGuilds
|
||||
from .serializers import (
|
||||
SubChannelSerializer,
|
||||
SubscriptionSerializer,
|
||||
SavedGuildSerializer
|
||||
)
|
||||
@ -28,6 +29,60 @@ class DefaultPagination(PageNumberPagination):
|
||||
max_page_size = 25
|
||||
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
# SubChannel Views
|
||||
|
||||
class SubChannel_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of SubChannel model instances.
|
||||
Can also be used to create a new instance.
|
||||
|
||||
Supports: GET, POST
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
pagination_class = DefaultPagination
|
||||
serializer_class = SubChannelSerializer
|
||||
queryset = SubChannel.objects.all().order_by("id")
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "channel_id", "subscription_id"]
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
try:
|
||||
self.perform_create(serializer)
|
||||
except IntegrityError as err:
|
||||
return Response(
|
||||
{"detail": str(err)},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
exception=True
|
||||
)
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
|
||||
class SubChannel_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular SubChannel model instances.
|
||||
|
||||
Supports: GET, PUT, PATCH, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = SubChannelSerializer
|
||||
queryset = SubChannel.objects.all().order_by("id")
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
# Subscription Views
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
# Generated by Django 5.0.1 on 2024-04-28 13:37
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0002_alter_savedguilds_options_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='added_by',
|
||||
field=models.ForeignKey(help_text='The user who added created this instance.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='added by'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='guild_id',
|
||||
field=models.CharField(help_text='Discord snowflake ID for the represented guild.', max_length=128, verbose_name='guild id'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='icon',
|
||||
field=models.CharField(help_text="Hash for the represented guild's icon.", max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Name of the represented guild.', max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='owner',
|
||||
field=models.BooleanField(default=False, help_text="Does the 'added by' user own this guild?"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='permissions',
|
||||
field=models.CharField(help_text='Guild permissions for the user who added this instance.', max_length=64),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SubChannel',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('channel_id', models.CharField(help_text='Discord snowflake ID for the represented Channel.', max_length=128, verbose_name='channel id')),
|
||||
('subscription_id', models.ForeignKey(help_text='The ID of the linked Subscription, must be unique.', on_delete=django.db.models.deletion.CASCADE, to='home.subscription', unique=True, verbose_name='subscription id')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.0.1 on 2024-04-28 13:46
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0003_alter_savedguilds_added_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='subchannel',
|
||||
name='subscription_id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subchannel',
|
||||
name='subscription',
|
||||
field=models.ForeignKey(default='1', help_text='The linked Subscription, must be unique.', on_delete=django.db.models.deletion.CASCADE, to='home.subscription', unique=True),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -41,36 +41,47 @@ class IconPathGenerator:
|
||||
|
||||
class SavedGuilds(models.Model):
|
||||
"""
|
||||
|
||||
Represents a saved Discord Guild (aka Server).
|
||||
These are shown in the UI on the sidebar, and can be selected
|
||||
to see associated Subscriptions.
|
||||
"""
|
||||
|
||||
id = models.AutoField(
|
||||
primary_key=True
|
||||
)
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
# Have to use charfield instead of positiveBigIntegerField due to an Sqlite
|
||||
# issue that rounds down the value
|
||||
# https://github.com/sequelize/sequelize/issues/9335
|
||||
guild_id = models.CharField(
|
||||
verbose_name=_("guild id"),
|
||||
max_length=128,
|
||||
help_text=_("Discord snowflake ID for the represented guild.")
|
||||
)
|
||||
|
||||
name = models.CharField(
|
||||
max_length=128
|
||||
max_length=128,
|
||||
help_text=_("Name of the represented guild.")
|
||||
)
|
||||
|
||||
icon = models.CharField(
|
||||
max_length=128
|
||||
max_length=128,
|
||||
help_text=_("Hash for the represented guild's icon.")
|
||||
)
|
||||
|
||||
added_by = models.ForeignKey(to="authentication.DiscordUser", on_delete=models.CASCADE)
|
||||
added_by = models.ForeignKey(
|
||||
verbose_name=_("added by"),
|
||||
to="authentication.DiscordUser",
|
||||
on_delete=models.CASCADE,
|
||||
help_text=_("The user who added created this instance.")
|
||||
)
|
||||
|
||||
permissions = models.CharField(
|
||||
max_length=64
|
||||
max_length=64,
|
||||
help_text=_("Guild permissions for the user who added this instance.")
|
||||
)
|
||||
|
||||
owner = models.BooleanField(
|
||||
default=False
|
||||
default=False,
|
||||
help_text=_("Does the 'added by' user own this guild?")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -81,20 +92,47 @@ class SavedGuilds(models.Model):
|
||||
verbose_name = "saved guild"
|
||||
verbose_name_plural = "saved guilds"
|
||||
get_latest_by = "-creation_datetime"
|
||||
|
||||
constraints = [
|
||||
# Prevent servers from having subscriptions with duplicate names
|
||||
models.UniqueConstraint(fields=["name", "guild_id"], name="unique name & guild_id pair")
|
||||
models.UniqueConstraint(
|
||||
fields=["name", "guild_id"],
|
||||
name="unique name & guild_id pair"
|
||||
)
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Subscription(models.Model):
|
||||
id = models.AutoField(
|
||||
primary_key=True
|
||||
class SubChannel(models.Model):
|
||||
"""
|
||||
Represents a Discord TextChannel, saved against a Subscription.
|
||||
SubChannels are used as targets to send content from Subscriptions.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
# Have to use charfield instead of positiveBigIntegerField due to an Sqlite
|
||||
# issue that rounds down the value
|
||||
# https://github.com/sequelize/sequelize/issues/9335
|
||||
channel_id = models.CharField(
|
||||
verbose_name=_("channel id"),
|
||||
max_length=128,
|
||||
help_text=_("Discord snowflake ID for the represented Channel.")
|
||||
)
|
||||
|
||||
subscription = models.ForeignKey(
|
||||
to="home.Subscription",
|
||||
on_delete=models.CASCADE,
|
||||
unique=True,
|
||||
help_text=_("The linked Subscription, must be unique.")
|
||||
)
|
||||
|
||||
|
||||
class Subscription(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
name = models.CharField(
|
||||
max_length=32,
|
||||
null=False,
|
||||
@ -140,7 +178,7 @@ class Subscription(models.Model):
|
||||
|
||||
@property
|
||||
def channels_count(self):
|
||||
return 0
|
||||
return len(SubChannel.objects.filter(subscription=self))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
Loading…
x
Reference in New Issue
Block a user