116 lines
3.6 KiB
Python
116 lines
3.6 KiB
Python
from django.shortcuts import render
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.db.models import Count
|
|
from django.db.models.functions import TruncDate
|
|
from django.utils import timezone
|
|
from datetime import timedelta
|
|
import json
|
|
|
|
from .models import ClickEvent
|
|
|
|
|
|
def get_client_ip(request):
|
|
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
|
if x_forwarded_for:
|
|
ip = x_forwarded_for.split(',')[0].strip()
|
|
else:
|
|
ip = request.META.get('REMOTE_ADDR')
|
|
return ip
|
|
|
|
|
|
@csrf_exempt
|
|
@require_http_methods(["POST"])
|
|
def track_bot_click(request):
|
|
"""Трекинг перехода в бота"""
|
|
ClickEvent.objects.create(
|
|
event_type='bot',
|
|
ip_address=get_client_ip(request),
|
|
user_agent=request.META.get('HTTP_USER_AGENT', ''),
|
|
referrer=request.META.get('HTTP_REFERER'),
|
|
)
|
|
return JsonResponse({'status': 'ok', 'event': 'bot'})
|
|
|
|
|
|
@csrf_exempt
|
|
@require_http_methods(["POST"])
|
|
def track_channel_click(request):
|
|
"""Трекинг перехода в TG канал"""
|
|
ClickEvent.objects.create(
|
|
event_type='channel',
|
|
ip_address=get_client_ip(request),
|
|
user_agent=request.META.get('HTTP_USER_AGENT', ''),
|
|
referrer=request.META.get('HTTP_REFERER'),
|
|
)
|
|
return JsonResponse({'status': 'ok', 'event': 'channel'})
|
|
|
|
|
|
def dashboard(request):
|
|
"""Страница статистики"""
|
|
today = timezone.now().date()
|
|
week_ago = today - timedelta(days=7)
|
|
month_ago = today - timedelta(days=30)
|
|
|
|
# Общая статистика
|
|
total_bot = ClickEvent.objects.filter(event_type='bot').count()
|
|
total_channel = ClickEvent.objects.filter(event_type='channel').count()
|
|
|
|
# Статистика за сегодня
|
|
today_bot = ClickEvent.objects.filter(
|
|
event_type='bot',
|
|
created_at__date=today
|
|
).count()
|
|
today_channel = ClickEvent.objects.filter(
|
|
event_type='channel',
|
|
created_at__date=today
|
|
).count()
|
|
|
|
# Статистика за неделю
|
|
week_bot = ClickEvent.objects.filter(
|
|
event_type='bot',
|
|
created_at__date__gte=week_ago
|
|
).count()
|
|
week_channel = ClickEvent.objects.filter(
|
|
event_type='channel',
|
|
created_at__date__gte=week_ago
|
|
).count()
|
|
|
|
# Данные для графика (последние 30 дней)
|
|
bot_by_day = ClickEvent.objects.filter(
|
|
event_type='bot',
|
|
created_at__date__gte=month_ago
|
|
).annotate(date=TruncDate('created_at')).values('date').annotate(
|
|
count=Count('id')
|
|
).order_by('date')
|
|
|
|
channel_by_day = ClickEvent.objects.filter(
|
|
event_type='channel',
|
|
created_at__date__gte=month_ago
|
|
).annotate(date=TruncDate('created_at')).values('date').annotate(
|
|
count=Count('id')
|
|
).order_by('date')
|
|
|
|
# Последние события
|
|
recent_events = ClickEvent.objects.all()[:20]
|
|
|
|
context = {
|
|
'total_bot': total_bot,
|
|
'total_channel': total_channel,
|
|
'today_bot': today_bot,
|
|
'today_channel': today_channel,
|
|
'week_bot': week_bot,
|
|
'week_channel': week_channel,
|
|
'bot_by_day': json.dumps([
|
|
{'date': item['date'].isoformat(), 'count': item['count']}
|
|
for item in bot_by_day
|
|
]),
|
|
'channel_by_day': json.dumps([
|
|
{'date': item['date'].isoformat(), 'count': item['count']}
|
|
for item in channel_by_day
|
|
]),
|
|
'recent_events': recent_events,
|
|
}
|
|
|
|
return render(request, 'metrics/dashboard.html', context)
|