Allow subscribe to orgs

This commit is contained in:
Joakim Hellsén 2025-08-02 05:45:20 +02:00
commit 4af2b02a01
10 changed files with 190 additions and 14 deletions

View file

@ -0,0 +1,34 @@
# Generated by Django 5.2.4 on 2025-08-02 03:39
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('twitch', '0002_notificationsubscription'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterUniqueTogether(
name='notificationsubscription',
unique_together={('user', 'game')},
),
migrations.AddField(
model_name='notificationsubscription',
name='organization',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='twitch.organization'),
),
migrations.AlterField(
model_name='notificationsubscription',
name='game',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='twitch.game'),
),
migrations.AlterUniqueTogether(
name='notificationsubscription',
unique_together={('user', 'game'), ('user', 'organization')},
),
]

View file

@ -203,12 +203,17 @@ class NotificationSubscription(models.Model):
"""Users can subscribe to games to get notified."""
user = models.ForeignKey(User, on_delete=models.CASCADE)
game = models.ForeignKey(Game, on_delete=models.CASCADE)
game = models.ForeignKey(Game, null=True, blank=True, on_delete=models.CASCADE)
organization = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE)
notify_found = models.BooleanField(default=False)
notify_live = models.BooleanField(default=False)
class Meta:
unique_together = ("user", "game")
unique_together: ClassVar[list[tuple[str, str]]] = [
("user", "game"),
("user", "organization"),
]
def __str__(self) -> str:
return f"{self.user} subscription to {Game.display_name}"

View file

@ -12,5 +12,8 @@ urlpatterns = [
path("campaigns/<str:pk>/", views.DropCampaignDetailView.as_view(), name="campaign_detail"),
path("games/", views.GameListView.as_view(), name="game_list"),
path("games/<str:pk>/", views.GameDetailView.as_view(), name="game_detail"),
path("games/<str:game_id>/subscribe/", views.subscribe_notifications, name="subscribe_notifications"),
path("games/<str:game_id>/subscribe/", views.subscribe_game_notifications, name="subscribe_notifications"),
path("organizations/", views.OrgListView.as_view(), name="org_list"),
path("organizations/<str:pk>/", views.OrgDetailView.as_view(), name="org_detail"),
path("organizations/<str:org_id>/subscribe/", views.subscribe_org_notifications, name="subscribe_org_notifications"),
]

View file

@ -8,6 +8,7 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Count, Prefetch, Q
from django.db.models.query import QuerySet
from django.http.response import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.generic import DetailView, ListView
@ -24,6 +25,37 @@ if TYPE_CHECKING:
logger: logging.Logger = logging.getLogger(__name__)
class OrgListView(ListView):
"""List view for organization."""
model = Organization
template_name = "twitch/org_list.html"
context_object_name = "orgs"
class OrgDetailView(DetailView):
"""Detail view for organization."""
model = Organization
template_name = "twitch/organization_detail.html"
context_object_name = "organization"
def get_context_data(self, **kwargs) -> dict[str, Any]:
"""Add additional context data.
Args:
**kwargs: Additional arguments.
Returns:
dict: Context data.
"""
organization: Organization = self.object
context = super().get_context_data(**kwargs)
games = Game.objects.filter(drop_campaigns__owner=organization).distinct()
context["games"] = games
return context
class DropCampaignListView(ListView):
"""List view for drop campaigns."""
@ -318,8 +350,8 @@ def dashboard(request: HttpRequest) -> HttpResponse:
@login_required
def subscribe_notifications(request: HttpRequest, game_id: str) -> HttpResponseRedirect:
"""Update notification for a user.
def subscribe_game_notifications(request: HttpRequest, game_id: str) -> HttpResponseRedirect:
"""Update Game notification for a user.
Args:
request: The HTTP request.
@ -338,22 +370,67 @@ def subscribe_notifications(request: HttpRequest, game_id: str) -> HttpResponseR
changes = []
if not created:
if subscription.notify_found != notify_found:
changes.append(f"Notify when drop is found: {'enabled' if notify_found else 'disabled'}")
changes.append(f"{'Enabled' if notify_found else 'Disabled'} notification when drop is found")
if subscription.notify_live != notify_live:
changes.append(f"Notify when drop is farmable: {'enabled' if notify_live else 'disabled'}")
changes.append(f"{'Enabled' if notify_live else 'Disabled'} notification when drop is farmable")
subscription.notify_found = notify_found
subscription.notify_live = notify_live
subscription.save()
if created:
message = "You have subscribed to notifications for this game."
message = f"You have subscribed to notifications for {game.display_name}"
elif changes:
message = "Updated notification preferences: " + ", ".join(changes)
message = "\n".join(changes)
else:
message = "No changes were made to your notification preferences."
message = ""
messages.success(request, message)
return redirect("twitch:game_detail", pk=game.id)
messages.warning(request, "Only POST is available for this view.")
return redirect("twitch:game_detail", pk=game.id)
@login_required
def subscribe_org_notifications(request: HttpRequest, org_id: str) -> HttpResponseRedirect:
"""Update Organization notification for a user.
Args:
request: The HTTP request.
org_id: The org we are updating.
Returns:
Redirect back to the twitch:organization_detail.
"""
organization: Organization = get_object_or_404(Organization, pk=org_id)
if request.method == "POST":
notify_found = bool(request.POST.get("notify_found"))
notify_live = bool(request.POST.get("notify_live"))
subscription, created = NotificationSubscription.objects.get_or_create(user=request.user, organization=organization)
changes = []
if not created:
if subscription.notify_found != notify_found:
changes.append(f"{'Enabled' if notify_found else 'Disabled'} notification when drop is found")
if subscription.notify_live != notify_live:
changes.append(f"{'Enabled' if notify_live else 'Disabled'} notification when drop is farmable")
subscription.notify_found = notify_found
subscription.notify_live = notify_live
subscription.save()
if created:
message = f"You have subscribed to notifications for this {organization.name}"
elif changes:
message = "\n".join(changes)
else:
message = ""
messages.success(request, message)
return redirect("organization_detail", org_id=organization.id)
messages.warning(request, "Only POST is available for this view.")
return redirect("organization_detail", org_id=organization.id)