django-chelseru 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. django_chelseru-1.0.2.dist-info/METADATA +95 -0
  2. django_chelseru-1.0.2.dist-info/RECORD +22 -0
  3. django_chelseru-1.0.2.dist-info/top_level.txt +1 -0
  4. drfchelseru/admin.py +24 -0
  5. drfchelseru/apps.py +9 -0
  6. drfchelseru/middlewares.py +44 -0
  7. drfchelseru/migrations/0001_initial.py +33 -0
  8. drfchelseru/migrations/0002_otpcode_session_user.py +92 -0
  9. drfchelseru/migrations/0003_rename_mobile_otpcode_mobile_number.py +18 -0
  10. drfchelseru/models.py +77 -0
  11. drfchelseru/serializers.py +34 -0
  12. drfchelseru/services.py +239 -0
  13. drfchelseru/settings.py +187 -0
  14. drfchelseru/signals.py +38 -0
  15. drfchelseru/urls.py +11 -0
  16. drfchelseru/validators.py +15 -0
  17. drfchelseru/views.py +213 -0
  18. django_chelseru-1.0.0.dist-info/METADATA +0 -56
  19. django_chelseru-1.0.0.dist-info/RECORD +0 -31
  20. django_chelseru-1.0.0.dist-info/top_level.txt +0 -3
  21. drf_chelseru_auth/admin.py +0 -3
  22. drf_chelseru_auth/apps.py +0 -6
  23. drf_chelseru_auth/models.py +0 -3
  24. drf_chelseru_auth/views.py +0 -3
  25. drf_chelseru_chat/__init__.py +0 -0
  26. drf_chelseru_chat/admin.py +0 -5
  27. drf_chelseru_chat/apps.py +0 -6
  28. drf_chelseru_chat/consumers.py +0 -82
  29. drf_chelseru_chat/middleware.py +0 -33
  30. drf_chelseru_chat/migrations/0001_initial.py +0 -36
  31. drf_chelseru_chat/migrations/__init__.py +0 -0
  32. drf_chelseru_chat/models.py +0 -23
  33. drf_chelseru_chat/routing.py +0 -6
  34. drf_chelseru_chat/serializers.py +0 -26
  35. drf_chelseru_chat/urls.py +0 -12
  36. drf_chelseru_chat/views.py +0 -59
  37. drf_chelseru_sms/__init__.py +0 -0
  38. drf_chelseru_sms/admin.py +0 -3
  39. drf_chelseru_sms/apps.py +0 -6
  40. drf_chelseru_sms/migrations/__init__.py +0 -0
  41. drf_chelseru_sms/models.py +0 -3
  42. drf_chelseru_sms/tests.py +0 -3
  43. drf_chelseru_sms/views.py +0 -3
  44. {django_chelseru-1.0.0.dist-info → django_chelseru-1.0.2.dist-info}/WHEEL +0 -0
  45. {django_chelseru-1.0.0.dist-info → django_chelseru-1.0.2.dist-info}/licenses/LICENSE +0 -0
  46. {drf_chelseru_auth → drfchelseru}/__init__.py +0 -0
  47. {drf_chelseru_auth → drfchelseru}/migrations/__init__.py +0 -0
  48. {drf_chelseru_auth → drfchelseru}/tests.py +0 -0
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-chelseru
3
+ Version: 1.0.2
4
+ Summary: Authentication system, online and real-time chat, SMS system for Iranian SMS services.
5
+ Home-page: https://pipdjango.chelseru.com
6
+ Author: Sobhan Bahman|Rashnu
7
+ Author-email: bahmanrashnu@gmail.com
8
+ Project-URL: Documentation, https://github.com/Chelseru/django-chelseru-lour/
9
+ Project-URL: Telegram Group, https://t.me/bahmanpy
10
+ Project-URL: Telegram Channel, https://t.me/ChelseruCom
11
+ Keywords: djangochelseruchat djangochat drfchat online-chat online real-time chat iran chelseru lor lur bahman rashnu lour sms djangoauth auth ywt otpauth otp authentication djangootp djangoiransms iransms djangosms djangokavenegar djangomelipayamak sobhan چت سبحان بهمن رشنو چلسرو جنگو پایتون لر لور آنلاین ریل تایم
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Framework :: Django
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: Django>=5.1.6
20
+ Requires-Dist: djangorestframework==3.15.2
21
+ Requires-Dist: djangorestframework_simplejwt==5.5.0
22
+ Requires-Dist: channels==4.2.2
23
+ Requires-Dist: channels_redis==4.2.1
24
+ Requires-Dist: daphne==4.1.2
25
+ Requires-Dist: zeep==4.3.1
26
+ Requires-Dist: user-agents==2.2.0
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: description-content-type
32
+ Dynamic: home-page
33
+ Dynamic: keywords
34
+ Dynamic: license-file
35
+ Dynamic: project-url
36
+ Dynamic: requires-dist
37
+ Dynamic: requires-python
38
+ Dynamic: summary
39
+
40
+ django-chelseruیک بسته جنگویی برای گپ‌زنی همزمان، راستی‌آزمایی پیامکی و فرستادن پیامک با یاری‌دهنده‌های ایرانی.نویسندهSobhan Bahman Rashnu🚀 ویژگی‌ها📱 راستی‌آزمایی پیامکی (رمز یک‌بارمصرف): راستی‌آزمایی امن کاربران با یاری‌گیری از رمزهای یک‌بارمصرف که از راه پیامک فرستاده می‌شوند.💬 گپ‌زنی همزمان: کارکرد پیام‌رسانی همزمان بر پایه WebSocket.✉️ سامانه‌های پیامکی: فرستادن پیامک از راه یاری‌دهنده‌های نامور پیامکی ایرانی.⚙️ نصببسته را با یاری‌گیری از pip نصب کنید:pip install django-chelseru
41
+ 'drfchelseru' را به INSTALLED_APPS در پرونده settings.py خود بیفزایید:INSTALLED_APPS = [
42
+ ...
43
+ 'channels',
44
+ 'rest_framework',
45
+ 'rest_framework_simplejwt',
46
+ 'drfchelseru',
47
+ ...
48
+ ]
49
+ 🛠️ پیکربندیبرای پیکربندی بسته، واژه‌نامه DJANGO_CHELSERU را به پرونده settings.py خود بیفزایید. این واژه‌نامه به شما پروانه می‌دهد تا چیدمان‌های راستی‌آزمایی و پیامک را خودساخته نمایید.# settings.py
50
+
51
+ DJANGO_CHELSERU = {
52
+ 'AUTH': {
53
+ 'AUTH_METHOD' : 'OTP', # روش‌های پشتیبانی شده: OTP, PASSWD
54
+ 'AUTH_SERVICE' : 'rest_framework_simplejwt', # سرویس‌های پشتیبانی شده: rest_framework_simplejwt
55
+ 'OPTIONS': {
56
+ 'OTP_LENGTH' : 8, # پیش‌فرض: 8
57
+ 'OTP_EXPIRE_PER_MINUTES': 4, # پیش‌فرض: 4
58
+ 'OTP_SMS_TEMPLATE_ID' : 1, # شناسه قالب پیامکی برای رمز یک‌بارمصرف
59
+ }
60
+ },
61
+ 'SMS': {
62
+ 'SMS_SERVICE': 'PARSIAN_WEBCO_IR', # یاری‌دهنده‌های پشتیبانی شده: PARSIAN_WEBCO_IR, MELI_PAYAMAK_COM, KAVENEGAR_COM
63
+ 'SETTINGS': {
64
+ 'PARSIAN_WEBCO_IR_API_KEY' : 'YOUR_PARSIAN_WEBCO_API_KEY',
65
+ 'MELI_PAYAMAK_COM_USERNAME' : 'YOUR_MELI_PAYAMAK_USERNAME',
66
+ 'MELI_PAYAMAK_COM_PASSWORD' : 'YOUR_MELI_PAYAMAK_PASSWORD',
67
+ 'MELI_PAYAMAK_COM_FROM' : 'YOUR_MELI_PAYAMAK_FROM_NUMBER',
68
+ 'KAVENEGAR_COM_API_KEY' : 'YOUR_KAVENEGAR_API_KEY',
69
+ 'KAVENEGAR_COM_FROM' : 'YOUR_KAVENEGAR_FROM_NUMBER',
70
+ },
71
+ 'TEMPLATES': {
72
+ 'T1': 1,
73
+ 'T2': 2,
74
+ ...
75
+ }
76
+ }
77
+ }
78
+ AUTH_METHOD: روش راستی‌آزمایی را روشن می‌سازد. برای راستی‌آزمایی پیامکی، از 'OTP' بهره بگیرید.OTP_LENGTH: درازای رمز یک‌بارمصرف.OTP_EXPIRE_PER_MINUTES: زمان پایان‌یافتن رمز یک‌بارمصرف بر پایه دقیقه.OTP_SMS_TEMPLATE_ID: شناسه قالب پیامکی که برای فرستادن رمز یک‌بارمصرف بهره گرفته می‌شود.SMS_SERVICE: یاری‌دهنده پیامکی دلخواه خود را برگزینید.SETTINGS: آگاهی‌های نیاز برای یاری‌دهنده پیامکی برگزیده‌تان را فراهم آورید.TEMPLATES: شناسه‌های قالب پیامکی خود را روشن سازید.🔌 نقطه‌های پایانیبرای به کارگیری کارکردهای این بسته، URLهای زیر را به پرونده urls.py خود بیفزایید.# urls.py
79
+
80
+ from django.urls import path, include
81
+
82
+ urlpatterns = [
83
+ ...
84
+ path('api/', include('drfchelseru.urls')),
85
+ ...
86
+ ]
87
+ این بسته نقطه‌های پایانی API زیر را فراهم می‌آورد:نقطه‌ پایانیشرحروش/api/otp/send/یک رمز یک‌بارمصرف به شماره همراه گفته‌شده می‌فرستد.POST/api/authenticate/کاربری را با رمز یک‌بارمصرف دریافت‌شده، راستی‌آزمایی می‌کند.POST/api/sessions/نشست‌های فعال کاربر را فهرست کرده و درایوری می‌کند.GET/api/message/send/یک پیامک با یاری‌دهنده پیکربندی‌شده می‌فرستد.POSTبه کارگیری نقطه‌های پایانی1. فرستادن رمز یک‌بارمصرف (/api/otp/send/)روش: POSTشرح: یک رمز یک‌بارمصرف به شماره همراه کاربر می‌فرستد.داده‌نماهای نیاز:داده‌نماگونهشرحنمونهmobile_numberstrشماره همراه کاربر.09121234567پاسخ‌ها:HTTP 200 OK: رمز یک‌بارمصرف با کامیابی فرستاده شد.{"details": "The OTP code was sent correctly."}
88
+ HTTP 400 BAD REQUEST: ساختار نادرست mobile_number.HTTP 409 CONFLICT: یک رمز یک‌بارمصرف پیش‌تر فرستاده شده و هنوز روایی دارد.{"details": "An OTP code has already been sent. Please wait X seconds before trying again."}
89
+ HTTP 500 INTERNAL SERVER ERROR: یک دشواری در کارگذار پیش آمده است.2. راستی‌آزمایی (/api/authenticate/)روش: POSTشرح: کاربر را با رمز یک‌بارمصرف فراهم شده، راستی‌آزمایی می‌کند. اگر با کامیابی انجام شود، توکن‌های JWT (access و refresh) را بازمی‌گرداند.داده‌نماهای نیاز:داده‌نماگونهشرحنمونهmobile_numberstrشماره همراه کاربر.09121234567codestrرمز یک‌بارمصرف دریافت شده از راه پیامک.12345678groupintاختیاری: یک شناسه دسته برای کاربر.1پاسخ‌ها:HTTP 200 OK: راستی‌آزمایی با کامیابی انجام شد.{
90
+ "access": "...",
91
+ "refresh": "..."
92
+ }
93
+ HTTP 401 UNAUTHORIZED: رمز یک‌بارمصرف ناروا یا پایان‌یافته.{"error": "The code sent to this mobile number was not found."}
94
+ HTTP 400 BAD REQUEST: داده‌نماهای نیاز ناپیدا یا ساختار نادرست.HTTP 500 INTERNAL SERVER ERROR: یک دشواری در کارگذار پیش آمده است.3. فرستادن پیامک (/api/message/send/)روش: POSTشرح: یک پیامک خودساخته را با یاری‌دهنده پیکربندی‌شده می‌فرستد.داده‌نماهای نیاز:داده‌نماگونهشرحنمونهmobile_numberstrشماره همراه گیرنده.09121234567message_textstrنوشتار پیام. (بیشینه ۲۹۰ نویسه)Hello, World!template_idintبرای برخی یاری‌دهنده‌ها (برای نمونه پارسیان) نیاز است.1پاسخ‌ها:HTTP 200 OK: پیام با کامیابی فرستاده شد.{"details": "The Message was sent correctly."}
95
+ HTTP 400 BAD REQUEST: دشواری‌های درست‌سنجی برای داده‌نماها.HTTP 401 UNAUTHORIZED: راستی‌آزمایی انجام نشد.HTTP 500 INTERNAL SERVER ERROR: یک دشواری در کارگذار پیش آمده است.HTTP 502 BAD GATEWAY: یاری‌دهنده پیامکی یک دشواری را بازگرداند.4. فهرست نشست‌ها (/api/sessions/)روش: GETشرح: همه نشست‌های فعال کاربران را فهرست می‌کند. نیاز به راستی‌آزمایی (IsAuthenticated) دارد.سربرگ‌های نیاز:سربرگارزشAuthorizationBearer <your_access_token>💡 مدل‌هااین بسته یک مدل Session برای درایوری نشست‌های فعال کاربران دارد. می‌توانید به این نشست‌ها از راه نقطه‌ پایانی /api/sessions/ دسترسی یافته و آنها را درایوری کنید.
@@ -0,0 +1,22 @@
1
+ django_chelseru-1.0.2.dist-info/licenses/LICENSE,sha256=VupU5KV4NteHaNQb-WH31G_WZWezxXoomjiCIAHoQJo,1089
2
+ drfchelseru/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ drfchelseru/admin.py,sha256=PmHIgD7XSObOTd9xx6_lgEfAr4Z_2bvkrnrHby1ZdK8,741
4
+ drfchelseru/apps.py,sha256=hOTTzFGLXiTPZeN8p_LLcSECLtsR2Q0SUo8zJzgM-qQ,211
5
+ drfchelseru/middlewares.py,sha256=ONzRCiiHrUicDXFVds2aTROb6QBIcWZyW_jXQgrAQAc,1450
6
+ drfchelseru/models.py,sha256=ffTiDI7a1rVMjMFeeZqBqbkCsciwnKCowf2u8vj6VRs,2774
7
+ drfchelseru/serializers.py,sha256=wYbvFmZuQzGEgi9S6B-kPuIAXJDcir6qKQuV6RgE3J4,769
8
+ drfchelseru/services.py,sha256=V8mdeeHjmqUFAQLAyaEm3JTk-E8V8SfQMQhXoYdjt_c,10134
9
+ drfchelseru/settings.py,sha256=pvGW6aMCrkW9kph_Zw6B_9qYeWb7wuIrUM1Lnu8kjhU,9055
10
+ drfchelseru/signals.py,sha256=2jISUF_jQVZD06tOqHasXtneZKVCrpeIJQeHo9BjLc0,1428
11
+ drfchelseru/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
12
+ drfchelseru/urls.py,sha256=SbSVU75NXNoH6YWvJrJbuo3kc6jgremOS8g0CLmk52w,410
13
+ drfchelseru/validators.py,sha256=jAJASfG4kPcqrGxxIcoR8VjS4L4n_EzZuxJtQ1g9qmo,480
14
+ drfchelseru/views.py,sha256=L_KcoHe_5SAJ-2xaRcYYL_V1Jgk1PwKJztV4wXpMa0s,10726
15
+ drfchelseru/migrations/0001_initial.py,sha256=LfkWAeQuPXNW3_igM-w_pyKafCeHQF3aReYgMXfMzEE,1034
16
+ drfchelseru/migrations/0002_otpcode_session_user.py,sha256=c3oyBTQo2kjsKr5r_XQrqaq-66F7pui-4H4mEyAXgJk,3126
17
+ drfchelseru/migrations/0003_rename_mobile_otpcode_mobile_number.py,sha256=eiD7t6etg6nOeT7BhJrSfEcR1yTPePXtATgtyu30520,377
18
+ drfchelseru/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ django_chelseru-1.0.2.dist-info/METADATA,sha256=iHcgLyl_b4q8kf4_VBN7YgHYxwnwG4OzADoCPqy7wWE,9553
20
+ django_chelseru-1.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
+ django_chelseru-1.0.2.dist-info/top_level.txt,sha256=fsaO1F03W3j4AYi0TfDGv5Cjb_Qrh6RSkwkWqfqaMns,12
22
+ django_chelseru-1.0.2.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ drfchelseru
drfchelseru/admin.py ADDED
@@ -0,0 +1,24 @@
1
+ from django.contrib import admin
2
+ from .models import User, OTPCode, Session, Message
3
+
4
+ @admin.register(User)
5
+ class MobileAdmin(admin.ModelAdmin):
6
+ list_display = ['id', 'user__id', 'user__username', 'mobile', 'user__is_active']
7
+
8
+
9
+ @admin.register(OTPCode)
10
+ class OTPCodeAdmin(admin.ModelAdmin):
11
+ list_display = ['id', 'code', 'mobile_number', 'created_at']
12
+ ordering = ('-created_at', )
13
+
14
+
15
+ @admin.register(Session)
16
+ class SessionAdmin(admin.ModelAdmin):
17
+ list_display = ['id', 'user__id', 'user__username', 'ip_address', 'last_seen']
18
+ ordering = ('-created_at', )
19
+
20
+ @admin.register(Message)
21
+ class MessageAdmin(admin.ModelAdmin):
22
+ list_display = ['id', 'mobile_number', 'message_text', 'status']
23
+ ordering = ('-created_at', )
24
+
drfchelseru/apps.py ADDED
@@ -0,0 +1,9 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class DrfchelseruConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "drfchelseru"
7
+
8
+ def ready(self):
9
+ import drfchelseru.signals
@@ -0,0 +1,44 @@
1
+ from django.utils.timezone import datetime
2
+ from .models import Session
3
+ import user_agents
4
+
5
+
6
+ class TakeUserSessionMiddlaware:
7
+ def __init__(self, get_response):
8
+ self.get_response = get_response
9
+
10
+ def __call__(self, request):
11
+ response = self.get_response(request)
12
+
13
+ if request.user.is_authenticated:
14
+ user_agent = request.META.get('HTTP_USER_AGENT', '')
15
+ ip = self.get_client_ip(request)
16
+
17
+ if not request.session.session_key:
18
+ request.session.create()
19
+
20
+ session_key = request.session.session_key
21
+
22
+ session, created = Session.objects.get_or_create(
23
+ user = request.user,
24
+ session_key = session_key,
25
+ defaults = {
26
+ 'user_agent': user_agent,
27
+ 'ip_address': ip,
28
+ 'device': user_agents.parse(user_agent).device.family,
29
+ 'browser': user_agents.parse(user_agent).browser.family,
30
+ }
31
+ )
32
+
33
+ session.user_agent = user_agent
34
+ session.ip_address = ip
35
+ session.last_seen = datetime.now()
36
+ session.save()
37
+
38
+ return response
39
+
40
+ def get_client_ip(self, request):
41
+ x_forwarded_for = request.META.get('X_FORWARDED_FOR')
42
+ if x_forwarded_for:
43
+ return x_forwarded_for.split(',')[0]
44
+ return request.META.get('REMOTE_ADDR')
@@ -0,0 +1,33 @@
1
+ # Generated by Django 5.1.6 on 2025-08-12 01:59
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ initial = True
9
+
10
+ dependencies = []
11
+
12
+ operations = [
13
+ migrations.CreateModel(
14
+ name="Message",
15
+ fields=[
16
+ (
17
+ "id",
18
+ models.BigAutoField(
19
+ auto_created=True,
20
+ primary_key=True,
21
+ serialize=False,
22
+ verbose_name="ID",
23
+ ),
24
+ ),
25
+ ("message_text", models.TextField()),
26
+ ("mobile_number", models.CharField(max_length=20)),
27
+ ("_from", models.CharField(blank=True, max_length=20, null=True)),
28
+ ("status", models.CharField(blank=True, max_length=20, null=True)),
29
+ ("updated_at", models.DateTimeField(auto_now=True)),
30
+ ("created_at", models.DateTimeField(auto_now_add=True)),
31
+ ],
32
+ ),
33
+ ]
@@ -0,0 +1,92 @@
1
+ # Generated by Django 5.1.6 on 2025-08-12 02:29
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
+ ("drfchelseru", "0001_initial"),
12
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name="OTPCode",
18
+ fields=[
19
+ (
20
+ "id",
21
+ models.BigAutoField(
22
+ auto_created=True,
23
+ primary_key=True,
24
+ serialize=False,
25
+ verbose_name="ID",
26
+ ),
27
+ ),
28
+ ("code", models.CharField(max_length=10)),
29
+ ("mobile", models.CharField(max_length=11)),
30
+ ("created_at", models.DateTimeField(auto_now_add=True)),
31
+ ],
32
+ ),
33
+ migrations.CreateModel(
34
+ name="Session",
35
+ fields=[
36
+ (
37
+ "id",
38
+ models.BigAutoField(
39
+ auto_created=True,
40
+ primary_key=True,
41
+ serialize=False,
42
+ verbose_name="ID",
43
+ ),
44
+ ),
45
+ ("session_key", models.CharField(max_length=40, unique=True)),
46
+ ("user_agent", models.TextField()),
47
+ ("ip_address", models.GenericIPAddressField()),
48
+ ("device", models.TextField()),
49
+ ("browser", models.TextField()),
50
+ ("last_seen", models.DateTimeField(auto_now=True)),
51
+ ("created_at", models.DateTimeField(auto_now_add=True)),
52
+ (
53
+ "user",
54
+ models.ForeignKey(
55
+ on_delete=django.db.models.deletion.DO_NOTHING,
56
+ related_name="session_drf_chelseru",
57
+ to=settings.AUTH_USER_MODEL,
58
+ ),
59
+ ),
60
+ ],
61
+ ),
62
+ migrations.CreateModel(
63
+ name="User",
64
+ fields=[
65
+ (
66
+ "id",
67
+ models.BigAutoField(
68
+ auto_created=True,
69
+ primary_key=True,
70
+ serialize=False,
71
+ verbose_name="ID",
72
+ ),
73
+ ),
74
+ ("mobile", models.CharField(max_length=11)),
75
+ (
76
+ "group",
77
+ models.IntegerField(
78
+ default=0,
79
+ help_text="choice group type or user level, with numbers.",
80
+ ),
81
+ ),
82
+ (
83
+ "user",
84
+ models.OneToOneField(
85
+ on_delete=django.db.models.deletion.CASCADE,
86
+ related_name="mobile_drf_chelseru",
87
+ to=settings.AUTH_USER_MODEL,
88
+ ),
89
+ ),
90
+ ],
91
+ ),
92
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.1.6 on 2025-08-12 03:15
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("drfchelseru", "0002_otpcode_session_user"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name="otpcode",
15
+ old_name="mobile",
16
+ new_name="mobile_number",
17
+ ),
18
+ ]
drfchelseru/models.py ADDED
@@ -0,0 +1,77 @@
1
+ from django.db import models
2
+ from django.contrib.auth.models import User as default_user
3
+ from django.utils.timezone import now, timedelta
4
+ from random import randint
5
+ from .settings import auth_init_check
6
+
7
+
8
+ class User(models.Model):
9
+ user = models.OneToOneField(default_user, on_delete=models.CASCADE, related_name='mobile_drf_chelseru')
10
+ mobile = models.CharField(max_length=11)
11
+ group = models.IntegerField(default=0, help_text='choice group type or user level, with numbers.')
12
+
13
+ def __str__(self):
14
+ return f'{self.user.username} | {self.mobile}'
15
+
16
+
17
+ class OTPCode(models.Model):
18
+ code = models.CharField(max_length=10)
19
+ mobile_number = models.CharField(max_length=11)
20
+ created_at = models.DateTimeField(auto_now_add=True)
21
+
22
+ def __str__(self):
23
+ return f'{self.code} -> {self.mobile_number} | {self.created_at}'
24
+
25
+ def save(self, *args, **kwargs):
26
+ """
27
+ Generates a new random code if one does not already exist.
28
+ """
29
+ if not self.code:
30
+ icheck = auth_init_check()
31
+ if icheck and isinstance(icheck, dict):
32
+ otp_len = icheck['OPTIONS']['len']
33
+ otp_exp_time = icheck['OPTIONS']['exp_time']
34
+
35
+ self.code = str(randint(int('1' + (otp_len - 1) * '0'), int(otp_len * '9')))
36
+ super().save(*args, **kwargs)
37
+
38
+ def check_code(self):
39
+ try:
40
+ icheck = auth_init_check()
41
+ if icheck and isinstance(icheck, dict):
42
+ otp_exp_time = icheck['OPTIONS']['exp_time']
43
+ if now().timestamp() <= (self.created_at + timedelta(seconds=otp_exp_time * 60)).timestamp():
44
+ self.delete()
45
+ return True
46
+ self.delete()
47
+ except:
48
+ pass
49
+ return False
50
+
51
+
52
+ class Session(models.Model):
53
+ user = models.ForeignKey(default_user, models.DO_NOTHING, related_name='session_drf_chelseru')
54
+ session_key = models.CharField(max_length=40, unique=True)
55
+ user_agent = models.TextField()
56
+ ip_address = models.GenericIPAddressField()
57
+ device = models.TextField()
58
+ browser = models.TextField()
59
+
60
+ last_seen = models.DateTimeField(auto_now=True)
61
+ created_at = models.DateTimeField(auto_now_add = True)
62
+
63
+ def __str__(self):
64
+ return f'{self.user} - {self.ip_address}'
65
+
66
+
67
+ class Message(models.Model):
68
+ message_text = models.TextField()
69
+ mobile_number = models.CharField(max_length=20)
70
+ _from = models.CharField(max_length=20, blank=True, null=True)
71
+ status = models.CharField(max_length=20, blank=True, null=True)
72
+
73
+ updated_at = models.DateTimeField(auto_now=True)
74
+ created_at = models.DateTimeField(auto_now_add=True)
75
+
76
+ def __str__(self):
77
+ return f'to: {self.mobile_number} , at: {self.created_at}'
@@ -0,0 +1,34 @@
1
+ from rest_framework.serializers import ModelSerializer
2
+ from django.contrib.auth.models import User
3
+ from .models import User as mobile, OTPCode, Session, Message
4
+
5
+
6
+ class DefaultUserSerializer(ModelSerializer):
7
+ class Meta:
8
+ model = User
9
+ fields = '__all__'
10
+
11
+
12
+ class MobileSerializer(ModelSerializer):
13
+ class Meta:
14
+ model = mobile
15
+ fields = '__all__'
16
+ depth = 1
17
+
18
+ class OTPCodeSerializer(ModelSerializer):
19
+ class Meta:
20
+ model = OTPCode
21
+ fields = '__all__'
22
+ read_only_fields = ('code', )
23
+
24
+
25
+ class SessionSerializer(ModelSerializer):
26
+ class Meta:
27
+ model = Session
28
+ fields = '__all__'
29
+
30
+
31
+ class MessageSerializer(ModelSerializer):
32
+ class Meta:
33
+ model = Message
34
+ fields = '__all__'