push notificantion test

This commit is contained in:
Parsa Nazer
2025-02-17 00:11:50 +03:30
parent 4fb1d2bdb9
commit ad022cdf6a
9 changed files with 136 additions and 9 deletions
+2
View File
@@ -27,3 +27,5 @@ ACCESS_TOKEN_LIFETIME = 5000
REFRESH_TOKEN_LIFETIME = 5000
SMS_API_KEY = ''
VAPID_PRIVATE_KEY = 'NajogmGTsGsZ_dfURrjUpgsm5fui-s5AzruBQgMh_I4'
+8
View File
@@ -88,3 +88,11 @@ class AddressAdmin(ModelAdmin, ImportExportModelAdmin):
def address_display(self, obj):
return obj.address[0:35] + '...'
address_display.short_description = 'ادرس'
@admin.register(PushSubscription)
class PushSubscription(ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm
export_form_class = ExportForm
compressed_fields = True
warn_unsaved_form = True
@@ -0,0 +1,25 @@
# Generated by Django 5.1.2 on 2025-02-16 20:03
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0012_alter_user_video_uploader'),
]
operations = [
migrations.CreateModel(
name='PushSubscription',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('endpoint', models.TextField()),
('keys', models.JSONField()),
('created_at', models.DateField(auto_now_add=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
+62 -1
View File
@@ -7,7 +7,7 @@ from django.utils import timezone
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken, OutstandingToken
import hashlib
from django.contrib import admin
from django.conf import settings
class UserManager(BaseUserManager):
def create_user(self, phone, password=None):
if not phone:
@@ -136,3 +136,64 @@ class UserAddressModel(models.Model):
class Meta:
verbose_name = 'ادرس کاربر'
verbose_name_plural = 'ادرس های کاربر'
import os
import json
from pywebpush import webpush, WebPushException
class PushSubscription(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
endpoint = models.TextField()
keys = models.JSONField()
created_at = models.DateField(auto_now_add=True)
def __str__(self):
return f'{self.user} push'
def send_notif(self, title, body):
payload = {
"title": title,
"body": body,
"icon": ''
}
try:
webpush(
subscription_info={
"endpoint": self.endpoint,
"keys": self.keys
},
data=json.dumps(payload),
vapid_private_key=settings.VAPID_PRIVATE_KEY,
vapid_claims={
"sub": "mailto:admin@example.com"
}
)
except WebPushException as ex:
print("Failed to send notification:", ex)
@classmethod
def send_group_notification(cls, user, title, body):
payload = {
"title": title,
"body": body,
"icon": ''
}
subscriptions = PushSubscription.objects.filter(user=user)
for sub in subscriptions:
try:
webpush(
subscription_info={
"endpoint": sub.endpoint,
"keys": sub.keys
},
data=json.dumps(payload),
vapid_private_key=settings.VAPID_PRIVATE_KEY,
vapid_claims={
"sub": "mailto:admin@example.com"
}
)
except WebPushException as ex:
print(f"Failed to send notification to {sub.user}:", ex)
+6
View File
@@ -24,3 +24,9 @@ class UserAddressSerializer(serializers.ModelSerializer):
if not user.is_authenticated:
raise serializers.ValidationError("You must be logged in to perform this action.")
return data
class PushSubscriptionSerializer(serializers.ModelSerializer):
class Meta:
model = PushSubscription
fields = ('endpoint', 'keys')
+1
View File
@@ -12,4 +12,5 @@ urlpatterns = [
path('address/delete/<int:pk>', views.DeleteAddressView.as_view(), name='delete-address'),
path('address/list', views.GetUserAddressesView.as_view(), name='list-addresses'),
path('address/<int:pk>', views.GetIDUserAddressView.as_view(), name='get-ID-address'),
path('subscribe', views.SubscribeView.as_view(), name='subscibe')
]
+15 -1
View File
@@ -2,7 +2,7 @@ from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from .serializers import ProfileSerializer, UserAddressSerializer, CustomTokenObtainPairSerializer
from .serializers import *
from .models import UserAddressModel, User
from rest_framework.permissions import IsAuthenticated, AllowAny
from drf_spectacular.utils import extend_schema, OpenApiParameter
@@ -172,3 +172,17 @@ class GetIDUserAddressView(generics.RetrieveAPIView):
def get_queryset(self):
return UserAddressModel.objects.filter(user=self.request.user)
class SubscribeView(APIView):
serializer_class = PushSubscriptionSerializer
def post(self, request):
push_ser = self.serializer_class(data=request.data)
if push_ser.is_valid():
PushSubscription.objects.update_or_create(
user=request.user,
defaults=(push_ser.validated_data)
)
return Response(status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_400_BAD_REQUEST)
+1 -1
View File
@@ -29,7 +29,7 @@ DEBUG = True
BASE_DIR = Path(__file__).resolve().parent.parent.parent
VAPID_PRIVATE_KEY = os.getenv('VAPID_PRIVATE_KEY')
# Application definition
+11 -1
View File
@@ -45,7 +45,17 @@ class OrderModel(models.Model):
# def total_without_tax(self):
# return sum(item.total() for item in self.items.all())
def save(self, *args, **kwargs):
if self.status == 'POSTED':
try:
push_object = PushSubscription.objects.get(user=self.user)
except:
print('object not found')
try:
push_object.send_notif('سفارش شما به پست شده تغییر کرد', 'سفارش شما به پست شده تغییر کرد')
except:
print('didnt send')
super().save(*args, **kwargs)
def total_with_discount(self):
total_with_item_discount = sum(item.total_with_discount() for item in self.items.all())