replace old models with new
This commit is contained in:
parent
8b803f5df0
commit
86074d2e13
@ -2,7 +2,7 @@
|
||||
|
||||
from rest_framework.permissions import BasePermission
|
||||
|
||||
from apps.home.models import r_Server
|
||||
from apps.home.models import Server
|
||||
from apps.authentication.models import ServerMember
|
||||
|
||||
|
||||
|
@ -5,23 +5,13 @@ import logging
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.home.models import (
|
||||
SubChannel,
|
||||
Filter,
|
||||
Server,
|
||||
ContentFilter,
|
||||
MessageMutator,
|
||||
MessageStyle,
|
||||
Subscription,
|
||||
SavedGuilds,
|
||||
TrackedContent,
|
||||
ArticleMutator,
|
||||
GuildSettings,
|
||||
UniqueContentRule,
|
||||
|
||||
#rewrite
|
||||
r_Server,
|
||||
r_ContentFilter,
|
||||
r_MessageMutator,
|
||||
r_MessageStyle,
|
||||
r_Subscription,
|
||||
r_Content,
|
||||
r_UniqueContentRule
|
||||
Content,
|
||||
UniqueContentRule
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -127,149 +117,15 @@ class DynamicModelSerializer(serializers.ModelSerializer):
|
||||
abstract = True
|
||||
|
||||
|
||||
#region Sub Channel
|
||||
|
||||
class SubChannelSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for SubChannel Model.
|
||||
"""
|
||||
|
||||
class ServerSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = SubChannel
|
||||
fields = ("id", "channel_id", "channel_name", "subscription")
|
||||
|
||||
|
||||
#region Filter
|
||||
|
||||
class FilterSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the Filter Model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Filter
|
||||
fields = ("id", "name", "matching_algorithm", "match", "is_insensitive", "is_whitelist", "guild_id")
|
||||
|
||||
|
||||
#region Article Mutator
|
||||
|
||||
class ArticleMutatorSerializer(DynamicModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ArticleMutator
|
||||
fields = ("id", "name", "value")
|
||||
|
||||
|
||||
#region Unique Content Rule
|
||||
|
||||
class UniqueContentRuleSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the UniqueContentRule model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = UniqueContentRule
|
||||
fields = ("id", "name", "value")
|
||||
|
||||
|
||||
#region Subscription (GET)
|
||||
|
||||
class SubscriptionSerializer_GET(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the Subscription Model.
|
||||
"""
|
||||
|
||||
article_title_mutators = ArticleMutatorSerializer(many=True)
|
||||
article_desc_mutators = ArticleMutatorSerializer(many=True)
|
||||
unique_content_rules = UniqueContentRuleSerializer(many=True)
|
||||
active = serializers.BooleanField(initial=True)
|
||||
|
||||
class Meta:
|
||||
model = Subscription
|
||||
fields = (
|
||||
"id", "name", "url", "guild_id", "channels_count", "creation_datetime", "extra_notes", "filters",
|
||||
"article_title_mutators", "article_desc_mutators", "article_fetch_image", "published_threshold", "embed_colour",
|
||||
"unique_content_rules", "active"
|
||||
)
|
||||
|
||||
|
||||
#region Subscription (POST)
|
||||
|
||||
class SubscriptionSerializer_POST(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the Subscription Model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Subscription
|
||||
fields = (
|
||||
"id", "name", "url", "guild_id", "channels_count", "creation_datetime", "extra_notes", "filters",
|
||||
"article_title_mutators", "article_desc_mutators", "article_fetch_image", "published_threshold", "embed_colour",
|
||||
"unique_content_rules", "active"
|
||||
)
|
||||
|
||||
|
||||
#region Saved Guild
|
||||
|
||||
class SavedGuildSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the SavedGuild model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = SavedGuilds
|
||||
fields = ("id", "guild_id", "name", "icon", "added_by", "permissions", "owner")
|
||||
|
||||
|
||||
#region Guild Setting
|
||||
|
||||
class GuildSettingsSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the GuildSettings model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = GuildSettings
|
||||
fields = ("id", "guild_id", "default_embed_colour", "active")
|
||||
|
||||
|
||||
#region Tracked Content (GET)
|
||||
|
||||
class TrackedContentSerializer_GET(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the TrackedContent model.
|
||||
"""
|
||||
|
||||
subscription = SubscriptionSerializer_GET()
|
||||
|
||||
class Meta:
|
||||
model = TrackedContent
|
||||
fields = ("id", "guid", "title", "url", "subscription", "channel_id", "message_id", "blocked", "creation_datetime")
|
||||
|
||||
|
||||
#region Tracked Content (POST)
|
||||
|
||||
class TrackedContentSerializer_POST(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the TrackedContent model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = TrackedContent
|
||||
fields = ("id", "guid", "title", "url", "subscription", "channel_id", "message_id", "blocked", "creation_datetime")
|
||||
|
||||
|
||||
#region rewrite
|
||||
|
||||
class r_ServerSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_Server
|
||||
model = Server
|
||||
fields = ("id", "name", "icon_hash", "active")
|
||||
|
||||
|
||||
class r_ContentFilterSerializer(DynamicModelSerializer):
|
||||
class ContentFilterSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_ContentFilter
|
||||
model = ContentFilter
|
||||
fields = (
|
||||
"id",
|
||||
"server",
|
||||
@ -281,15 +137,15 @@ class r_ContentFilterSerializer(DynamicModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
class r_MessageMutatorSerializer(DynamicModelSerializer):
|
||||
class MessageMutatorSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_MessageMutator
|
||||
model = MessageMutator
|
||||
fields = ("id", "name", "value")
|
||||
|
||||
|
||||
class r_MessageStyleSerializer(DynamicModelSerializer):
|
||||
class MessageStyleSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_MessageStyle
|
||||
model = MessageStyle
|
||||
fields = (
|
||||
"id",
|
||||
"server",
|
||||
@ -304,14 +160,14 @@ class r_MessageStyleSerializer(DynamicModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
class r_SubscriptionSerializer(DynamicModelSerializer):
|
||||
class SubscriptionSerializer(DynamicModelSerializer):
|
||||
filters = serializers.PrimaryKeyRelatedField(
|
||||
queryset=r_ContentFilter.objects.all(),
|
||||
queryset=ContentFilter.objects.all(),
|
||||
many=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = r_Subscription
|
||||
model = Subscription
|
||||
fields = (
|
||||
"id",
|
||||
"server",
|
||||
@ -332,7 +188,7 @@ class r_SubscriptionSerializer(DynamicModelSerializer):
|
||||
|
||||
# Prevent using filters from a different server
|
||||
selected_filters = data.get("filters", [])
|
||||
valid_filter_ids = r_ContentFilter.objects.filter(server=server).values_list("id", flat=True)
|
||||
valid_filter_ids = ContentFilter.objects.filter(server=server).values_list("id", flat=True)
|
||||
if any(fltr.id not in valid_filter_ids for fltr in selected_filters):
|
||||
raise serializers.ValidationError(
|
||||
{"filters": "All filters must belong to the specified server."}
|
||||
@ -348,9 +204,9 @@ class r_SubscriptionSerializer(DynamicModelSerializer):
|
||||
return data
|
||||
|
||||
|
||||
class r_ContentSerializer(DynamicModelSerializer):
|
||||
class ContentSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_Content
|
||||
model = Content
|
||||
fields = (
|
||||
"id",
|
||||
"subscription",
|
||||
@ -362,7 +218,7 @@ class r_ContentSerializer(DynamicModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
class r_UniqueContentRuleSerializer(DynamicModelSerializer):
|
||||
class UniqueContentRuleSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = r_UniqueContentRule
|
||||
model = UniqueContentRule
|
||||
fields = ("id", "name", "value")
|
||||
|
142
apps/api/urls.py
142
apps/api/urls.py
@ -4,123 +4,61 @@ from django.urls import path, include
|
||||
from rest_framework.authtoken.views import obtain_auth_token
|
||||
|
||||
from .views import (
|
||||
SubChannel_ListView,
|
||||
SubChannel_DetailView,
|
||||
Filter_ListView,
|
||||
Filter_DetailView,
|
||||
Server_ListView,
|
||||
Server_DetailView,
|
||||
ContentFilter_ListView,
|
||||
ContentFilter_DetailView,
|
||||
MessageMutator_ListView,
|
||||
MessageMutator_DetailView,
|
||||
MessageStyle_ListView,
|
||||
MessageStyle_DetailView,
|
||||
Subscription_ListView,
|
||||
Subscription_DetailView,
|
||||
Subscription_SubChannelView,
|
||||
SavedGuild_ListView,
|
||||
SavedGuild_DetailView,
|
||||
TrackedContent_ListView,
|
||||
TrackedContent_DetailView,
|
||||
ArticleMutator_ListView,
|
||||
ArticleMutator_DetailView,
|
||||
GuildSettings_ListView,
|
||||
GuildSettings_DetailView,
|
||||
Content_ListView,
|
||||
Content_DetailView,
|
||||
UniqueContentRule_ListView,
|
||||
UniqueContentRule_DetailView,
|
||||
|
||||
#rewrite
|
||||
r_Server_ListView,
|
||||
r_Server_DetailView,
|
||||
r_ContentFilter_ListView,
|
||||
r_ContentFilter_DetailView,
|
||||
r_MessageMutator_ListView,
|
||||
r_MessageMutator_DetailView,
|
||||
r_MessageStyle_ListView,
|
||||
r_MessageStyle_DetailView,
|
||||
r_Subscription_ListView,
|
||||
r_Subscription_DetailView,
|
||||
r_Content_ListView,
|
||||
r_Content_DetailView,
|
||||
r_UniqueContentRule_ListView,
|
||||
r_UniqueContentRule_DetailView
|
||||
UniqueContentRule_DetailView
|
||||
)
|
||||
|
||||
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("servers/", include([
|
||||
path("", Server_ListView.as_view()),
|
||||
path("<int:pk>/", include([
|
||||
path("", Server_DetailView.as_view()),
|
||||
|
||||
path("filter/", include([
|
||||
path("", Filter_ListView.as_view(), name="filter"),
|
||||
path("<str:pk>/", Filter_DetailView.as_view(), name="filter-detail")
|
||||
])),
|
||||
path("filters/", include([
|
||||
path("", ContentFilter_ListView.as_view()),
|
||||
path("<int:pk>/", ContentFilter_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("subscription/", include([
|
||||
path("", Subscription_ListView.as_view(), name="subscription"),
|
||||
path("<str:pk>/", include([
|
||||
path("", Subscription_DetailView.as_view(), name="subscription-detail"),
|
||||
path("subchannels/", Subscription_SubChannelView.as_view(), name="subscription-channels")
|
||||
path("message-styles/", include([
|
||||
path("", MessageStyle_ListView.as_view()),
|
||||
path("<int:pk>/", MessageStyle_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("subscriptions/", include([
|
||||
path("", Subscription_ListView.as_view()),
|
||||
path("<int:pk>/", include([
|
||||
path("", Subscription_DetailView.as_view()),
|
||||
path("content/", include([
|
||||
path("", Content_ListView.as_view()),
|
||||
path("<int:pk>/", Content_DetailView.as_view())
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
])),
|
||||
|
||||
path("saved-guilds/", include([
|
||||
path("", SavedGuild_ListView.as_view(), name="saved-guilds"),
|
||||
path("<int:pk>/", SavedGuild_DetailView.as_view(), name="saved-guilds-detail")
|
||||
path("message-mutators/", include([
|
||||
path("", MessageMutator_ListView.as_view()),
|
||||
path("<int:pk>/", MessageMutator_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("guild-settings/", include([
|
||||
path("", GuildSettings_ListView.as_view(), name="guild-settings"),
|
||||
path("<int:pk>/", GuildSettings_DetailView.as_view(), name="guild-settings-detail")
|
||||
])),
|
||||
|
||||
path("tracked-content/", include([
|
||||
path("", TrackedContent_ListView.as_view(), name="tracked-content"),
|
||||
path("<path:pk>/", TrackedContent_DetailView.as_view(), name="tracked-content-detail")
|
||||
])),
|
||||
|
||||
path("article-mutator/", include([
|
||||
path("", ArticleMutator_ListView.as_view(), name="article-mutator"),
|
||||
path("<int:pk>/", ArticleMutator_DetailView.as_view(), name="article-mutator-detail")
|
||||
])),
|
||||
|
||||
path("unique-content-rule/", include([
|
||||
path("", UniqueContentRule_ListView.as_view(), name="unique-content-rule"),
|
||||
path("<int:pk>/", UniqueContentRule_DetailView.as_view(), name="unique-content-rule-detail")
|
||||
])),
|
||||
|
||||
|
||||
#region rewrite
|
||||
|
||||
path("r_servers/", include([
|
||||
path("", r_Server_ListView.as_view()),
|
||||
path("<int:pk>/", r_Server_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_content-filters/", include([
|
||||
path("", r_ContentFilter_ListView.as_view()),
|
||||
path("<int:pk>/", r_ContentFilter_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_message-mutators/", include([
|
||||
path("", r_MessageMutator_ListView.as_view()),
|
||||
path("<int:pk>/", r_MessageMutator_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_message-styles/", include([
|
||||
path("", r_MessageStyle_ListView.as_view()),
|
||||
path("<int:pk>/", r_MessageStyle_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_subscriptions/", include([
|
||||
path("", r_Subscription_ListView.as_view()),
|
||||
path("<int:pk>/", r_Subscription_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_content/", include([
|
||||
path("", r_Content_ListView.as_view()),
|
||||
path("<int:pk>/", r_Content_DetailView.as_view())
|
||||
])),
|
||||
|
||||
path("r_unique-content-rules/", include([
|
||||
path("", r_UniqueContentRule_ListView.as_view()),
|
||||
path("<int:pk>/", r_UniqueContentRule_DetailView.as_view())
|
||||
path("unique-content-rules/", include([
|
||||
path("", UniqueContentRule_ListView.as_view()),
|
||||
path("<int:pk>/", UniqueContentRule_DetailView.as_view())
|
||||
]))
|
||||
]
|
||||
|
@ -14,46 +14,24 @@ from rest_framework.authentication import SessionAuthentication, TokenAuthentica
|
||||
from rest_framework.parsers import MultiPartParser, FormParser
|
||||
|
||||
from apps.home.models import (
|
||||
SubChannel,
|
||||
Filter,
|
||||
Server,
|
||||
ContentFilter,
|
||||
MessageMutator,
|
||||
MessageStyle,
|
||||
Subscription,
|
||||
SavedGuilds,
|
||||
TrackedContent,
|
||||
ArticleMutator,
|
||||
GuildSettings,
|
||||
UniqueContentRule,
|
||||
|
||||
#rewrite
|
||||
r_Server,
|
||||
r_ContentFilter,
|
||||
r_MessageMutator,
|
||||
r_MessageStyle,
|
||||
r_Subscription,
|
||||
r_Content,
|
||||
r_UniqueContentRule
|
||||
Content,
|
||||
UniqueContentRule
|
||||
)
|
||||
from apps.authentication.models import DiscordUser, ServerMember
|
||||
from .metadata import ExpandedMetadata
|
||||
from .serializers import (
|
||||
SubChannelSerializer,
|
||||
FilterSerializer,
|
||||
SubscriptionSerializer_GET,
|
||||
SubscriptionSerializer_POST,
|
||||
SavedGuildSerializer,
|
||||
TrackedContentSerializer_GET,
|
||||
TrackedContentSerializer_POST,
|
||||
ArticleMutatorSerializer,
|
||||
GuildSettingsSerializer,
|
||||
UniqueContentRuleSerializer,
|
||||
|
||||
#rewrite
|
||||
r_ServerSerializer,
|
||||
r_ContentFilterSerializer,
|
||||
r_MessageMutatorSerializer,
|
||||
r_MessageStyleSerializer,
|
||||
r_SubscriptionSerializer,
|
||||
r_ContentSerializer,
|
||||
r_UniqueContentRuleSerializer
|
||||
ServerSerializer,
|
||||
ContentFilterSerializer,
|
||||
MessageMutatorSerializer,
|
||||
MessageStyleSerializer,
|
||||
SubscriptionSerializer,
|
||||
ContentSerializer,
|
||||
UniqueContentRuleSerializer
|
||||
)
|
||||
from .permissions import HasServerAccess
|
||||
from .errors import NotAMemberError
|
||||
@ -73,611 +51,6 @@ def is_automated_admin(user):
|
||||
return user.user_type == DiscordUser.USER_TYPES.AUTOMATED_USER and user.is_superuser
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region SubChannels
|
||||
|
||||
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", "channel_name", "subscription"]
|
||||
search_fields = ["channel_name"]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return SubChannel.objects.all()
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return SubChannel.objects.filter(subscription__guild_id__in=guild_ids)
|
||||
|
||||
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")
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return SubChannel.objects.all()
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return SubChannel.objects.filter(subscription__guild_id__in=guild_ids)
|
||||
|
||||
|
||||
#region Unique Content Rule
|
||||
|
||||
class UniqueContentRule_ListView(generics.ListAPIView):
|
||||
"""
|
||||
View to provide a list of UniqueContentRule 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 = UniqueContentRuleSerializer
|
||||
metadata_class = ExpandedMetadata
|
||||
queryset = UniqueContentRule.objects.all().order_by("id")
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "name", "value"]
|
||||
|
||||
|
||||
class UniqueContentRule_DetailView(generics.RetrieveAPIView):
|
||||
"""
|
||||
View to provide details on a particular UniqueContentRule model instances.
|
||||
|
||||
Supports: GET
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = UniqueContentRuleSerializer
|
||||
queryset = UniqueContentRule.objects.all().order_by("id")
|
||||
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region Filter
|
||||
|
||||
class Filter_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of Filter 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 = FilterSerializer
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "name", "matching_algorithm", "match", "is_insensitive", "is_whitelist", "guild_id"]
|
||||
search_fields = ["name", "match"]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return Filter.objects.all().order_by("id")
|
||||
|
||||
saved_guild_ids = SavedGuilds.objects \
|
||||
.filter(added_by=self.request.user.id) \
|
||||
.values("guild_id")
|
||||
|
||||
return Filter.objects \
|
||||
.filter(guild_id__in=Subquery(saved_guild_ids)) \
|
||||
.order_by("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 Filter_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular Filter model instances.
|
||||
|
||||
Supports: GET, PUT, PATCH, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = FilterSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return Filter.objects.all().order_by("id")
|
||||
|
||||
saved_guild_ids = SavedGuilds.objects \
|
||||
.filter(added_by=self.request.user.id) \
|
||||
.values("guild_id")
|
||||
|
||||
return Filter.objects \
|
||||
.filter(guild_id__in=Subquery(saved_guild_ids)) \
|
||||
.order_by("id")
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region Subscription
|
||||
|
||||
class Subscription_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of Subscription 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
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = [
|
||||
"id", "name", "url", "guild_id", "creation_datetime", "extra_notes", "filters", "unique_content_rules",
|
||||
"article_title_mutators", "article_desc_mutators", "embed_colour", "published_threshold", "active"
|
||||
]
|
||||
search_fields = ["name", "url", "extra_notes"]
|
||||
ordering_fields = ["name", "creation_datetime", "active"]
|
||||
|
||||
read_serializer_class = SubscriptionSerializer_GET
|
||||
write_serializer_class = SubscriptionSerializer_POST
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == "POST":
|
||||
return self.write_serializer_class
|
||||
|
||||
return self.read_serializer_class
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return Subscription.objects.all().order_by("-creation_datetime")
|
||||
|
||||
saved_guild_ids = SavedGuilds.objects \
|
||||
.filter(added_by=self.request.user.id) \
|
||||
.values("guild_id")
|
||||
|
||||
return Subscription.objects \
|
||||
.filter(guild_id__in=Subquery(saved_guild_ids)) \
|
||||
.order_by("-creation_datetime")
|
||||
|
||||
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 Subscription_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular Subscription model instances.
|
||||
|
||||
Supports: GET, PUT, PATCH, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = SubscriptionSerializer_POST
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return Subscription.objects.all().order_by("-creation_datetime")
|
||||
|
||||
saved_guild_ids = SavedGuilds.objects \
|
||||
.filter(added_by=self.request.user.id) \
|
||||
.values("guild_id")
|
||||
|
||||
return Subscription.objects \
|
||||
.filter(guild_id__in=Subquery(saved_guild_ids)) \
|
||||
.order_by("-creation_datetime")
|
||||
|
||||
|
||||
class Subscription_SubChannelView(generics.DestroyAPIView):
|
||||
"""
|
||||
View to erase all subscription channels quickly.
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
subscriptions = Subscription.objects.all()
|
||||
else:
|
||||
saved_guild_ids = SavedGuilds.objects \
|
||||
.filter(added_by=self.request.user.id) \
|
||||
.values("guild_id")
|
||||
|
||||
subscriptions = Subscription.objects \
|
||||
.filter(guild_id__in=Subquery(saved_guild_ids))
|
||||
|
||||
if not subscriptions:
|
||||
return Response(
|
||||
{"detail": "You are forbidden from viewing this subscription"},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
subscription = subscriptions.filter(id=kwargs["pk"]).first()
|
||||
|
||||
if not subscription:
|
||||
return Response(
|
||||
{"detail": "not found"},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
|
||||
channels = SubChannel.objects.filter(subscription=subscription)
|
||||
channels.delete();
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
# =================================================================================================
|
||||
#region Saved Guilds
|
||||
|
||||
class SavedGuild_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of SavedGuild model instances.
|
||||
Can also be used to create a new instance.
|
||||
|
||||
Supports: GET, POST
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
pagination_class = None
|
||||
serializer_class = SavedGuildSerializer
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "guild_id", "name", "icon", "added_by", "permissions", "owner"]
|
||||
search_fields = ["name"]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return SavedGuilds.objects.all()
|
||||
|
||||
return SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
|
||||
def post(self, request):
|
||||
|
||||
# TODO:
|
||||
# the data used for admin/owner verification is provided
|
||||
# from the client, this is a potential attack vector, and
|
||||
# should be rewritten.
|
||||
|
||||
is_owner = request.data["owner"].lower() == "true"
|
||||
|
||||
# Check user is admin in server
|
||||
if not (self.is_server_admin(request.data["permissions"]) or is_owner):
|
||||
return Response(
|
||||
{"detail": "You must be a server administrator"},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
exception=False
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
def is_server_admin(self, permissions) -> bool:
|
||||
|
||||
return (int(permissions) & 1 << 3) == 1 << 3
|
||||
|
||||
|
||||
class SavedGuild_DetailView(generics.RetrieveDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular SavedGuild model instances.
|
||||
|
||||
Supports: GET, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = SavedGuildSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return SavedGuilds.objects.all()
|
||||
|
||||
return SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region Guild Settings
|
||||
|
||||
class GuildSettings_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of GuildSettings 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 = GuildSettingsSerializer
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "guild_id", "default_embed_colour", "active"]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return GuildSettings.objects.all()
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return GuildSettings.objects.filter(guild_id__in=guild_ids)
|
||||
|
||||
def post(self, request):
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=request.user)
|
||||
|
||||
if not saved_guilds:
|
||||
return Response(
|
||||
{"detail": "You must have an instance of saved guild with this guild_id"},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
exception=False
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
def is_server_admin(self, permissions) -> bool:
|
||||
|
||||
return (int(permissions) & 1 << 3) == 1 << 3
|
||||
|
||||
|
||||
class GuildSettings_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular GuildSettings model instances.
|
||||
|
||||
Supports: GET, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = GuildSettingsSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return GuildSettings.objects.all()
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return GuildSettings.objects.filter(guild_id__in=guild_ids)
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region Tracked Content
|
||||
|
||||
class TrackedContent_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of TrackedContent 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
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["guid", "title", "url", "subscription", "subscription__guild_id", "channel_id", "blocked", "creation_datetime"]
|
||||
search_fields = ["guid", "title", "url", "subscription__name", "subscription__url"]
|
||||
ordering_fields = ["title", "subscription", "creation_datetime", "blocked"]
|
||||
|
||||
read_serializer_class = TrackedContentSerializer_GET
|
||||
write_serializer_class = TrackedContentSerializer_POST
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == "POST":
|
||||
return self.write_serializer_class
|
||||
|
||||
return self.read_serializer_class
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return TrackedContent.objects.all().order_by("-creation_datetime")
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return TrackedContent.objects.filter(subscription__guild_id__in=guild_ids).order_by("-creation_datetime")
|
||||
|
||||
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 TrackedContent_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular TrackedContent model instances.
|
||||
|
||||
Supports: GET, PUT, PATCH, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = TrackedContentSerializer_POST
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return TrackedContent.objects.all()
|
||||
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return TrackedContent.objects.filter(subscription__guild_id__in=guild_ids)
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
#region Article Mutator
|
||||
|
||||
class ArticleMutator_ListView(generics.ListAPIView):
|
||||
"""
|
||||
View to provide a list of ArticleMutator model instances.
|
||||
Can also be used to create a new instance.
|
||||
|
||||
Supports: GET, POST
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
metadata_class = ExpandedMetadata
|
||||
queryset = ArticleMutator.objects.all().order_by("id")
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "name", "value"]
|
||||
|
||||
serializer_class = ArticleMutatorSerializer
|
||||
|
||||
|
||||
class ArticleMutator_DetailView(generics.RetrieveAPIView):
|
||||
"""
|
||||
View to provide details on a particular ArticleMutator model instances.
|
||||
|
||||
Supports: GET
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = ArticleMutatorSerializer
|
||||
queryset = ArticleMutator.objects.all().order_by("id")
|
||||
|
||||
|
||||
#region rewrite
|
||||
|
||||
|
||||
class ListView(generics.ListAPIView):
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
@ -712,120 +85,122 @@ class DeletableDetailView(generics.RetrieveDestroyAPIView):
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
|
||||
class r_Server_ListView(ListView):
|
||||
class Server_ListView(ListView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_ServerSerializer
|
||||
serializer_class = ServerSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Server.objects.all()
|
||||
servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
|
||||
return Server.objects.filter(id__in=servers)
|
||||
|
||||
|
||||
class r_Server_DetailView(DetailView):
|
||||
serializer_class = r_ServerSerializer
|
||||
class Server_DetailView(DetailView):
|
||||
serializer_class = ServerSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Server.objects.all()
|
||||
servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
|
||||
return Server.objects.filter(id__in=servers)
|
||||
|
||||
|
||||
class r_ContentFilter_ListView(ListCreateView):
|
||||
class ContentFilter_ListView(ListCreateView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_ContentFilterSerializer
|
||||
serializer_class = ContentFilterSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_ContentFilter.objects.all()
|
||||
return ContentFilter.objects.all()
|
||||
|
||||
|
||||
class r_ContentFilter_DetailView(ChangableDetailView):
|
||||
serializer_class = r_ContentFilterSerializer
|
||||
class ContentFilter_DetailView(ChangableDetailView):
|
||||
serializer_class = ContentFilterSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_ContentFilter.objects.all()
|
||||
return ContentFilter.objects.all()
|
||||
|
||||
|
||||
class r_MessageMutator_ListView(ListView): # instances of this one are pre-defined ONLY
|
||||
class MessageMutator_ListView(ListView): # instances of this one are pre-defined ONLY
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_MessageMutatorSerializer
|
||||
serializer_class = MessageMutatorSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_MessageMutator.objects.all()
|
||||
return MessageMutator.objects.all()
|
||||
|
||||
|
||||
class r_MessageMutator_DetailView(DetailView):
|
||||
serializer_class = r_MessageMutatorSerializer
|
||||
class MessageMutator_DetailView(DetailView):
|
||||
serializer_class = MessageMutatorSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_MessageMutator.objects.all()
|
||||
return MessageMutator.objects.all()
|
||||
|
||||
|
||||
class r_MessageStyle_ListView(ListCreateView):
|
||||
class MessageStyle_ListView(ListCreateView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_MessageStyleSerializer
|
||||
serializer_class = MessageStyleSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_MessageStyle.objects.all()
|
||||
return MessageStyle.objects.all()
|
||||
|
||||
|
||||
class r_MessageStyle_DetailView(ChangableDetailView):
|
||||
serializer_class = r_MessageStyleSerializer
|
||||
class MessageStyle_DetailView(ChangableDetailView):
|
||||
serializer_class = MessageStyleSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_MessageStyle.objects.all()
|
||||
return MessageStyle.objects.all()
|
||||
|
||||
|
||||
class r_Subscription_ListView(ListCreateView):
|
||||
class Subscription_ListView(ListCreateView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_SubscriptionSerializer
|
||||
serializer_class = SubscriptionSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Subscription.objects.all()
|
||||
return Subscription.objects.all()
|
||||
|
||||
|
||||
class r_Subscription_DetailView(ChangableDetailView):
|
||||
serializer_class = r_SubscriptionSerializer
|
||||
class Subscription_DetailView(ChangableDetailView):
|
||||
serializer_class = SubscriptionSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Subscription.objects.all()
|
||||
return Subscription.objects.all()
|
||||
|
||||
|
||||
class r_Content_ListView(ListCreateView):
|
||||
class Content_ListView(ListCreateView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_ContentSerializer
|
||||
serializer_class = ContentSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Content.objects.all()
|
||||
return Content.objects.all()
|
||||
|
||||
|
||||
class r_Content_DetailView(ChangableDetailView):
|
||||
serializer_class = r_ContentSerializer
|
||||
class Content_DetailView(ChangableDetailView):
|
||||
serializer_class = ContentSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_Content.objects.all()
|
||||
return Content.objects.all()
|
||||
|
||||
|
||||
class r_UniqueContentRule_ListView(ListCreateView):
|
||||
class UniqueContentRule_ListView(ListCreateView):
|
||||
filterset_fields = []
|
||||
search_fields = []
|
||||
ordering_fields = []
|
||||
serializer_class = r_UniqueContentRuleSerializer
|
||||
serializer_class = UniqueContentRuleSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_UniqueContentRule.objects.all()
|
||||
return UniqueContentRule.objects.all()
|
||||
|
||||
|
||||
class r_UniqueContentRule_DetailView(ChangableDetailView):
|
||||
serializer_class = r_UniqueContentRuleSerializer
|
||||
class UniqueContentRule_DetailView(ChangableDetailView):
|
||||
serializer_class = UniqueContentRuleSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return r_UniqueContentRule.objects.all()
|
||||
return UniqueContentRule.objects.all()
|
||||
|
@ -1,6 +1,8 @@
|
||||
# Generated by Django 5.0.4 on 2024-05-03 13:14
|
||||
# Generated by Django 5.0.4 on 2024-09-24 14:05
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@ -10,6 +12,7 @@ class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('home', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@ -26,6 +29,8 @@ class Migration(migrations.Migration):
|
||||
('mfa_enabled', models.BooleanField(help_text='whether the user has two factor enabled on their account', verbose_name='mfa enabled')),
|
||||
('last_login', models.DateTimeField(default=django.utils.timezone.now, help_text='datetime of the previous login', verbose_name='last login')),
|
||||
('access_token', models.CharField(help_text='token for the application to make api calls on behalf of the user.', max_length=100, verbose_name='access token')),
|
||||
('token_expires', models.DateTimeField(help_text='when to request a new access token.', verbose_name='token expires')),
|
||||
('refresh_token', models.CharField(help_text='token for the application to request a new access token.', max_length=100, verbose_name='refresh token')),
|
||||
('user_type', models.CharField(choices=[('D', 'discord'), ('A', 'automated')], default='D', help_text='What type of user is this?', max_length=32, verbose_name='user type')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Use as a "soft delete" rather than deleting the user.', verbose_name='active status')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
@ -37,4 +42,14 @@ class Migration(migrations.Migration):
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ServerMember',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('permissions', models.CharField(max_length=32)),
|
||||
('is_owner', models.BooleanField(default=False)),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.server')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
@ -1,20 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-05-31 22:41
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='discorduser',
|
||||
name='token_expires',
|
||||
field=models.DateTimeField(default=timezone.now, help_text='when to request a new access token.', verbose_name='token expires'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-01 16:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0002_discorduser_token_expires'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='discorduser',
|
||||
name='refresh_token',
|
||||
field=models.CharField(default='1', help_text='token for the application to request a new access token.', max_length=100, verbose_name='refresh token'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,26 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-19 20:20
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0003_discorduser_refresh_token'),
|
||||
('home', '0026_temp_testonly_migration'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ServerMember',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('nick', models.CharField(max_length=32)),
|
||||
('permissions', models.CharField(max_length=32)),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_server')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-23 20:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0004_servermember'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='servermember',
|
||||
name='nick',
|
||||
field=models.CharField(blank=True, max_length=32, null=True),
|
||||
),
|
||||
]
|
@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-23 20:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0005_alter_servermember_nick'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='servermember',
|
||||
name='nick',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='servermember',
|
||||
name='is_owner',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -168,7 +168,7 @@ class ServerMember(models.Model):
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
user = models.ForeignKey(to=DiscordUser, on_delete=models.CASCADE)
|
||||
server = models.ForeignKey(to="home.r_Server", on_delete=models.CASCADE)
|
||||
server = models.ForeignKey(to="home.Server", on_delete=models.CASCADE)
|
||||
permissions = models.CharField(max_length=32)
|
||||
is_owner = models.BooleanField(default=False)
|
||||
|
||||
|
@ -3,83 +3,23 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import (
|
||||
Server,
|
||||
ContentFilter,
|
||||
MessageMutator,
|
||||
MessageStyle,
|
||||
Subscription,
|
||||
SavedGuilds,
|
||||
Filter,
|
||||
SubChannel,
|
||||
TrackedContent,
|
||||
ArticleMutator,
|
||||
GuildSettings,
|
||||
|
||||
# temp rewrite
|
||||
r_Server,
|
||||
r_ContentFilter,
|
||||
r_MessageMutator,
|
||||
r_MessageStyle,
|
||||
r_Subscription,
|
||||
r_Content,
|
||||
r_UniqueContentRule
|
||||
Content,
|
||||
UniqueContentRule
|
||||
)
|
||||
|
||||
|
||||
@admin.register(Subscription)
|
||||
class SubscriptionAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "name", "url", "guild_id",
|
||||
"creation_datetime", "active"
|
||||
]
|
||||
|
||||
@admin.register(SubChannel)
|
||||
class SubChannelAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "channel_id", "subscription"
|
||||
]
|
||||
|
||||
|
||||
@admin.register(Filter)
|
||||
class FilterAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "name", "guild_id"
|
||||
]
|
||||
|
||||
|
||||
@admin.register(TrackedContent)
|
||||
class TrackedContentAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"guid", "title", "url", "subscription", "blocked", "creation_datetime"
|
||||
]
|
||||
|
||||
|
||||
@admin.register(SavedGuilds)
|
||||
class SavedGuildAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "name", "icon"
|
||||
]
|
||||
|
||||
|
||||
@admin.register(ArticleMutator)
|
||||
class ArticleMutatorAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "name", "value"
|
||||
]
|
||||
|
||||
@admin.register(GuildSettings)
|
||||
class GuildSettingsAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "guild_id", "default_embed_colour", "active"
|
||||
]
|
||||
|
||||
|
||||
#region rewrite
|
||||
|
||||
|
||||
@admin.register(r_Server)
|
||||
class r_ServerAdmin(admin.ModelAdmin):
|
||||
@admin.register(Server)
|
||||
class ServerAdmin(admin.ModelAdmin):
|
||||
list_display = ["id", "name", "icon_hash", "active"]
|
||||
|
||||
|
||||
@admin.register(r_ContentFilter)
|
||||
class r_ContentFilterAdmin(admin.ModelAdmin):
|
||||
@admin.register(ContentFilter)
|
||||
class ContentFilterAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"server",
|
||||
@ -91,8 +31,8 @@ class r_ContentFilterAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
@admin.register(r_MessageMutator)
|
||||
class r_MessageMutatorAdmin(admin.ModelAdmin):
|
||||
@admin.register(MessageMutator)
|
||||
class MessageMutatorAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"name",
|
||||
@ -100,8 +40,8 @@ class r_MessageMutatorAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
@admin.register(r_MessageStyle)
|
||||
class r_MessageStyleAdmin(admin.ModelAdmin):
|
||||
@admin.register(MessageStyle)
|
||||
class MessageStyleAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"server",
|
||||
@ -116,8 +56,8 @@ class r_MessageStyleAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
@admin.register(r_Subscription)
|
||||
class r_Subscription(admin.ModelAdmin):
|
||||
@admin.register(Subscription)
|
||||
class Subscription(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"server",
|
||||
@ -131,8 +71,8 @@ class r_Subscription(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
@admin.register(r_Content)
|
||||
class r_ContentAdmin(admin.ModelAdmin):
|
||||
@admin.register(Content)
|
||||
class ContentAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"subscription",
|
||||
@ -144,8 +84,8 @@ class r_ContentAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
@admin.register(r_UniqueContentRule)
|
||||
class r_UniqueContentRule(admin.ModelAdmin):
|
||||
@admin.register(UniqueContentRule)
|
||||
class UniqueContentRule(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"name",
|
||||
|
@ -1,8 +1,7 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-17 01:11
|
||||
# Generated by Django 5.0.4 on 2024-09-24 14:05
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@ -11,53 +10,70 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Filter',
|
||||
name='MessageMutator',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Server',
|
||||
fields=[
|
||||
('id', models.PositiveIntegerField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('icon_hash', models.CharField(blank=True, max_length=128, null=True)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UniqueContentRule',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MessageStyle',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('is_embed', models.BooleanField(default=True)),
|
||||
('is_hyperlinked', models.BooleanField()),
|
||||
('show_author', models.BooleanField()),
|
||||
('show_timestamp', models.BooleanField()),
|
||||
('show_images', models.BooleanField()),
|
||||
('fetch_images', models.BooleanField()),
|
||||
('description_mutator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='desc_mutated_messagestyle', to='home.messagemutator')),
|
||||
('title_mutator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='title_mutated_messagestyle', to='home.messagemutator')),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.server')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ContentFilter',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=32)),
|
||||
('keywords', models.CharField(blank=True, max_length=128, null=True)),
|
||||
('regex', models.CharField(blank=True, max_length=128, null=True)),
|
||||
('whitelist', models.BooleanField(default=False)),
|
||||
('guild_id', models.CharField(max_length=128)),
|
||||
('match', models.CharField(max_length=256)),
|
||||
('matching_algorithm', models.PositiveIntegerField(choices=[(0, 'None'), (1, 'Any: Item contains any of these words (space separated)'), (2, 'All: Item contains all of these words (space separated)'), (3, 'Exact: Item contains this string'), (4, 'Regular expression: Item matches this regex'), (5, 'Fuzzy: Item contains a word similar to this word')])),
|
||||
('is_insensitive', models.BooleanField()),
|
||||
('is_whitelist', models.BooleanField()),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.server')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'filter',
|
||||
'verbose_name_plural': 'filters',
|
||||
'get_latest_by': 'id',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SavedGuilds',
|
||||
name='BotLogicLogs',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('guild_id', models.CharField(help_text='Discord snowflake ID for the represented guild.', max_length=128, verbose_name='guild id')),
|
||||
('name', models.CharField(help_text='Name of the represented guild.', max_length=128)),
|
||||
('icon', models.CharField(help_text="Hash for the represented guild's icon.", max_length=128)),
|
||||
('permissions', models.CharField(help_text='Guild permissions for the user who added this instance.', max_length=64)),
|
||||
('owner', models.BooleanField(default=False, help_text="Does the 'added by' user own this guild?")),
|
||||
('level', models.CharField(max_length=32)),
|
||||
('message', models.CharField(max_length=256)),
|
||||
('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.server')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'saved guild',
|
||||
'verbose_name_plural': 'saved guilds',
|
||||
'get_latest_by': '-creation_datetime',
|
||||
},
|
||||
),
|
||||
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')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SubChannel',
|
||||
'verbose_name_plural': 'SubChannels',
|
||||
'get_latest_by': 'id',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Subscription',
|
||||
@ -65,76 +81,26 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=32)),
|
||||
('url', models.URLField()),
|
||||
('guild_id', models.CharField(max_length=128)),
|
||||
('creation_datetime', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('extra_notes', models.CharField(blank=True, max_length=250, null=True)),
|
||||
('uwuify', models.BooleanField(default=False)),
|
||||
('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('updated_at', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('extra_notes', models.CharField(blank=True, default='', max_length=250)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
('filters', models.ManyToManyField(blank=True, to='home.contentfilter')),
|
||||
('message_style', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='home.messagestyle')),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.server')),
|
||||
('unique_rules', models.ManyToManyField(to='home.uniquecontentrule')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'subscription',
|
||||
'verbose_name_plural': 'subscriptions',
|
||||
'get_latest_by': '-creation_datetime',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TrackedContent',
|
||||
name='Content',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('guid', models.CharField(max_length=128)),
|
||||
('title', models.CharField(max_length=128)),
|
||||
('url', models.URLField(unique=True)),
|
||||
('blocked', models.BooleanField(default=False)),
|
||||
('creation_datetime', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('guild_id', models.CharField(max_length=128)),
|
||||
('item_id', models.CharField(max_length=1024)),
|
||||
('item_guid', models.CharField(max_length=1024)),
|
||||
('item_url', models.CharField(max_length=1024)),
|
||||
('item_title', models.CharField(max_length=1024)),
|
||||
('item_content_hash', models.CharField(max_length=1024)),
|
||||
('subscription', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.subscription')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'tracked contents',
|
||||
'get_latest_by': '-creation_datetime',
|
||||
},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='filter',
|
||||
constraint=models.UniqueConstraint(fields=('name', 'guild_id'), name='unique name & guild id pair'),
|
||||
),
|
||||
migrations.AddField(
|
||||
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.AddField(
|
||||
model_name='subscription',
|
||||
name='filters',
|
||||
field=models.ManyToManyField(blank=True, to='home.filter'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subchannel',
|
||||
name='subscription',
|
||||
field=models.ForeignKey(help_text='The linked Subscription, must be unique.', on_delete=django.db.models.deletion.CASCADE, to='home.subscription'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='trackedcontent',
|
||||
name='subscription',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.subscription'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='savedguilds',
|
||||
constraint=models.UniqueConstraint(fields=('added_by', 'guild_id'), name='unique added_by & guild_id pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='subscription',
|
||||
constraint=models.UniqueConstraint(fields=('name', 'guild_id'), name='unique name & server pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='subchannel',
|
||||
constraint=models.UniqueConstraint(fields=('channel_id', 'subscription'), name='unique channel id and subscription pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('guid', 'guild_id'), name='unique guid & guild_id pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('url', 'guild_id'), name='unique url & guild_id pair'),
|
||||
),
|
||||
]
|
||||
|
@ -1,21 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-17 01:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ArticleMutator',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
]
|
47
apps/home/migrations/0002_predefined_data.py
Normal file
47
apps/home/migrations/0002_predefined_data.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-24 14:06
|
||||
# This migration was manually configured to create predefined data by corbz
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def add_mutators(apps, schema_editor):
|
||||
model = apps.get_model("home", "MessageMutator")
|
||||
model.objects.create(name="Uwuify", value="uwuify")
|
||||
model.objects.create(name="Uwuify (NSFW)", value="uwuify_nsfw")
|
||||
model.objects.create(name="Gothic Script", value="gothic")
|
||||
model.objects.create(name="Emoji Substitute", value="emj_substitute")
|
||||
model.objects.create(name="Zalgo", value="zalgo")
|
||||
model.objects.create(name="Morse Code", value="morse_code")
|
||||
model.objects.create(name="Binary", value="to_bin")
|
||||
model.objects.create(name="Hexadecimal", value="to_hex")
|
||||
model.objects.create(name="Remove Vowels", value="rm_vowels")
|
||||
model.objects.create(name="Double Characters", value="dbl_chars")
|
||||
model.objects.create(name="Small Case", value="small_caps")
|
||||
model.objects.create(name="L33t Sp34k", value="leet_speak")
|
||||
model.objects.create(name="Pig Latin", value="pig_latin")
|
||||
model.objects.create(name="Upside Down", value="flipped")
|
||||
model.objects.create(name="All Reversed", value="reverse_text")
|
||||
model.objects.create(name="Reversed Words", value="backwards_words")
|
||||
model.objects.create(name="Shuffle Words", value="shuffle_words")
|
||||
model.objects.create(name="Random Case", value="rnd_case")
|
||||
model.objects.create(name="Gibberish", value="gibberish")
|
||||
model.objects.create(name="Shakespearean", value="shakespear")
|
||||
|
||||
def add_rules(apps, schema_editor):
|
||||
model = apps.get_model("home", "UniqueContentRule")
|
||||
model.objects.create(name="GUID", value="GUID")
|
||||
model.objects.create(name="ID", value="ID")
|
||||
model.objects.create(name="URL", value="URL")
|
||||
model.objects.create(name="Title", value="TITLE")
|
||||
model.objects.create(name="Content Hash", value="CONTENT")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_mutators),
|
||||
migrations.RunPython(add_rules)
|
||||
]
|
@ -1,37 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-17 01:23
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def add_mutators(apps, schema_editor):
|
||||
ArticleMutator = apps.get_model("home", "ArticleMutator")
|
||||
ArticleMutator.objects.create(name="Uwuify", value="uwuify")
|
||||
ArticleMutator.objects.create(name="Uwuify (NSFW)", value="uwuify_nsfw")
|
||||
ArticleMutator.objects.create(name="Gothic Script", value="gothic")
|
||||
ArticleMutator.objects.create(name="Emoji Substitute", value="emj_substitute")
|
||||
ArticleMutator.objects.create(name="Zalgo", value="zalgo")
|
||||
ArticleMutator.objects.create(name="Morse Code", value="morse_code")
|
||||
ArticleMutator.objects.create(name="Binary", value="to_bin")
|
||||
ArticleMutator.objects.create(name="Hexadecimal", value="to_hex")
|
||||
ArticleMutator.objects.create(name="Remove Vowels", value="rm_vowels")
|
||||
ArticleMutator.objects.create(name="Double Characters", value="dbl_chars")
|
||||
ArticleMutator.objects.create(name="Small Case", value="small_caps")
|
||||
ArticleMutator.objects.create(name="L33t Sp34k", value="leet_speak")
|
||||
ArticleMutator.objects.create(name="Pig Latin", value="pig_latin")
|
||||
ArticleMutator.objects.create(name="Upside Down", value="flipped")
|
||||
ArticleMutator.objects.create(name="All Reversed", value="reverse_text")
|
||||
ArticleMutator.objects.create(name="Reversed Words", value="backwards_words")
|
||||
ArticleMutator.objects.create(name="Shuffle Words", value="shuffle_words")
|
||||
ArticleMutator.objects.create(name="Random Case", value="rnd_case")
|
||||
ArticleMutator.objects.create(name="Gibberish", value="gibberish")
|
||||
ArticleMutator.objects.create(name="Shakespearean", value="shakespear")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0002_articlemutator'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_mutators)
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-17 01:31
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0003_initial_mutator_data'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='subscription',
|
||||
name='uwuify',
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-17 01:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0004_remove_subscription_uwuify'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='mutators',
|
||||
field=models.ManyToManyField(blank=True, to='home.articlemutator'),
|
||||
),
|
||||
]
|
@ -1,23 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-18 11:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0005_subscription_mutators'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='guid',
|
||||
field=models.CharField(max_length=256),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='title',
|
||||
field=models.CharField(max_length=728),
|
||||
),
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-25 08:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0006_alter_trackedcontent_guid_alter_trackedcontent_title'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='subscription',
|
||||
name='mutators',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='article_desc_mutators',
|
||||
field=models.ManyToManyField(blank=True, related_name='desc_mutated_subscriptions', to='home.articlemutator'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='article_title_mutators',
|
||||
field=models.ManyToManyField(blank=True, related_name='title_mutated_subscriptions', to='home.articlemutator'),
|
||||
),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-25 09:41
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0007_remove_subscription_mutators_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='article_fetch_limit',
|
||||
field=models.PositiveSmallIntegerField(default=10, validators=[django.core.validators.MaxValueValidator(1), django.core.validators.MinValueValidator(10)]),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='reset_article_fetch_limit',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-26 13:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0008_subscription_article_fetch_limit_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='embed_colour',
|
||||
field=models.CharField(default='3498db', max_length=6),
|
||||
),
|
||||
]
|
@ -1,23 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-02 11:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0009_subscription_embed_colour'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='embed_colour',
|
||||
field=models.CharField(blank=True, default='3498db', max_length=6),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='url',
|
||||
field=models.URLField(),
|
||||
),
|
||||
]
|
@ -1,34 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-02 12:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0010_alter_subscription_embed_colour_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name='trackedcontent',
|
||||
name='unique guid & guild_id pair',
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name='trackedcontent',
|
||||
name='unique url & guild_id pair',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='trackedcontent',
|
||||
old_name='guild_id',
|
||||
new_name='channel_id',
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('guid', 'channel_id'), name='unique guid & guild_id pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('url', 'channel_id'), name='unique url & guild_id pair'),
|
||||
),
|
||||
]
|
@ -1,34 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-05 13:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0011_remove_trackedcontent_unique_guid_guild_id_pair_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name='trackedcontent',
|
||||
name='unique guid & guild_id pair',
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name='trackedcontent',
|
||||
name='unique url & guild_id pair',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='article_fetch_image',
|
||||
field=models.BooleanField(default=True, help_text='Will the resulting article have an image?'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('guid', 'channel_id'), name='unique guid & channel_id pair'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='trackedcontent',
|
||||
constraint=models.UniqueConstraint(fields=('url', 'channel_id'), name='unique url & channel_id pair'),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-10 09:08
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0012_remove_trackedcontent_unique_guid_guild_id_pair_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='published_theshold',
|
||||
field=models.DateField(blank=True, default=django.utils.timezone.now),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-10 09:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0013_subscription_published_theshold'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='subscription',
|
||||
old_name='published_theshold',
|
||||
new_name='published_threshold',
|
||||
),
|
||||
]
|
@ -1,67 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-10 13:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0014_rename_published_theshold_subscription_published_threshold'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='filter',
|
||||
options={'ordering': ('name',)},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='filter',
|
||||
name='keywords',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='filter',
|
||||
name='regex',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='filter',
|
||||
name='whitelist',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='subscription',
|
||||
name='article_fetch_limit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='subscription',
|
||||
name='reset_article_fetch_limit',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='filter',
|
||||
name='is_insensitive',
|
||||
field=models.BooleanField(default=True, verbose_name='is insensitive'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='filter',
|
||||
name='is_whitelist',
|
||||
field=models.BooleanField(default=False, verbose_name='is whitelist'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='filter',
|
||||
name='match',
|
||||
field=models.CharField(blank=True, max_length=256, verbose_name='match'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='filter',
|
||||
name='matching_algorithm',
|
||||
field=models.PositiveIntegerField(choices=[(0, 'None'), (1, 'Any word'), (2, 'All words'), (3, 'Exact match'), (4, 'Regular expression'), (5, 'Fuzzy word'), (6, 'Automatic')], default=1, verbose_name='matching algorithm'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='filter',
|
||||
name='guild_id',
|
||||
field=models.CharField(max_length=128, verbose_name='guild id'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='filter',
|
||||
name='name',
|
||||
field=models.CharField(max_length=128, verbose_name='name'),
|
||||
),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-10 19:19
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0015_alter_filter_options_remove_filter_keywords_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='filter',
|
||||
name='matching_algorithm',
|
||||
field=models.PositiveIntegerField(choices=[(0, 'None'), (1, 'Any: Item contains any of these words (space separated)'), (2, 'All: Item contains all of these words (space separated)'), (3, 'Exact: Item contains this string'), (4, 'Regular expression: Item matches this regex'), (5, 'Fuzzy: Item contains a word similar to this word')], default=1, verbose_name='matching algorithm'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='published_threshold',
|
||||
field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-11 21:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0016_alter_filter_matching_algorithm_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='trackedcontent',
|
||||
name='message_id',
|
||||
field=models.CharField(max_length=128),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-20 18:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0017_trackedcontent_message_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subchannel',
|
||||
name='channel_name',
|
||||
field=models.CharField(default='placeholder-channel-name', help_text='Name of the represented Channel.', max_length=256, verbose_name='channel name'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-23 14:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0018_subchannel_channel_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='savedguilds',
|
||||
name='default_embed_colour',
|
||||
field=models.CharField(blank=True, default='3498db', max_length=6),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-07-23 15:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0019_savedguilds_default_embed_colour'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='GuildSettings',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('guild_id', models.CharField(help_text='Discord snowflake ID for the represented guild.', max_length=128, verbose_name='guild id')),
|
||||
('default_embed_colour', models.CharField(blank=True, default='3498db', max_length=6, verbose_name='default embed colour')),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,122 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-08-14 20:41
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0020_guildsettings'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='guildsettings',
|
||||
options={'get_latest_by': 'id', 'verbose_name': 'guild settings', 'verbose_name_plural': 'guild settings'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='savedguilds',
|
||||
name='default_embed_colour',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='guildsettings',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, help_text='Subscriptions of inactive guilds will also be treated as inactive', verbose_name='Active'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='guildsettings',
|
||||
name='guild_id',
|
||||
field=models.CharField(help_text='Discord snowflake ID for the represented guild.', max_length=128, unique=True, verbose_name='guild id'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='id',
|
||||
field=models.AutoField(primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, verbose_name='Active'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='article_fetch_image',
|
||||
field=models.BooleanField(default=True, help_text='Will the resulting article have an image?', verbose_name='Fetch Article Images'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='creation_datetime',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Created At'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='embed_colour',
|
||||
field=models.CharField(blank=True, default='3498db', max_length=6, verbose_name='Embed Colour'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='extra_notes',
|
||||
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='Extra Notes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='guild_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Guild ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='name',
|
||||
field=models.CharField(max_length=32, verbose_name='Name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='published_threshold',
|
||||
field=models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name='Published Threshold'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='url',
|
||||
field=models.URLField(verbose_name='URL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='blocked',
|
||||
field=models.BooleanField(default=False, verbose_name='Blocked'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='channel_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Channel ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='creation_datetime',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Created At'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='guid',
|
||||
field=models.CharField(help_text='RSS provided GUID of the content', max_length=256, verbose_name='GUID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='id',
|
||||
field=models.AutoField(primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='message_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Message ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='title',
|
||||
field=models.CharField(max_length=728, verbose_name='Title'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='url',
|
||||
field=models.URLField(verbose_name='URL'),
|
||||
),
|
||||
]
|
@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-08-14 20:46
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def create_missing_guild_settings(apps, scheme_editor):
|
||||
SavedGuilds = apps.get_model("home", "SavedGuilds")
|
||||
GuildSettings = apps.get_model("home", "GuildSettings")
|
||||
|
||||
for saved_guild in SavedGuilds.objects.all():
|
||||
GuildSettings.objects.get_or_create(guild_id=saved_guild.guild_id)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0021_alter_guildsettings_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_missing_guild_settings),
|
||||
]
|
@ -1,26 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-13 23:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0022_populate_guild_settings'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UniqueContentRule',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subscription',
|
||||
name='unique_content_rules',
|
||||
field=models.ManyToManyField(to='home.uniquecontentrule'),
|
||||
),
|
||||
]
|
@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-13 23:32
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def add_rules(apps, schema_editor):
|
||||
Rules = apps.get_model("home", "UniqueContentRule")
|
||||
Rules.objects.create(name="GUID", value="GUID")
|
||||
Rules.objects.create(name="ID", value="ID")
|
||||
Rules.objects.create(name="URL", value="URL")
|
||||
Rules.objects.create(name="Title", value="TITLE")
|
||||
Rules.objects.create(name="Content Hash", value="CONTENT")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0023_uniquecontentrule_subscription_unique_content_rules'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_rules)
|
||||
]
|
@ -1,25 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-15 13:40
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def set_rules_to_ruleless_subs(apps, scheme_editor):
|
||||
Subs = apps.get_model("home", "Subscription")
|
||||
Rules = apps.get_model("home", "UniqueContentRule")
|
||||
no_rule_subs = Subs.objects.filter(unique_content_rules=None)
|
||||
|
||||
guid_rule = Rules.objects.get(value="GUID")
|
||||
id_rule = Rules.objects.get(value="ID")
|
||||
|
||||
for sub in no_rule_subs:
|
||||
sub.unique_content_rules.set([guid_rule.pk, id_rule.pk])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0024_initial_uniquecontentrule_data'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(set_rules_to_ruleless_subs)
|
||||
]
|
@ -1,104 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-18 20:26
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0025_set_uniquerules'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='r_MessageMutator',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_Server',
|
||||
fields=[
|
||||
('id', models.PositiveIntegerField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('icon_hash', models.CharField(max_length=128)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_UniqueContentRule',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=64)),
|
||||
('value', models.CharField(max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_MessageStyle',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('is_embed', models.BooleanField(default=True)),
|
||||
('is_hyperlinked', models.BooleanField()),
|
||||
('show_author', models.BooleanField()),
|
||||
('show_timestamp', models.BooleanField()),
|
||||
('show_images', models.BooleanField()),
|
||||
('fetch_images', models.BooleanField()),
|
||||
('description_mutator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='desc_mutated_messagestyle', to='home.r_messagemutator')),
|
||||
('title_mutator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='title_mutated_messagestyle', to='home.r_messagemutator')),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_server')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_ContentFilter',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=32)),
|
||||
('match', models.CharField(max_length=256)),
|
||||
('matching_algorithm', models.PositiveIntegerField(choices=[(0, 'None'), (1, 'Any: Item contains any of these words (space separated)'), (2, 'All: Item contains all of these words (space separated)'), (3, 'Exact: Item contains this string'), (4, 'Regular expression: Item matches this regex'), (5, 'Fuzzy: Item contains a word similar to this word')])),
|
||||
('is_insensitive', models.BooleanField()),
|
||||
('is_whitelist', models.BooleanField()),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_server')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BotLogicLogs',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('level', models.CharField(max_length=32)),
|
||||
('message', models.CharField(max_length=256)),
|
||||
('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_server')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_Subscription',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=32)),
|
||||
('url', models.URLField()),
|
||||
('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('updated_at', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('extra_notes', models.CharField(blank=True, default='', max_length=250)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
('filters', models.ManyToManyField(blank=True, to='home.r_contentfilter')),
|
||||
('message_style', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='home.r_messagestyle')),
|
||||
('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_server')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='r_Content',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('item_id', models.CharField(max_length=1024)),
|
||||
('item_guid', models.CharField(max_length=1024)),
|
||||
('item_url', models.CharField(max_length=1024)),
|
||||
('item_title', models.CharField(max_length=1024)),
|
||||
('item_content_hash', models.CharField(max_length=1024)),
|
||||
('subscription', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.r_subscription')),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.0.4 on 2024-09-23 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0026_temp_testonly_migration'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='r_server',
|
||||
name='icon_hash',
|
||||
field=models.CharField(blank=True, max_length=128, null=True),
|
||||
),
|
||||
]
|
@ -9,421 +9,25 @@ from django.core.exceptions import ValidationError
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#region Guild Settings
|
||||
# region Server
|
||||
|
||||
class GuildSettings(models.Model):
|
||||
class Server(models.Model):
|
||||
"""
|
||||
Represents settings for a saved Discord Guild `SavedGuild`.
|
||||
These objects aren't linked through foreignkey because
|
||||
`SavedGuild` is user user unique, not Discord Guild unique.
|
||||
Represents a Discord Server.
|
||||
Instances of this model are automatically handled, and manual intervension
|
||||
should be avoided if possible.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
guild_id = models.CharField(
|
||||
verbose_name=_("guild id"),
|
||||
max_length=128,
|
||||
help_text=_("Discord snowflake ID for the represented guild."),
|
||||
unique=True
|
||||
)
|
||||
|
||||
default_embed_colour = models.CharField(
|
||||
verbose_name=_("default embed colour"),
|
||||
max_length=6,
|
||||
default="3498db",
|
||||
blank=True
|
||||
)
|
||||
|
||||
active = models.BooleanField(
|
||||
verbose_name=_("Active"),
|
||||
default=True,
|
||||
help_text=_("Subscriptions of inactive guilds will also be treated as inactive")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the GuildSettings model.
|
||||
"""
|
||||
|
||||
verbose_name = "guild settings"
|
||||
verbose_name_plural = "guild settings"
|
||||
get_latest_by = "id"
|
||||
|
||||
|
||||
#region Saved Guilds
|
||||
|
||||
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(_("ID"), 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,
|
||||
help_text=_("Name of the represented guild.")
|
||||
)
|
||||
|
||||
icon = models.CharField(
|
||||
max_length=128,
|
||||
help_text=_("Hash for the represented guild's icon.")
|
||||
)
|
||||
|
||||
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,
|
||||
help_text=_("Guild permissions for the user who added this instance.")
|
||||
)
|
||||
|
||||
owner = models.BooleanField(
|
||||
default=False,
|
||||
help_text=_("Does the 'added by' user own this guild?")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the SavedGuilds 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=["added_by", "guild_id"],
|
||||
name="unique added_by & guild_id pair"
|
||||
)
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
return GuildSettings.objects.get(guild_id=self.guild_id)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
GuildSettings.objects.get_or_create(guild_id=self.guild_id)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
#region Sub Channels
|
||||
|
||||
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.")
|
||||
)
|
||||
|
||||
channel_name = models.CharField(
|
||||
verbose_name=_("channel name"),
|
||||
max_length=256,
|
||||
help_text=_("Name of the represented Channel.")
|
||||
)
|
||||
|
||||
subscription = models.ForeignKey(
|
||||
to="home.Subscription",
|
||||
on_delete=models.CASCADE,
|
||||
help_text=_("The linked Subscription, must be unique.")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the SubChannel Model.
|
||||
"""
|
||||
|
||||
verbose_name = "SubChannel"
|
||||
verbose_name_plural = "SubChannels"
|
||||
get_latest_by = "id"
|
||||
constraints = [
|
||||
# Prevent servers from having subscriptions with duplicate names
|
||||
models.UniqueConstraint(
|
||||
fields=["channel_id", "subscription"],
|
||||
name="unique channel id and subscription pair")
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.channel_id
|
||||
|
||||
|
||||
#region Filters
|
||||
|
||||
# using a brilliant matching model design from paperless-ngx src
|
||||
class Filter(models.Model):
|
||||
MATCH_NONE = 0
|
||||
MATCH_ANY = 1
|
||||
MATCH_ALL = 2
|
||||
MATCH_LITERAL = 3
|
||||
MATCH_REGEX = 4
|
||||
MATCH_FUZZY = 5
|
||||
MATCH_AUTO = 6
|
||||
|
||||
MATCHING_ALGORITHMS = (
|
||||
(MATCH_NONE, _("None")),
|
||||
(MATCH_ANY, _("Any: Item contains any of these words (space separated)")),
|
||||
(MATCH_ALL, _("All: Item contains all of these words (space separated)")),
|
||||
(MATCH_LITERAL, _("Exact: Item contains this string")),
|
||||
(MATCH_REGEX, _("Regular expression: Item matches this regex")),
|
||||
(MATCH_FUZZY, _("Fuzzy: Item contains a word similar to this word")),
|
||||
# (MATCH_AUTO, _("Automatic")),
|
||||
)
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
name = models.CharField(_("name"), max_length=128)
|
||||
|
||||
match = models.CharField(_("match"), max_length=256, blank=True)
|
||||
|
||||
matching_algorithm = models.PositiveIntegerField(
|
||||
_("matching algorithm"),
|
||||
choices=MATCHING_ALGORITHMS,
|
||||
default=MATCH_ANY,
|
||||
)
|
||||
|
||||
is_insensitive = models.BooleanField(_("is insensitive"), default=True)
|
||||
|
||||
is_whitelist = models.BooleanField(_("is whitelist"), default=False)
|
||||
|
||||
# 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(_("guild id"), max_length=128)
|
||||
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["name", "guild_id"],
|
||||
name="unique name & guild id pair"
|
||||
)
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild_id} - {self.name}"
|
||||
|
||||
|
||||
#region Subscription
|
||||
|
||||
class Subscription(models.Model):
|
||||
"""
|
||||
The Subscription Model.
|
||||
'Subscription' in the context of PYRSS is an RSS Feed with various settings.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
name = models.CharField(
|
||||
_("Name"),
|
||||
max_length=32,
|
||||
null=False,
|
||||
blank=False
|
||||
)
|
||||
|
||||
url = models.URLField(_("URL"))
|
||||
|
||||
# NOTE:
|
||||
# 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(
|
||||
_("Guild ID"),
|
||||
max_length=128
|
||||
)
|
||||
|
||||
creation_datetime = models.DateTimeField(
|
||||
_("Created At"),
|
||||
default=timezone.now,
|
||||
editable=False
|
||||
)
|
||||
|
||||
extra_notes = models.CharField(
|
||||
_("Extra Notes"),
|
||||
max_length=250,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
filters = models.ManyToManyField(to="home.Filter", blank=True)
|
||||
|
||||
unique_content_rules = models.ManyToManyField(
|
||||
to="home.UniqueContentRule",
|
||||
blank=False
|
||||
);
|
||||
|
||||
article_title_mutators = models.ManyToManyField(
|
||||
to="home.ArticleMutator",
|
||||
related_name="title_mutated_subscriptions",
|
||||
blank=True,
|
||||
)
|
||||
|
||||
article_desc_mutators = models.ManyToManyField(
|
||||
to="home.ArticleMutator",
|
||||
related_name="desc_mutated_subscriptions",
|
||||
blank=True,
|
||||
)
|
||||
|
||||
embed_colour = models.CharField(
|
||||
_("Embed Colour"),
|
||||
max_length=6,
|
||||
default="3498db",
|
||||
blank=True
|
||||
)
|
||||
|
||||
published_threshold = models.DateTimeField(_("Published Threshold"), default=timezone.now, blank=True)
|
||||
|
||||
article_fetch_image = models.BooleanField(
|
||||
_("Fetch Article Images"),
|
||||
default=True,
|
||||
help_text="Will the resulting article have an image?"
|
||||
)
|
||||
|
||||
active = models.BooleanField(_("Active"), default=True)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the Subscription Model.
|
||||
"""
|
||||
|
||||
verbose_name = "subscription"
|
||||
verbose_name_plural = "subscriptions"
|
||||
get_latest_by = "-creation_datetime"
|
||||
constraints = [
|
||||
# Prevent servers from having subscriptions with duplicate names
|
||||
models.UniqueConstraint(fields=["name", "guild_id"], name="unique name & server pair")
|
||||
]
|
||||
|
||||
@property
|
||||
def channels_count(self) -> int:
|
||||
"""
|
||||
Returns the number of 'SubChannel' objects assocaited
|
||||
with this subscription.
|
||||
"""
|
||||
|
||||
return len(SubChannel.objects.filter(subscription=self))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
new_text = "New " if self._state.adding else ""
|
||||
log.debug("%sSubscription Saved %s", new_text, self.id)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
#region Tracked Content
|
||||
|
||||
class TrackedContent(models.Model):
|
||||
"""
|
||||
Tracked Content Model
|
||||
'Tracked Content' identifies articles and tracks them being sent.
|
||||
This is used to ensure duplicate articles aren't sent in feeds.
|
||||
"""
|
||||
|
||||
id = models.AutoField(_("ID"), primary_key=True)
|
||||
|
||||
guid = models.CharField(
|
||||
_("GUID"),
|
||||
max_length=256,
|
||||
help_text=_("RSS provided GUID of the content")
|
||||
)
|
||||
|
||||
title = models.CharField(_("Title"), max_length=728)
|
||||
|
||||
url = models.URLField(_("URL"))
|
||||
|
||||
subscription = models.ForeignKey(to=Subscription, on_delete=models.CASCADE)
|
||||
|
||||
channel_id = models.CharField(_("Channel ID"), max_length=128)
|
||||
|
||||
message_id = models.CharField(_("Message ID"), max_length=128)
|
||||
|
||||
blocked = models.BooleanField(_("Blocked"), default=False)
|
||||
|
||||
creation_datetime = models.DateTimeField(
|
||||
_("Created At"),
|
||||
default=timezone.now,
|
||||
editable=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
||||
verbose_name = "tracked content"
|
||||
verbose_name = "tracked contents"
|
||||
get_latest_by = "-creation_datetime"
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=["guid", "channel_id"], name="unique guid & channel_id pair"),
|
||||
models.UniqueConstraint(fields=["url", "channel_id"], name="unique url & channel_id pair")
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.title
|
||||
|
||||
|
||||
#region Article Mutator
|
||||
|
||||
class ArticleMutator(models.Model):
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=64)
|
||||
value = models.CharField(max_length=32)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
#region UniqueContentRules
|
||||
|
||||
class UniqueContentRule(models.Model):
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=64)
|
||||
value = models.CharField(max_length=32)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
|
||||
|
||||
#region Rewrite - - - - - - - -
|
||||
|
||||
|
||||
class r_Server(models.Model):
|
||||
id = models.PositiveIntegerField(primary_key=True)
|
||||
name = models.CharField(max_length=128)
|
||||
icon_hash = models.CharField(max_length=128, blank=True, null=True)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "server"
|
||||
verbose_name_plural = "servers"
|
||||
get_latest_by = "name"
|
||||
|
||||
@property
|
||||
def icon_url(self):
|
||||
return f"https://cdn.discordapp.com/icons/{self.id}/{self.icon_hash}.webp?size=80"
|
||||
@ -432,9 +36,16 @@ class r_Server(models.Model):
|
||||
return self.name
|
||||
|
||||
|
||||
class r_ContentFilter(models.Model):
|
||||
# region Content Filter
|
||||
|
||||
class ContentFilter(models.Model):
|
||||
"""
|
||||
Filters for the content produced by Subscriptions.
|
||||
Owned by the related server.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
server = models.ForeignKey(to=r_Server, on_delete=models.CASCADE)
|
||||
server = models.ForeignKey(to=Server, on_delete=models.CASCADE)
|
||||
|
||||
MATCH_NONE = 0
|
||||
MATCH_ANY = 1
|
||||
@ -459,23 +70,47 @@ class r_ContentFilter(models.Model):
|
||||
is_insensitive = models.BooleanField()
|
||||
is_whitelist = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "filter"
|
||||
verbose_name_plural = "filters"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
# Instances of this model are predefined only
|
||||
class r_MessageMutator(models.Model):
|
||||
# region Message Mutator
|
||||
|
||||
class MessageMutator(models.Model):
|
||||
"""
|
||||
Mutators to be applied via the Bot.
|
||||
Instances of this model are predefined via migrations.
|
||||
Manual editing should be avoided at all costs!
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=64)
|
||||
value = models.CharField(max_length=32)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "message mutator"
|
||||
verbose_name_plural = "message mutators"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class r_MessageStyle(models.Model):
|
||||
# region Message Style
|
||||
|
||||
class MessageStyle(models.Model):
|
||||
"""
|
||||
Custom styles to be applied via the Bot.
|
||||
Owned by the related server.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
server = models.ForeignKey(to=r_Server, on_delete=models.CASCADE)
|
||||
server = models.ForeignKey(to=Server, on_delete=models.CASCADE)
|
||||
|
||||
is_embed = models.BooleanField(default=True)
|
||||
is_hyperlinked = models.BooleanField() # title only
|
||||
@ -485,27 +120,61 @@ class r_MessageStyle(models.Model):
|
||||
fetch_images = models.BooleanField() # if not included with RSS item
|
||||
|
||||
title_mutator = models.ForeignKey(
|
||||
to=r_MessageMutator,
|
||||
to=MessageMutator,
|
||||
related_name="title_mutated_messagestyle",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True
|
||||
)
|
||||
description_mutator = models.ForeignKey(
|
||||
to=r_MessageMutator,
|
||||
to=MessageMutator,
|
||||
related_name="desc_mutated_messagestyle",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "message style"
|
||||
verbose_name_plural = "message styles"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.server.name} - {self.id}"
|
||||
|
||||
|
||||
class r_Subscription(models.Model):
|
||||
# region Unique Content Rule
|
||||
|
||||
class UniqueContentRule(models.Model):
|
||||
"""
|
||||
Definitions for what content should be unique
|
||||
Instances of this model are predefined via migrations.
|
||||
Manual editing should be avoided at all costs!
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
server = models.ForeignKey(to=r_Server, on_delete=models.CASCADE, blank=False)
|
||||
name = models.CharField(max_length=64)
|
||||
value = models.CharField(max_length=32)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "unique content rule"
|
||||
verbose_name_plural = "unique content rules"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
# region Subscription
|
||||
|
||||
class Subscription(models.Model):
|
||||
"""
|
||||
These represent RSSFeeds, storing relevant settings for managing them.
|
||||
Owned by the related server.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
server = models.ForeignKey(to=Server, on_delete=models.CASCADE, blank=False)
|
||||
|
||||
name = models.CharField(max_length=32, blank=False)
|
||||
url = models.URLField()
|
||||
@ -514,16 +183,28 @@ class r_Subscription(models.Model):
|
||||
extra_notes = models.CharField(max_length=250, default="", blank=True)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
filters = models.ManyToManyField(to=r_ContentFilter, blank=True)
|
||||
message_style = models.ForeignKey(to=r_MessageStyle, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
filters = models.ManyToManyField(to=ContentFilter, blank=True)
|
||||
message_style = models.ForeignKey(to=MessageStyle, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
unique_rules = models.ManyToManyField(to=UniqueContentRule, blank=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "subscription"
|
||||
verbose_name_plural = "subscriptions"
|
||||
get_latest_by = "updated_at"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class r_Content(models.Model):
|
||||
# region Content
|
||||
|
||||
class Content(models.Model):
|
||||
"""
|
||||
Represents a processed item created from a Subscription.
|
||||
"""
|
||||
|
||||
id = models.AutoField(primary_key=True)
|
||||
subscription = models.ForeignKey(to=r_Subscription, on_delete=models.CASCADE)
|
||||
subscription = models.ForeignKey(to=Subscription, on_delete=models.CASCADE)
|
||||
|
||||
# 'item_' prefix is to differentiate between the internal identifiers and the stored data
|
||||
item_id = models.CharField(max_length=1024)
|
||||
@ -532,28 +213,30 @@ class r_Content(models.Model):
|
||||
item_title = models.CharField(max_length=1024)
|
||||
item_content_hash = models.CharField(max_length=1024)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "content"
|
||||
verbose_name_plural = "content"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.subscription.name} - {self.id}"
|
||||
|
||||
|
||||
# Instances of this model are predefined only
|
||||
class r_UniqueContentRule(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=64)
|
||||
value = models.CharField(max_length=32)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
# region Bot Logic Logs
|
||||
|
||||
# Relevant logs from the bot logic
|
||||
class BotLogicLogs(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
server = models.ForeignKey(to=r_Server, on_delete=models.CASCADE)
|
||||
server = models.ForeignKey(to=Server, on_delete=models.CASCADE)
|
||||
|
||||
level = models.CharField(max_length=32)
|
||||
message = models.CharField(max_length=256)
|
||||
created_at = models.DateTimeField(default=timezone.now, editable=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "bot logic log"
|
||||
verbose_name_plural = "bot logic logs"
|
||||
get_latest_by = "id"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.server.name} - {self.id}"
|
||||
|
@ -9,7 +9,7 @@ from django.shortcuts import redirect
|
||||
from django.http import JsonResponse, HttpResponse
|
||||
from django.views.generic import TemplateView, View
|
||||
|
||||
from apps.home.models import r_Server
|
||||
from apps.home.models import Server
|
||||
from apps.authentication.models import DiscordUser, ServerMember
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ class GuildsView(View):
|
||||
await self.delete_member(user, data["id"])
|
||||
return
|
||||
|
||||
server = await r_Server.objects.aget_or_create(
|
||||
server = await Server.objects.aget_or_create(
|
||||
id=data["id"],
|
||||
name=data["name"],
|
||||
icon_hash=data["icon"]
|
||||
|
@ -32,30 +32,6 @@ function makeQuerystring(filters, sort) {
|
||||
return sort ? querystring += `ordering=${sort}` : querystring;
|
||||
}
|
||||
|
||||
// Saved Guilds
|
||||
|
||||
async function getSavedGuilds(userId) {
|
||||
return await ajaxRequest(`/api/saved-guilds/?added_by=${userId}`, "GET");
|
||||
}
|
||||
|
||||
async function getSavedGuild(id) {
|
||||
return await ajaxRequest(`/api/saved-guilds/${id}/`, "GET");
|
||||
}
|
||||
|
||||
async function newSavedGuild(formData) {
|
||||
return await ajaxRequest("/api/saved-guilds/", "POST", formData);
|
||||
}
|
||||
|
||||
async function deleteSavedGuild(id) {
|
||||
return await ajaxRequest(`/api/saved-guilds/${id}/`, "DELETE");
|
||||
}
|
||||
|
||||
// Loading Guilds
|
||||
|
||||
async function loadGuilds() {
|
||||
return await ajaxRequest("/guilds/", "GET");
|
||||
}
|
||||
|
||||
// Loading Channels
|
||||
async function loadChannels(guildId) {
|
||||
return await ajaxRequest(`/channels?guild=${guildId}`, "GET");
|
||||
@ -63,30 +39,30 @@ async function loadChannels(guildId) {
|
||||
|
||||
// Subscriptions
|
||||
|
||||
async function getSubscriptions(filters, sort) {
|
||||
let querystring = makeQuerystring(filters, sort);
|
||||
return await ajaxRequest(`/api/subscription/${querystring}`, "GET");
|
||||
}
|
||||
// async function getSubscriptions(filters, sort) {
|
||||
// let querystring = makeQuerystring(filters, sort);
|
||||
// return await ajaxRequest(`/api/subscription/${querystring}`, "GET");
|
||||
// }
|
||||
|
||||
async function getSubscription(id) {
|
||||
return await ajaxRequest(`/api/subscription/${id}/`, "GET");
|
||||
}
|
||||
// async function getSubscription(id) {
|
||||
// return await ajaxRequest(`/api/subscription/${id}/`, "GET");
|
||||
// }
|
||||
|
||||
async function newSubscription(formData) {
|
||||
return await ajaxRequest("/api/subscription/", "POST", formData);
|
||||
}
|
||||
// async function newSubscription(formData) {
|
||||
// return await ajaxRequest("/api/subscription/", "POST", formData);
|
||||
// }
|
||||
|
||||
async function deleteSubscription(id) {
|
||||
return await ajaxRequest(`/api/subscription/${id}/`, "DELETE");
|
||||
}
|
||||
// async function deleteSubscription(id) {
|
||||
// return await ajaxRequest(`/api/subscription/${id}/`, "DELETE");
|
||||
// }
|
||||
|
||||
async function editSubscription(id, formData) {
|
||||
return await ajaxRequest(`/api/subscription/${id}/`, "PUT", formData);
|
||||
}
|
||||
// async function editSubscription(id, formData) {
|
||||
// return await ajaxRequest(`/api/subscription/${id}/`, "PUT", formData);
|
||||
// }
|
||||
|
||||
async function getSubscriptionOptions() {
|
||||
return await ajaxRequest("/api/subscription/", "OPTIONS")
|
||||
}
|
||||
// async function getSubscriptionOptions() {
|
||||
// return await ajaxRequest("/api/subscription/", "OPTIONS")
|
||||
// }
|
||||
|
||||
|
||||
// SubChannels
|
||||
@ -186,10 +162,47 @@ async function getUniqueContentRule(ruleId) {
|
||||
|
||||
//#region rewrite
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// #region Servers
|
||||
|
||||
async function generateServers() {
|
||||
return ajaxRequest("/generate-servers/", "GET");
|
||||
}
|
||||
|
||||
async function getServers() {
|
||||
return ajaxRequest("/api/r_servers/", "GET");
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Subscriptions
|
||||
|
||||
async function getSubscriptions(filters, sort) {
|
||||
let querystring = makeQuerystring(filters, sort);
|
||||
return await ajaxRequest(`/api/r_subscriptions/${querystring}`, "GET");
|
||||
}
|
||||
|
||||
async function getSubscription(id) {
|
||||
return await ajaxRequest(`/api/r_subscriptions/${id}/`, "GET");
|
||||
}
|
||||
|
||||
async function newSubscription(formData) {
|
||||
return await ajaxRequest("/api/r_subscriptions/", "POST", formData);
|
||||
}
|
||||
|
||||
async function deleteSubscription(id) {
|
||||
return await ajaxRequest(`/api/r_subscriptions/${id}/`, "DELETE");
|
||||
}
|
||||
|
||||
async function editSubscription(id, formData) {
|
||||
return await ajaxRequest(`/api/r_subscriptions/${id}/`, "PUT", formData);
|
||||
}
|
||||
|
||||
async function getSubscriptionOptions() {
|
||||
return await ajaxRequest("/api/r_subscriptions/", "OPTIONS")
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
@ -1,11 +1,11 @@
|
||||
$(document).ready(async function() {
|
||||
await loadServers();
|
||||
|
||||
await initSubscriptionTable();
|
||||
await initFiltersTable();
|
||||
await initContentTable();
|
||||
|
||||
$("#subscriptionsTab").click();
|
||||
|
||||
await loadServers();
|
||||
});
|
||||
|
||||
$(document).on("selectedServerChange", function() {
|
||||
|
@ -97,7 +97,6 @@ function selectServer(id) {
|
||||
selectServer = null;
|
||||
return;
|
||||
}
|
||||
debugger
|
||||
|
||||
// Change appearance of selected vs none-selected items
|
||||
$("#serverList .server-item").removeClass("active");
|
||||
|
Loading…
x
Reference in New Issue
Block a user