From db72590b8dc485a5766fad18425dd4346749720c Mon Sep 17 00:00:00 2001 From: Ekaropolus Date: Tue, 20 May 2025 14:57:17 -0600 Subject: [PATCH] Models for comments and shares counts on meta pages --- pxy_meta_pages/admin.py | 22 +++++++- .../0003_eventtype_facebookevent.py | 34 +++++++++++++ pxy_meta_pages/models.py | 50 +++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 pxy_meta_pages/migrations/0003_eventtype_facebookevent.py diff --git a/pxy_meta_pages/admin.py b/pxy_meta_pages/admin.py index 4869359..12eb54d 100644 --- a/pxy_meta_pages/admin.py +++ b/pxy_meta_pages/admin.py @@ -9,11 +9,24 @@ class FacebookPageAssistantAdmin(admin.ModelAdmin): """ Admin panel configuration for managing Facebook Page Assistants. """ - list_display = ("page_name", "page_id", "assistant", "is_subscribed", "created_at") + list_display = ( + "page_name", "page_id", "assistant", + "is_subscribed", "created_at", + "comment_count", "share_count" + ) + search_fields = ("page_name", "page_id", "assistant__name") list_filter = ("is_subscribed", "assistant") actions = ["subscribe_to_webhook", "check_subscription_status"] + def comment_count(self, obj): + return obj.events.filter(event_type__code="comment").count() + comment_count.short_description = "Comments" + + def share_count(self, obj): + return obj.events.filter(event_type__code="share").count() + share_count.short_description = "Shares" + def subscribe_to_webhook(self, request, queryset): """ Subscribes selected pages to Facebook webhooks using FacebookService. @@ -74,3 +87,10 @@ class FacebookPageAssistantAdmin(admin.ModelAdmin): self.message_user(request, f"Failed to check subscription for {page.page_name}: {e}", level="error") check_subscription_status.short_description = "Check webhook subscription status" + +from .models import EventType + +@admin.register(EventType) +class EventTypeAdmin(admin.ModelAdmin): + list_display = ("code", "label") + search_fields = ("code", "label") diff --git a/pxy_meta_pages/migrations/0003_eventtype_facebookevent.py b/pxy_meta_pages/migrations/0003_eventtype_facebookevent.py new file mode 100644 index 0000000..c49a579 --- /dev/null +++ b/pxy_meta_pages/migrations/0003_eventtype_facebookevent.py @@ -0,0 +1,34 @@ +# Generated by Django 5.0.3 on 2025-05-20 20:29 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pxy_meta_pages', '0002_facebookpageassistant_is_subscribed'), + ] + + operations = [ + migrations.CreateModel( + name='EventType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(help_text="Machine-readable code for the event type (e.g. 'comment', 'share')", max_length=50, unique=True)), + ('label', models.CharField(help_text='Human-readable label for the event type', max_length=100)), + ], + ), + migrations.CreateModel( + name='FacebookEvent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('sender_id', models.CharField(blank=True, help_text='ID of the user who triggered the event', max_length=100, null=True)), + ('object_id', models.CharField(help_text='Identifier of the comment or share object', max_length=100)), + ('message', models.TextField(blank=True, help_text='Text content (for comments) or message attached to the event', null=True)), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('event_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='facebook_events', to='pxy_meta_pages.eventtype')), + ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events', to='pxy_meta_pages.facebookpageassistant')), + ], + ), + ] diff --git a/pxy_meta_pages/models.py b/pxy_meta_pages/models.py index dd353d2..860419d 100644 --- a/pxy_meta_pages/models.py +++ b/pxy_meta_pages/models.py @@ -15,3 +15,53 @@ class FacebookPageAssistant(models.Model): def __str__(self): return f"{self.page_name} ({self.page_id}) -> {self.assistant.name}" +class EventType(models.Model): + """ + Catalog of possible event types for FacebookPageAssistant. + """ + code = models.CharField( + max_length=50, + unique=True, + help_text="Machine-readable code for the event type (e.g. 'comment', 'share')" + ) + label = models.CharField( + max_length=100, + help_text="Human-readable label for the event type" + ) + + def __str__(self): + return self.label + + +class FacebookEvent(models.Model): + """ + Log of individual events (comments, shares, etc.) for a Facebook page. + """ + page = models.ForeignKey( + FacebookPageAssistant, + on_delete=models.CASCADE, + related_name="events" + ) + event_type = models.ForeignKey( + EventType, + on_delete=models.PROTECT, + related_name="facebook_events" + ) + sender_id = models.CharField( + max_length=100, + blank=True, null=True, + help_text="ID of the user who triggered the event" + ) + object_id = models.CharField( + max_length=100, + help_text="Identifier of the comment or share object" + ) + message = models.TextField( + blank=True, null=True, + help_text="Text content (for comments) or message attached to the event" + ) + timestamp = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.page.page_name}: {self.event_type.code} @ {self.timestamp:%Y-%m-%d %H:%M}" + \ No newline at end of file