Spaces:
Running
Running
Commit
·
d5374bf
1
Parent(s):
e744e38
Add notification app with initial models, views, and admin configuration; remove unused image files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- api/__pycache__/__init__.cpython-313.pyc +0 -0
- api/__pycache__/admin.cpython-313.pyc +0 -0
- api/__pycache__/apps.cpython-313.pyc +0 -0
- api/__pycache__/models.cpython-313.pyc +0 -0
- api/__pycache__/urls.cpython-313.pyc +0 -0
- api/__pycache__/utils.cpython-313.pyc +0 -0
- api/__pycache__/views.cpython-313.pyc +0 -0
- api/admin.py +66 -18
- api/migrations/0016_pushsubscription.py +26 -0
- api/migrations/0017_optionpoll_poll.py +34 -0
- api/migrations/0018_rename_participant_poll_participants.py +18 -0
- api/migrations/0019_bhajancategory_icon.py +18 -0
- api/migrations/0020_alter_bhajan_audio_url.py +18 -0
- api/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0002_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0003_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0004_alter_bhajancategory_svg.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0005_remove_bhajan_lyrics_en_url_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0006_bhajan_isaudio_bhajan_iseng_bhajan_isger_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0007_remove_bhajancategory_svg.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0008_bhajan_bhajanid.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0009_event_color_alter_event_created_by_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0010_event_time.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0011_delete_message.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0012_notification_title.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0013_bhagat_profile_image_alter_bhagat_user_type_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0014_rename_address_bhagat_streetname_bhagat_city_and_more.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0015_alter_bhagat_phone.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0016_pushsubscription.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0017_optionpoll_poll.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0018_rename_participant_poll_participants.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0019_bhajancategory_icon.cpython-313.pyc +0 -0
- api/migrations/__pycache__/0020_alter_bhajan_audio_url.cpython-313.pyc +0 -0
- api/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- api/models.py +56 -11
- api/urls.py +21 -15
- api/views.py +447 -184
- downloads/1.jpg +0 -3
- downloads/10.png +0 -0
- downloads/100.png +0 -3
- downloads/101.png +0 -3
- downloads/102.png +0 -3
- downloads/103.png +0 -3
- downloads/104.png +0 -3
- downloads/105.png +0 -3
- downloads/106.png +0 -3
- downloads/107.png +0 -3
- downloads/108.png +0 -3
- downloads/109.jpg +0 -0
- downloads/11.png +0 -3
api/__pycache__/__init__.cpython-313.pyc
ADDED
Binary file (139 Bytes). View file
|
|
api/__pycache__/admin.cpython-313.pyc
ADDED
Binary file (3.6 kB). View file
|
|
api/__pycache__/apps.cpython-313.pyc
ADDED
Binary file (497 Bytes). View file
|
|
api/__pycache__/models.cpython-313.pyc
ADDED
Binary file (11.2 kB). View file
|
|
api/__pycache__/urls.cpython-313.pyc
ADDED
Binary file (2.02 kB). View file
|
|
api/__pycache__/utils.cpython-313.pyc
ADDED
Binary file (2.96 kB). View file
|
|
api/__pycache__/views.cpython-313.pyc
ADDED
Binary file (25.6 kB). View file
|
|
api/admin.py
CHANGED
@@ -1,36 +1,81 @@
|
|
1 |
from django.contrib import admin
|
2 |
-
from .models import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
from import_export.admin import ImportExportModelAdmin
|
4 |
|
|
|
5 |
# Register your models here.
|
6 |
class BhagatAdmin(ImportExportModelAdmin):
|
7 |
-
list_display = (
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
class RegionAdmin(ImportExportModelAdmin):
|
12 |
-
list_display = (
|
|
|
13 |
|
14 |
class BhajanCategoryAdmin(ImportExportModelAdmin):
|
15 |
-
list_display = (
|
16 |
-
search_fields = (
|
17 |
-
|
|
|
18 |
class BhajanAdmin(ImportExportModelAdmin):
|
19 |
-
list_display = (
|
20 |
-
search_fields = (
|
21 |
-
list_filter = (
|
22 |
# 'musicPreivew',
|
23 |
|
|
|
24 |
class EventAdmin(ImportExportModelAdmin):
|
25 |
-
list_display = (
|
26 |
-
list_filter = (
|
27 |
-
search_fields = (
|
28 |
-
list_editable = (
|
|
|
29 |
|
30 |
class NotificationAdmin(ImportExportModelAdmin):
|
31 |
-
list_display = (
|
32 |
-
list_filter = (
|
33 |
-
search_fields = (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
admin.site.register(Bhagat, BhagatAdmin)
|
36 |
admin.site.register(Region, RegionAdmin)
|
@@ -38,3 +83,6 @@ admin.site.register(BhajanCategory, BhajanCategoryAdmin)
|
|
38 |
admin.site.register(Bhajan, BhajanAdmin)
|
39 |
admin.site.register(Event, EventAdmin)
|
40 |
admin.site.register(Notification, NotificationAdmin)
|
|
|
|
|
|
|
|
1 |
from django.contrib import admin
|
2 |
+
from .models import (
|
3 |
+
Bhagat,
|
4 |
+
Event,
|
5 |
+
Attendance,
|
6 |
+
Notification,
|
7 |
+
Region,
|
8 |
+
BhajanCategory,
|
9 |
+
Bhajan,
|
10 |
+
PushSubscription,
|
11 |
+
OptionPoll,
|
12 |
+
Poll,
|
13 |
+
)
|
14 |
from import_export.admin import ImportExportModelAdmin
|
15 |
|
16 |
+
|
17 |
# Register your models here.
|
18 |
class BhagatAdmin(ImportExportModelAdmin):
|
19 |
+
list_display = (
|
20 |
+
"get_full_name",
|
21 |
+
"profileImage",
|
22 |
+
"email",
|
23 |
+
"region",
|
24 |
+
"user_type",
|
25 |
+
"assigned_to",
|
26 |
+
)
|
27 |
+
list_filter = ("region", "user_type")
|
28 |
+
search_fields = (
|
29 |
+
"get_full_name",
|
30 |
+
"email",
|
31 |
+
"region",
|
32 |
+
"user_type",
|
33 |
+
"assigned_to",
|
34 |
+
)
|
35 |
+
|
36 |
|
37 |
class RegionAdmin(ImportExportModelAdmin):
|
38 |
+
list_display = ("name",)
|
39 |
+
|
40 |
|
41 |
class BhajanCategoryAdmin(ImportExportModelAdmin):
|
42 |
+
list_display = ("name", "icon_image", "link")
|
43 |
+
search_fields = ("name",)
|
44 |
+
|
45 |
+
|
46 |
class BhajanAdmin(ImportExportModelAdmin):
|
47 |
+
list_display = ("title", "title_guj", "category", "lyricsBtn")
|
48 |
+
search_fields = ("title", "title_guj", "category__name")
|
49 |
+
list_filter = ("category",)
|
50 |
# 'musicPreivew',
|
51 |
|
52 |
+
|
53 |
class EventAdmin(ImportExportModelAdmin):
|
54 |
+
list_display = ("title", "date", "region", "is_approved", "color")
|
55 |
+
list_filter = ("region", "is_approved", "color")
|
56 |
+
search_fields = ("title", "date", "region", "is_approved", "color")
|
57 |
+
list_editable = ("is_approved", "color")
|
58 |
+
|
59 |
|
60 |
class NotificationAdmin(ImportExportModelAdmin):
|
61 |
+
list_display = ("sender", "title", "timestamp", "notification_type")
|
62 |
+
list_filter = ("notification_type",)
|
63 |
+
search_fields = ("sender__first_name", "title", "notification_type")
|
64 |
+
|
65 |
+
|
66 |
+
class PushSubscriptionAdmin(ImportExportModelAdmin):
|
67 |
+
list_display = ("user", "endpoint")
|
68 |
+
|
69 |
+
|
70 |
+
class OptionPollAdmin(ImportExportModelAdmin):
|
71 |
+
list_display = ("optionText",)
|
72 |
+
search_fields = ("optionText",)
|
73 |
+
|
74 |
+
|
75 |
+
class PollAdmin(ImportExportModelAdmin):
|
76 |
+
list_display = ("question", "created_by", "created_at")
|
77 |
+
search_fields = ("question", "created_by")
|
78 |
+
|
79 |
|
80 |
admin.site.register(Bhagat, BhagatAdmin)
|
81 |
admin.site.register(Region, RegionAdmin)
|
|
|
83 |
admin.site.register(Bhajan, BhajanAdmin)
|
84 |
admin.site.register(Event, EventAdmin)
|
85 |
admin.site.register(Notification, NotificationAdmin)
|
86 |
+
admin.site.register(PushSubscription, PushSubscriptionAdmin)
|
87 |
+
admin.site.register(OptionPoll, OptionPollAdmin)
|
88 |
+
admin.site.register(Poll, PollAdmin)
|
api/migrations/0016_pushsubscription.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.6 on 2025-02-13 21:48
|
2 |
+
|
3 |
+
import django.db.models.deletion
|
4 |
+
from django.conf import settings
|
5 |
+
from django.db import migrations, models
|
6 |
+
|
7 |
+
|
8 |
+
class Migration(migrations.Migration):
|
9 |
+
|
10 |
+
dependencies = [
|
11 |
+
('api', '0015_alter_bhagat_phone'),
|
12 |
+
]
|
13 |
+
|
14 |
+
operations = [
|
15 |
+
migrations.CreateModel(
|
16 |
+
name='PushSubscription',
|
17 |
+
fields=[
|
18 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
19 |
+
('endpoint', models.URLField(max_length=500)),
|
20 |
+
('p256dh', models.CharField(max_length=200)),
|
21 |
+
('auth', models.CharField(max_length=100)),
|
22 |
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
23 |
+
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
24 |
+
],
|
25 |
+
),
|
26 |
+
]
|
api/migrations/0017_optionpoll_poll.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.6 on 2025-02-14 17:09
|
2 |
+
|
3 |
+
import django.db.models.deletion
|
4 |
+
from django.conf import settings
|
5 |
+
from django.db import migrations, models
|
6 |
+
|
7 |
+
|
8 |
+
class Migration(migrations.Migration):
|
9 |
+
|
10 |
+
dependencies = [
|
11 |
+
('api', '0016_pushsubscription'),
|
12 |
+
]
|
13 |
+
|
14 |
+
operations = [
|
15 |
+
migrations.CreateModel(
|
16 |
+
name='OptionPoll',
|
17 |
+
fields=[
|
18 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
19 |
+
('optionText', models.TextField()),
|
20 |
+
('voters', models.ManyToManyField(blank=True, related_name='options_voters', to=settings.AUTH_USER_MODEL)),
|
21 |
+
],
|
22 |
+
),
|
23 |
+
migrations.CreateModel(
|
24 |
+
name='Poll',
|
25 |
+
fields=[
|
26 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
27 |
+
('question', models.TextField()),
|
28 |
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
29 |
+
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='polls_creator', to=settings.AUTH_USER_MODEL)),
|
30 |
+
('options', models.ManyToManyField(blank=True, related_name='polls_options', to='api.optionpoll')),
|
31 |
+
('participant', models.ManyToManyField(blank=True, related_name='polls_participant', to=settings.AUTH_USER_MODEL)),
|
32 |
+
],
|
33 |
+
),
|
34 |
+
]
|
api/migrations/0018_rename_participant_poll_participants.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.6 on 2025-02-14 17:33
|
2 |
+
|
3 |
+
from django.db import migrations
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
dependencies = [
|
9 |
+
('api', '0017_optionpoll_poll'),
|
10 |
+
]
|
11 |
+
|
12 |
+
operations = [
|
13 |
+
migrations.RenameField(
|
14 |
+
model_name='poll',
|
15 |
+
old_name='participant',
|
16 |
+
new_name='participants',
|
17 |
+
),
|
18 |
+
]
|
api/migrations/0019_bhajancategory_icon.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.6 on 2025-02-15 18:50
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
dependencies = [
|
9 |
+
('api', '0018_rename_participant_poll_participants'),
|
10 |
+
]
|
11 |
+
|
12 |
+
operations = [
|
13 |
+
migrations.AddField(
|
14 |
+
model_name='bhajancategory',
|
15 |
+
name='icon',
|
16 |
+
field=models.URLField(blank=True),
|
17 |
+
),
|
18 |
+
]
|
api/migrations/0020_alter_bhajan_audio_url.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.6 on 2025-02-15 22:46
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
dependencies = [
|
9 |
+
('api', '0019_bhajancategory_icon'),
|
10 |
+
]
|
11 |
+
|
12 |
+
operations = [
|
13 |
+
migrations.AlterField(
|
14 |
+
model_name='bhajan',
|
15 |
+
name='audio_url',
|
16 |
+
field=models.CharField(blank=True, max_length=500),
|
17 |
+
),
|
18 |
+
]
|
api/migrations/__pycache__/0001_initial.cpython-313.pyc
ADDED
Binary file (9.14 kB). View file
|
|
api/migrations/__pycache__/0002_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc
ADDED
Binary file (1.54 kB). View file
|
|
api/migrations/__pycache__/0003_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc
ADDED
Binary file (1.31 kB). View file
|
|
api/migrations/__pycache__/0004_alter_bhajancategory_svg.cpython-313.pyc
ADDED
Binary file (803 Bytes). View file
|
|
api/migrations/__pycache__/0005_remove_bhajan_lyrics_en_url_and_more.cpython-313.pyc
ADDED
Binary file (1.47 kB). View file
|
|
api/migrations/__pycache__/0006_bhajan_isaudio_bhajan_iseng_bhajan_isger_and_more.cpython-313.pyc
ADDED
Binary file (1.13 kB). View file
|
|
api/migrations/__pycache__/0007_remove_bhajancategory_svg.cpython-313.pyc
ADDED
Binary file (709 Bytes). View file
|
|
api/migrations/__pycache__/0008_bhajan_bhajanid.cpython-313.pyc
ADDED
Binary file (784 Bytes). View file
|
|
api/migrations/__pycache__/0009_event_color_alter_event_created_by_and_more.cpython-313.pyc
ADDED
Binary file (1.71 kB). View file
|
|
api/migrations/__pycache__/0010_event_time.cpython-313.pyc
ADDED
Binary file (779 Bytes). View file
|
|
api/migrations/__pycache__/0011_delete_message.cpython-313.pyc
ADDED
Binary file (630 Bytes). View file
|
|
api/migrations/__pycache__/0012_notification_title.cpython-313.pyc
ADDED
Binary file (789 Bytes). View file
|
|
api/migrations/__pycache__/0013_bhagat_profile_image_alter_bhagat_user_type_and_more.cpython-313.pyc
ADDED
Binary file (1.38 kB). View file
|
|
api/migrations/__pycache__/0014_rename_address_bhagat_streetname_bhagat_city_and_more.cpython-313.pyc
ADDED
Binary file (1.3 kB). View file
|
|
api/migrations/__pycache__/0015_alter_bhagat_phone.cpython-313.pyc
ADDED
Binary file (813 Bytes). View file
|
|
api/migrations/__pycache__/0016_pushsubscription.cpython-313.pyc
ADDED
Binary file (1.54 kB). View file
|
|
api/migrations/__pycache__/0017_optionpoll_poll.cpython-313.pyc
ADDED
Binary file (1.99 kB). View file
|
|
api/migrations/__pycache__/0018_rename_participant_poll_participants.cpython-313.pyc
ADDED
Binary file (719 Bytes). View file
|
|
api/migrations/__pycache__/0019_bhajancategory_icon.cpython-313.pyc
ADDED
Binary file (781 Bytes). View file
|
|
api/migrations/__pycache__/0020_alter_bhajan_audio_url.cpython-313.pyc
ADDED
Binary file (790 Bytes). View file
|
|
api/migrations/__pycache__/__init__.cpython-313.pyc
ADDED
Binary file (150 Bytes). View file
|
|
api/models.py
CHANGED
@@ -28,14 +28,21 @@ class Bhagat(AbstractUser):
|
|
28 |
pincode = models.CharField(max_length=10, null=True)
|
29 |
assigned_to = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_users')
|
30 |
profile_image = models.URLField(blank=True)
|
31 |
-
|
32 |
def __str__(self):
|
33 |
return self.first_name + ' ' + self.last_name
|
34 |
|
35 |
def save(self, *args, **kwargs):
|
36 |
-
self.
|
|
|
37 |
super().save(*args, **kwargs)
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
class Region(models.Model):
|
41 |
name = models.CharField(max_length=100)
|
@@ -75,31 +82,36 @@ class Notification(models.Model):
|
|
75 |
class BhajanCategory(models.Model):
|
76 |
name = models.CharField(max_length=100)
|
77 |
link = models.CharField(max_length=100)
|
78 |
-
|
|
|
79 |
def __str__(self):
|
80 |
return self.name
|
81 |
|
|
|
|
|
|
|
|
|
82 |
class Bhajan(models.Model):
|
83 |
-
bhajanId = models.IntegerField(blank=True,default=0)
|
84 |
-
title = models.CharField(max_length=500,blank=True)
|
85 |
-
title_guj = models.CharField(max_length=500,blank=True)
|
86 |
category = models.ForeignKey(BhajanCategory, on_delete=models.CASCADE)
|
87 |
lyrics = models.CharField(max_length=50, blank=True)
|
88 |
-
audio_url = models.
|
89 |
isEng = models.BooleanField(default=False)
|
90 |
isHnd = models.BooleanField(default=False)
|
91 |
isGer = models.BooleanField(default=False)
|
92 |
isAudio = models.BooleanField(default=False)
|
93 |
-
|
94 |
def __str__(self):
|
95 |
return self.title
|
96 |
-
|
97 |
def musicPreivew(self):
|
98 |
if self.isAudio:
|
99 |
return mark_safe('<audio controls><source src="https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/%s" type="audio/mpeg"></audio>' % self.audio_url)
|
100 |
else:
|
101 |
return 'No Audio Available'
|
102 |
-
|
103 |
def lyricsBtn(self):
|
104 |
# i have four languages in my bhajan so add them all as buttons and show them on click
|
105 |
languages = [["","GUJ"]]
|
@@ -113,4 +125,37 @@ class Bhajan(models.Model):
|
|
113 |
for lang in languages:
|
114 |
html += '<li style="padding-bottom:12px"><a href="https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/'+lang[0] + self.lyrics+'" target="_blank" class="import_link">'+(lang[1])+'</a></li>'
|
115 |
html += '</ul>'
|
116 |
-
return mark_safe(html)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
pincode = models.CharField(max_length=10, null=True)
|
29 |
assigned_to = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_users')
|
30 |
profile_image = models.URLField(blank=True)
|
31 |
+
|
32 |
def __str__(self):
|
33 |
return self.first_name + ' ' + self.last_name
|
34 |
|
35 |
def save(self, *args, **kwargs):
|
36 |
+
if not self.password.startswith("pbkdf2_sha256"):
|
37 |
+
self.set_password(self.password)
|
38 |
super().save(*args, **kwargs)
|
39 |
|
40 |
+
def profileImage(self):
|
41 |
+
return mark_safe('<img src="%s" width="50" height="50" />' % self.profile_image)
|
42 |
+
|
43 |
+
def get_full_name(self):
|
44 |
+
return super().get_full_name()
|
45 |
+
|
46 |
|
47 |
class Region(models.Model):
|
48 |
name = models.CharField(max_length=100)
|
|
|
82 |
class BhajanCategory(models.Model):
|
83 |
name = models.CharField(max_length=100)
|
84 |
link = models.CharField(max_length=100)
|
85 |
+
icon = models.URLField(blank=True)
|
86 |
+
|
87 |
def __str__(self):
|
88 |
return self.name
|
89 |
|
90 |
+
def icon_image(self):
|
91 |
+
return mark_safe('<img src="%s" width="50" height="50" />' % self.icon)
|
92 |
+
|
93 |
+
|
94 |
class Bhajan(models.Model):
|
95 |
+
bhajanId = models.IntegerField(blank=True, default=0)
|
96 |
+
title = models.CharField(max_length=500, blank=True)
|
97 |
+
title_guj = models.CharField(max_length=500, blank=True)
|
98 |
category = models.ForeignKey(BhajanCategory, on_delete=models.CASCADE)
|
99 |
lyrics = models.CharField(max_length=50, blank=True)
|
100 |
+
audio_url = models.CharField(max_length=500, blank=True)
|
101 |
isEng = models.BooleanField(default=False)
|
102 |
isHnd = models.BooleanField(default=False)
|
103 |
isGer = models.BooleanField(default=False)
|
104 |
isAudio = models.BooleanField(default=False)
|
105 |
+
|
106 |
def __str__(self):
|
107 |
return self.title
|
108 |
+
|
109 |
def musicPreivew(self):
|
110 |
if self.isAudio:
|
111 |
return mark_safe('<audio controls><source src="https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/%s" type="audio/mpeg"></audio>' % self.audio_url)
|
112 |
else:
|
113 |
return 'No Audio Available'
|
114 |
+
|
115 |
def lyricsBtn(self):
|
116 |
# i have four languages in my bhajan so add them all as buttons and show them on click
|
117 |
languages = [["","GUJ"]]
|
|
|
125 |
for lang in languages:
|
126 |
html += '<li style="padding-bottom:12px"><a href="https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/'+lang[0] + self.lyrics+'" target="_blank" class="import_link">'+(lang[1])+'</a></li>'
|
127 |
html += '</ul>'
|
128 |
+
return mark_safe(html)
|
129 |
+
|
130 |
+
|
131 |
+
class PushSubscription(models.Model):
|
132 |
+
user = models.ForeignKey(Bhagat, on_delete=models.CASCADE, null=True)
|
133 |
+
endpoint = models.URLField(max_length=500)
|
134 |
+
p256dh = models.CharField(max_length=200)
|
135 |
+
auth = models.CharField(max_length=100)
|
136 |
+
created_at = models.DateTimeField(auto_now_add=True)
|
137 |
+
|
138 |
+
|
139 |
+
class OptionPoll(models.Model):
|
140 |
+
optionText = models.TextField()
|
141 |
+
voters = models.ManyToManyField(Bhagat, related_name="options_voters", blank=True)
|
142 |
+
|
143 |
+
def __str__(self):
|
144 |
+
return self.optionText
|
145 |
+
|
146 |
+
|
147 |
+
class Poll(models.Model):
|
148 |
+
question = models.TextField()
|
149 |
+
options = models.ManyToManyField(
|
150 |
+
OptionPoll, related_name="polls_options", blank=True
|
151 |
+
)
|
152 |
+
participants = models.ManyToManyField(
|
153 |
+
Bhagat, related_name="polls_participant", blank=True
|
154 |
+
)
|
155 |
+
created_by = models.ForeignKey(
|
156 |
+
Bhagat, on_delete=models.CASCADE, related_name="polls_creator"
|
157 |
+
)
|
158 |
+
created_at = models.DateTimeField(auto_now_add=True)
|
159 |
+
|
160 |
+
def __str__(self):
|
161 |
+
return self.question
|
api/urls.py
CHANGED
@@ -3,19 +3,25 @@ from . import views
|
|
3 |
from rest_framework_simplejwt.views import TokenRefreshView
|
4 |
|
5 |
urlpatterns = [
|
6 |
-
path(
|
7 |
-
path(
|
8 |
-
path(
|
9 |
-
path(
|
10 |
-
path(
|
11 |
-
|
12 |
-
path(
|
13 |
-
path(
|
14 |
-
|
15 |
-
path(
|
16 |
-
|
17 |
-
|
18 |
-
path(
|
19 |
-
|
20 |
-
path(
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
]
|
|
|
3 |
from rest_framework_simplejwt.views import TokenRefreshView
|
4 |
|
5 |
urlpatterns = [
|
6 |
+
path("login/", views.login, name="login"),
|
7 |
+
path("logout/", views.logout, name="logout"),
|
8 |
+
path("get-user-profile/", views.get_user_profile, name="get_user_profile"),
|
9 |
+
path("profile-updater/", views.profile_updater, name="profile_updater"),
|
10 |
+
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
|
11 |
+
path("dataEntry/", views.dataEntry, name="dataEntry"),
|
12 |
+
path("send-notification/", views.send_notification, name="send_notification"),
|
13 |
+
path("bhajan-list/<str:catLink>", views.bhajanList, name="bhajanList"),
|
14 |
+
path("bhajan-category-list/", views.bhajanCategoryList, name="bhajanCategoryList"),
|
15 |
+
path(
|
16 |
+
"bhajan-detail/<str:catLink>/<int:id>", views.bhajanDetail, name="bhajanDetail"
|
17 |
+
),
|
18 |
+
path("event-list/", views.eventList, name="eventList"),
|
19 |
+
path("bhakto-list/", views.bhaktoList, name="bhaktoList"),
|
20 |
+
path("notification/", views.notification, name="notification"),
|
21 |
+
path("push-subscription/", views.save_push_subscription, name="push_subscription"),
|
22 |
+
path("send-otp/", views.send_otp, name="send_otp"),
|
23 |
+
path("verify-otp/", views.verify_otp, name="verify_otp"),
|
24 |
+
path("change-password/", views.change_password, name="change_password"),
|
25 |
+
path("polls/", views.polls, name="polls"),
|
26 |
+
path("poll-voters/<int:id>", views.voterList, name="voterList"),
|
27 |
]
|
api/views.py
CHANGED
@@ -5,8 +5,20 @@ from django.http import JsonResponse, HttpResponse
|
|
5 |
from django.views.decorators.http import require_POST
|
6 |
from django.utils import timezone
|
7 |
import json
|
8 |
-
from .models import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
from django.conf import settings
|
|
|
10 |
import requests
|
11 |
|
12 |
from rest_framework.decorators import api_view, permission_classes
|
@@ -14,6 +26,7 @@ from rest_framework.permissions import AllowAny
|
|
14 |
from rest_framework.response import Response
|
15 |
from .utils import jwt_required
|
16 |
from rest_framework_simplejwt.tokens import RefreshToken
|
|
|
17 |
|
18 |
|
19 |
def gCaptchaVerifer(token):
|
@@ -24,15 +37,15 @@ def gCaptchaVerifer(token):
|
|
24 |
|
25 |
|
26 |
def is_superadmin(user):
|
27 |
-
return user.user_type ==
|
28 |
|
29 |
|
30 |
def is_regionadmin(user):
|
31 |
-
return user.user_type ==
|
32 |
|
33 |
|
34 |
def is_monitor(user):
|
35 |
-
return user.user_type ==
|
36 |
|
37 |
|
38 |
def dataEntry(request):
|
@@ -57,52 +70,78 @@ def dataEntry(request):
|
|
57 |
|
58 |
def bhajanCategoryList(request):
|
59 |
categories = BhajanCategory.objects.all()
|
60 |
-
bhajans = Bhajan.objects.all()
|
61 |
-
bhajanArr = []
|
62 |
-
for bhajan in bhajans:
|
63 |
-
bhajanArr.append({
|
64 |
-
"id": bhajan.bhajanId,
|
65 |
-
"title": bhajan.title,
|
66 |
-
"title_guj": bhajan.title_guj,
|
67 |
-
"category": bhajan.category.name,
|
68 |
-
"lyrics": bhajan.lyrics,
|
69 |
-
"audio_url": bhajan.audio_url,
|
70 |
-
"isEng": bhajan.isEng,
|
71 |
-
"isHnd": bhajan.isHnd,
|
72 |
-
"isGer": bhajan.isGer,
|
73 |
-
"isAudio": bhajan.isAudio
|
74 |
-
})
|
75 |
categoryArr = []
|
76 |
for category in categories:
|
77 |
-
categoryArr.append(
|
78 |
-
"name": category.name,
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
|
83 |
-
return JsonResponse(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
|
86 |
-
def bhajanDetail(request, id):
|
87 |
-
bhajan = Bhajan.objects.get(bhajanId=id)
|
88 |
if bhajan is None:
|
89 |
return JsonResponse({"error": "Bhajan not found"})
|
90 |
else:
|
91 |
-
return JsonResponse(
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
|
|
106 |
|
107 |
|
108 |
def eventList(request):
|
@@ -110,34 +149,45 @@ def eventList(request):
|
|
110 |
eventArr = []
|
111 |
for event in events:
|
112 |
# convert date to Sept 26,2024 | 8:30 - 9:30
|
113 |
-
dateFormatted =
|
114 |
-
|
115 |
-
"
|
116 |
-
|
117 |
-
"
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
return JsonResponse({"events": eventArr})
|
127 |
|
|
|
128 |
@jwt_required()
|
129 |
def notification(request):
|
130 |
notifications = Notification.objects.all()
|
131 |
notificationArr = []
|
132 |
for notification in notifications:
|
133 |
-
notificationArr.append(
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
|
|
|
|
141 |
return JsonResponse({"notifications": notificationArr})
|
142 |
|
143 |
|
@@ -145,48 +195,55 @@ def notification(request):
|
|
145 |
@csrf_exempt
|
146 |
@jwt_required()
|
147 |
def send_notification(request):
|
148 |
-
if request.method ==
|
149 |
-
content = request.POST.get(
|
150 |
-
recipient_type = request.POST.get(
|
151 |
-
if recipient_type == 'all':
|
152 |
-
recipients = Bhagat.objects.all()
|
153 |
-
elif recipient_type == 'monitors':
|
154 |
-
recipients = Bhagat.objects.filter(user_type='monitor')
|
155 |
-
elif recipient_type == 'regionadmins':
|
156 |
-
recipients = Bhagat.objects.filter(user_type='regionadmin')
|
157 |
|
158 |
-
notification = Notification.objects.create(
|
159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
|
161 |
-
|
|
|
162 |
|
163 |
|
164 |
def birthday_notifications():
|
165 |
today = timezone.now().date()
|
166 |
-
birthday_users = Bhagat.objects.filter(
|
|
|
|
|
167 |
for user in birthday_users:
|
168 |
notification = Notification.objects.create(
|
169 |
-
sender=Bhagat.objects.get(user_type=
|
170 |
content=f"Happy Birthday to {user.get_full_name()}!",
|
171 |
-
notification_type=
|
172 |
)
|
173 |
notification.recipients.set(Bhagat.objects.all())
|
174 |
|
175 |
|
176 |
@csrf_exempt
|
177 |
def login(request):
|
178 |
-
if request.method ==
|
179 |
-
username = request.POST.get(
|
180 |
-
password = request.POST.get(
|
181 |
-
captcha_response = request.POST.get(
|
182 |
|
183 |
# Verify captcha
|
184 |
result = gCaptchaVerifer(captcha_response)
|
185 |
if not result.get("success"):
|
186 |
-
return JsonResponse({
|
187 |
-
"error": "Invalid Captcha",
|
188 |
-
"status": "error"
|
189 |
-
})
|
190 |
|
191 |
# Authenticate user
|
192 |
user = Bhagat.objects.filter(username=username).first()
|
@@ -194,145 +251,131 @@ def login(request):
|
|
194 |
# Generate tokens
|
195 |
refresh = RefreshToken.for_user(user)
|
196 |
|
197 |
-
return JsonResponse(
|
198 |
-
|
199 |
-
|
200 |
-
"
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
"
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
|
|
|
|
213 |
}
|
214 |
-
|
215 |
-
|
216 |
-
return JsonResponse({
|
217 |
-
"error": "Invalid credentials",
|
218 |
-
"status": "error"
|
219 |
-
})
|
220 |
|
221 |
-
|
222 |
-
"error": "Invalid Method",
|
223 |
-
"status": "error"
|
224 |
-
})
|
225 |
|
|
|
226 |
|
227 |
|
228 |
@csrf_exempt
|
229 |
@jwt_required()
|
230 |
def logout(request):
|
231 |
-
if request.method ==
|
232 |
-
refresh_token = request.POST.get(
|
233 |
if not refresh_token:
|
234 |
-
return JsonResponse(
|
235 |
-
|
236 |
-
|
237 |
-
})
|
238 |
else:
|
239 |
try:
|
240 |
refresh = RefreshToken(refresh_token)
|
241 |
refresh.blacklist()
|
242 |
-
return JsonResponse(
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
})
|
251 |
-
return JsonResponse({
|
252 |
-
"status": "error",
|
253 |
-
"error": "Invalid Method"
|
254 |
-
})
|
255 |
|
256 |
|
257 |
@jwt_required()
|
258 |
def get_user_profile(request):
|
259 |
try:
|
260 |
user = request.user
|
261 |
-
return JsonResponse(
|
262 |
-
|
263 |
-
|
264 |
-
"
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
|
|
|
|
273 |
}
|
274 |
-
|
275 |
except Exception as e:
|
276 |
-
return JsonResponse({
|
277 |
-
|
278 |
-
"error": str(e)
|
279 |
-
})
|
280 |
|
281 |
@csrf_exempt
|
282 |
@jwt_required()
|
283 |
def profile_updater(request):
|
284 |
-
if request.method ==
|
285 |
try:
|
286 |
user = request.user
|
287 |
-
first_name = request.POST.get(
|
288 |
if first_name:
|
289 |
user.first_name = first_name
|
290 |
-
last_name = request.POST.get(
|
291 |
if last_name:
|
292 |
user.last_name = last_name
|
293 |
-
email = request.POST.get(
|
294 |
if email:
|
295 |
user.email = email
|
296 |
-
phone = request.POST.get(
|
297 |
if phone:
|
298 |
user.phone = phone
|
299 |
-
region_name = request.POST.get(
|
300 |
if region_name:
|
301 |
user.region = Region.objects.get(name=region_name)
|
302 |
-
birth_date = request.POST.get(
|
303 |
if birth_date:
|
304 |
user.birthday = birth_date
|
305 |
-
street_name = request.POST.get(
|
306 |
if street_name:
|
307 |
user.streetName = street_name
|
308 |
-
pincode = request.POST.get(
|
309 |
if pincode:
|
310 |
user.pincode = pincode
|
311 |
-
city = request.POST.get(
|
312 |
if city:
|
313 |
user.city = city
|
314 |
-
state = request.POST.get(
|
315 |
if state:
|
316 |
user.state = state
|
317 |
-
country = request.POST.get(
|
318 |
if country:
|
319 |
user.country = country
|
320 |
-
profile_image = request.POST.get(
|
321 |
if profile_image:
|
322 |
user.profile_image = profile_image
|
323 |
user.save()
|
324 |
-
return JsonResponse(
|
325 |
-
"status": "success",
|
326 |
-
|
327 |
-
})
|
328 |
except Exception as e:
|
329 |
-
return JsonResponse({
|
330 |
-
"status": "error",
|
331 |
-
"error": str(e)
|
332 |
-
})
|
333 |
else:
|
334 |
user = request.user
|
335 |
-
|
|
|
336 |
"first_name": user.first_name,
|
337 |
"last_name": user.last_name,
|
338 |
"email": user.email,
|
@@ -344,12 +387,15 @@ def profile_updater(request):
|
|
344 |
"city": user.city,
|
345 |
"state": user.state,
|
346 |
"country": user.country,
|
347 |
-
"profile_image": user.profile_image
|
348 |
}
|
349 |
-
return JsonResponse(
|
350 |
-
|
351 |
-
|
352 |
-
|
|
|
|
|
|
|
353 |
|
354 |
|
355 |
@jwt_required()
|
@@ -358,12 +404,229 @@ def bhaktoList(request):
|
|
358 |
bhaktos = Bhagat.objects.filter(assigned_to=current_user).all()
|
359 |
bhaktoArr = []
|
360 |
for bhakto in bhaktos:
|
361 |
-
bhaktoArr.append(
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
from django.views.decorators.http import require_POST
|
6 |
from django.utils import timezone
|
7 |
import json
|
8 |
+
from .models import (
|
9 |
+
Bhagat,
|
10 |
+
Event,
|
11 |
+
Attendance,
|
12 |
+
PushSubscription,
|
13 |
+
Notification,
|
14 |
+
Region,
|
15 |
+
BhajanCategory,
|
16 |
+
Bhajan,
|
17 |
+
OptionPoll,
|
18 |
+
Poll,
|
19 |
+
)
|
20 |
from django.conf import settings
|
21 |
+
from django.core import serializers
|
22 |
import requests
|
23 |
|
24 |
from rest_framework.decorators import api_view, permission_classes
|
|
|
26 |
from rest_framework.response import Response
|
27 |
from .utils import jwt_required
|
28 |
from rest_framework_simplejwt.tokens import RefreshToken
|
29 |
+
from pywebpush import webpush, WebPushException
|
30 |
|
31 |
|
32 |
def gCaptchaVerifer(token):
|
|
|
37 |
|
38 |
|
39 |
def is_superadmin(user):
|
40 |
+
return user.user_type == "superadmin"
|
41 |
|
42 |
|
43 |
def is_regionadmin(user):
|
44 |
+
return user.user_type == "regionadmin"
|
45 |
|
46 |
|
47 |
def is_monitor(user):
|
48 |
+
return user.user_type == "monitor"
|
49 |
|
50 |
|
51 |
def dataEntry(request):
|
|
|
70 |
|
71 |
def bhajanCategoryList(request):
|
72 |
categories = BhajanCategory.objects.all()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
categoryArr = []
|
74 |
for category in categories:
|
75 |
+
categoryArr.append(
|
76 |
+
{"name": category.name, "link": category.link, "icon": category.icon}
|
77 |
+
)
|
78 |
+
lyricsBase = (
|
79 |
+
"https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/"
|
80 |
+
)
|
81 |
+
audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
|
82 |
+
return JsonResponse(
|
83 |
+
{"categories": categoryArr, "lyricsBase": lyricsBase, "audioBase": audioBase}
|
84 |
+
)
|
85 |
+
|
86 |
+
|
87 |
+
def bhajanList(request, catLink):
|
88 |
+
if catLink == "all-kirtan":
|
89 |
+
bhajans = Bhajan.objects.all()
|
90 |
+
category = "All Kirtan"
|
91 |
+
else:
|
92 |
+
bhajans = Bhajan.objects.filter(category__link=catLink)
|
93 |
+
category = BhajanCategory.objects.get(link=catLink).name
|
94 |
+
bhajanArr = []
|
95 |
+
for bhajan in bhajans:
|
96 |
+
bhajanArr.append(
|
97 |
+
{
|
98 |
+
"id": bhajan.bhajanId,
|
99 |
+
"title": bhajan.title,
|
100 |
+
"title_guj": bhajan.title_guj,
|
101 |
+
"lyrics": bhajan.lyrics,
|
102 |
+
"audio_url": bhajan.audio_url,
|
103 |
+
"isEng": bhajan.isEng,
|
104 |
+
"isHnd": bhajan.isHnd,
|
105 |
+
"isGer": bhajan.isGer,
|
106 |
+
"isAudio": bhajan.isAudio,
|
107 |
+
}
|
108 |
+
)
|
109 |
+
|
110 |
+
lyricsBase = (
|
111 |
+
"https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/"
|
112 |
+
)
|
113 |
audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
|
114 |
+
return JsonResponse(
|
115 |
+
{
|
116 |
+
"bhajans": bhajanArr,
|
117 |
+
"lyricsBase": lyricsBase,
|
118 |
+
"audioBase": audioBase,
|
119 |
+
"category": category,
|
120 |
+
}
|
121 |
+
)
|
122 |
|
123 |
|
124 |
+
def bhajanDetail(request, catLink, id):
|
125 |
+
bhajan = Bhajan.objects.get(bhajanId=id, category__link=catLink)
|
126 |
if bhajan is None:
|
127 |
return JsonResponse({"error": "Bhajan not found"})
|
128 |
else:
|
129 |
+
return JsonResponse(
|
130 |
+
{
|
131 |
+
"id": bhajan.bhajanId,
|
132 |
+
"title": bhajan.title,
|
133 |
+
"title_guj": bhajan.title_guj,
|
134 |
+
"category": bhajan.category.name,
|
135 |
+
"lyrics": bhajan.lyrics,
|
136 |
+
"audio_url": bhajan.audio_url,
|
137 |
+
"isEng": bhajan.isEng,
|
138 |
+
"isHnd": bhajan.isHnd,
|
139 |
+
"isGer": bhajan.isGer,
|
140 |
+
"isAudio": bhajan.isAudio,
|
141 |
+
"lyricsBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/",
|
142 |
+
"audioBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/",
|
143 |
+
}
|
144 |
+
)
|
145 |
|
146 |
|
147 |
def eventList(request):
|
|
|
149 |
eventArr = []
|
150 |
for event in events:
|
151 |
# convert date to Sept 26,2024 | 8:30 - 9:30
|
152 |
+
dateFormatted = (
|
153 |
+
event.date.strftime("%b %d, %Y")
|
154 |
+
+ " | "
|
155 |
+
+ event.date.strftime("%I:%M %p")
|
156 |
+
+ " - "
|
157 |
+
+ event.time.strftime("%I:%M %p")
|
158 |
+
)
|
159 |
+
eventArr.append(
|
160 |
+
{
|
161 |
+
"title": event.title,
|
162 |
+
"description": event.description,
|
163 |
+
"date": dateFormatted,
|
164 |
+
"day": int(event.date.strftime("%d")),
|
165 |
+
"month": int(event.date.strftime("%m")),
|
166 |
+
"year": int(event.date.strftime("%Y")),
|
167 |
+
"created_by": event.created_by.__str__(),
|
168 |
+
"region": event.region.name,
|
169 |
+
"is_approved": event.is_approved,
|
170 |
+
"color": event.color,
|
171 |
+
}
|
172 |
+
)
|
173 |
return JsonResponse({"events": eventArr})
|
174 |
|
175 |
+
|
176 |
@jwt_required()
|
177 |
def notification(request):
|
178 |
notifications = Notification.objects.all()
|
179 |
notificationArr = []
|
180 |
for notification in notifications:
|
181 |
+
notificationArr.append(
|
182 |
+
{
|
183 |
+
"sender": notification.sender.__str__(),
|
184 |
+
"category": notification.sender.user_type,
|
185 |
+
"title": notification.title,
|
186 |
+
"content": notification.content,
|
187 |
+
"timestamp": notification.timestamp.strftime("%b %d, %Y | %I:%M %p"),
|
188 |
+
"notification_type": notification.notification_type,
|
189 |
+
}
|
190 |
+
)
|
191 |
return JsonResponse({"notifications": notificationArr})
|
192 |
|
193 |
|
|
|
195 |
@csrf_exempt
|
196 |
@jwt_required()
|
197 |
def send_notification(request):
|
198 |
+
if request.method == "POST":
|
199 |
+
content = request.POST.get("content")
|
200 |
+
recipient_type = request.POST.get("recipient_type")
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
+
notification = Notification.objects.create(
|
203 |
+
sender=request.user, content=content, notification_type="custom"
|
204 |
+
)
|
205 |
+
|
206 |
+
# Send web push notifications
|
207 |
+
subscriptions = PushSubscription.objects.all()
|
208 |
+
for subscription in subscriptions:
|
209 |
+
send_push_notification(
|
210 |
+
subscription,
|
211 |
+
{
|
212 |
+
"title": "New Notification",
|
213 |
+
"content": content,
|
214 |
+
"url": "/notifications",
|
215 |
+
},
|
216 |
+
)
|
217 |
|
218 |
+
return JsonResponse({"status": "success"})
|
219 |
+
return JsonResponse({"status": "error"})
|
220 |
|
221 |
|
222 |
def birthday_notifications():
|
223 |
today = timezone.now().date()
|
224 |
+
birthday_users = Bhagat.objects.filter(
|
225 |
+
birthday__month=today.month, birthday__day=today.day
|
226 |
+
)
|
227 |
for user in birthday_users:
|
228 |
notification = Notification.objects.create(
|
229 |
+
sender=Bhagat.objects.get(user_type="superadmin"),
|
230 |
content=f"Happy Birthday to {user.get_full_name()}!",
|
231 |
+
notification_type="birthday",
|
232 |
)
|
233 |
notification.recipients.set(Bhagat.objects.all())
|
234 |
|
235 |
|
236 |
@csrf_exempt
|
237 |
def login(request):
|
238 |
+
if request.method == "POST":
|
239 |
+
username = request.POST.get("username")
|
240 |
+
password = request.POST.get("password")
|
241 |
+
captcha_response = request.POST.get("captcha_response")
|
242 |
|
243 |
# Verify captcha
|
244 |
result = gCaptchaVerifer(captcha_response)
|
245 |
if not result.get("success"):
|
246 |
+
return JsonResponse({"error": "Invalid Captcha", "status": "error"})
|
|
|
|
|
|
|
247 |
|
248 |
# Authenticate user
|
249 |
user = Bhagat.objects.filter(username=username).first()
|
|
|
251 |
# Generate tokens
|
252 |
refresh = RefreshToken.for_user(user)
|
253 |
|
254 |
+
return JsonResponse(
|
255 |
+
{
|
256 |
+
"status": "success",
|
257 |
+
"tokens": {
|
258 |
+
"access_token": str(refresh.access_token),
|
259 |
+
"refresh_token": str(refresh),
|
260 |
+
},
|
261 |
+
"user": {
|
262 |
+
"id": user.id,
|
263 |
+
"username": user.username,
|
264 |
+
"first_name": user.first_name,
|
265 |
+
"last_name": user.last_name,
|
266 |
+
"email": user.email,
|
267 |
+
"phone": user.phone,
|
268 |
+
"region": user.region.name,
|
269 |
+
"user_type": user.user_type,
|
270 |
+
"profile_image": user.profile_image,
|
271 |
+
},
|
272 |
}
|
273 |
+
)
|
|
|
|
|
|
|
|
|
|
|
274 |
|
275 |
+
return JsonResponse({"error": "Invalid credentials", "status": "error"})
|
|
|
|
|
|
|
276 |
|
277 |
+
return JsonResponse({"error": "Invalid Method", "status": "error"})
|
278 |
|
279 |
|
280 |
@csrf_exempt
|
281 |
@jwt_required()
|
282 |
def logout(request):
|
283 |
+
if request.method == "POST":
|
284 |
+
refresh_token = request.POST.get("refresh_token")
|
285 |
if not refresh_token:
|
286 |
+
return JsonResponse(
|
287 |
+
{"error": "Refresh token is required", "status": "error"}
|
288 |
+
)
|
|
|
289 |
else:
|
290 |
try:
|
291 |
refresh = RefreshToken(refresh_token)
|
292 |
refresh.blacklist()
|
293 |
+
return JsonResponse(
|
294 |
+
{"status": "success", "message": "Successfully logged out"}
|
295 |
+
)
|
296 |
+
except Exception as e:
|
297 |
+
return JsonResponse(
|
298 |
+
{"error": "Invalid token | " + str(e), "status": "error"}
|
299 |
+
)
|
300 |
+
return JsonResponse({"status": "error", "error": "Invalid Method"})
|
|
|
|
|
|
|
|
|
|
|
301 |
|
302 |
|
303 |
@jwt_required()
|
304 |
def get_user_profile(request):
|
305 |
try:
|
306 |
user = request.user
|
307 |
+
return JsonResponse(
|
308 |
+
{
|
309 |
+
"status": "success",
|
310 |
+
"user": {
|
311 |
+
"id": user.id,
|
312 |
+
"username": user.username,
|
313 |
+
"first_name": user.first_name,
|
314 |
+
"last_name": user.last_name,
|
315 |
+
"email": user.email,
|
316 |
+
"phone": user.phone,
|
317 |
+
"region": user.region.name,
|
318 |
+
"user_type": user.user_type,
|
319 |
+
"profile_image": user.profile_image,
|
320 |
+
},
|
321 |
}
|
322 |
+
)
|
323 |
except Exception as e:
|
324 |
+
return JsonResponse({"status": "error", "error": str(e)})
|
325 |
+
|
|
|
|
|
326 |
|
327 |
@csrf_exempt
|
328 |
@jwt_required()
|
329 |
def profile_updater(request):
|
330 |
+
if request.method == "POST":
|
331 |
try:
|
332 |
user = request.user
|
333 |
+
first_name = request.POST.get("first_name")
|
334 |
if first_name:
|
335 |
user.first_name = first_name
|
336 |
+
last_name = request.POST.get("last_name")
|
337 |
if last_name:
|
338 |
user.last_name = last_name
|
339 |
+
email = request.POST.get("email")
|
340 |
if email:
|
341 |
user.email = email
|
342 |
+
phone = request.POST.get("phone")
|
343 |
if phone:
|
344 |
user.phone = phone
|
345 |
+
region_name = request.POST.get("region")
|
346 |
if region_name:
|
347 |
user.region = Region.objects.get(name=region_name)
|
348 |
+
birth_date = request.POST.get("birth_date")
|
349 |
if birth_date:
|
350 |
user.birthday = birth_date
|
351 |
+
street_name = request.POST.get("street_name")
|
352 |
if street_name:
|
353 |
user.streetName = street_name
|
354 |
+
pincode = request.POST.get("pincode")
|
355 |
if pincode:
|
356 |
user.pincode = pincode
|
357 |
+
city = request.POST.get("city")
|
358 |
if city:
|
359 |
user.city = city
|
360 |
+
state = request.POST.get("state")
|
361 |
if state:
|
362 |
user.state = state
|
363 |
+
country = request.POST.get("country")
|
364 |
if country:
|
365 |
user.country = country
|
366 |
+
profile_image = request.POST.get("profile_image")
|
367 |
if profile_image:
|
368 |
user.profile_image = profile_image
|
369 |
user.save()
|
370 |
+
return JsonResponse(
|
371 |
+
{"status": "success", "message": "Profile updated successfully"}
|
372 |
+
)
|
|
|
373 |
except Exception as e:
|
374 |
+
return JsonResponse({"status": "error", "error": str(e)})
|
|
|
|
|
|
|
375 |
else:
|
376 |
user = request.user
|
377 |
+
regions = Region.objects.all()
|
378 |
+
data = {
|
379 |
"first_name": user.first_name,
|
380 |
"last_name": user.last_name,
|
381 |
"email": user.email,
|
|
|
387 |
"city": user.city,
|
388 |
"state": user.state,
|
389 |
"country": user.country,
|
390 |
+
"profile_image": user.profile_image,
|
391 |
}
|
392 |
+
return JsonResponse(
|
393 |
+
{
|
394 |
+
"status": "success",
|
395 |
+
"regions": [region.name for region in regions],
|
396 |
+
"user": data,
|
397 |
+
}
|
398 |
+
)
|
399 |
|
400 |
|
401 |
@jwt_required()
|
|
|
404 |
bhaktos = Bhagat.objects.filter(assigned_to=current_user).all()
|
405 |
bhaktoArr = []
|
406 |
for bhakto in bhaktos:
|
407 |
+
bhaktoArr.append(
|
408 |
+
{
|
409 |
+
"id": bhakto.id,
|
410 |
+
"first_name": bhakto.first_name,
|
411 |
+
"last_name": bhakto.last_name,
|
412 |
+
"region": bhakto.region.name,
|
413 |
+
"user_type": bhakto.user_type,
|
414 |
+
"profile_image": bhakto.profile_image,
|
415 |
+
}
|
416 |
+
)
|
417 |
+
return JsonResponse({"bhaktos": bhaktoArr})
|
418 |
+
|
419 |
+
|
420 |
+
@api_view(["POST"])
|
421 |
+
@permission_classes([AllowAny])
|
422 |
+
def send_otp(request):
|
423 |
+
try:
|
424 |
+
data = json.loads(request.body)
|
425 |
+
phone = data.get("phone")
|
426 |
+
|
427 |
+
if not phone:
|
428 |
+
return JsonResponse(
|
429 |
+
{"status": "error", "error": "Phone number is required"}
|
430 |
+
)
|
431 |
+
|
432 |
+
# Check if user exists
|
433 |
+
user = Bhagat.objects.filter(phone=phone).first()
|
434 |
+
if not user:
|
435 |
+
return JsonResponse(
|
436 |
+
{"status": "error", "error": "No account found with this phone number"}
|
437 |
+
)
|
438 |
+
|
439 |
+
# Generate dummy OTP (in production, use proper OTP generation and SMS service)
|
440 |
+
otp = "123456" # Dummy OTP for testing
|
441 |
+
print(f"Generated OTP for {phone}: {otp}") # This simulates sending OTP
|
442 |
+
|
443 |
+
# In production, store OTP with timestamp in database or cache
|
444 |
+
# For now, we'll just return success
|
445 |
+
return JsonResponse({"status": "success", "message": "OTP sent successfully"})
|
446 |
+
|
447 |
+
except Exception as e:
|
448 |
+
return JsonResponse({"status": "error", "error": str(e)})
|
449 |
+
|
450 |
+
|
451 |
+
@api_view(["POST"])
|
452 |
+
@permission_classes([AllowAny])
|
453 |
+
def verify_otp(request):
|
454 |
+
try:
|
455 |
+
data = json.loads(request.body)
|
456 |
+
phone = data.get("phone")
|
457 |
+
otp = data.get("otp")
|
458 |
+
|
459 |
+
if not phone or not otp:
|
460 |
+
return JsonResponse(
|
461 |
+
{"status": "error", "error": "Phone number and OTP are required"}
|
462 |
+
)
|
463 |
+
|
464 |
+
# For demo purposes, accept any 6-digit OTP
|
465 |
+
if otp == "123456": # Dummy verification
|
466 |
+
return JsonResponse(
|
467 |
+
{"status": "success", "message": "OTP verified successfully"}
|
468 |
+
)
|
469 |
+
|
470 |
+
return JsonResponse({"status": "error", "error": "Invalid OTP"})
|
471 |
+
|
472 |
+
except Exception as e:
|
473 |
+
return JsonResponse({"status": "error", "error": str(e)})
|
474 |
+
|
475 |
+
|
476 |
+
@api_view(["POST"])
|
477 |
+
@jwt_required()
|
478 |
+
@csrf_exempt
|
479 |
+
@permission_classes([AllowAny])
|
480 |
+
def change_password(request):
|
481 |
+
try:
|
482 |
+
data = json.loads(request.body)
|
483 |
+
new_password = data.get("new_password")
|
484 |
+
|
485 |
+
if not new_password:
|
486 |
+
return JsonResponse(
|
487 |
+
{
|
488 |
+
"status": "error",
|
489 |
+
"error": "Phone number and new password are required",
|
490 |
+
}
|
491 |
+
)
|
492 |
+
|
493 |
+
# Update user's password
|
494 |
+
user = request.user
|
495 |
+
if not user:
|
496 |
+
return JsonResponse({"status": "error", "error": "User not found"})
|
497 |
+
|
498 |
+
user.password = new_password
|
499 |
+
user.save()
|
500 |
+
|
501 |
+
return JsonResponse(
|
502 |
+
{"status": "success", "message": "Password changed successfully"}
|
503 |
+
)
|
504 |
+
|
505 |
+
except Exception as e:
|
506 |
+
return JsonResponse({"status": "error", "error": str(e)})
|
507 |
+
|
508 |
+
|
509 |
+
@jwt_required()
|
510 |
+
@api_view(["POST"])
|
511 |
+
@csrf_exempt
|
512 |
+
@permission_classes([AllowAny])
|
513 |
+
def save_push_subscription(request):
|
514 |
+
try:
|
515 |
+
subscription_data = json.loads(request.body)
|
516 |
+
user = request.user
|
517 |
+
pushUser = PushSubscription.objects.filter(user=user).first()
|
518 |
+
if pushUser:
|
519 |
+
pushUser.endpoint = subscription_data["endpoint"]
|
520 |
+
pushUser.p256dh = subscription_data["keys"]["p256dh"]
|
521 |
+
pushUser.auth = subscription_data["keys"]["auth"]
|
522 |
+
pushUser.save()
|
523 |
+
else:
|
524 |
+
PushSubscription.objects.create(
|
525 |
+
user=user,
|
526 |
+
endpoint=subscription_data["endpoint"],
|
527 |
+
p256dh=subscription_data["keys"]["p256dh"],
|
528 |
+
auth=subscription_data["keys"]["auth"],
|
529 |
+
)
|
530 |
+
return JsonResponse({"status": "success"})
|
531 |
+
except Exception as e:
|
532 |
+
return JsonResponse({"status": "error", "message": str(e)})
|
533 |
+
|
534 |
+
|
535 |
+
def send_push_notification(subscription, message):
|
536 |
+
try:
|
537 |
+
webpush(
|
538 |
+
subscription_info={
|
539 |
+
"endpoint": subscription.endpoint,
|
540 |
+
"keys": {"p256dh": subscription.p256dh, "auth": subscription.auth},
|
541 |
+
},
|
542 |
+
data=json.dumps(message),
|
543 |
+
vapid_private_key=settings.WEBPUSH_SETTINGS["VAPID_PRIVATE_KEY"],
|
544 |
+
vapid_claims={
|
545 |
+
"sub": f"mailto:{settings.WEBPUSH_SETTINGS['VAPID_ADMIN_EMAIL']}"
|
546 |
+
},
|
547 |
+
)
|
548 |
+
except WebPushException as e:
|
549 |
+
print(f"Web push failed: {e}")
|
550 |
+
|
551 |
+
|
552 |
+
@api_view(["GET", "POST"])
|
553 |
+
@jwt_required()
|
554 |
+
@csrf_exempt
|
555 |
+
@permission_classes([AllowAny])
|
556 |
+
def polls(request):
|
557 |
+
if request.method == "GET":
|
558 |
+
user = request.user
|
559 |
+
polls = Poll.objects.filter(participants=user)
|
560 |
+
pollArr = []
|
561 |
+
for poll in polls:
|
562 |
+
tempPoll = {}
|
563 |
+
tempPoll["id"] = poll.id
|
564 |
+
tempPoll["question"] = poll.question
|
565 |
+
tempPoll["options"] = []
|
566 |
+
for option in poll.options.all():
|
567 |
+
tempOption = {}
|
568 |
+
tempOption["id"] = option.id
|
569 |
+
tempOption["optionText"] = option.optionText
|
570 |
+
tempOption["count"] = option.voters.all().count()
|
571 |
+
tempOption["precentage"] = (
|
572 |
+
option.voters.all().count() / poll.participants.all().count()
|
573 |
+
) * 100
|
574 |
+
tempOption["voters"] = []
|
575 |
+
for voter in option.voters.all()[:2]:
|
576 |
+
tempOption["voters"].append(
|
577 |
+
{
|
578 |
+
"id": voter.profile_image,
|
579 |
+
"first_name": voter.first_name,
|
580 |
+
"last_name": voter.last_name,
|
581 |
+
"profile_image": voter.profile_image,
|
582 |
+
}
|
583 |
+
)
|
584 |
+
tempPoll["options"].append(tempOption)
|
585 |
+
tempPoll["created_by"] = {
|
586 |
+
"id": poll.created_by.profile_image,
|
587 |
+
"first_name": poll.created_by.first_name,
|
588 |
+
"last_name": poll.created_by.last_name,
|
589 |
+
"profile_image": poll.created_by.profile_image,
|
590 |
+
}
|
591 |
+
tempPoll["created_at"] = poll.created_at
|
592 |
+
pollArr.append(tempPoll)
|
593 |
+
return JsonResponse({"data": pollArr})
|
594 |
+
if request.method == "POST":
|
595 |
+
data = json.loads(request.body)
|
596 |
+
user = request.user
|
597 |
+
poll = Poll.objects.get(id=id)
|
598 |
+
option = OptionPoll.objects.get(id=data.get("option"))
|
599 |
+
option.votes.add(user)
|
600 |
+
return JsonResponse(
|
601 |
+
{"status": "success", "message": "Vote submitted successfully"}
|
602 |
+
)
|
603 |
+
|
604 |
+
|
605 |
+
@api_view(["GET"])
|
606 |
+
@jwt_required()
|
607 |
+
@permission_classes([AllowAny])
|
608 |
+
def voterList(request, id):
|
609 |
+
poll = Poll.objects.filter(participants=user).get(id=id)
|
610 |
+
if not poll:
|
611 |
+
return JsonResponse(
|
612 |
+
{"error": "Poll may not exist or you may not have access to it"}
|
613 |
+
)
|
614 |
+
else:
|
615 |
+
user = request.user
|
616 |
+
options = poll.options.all()
|
617 |
+
optionsList = []
|
618 |
+
for option in options:
|
619 |
+
tempOption = {}
|
620 |
+
tempOption["id"] = option.id
|
621 |
+
tempOption["optionText"] = option.optionText
|
622 |
+
tempOption["voters"] = []
|
623 |
+
for voter in option.voters.all():
|
624 |
+
tempOption["voters"].append(
|
625 |
+
{
|
626 |
+
"id": voter.profile_image,
|
627 |
+
"first_name": voter.first_name,
|
628 |
+
"last_name": voter.last_name,
|
629 |
+
"profile_image": voter.profile_image,
|
630 |
+
}
|
631 |
+
)
|
632 |
+
return JsonResponse({"data": optionsList})
|
downloads/1.jpg
DELETED
Git LFS Details
|
downloads/10.png
DELETED
Binary file (835 kB)
|
|
downloads/100.png
DELETED
Git LFS Details
|
downloads/101.png
DELETED
Git LFS Details
|
downloads/102.png
DELETED
Git LFS Details
|
downloads/103.png
DELETED
Git LFS Details
|
downloads/104.png
DELETED
Git LFS Details
|
downloads/105.png
DELETED
Git LFS Details
|
downloads/106.png
DELETED
Git LFS Details
|
downloads/107.png
DELETED
Git LFS Details
|
downloads/108.png
DELETED
Git LFS Details
|
downloads/109.jpg
DELETED
Binary file (500 kB)
|
|
downloads/11.png
DELETED
Git LFS Details
|