π Overview
generate_statistics_task generates a daily report for each user and sends it via Telegram.
The report includes separate categories:
- blocked domains by Google Safe Browsing
- blocked domains by DNS
- replaced domains by rotation
- unblocked domains
- manually switched domains
β± Schedule (Celery Beat)
Configured in config/settings.py:
generate_statistics_taskβ daily at08:30
π Task Definition
@celery.task
def generate_statistics_task():
yesterday = (timezone.now() - timezone.timedelta(days=1)).date()
for user in UserModel.objects.all():
TelegramSender.send_daily_statistics_message(
report_date=yesterday.strftime("%Y-%m-%d"),
domain_blocked_by_google=list(
Link.objects.filter(
owner=user,
blocked_at__date=yesterday,
reason__in=BlockReasons.google_safe_browsing(),
).exclude(status=LinkStatuses.ACTIVE)
.values_list("domain", flat=True)
.distinct()
),
domain_blocked_by_dns=list(
Link.objects.filter(
owner=user,
blocked_at__date=yesterday,
reason=BlockReasons.DNS_NOT_RESOLVABLE,
).exclude(status=LinkStatuses.ACTIVE)
.values_list("domain", flat=True)
.distinct()
),
domain_blocked_by_rotation=list(
Link.objects.filter(
owner=user,
blocked_at__date=yesterday,
reason=BlockReasons.ROTATION,
).exclude(status=LinkStatuses.ACTIVE)
.values_list("domain", flat=True)
.distinct()
),
unblocked_domains=list(
Link.objects.filter(owner=user, unblocked_at__date=yesterday)
.exclude(status=LinkStatuses.BLOCKED)
.values_list("domain", flat=True)
.distinct()
),
manually_switched_domains=list(
Link.objects.filter(
owner=user,
blocked_at__date=yesterday,
reason=BlockReasons.BLOCKED_BY_USER,
).exclude(status=LinkStatuses.ACTIVE)
.values_list("domain", flat=True)
.distinct()
),
user=user,
)βοΈ Task Behavior & Flow
- Calculates the date for βyesterdayβ.
- For each user:
- queries
Linkrecords by date + reason - extracts distinct domains
- sends a single Telegram message (see Telegram Messages)
- queries