mirror of
https://github.com/lemeow125/DRF_Template.git
synced 2024-11-17 04:09:25 +08:00
Compare commits
6 commits
069aba80b1
...
c567582124
Author | SHA1 | Date | |
---|---|---|---|
c567582124 | |||
1c20a68cb0 | |||
1c1a5ae1c4 | |||
aa52da056c | |||
d126fdbd32 | |||
0184530802 |
41 changed files with 205 additions and 1646 deletions
12
Dockerfile
12
Dockerfile
|
@ -1,4 +1,4 @@
|
||||||
FROM python:3.11.9-bookworm
|
FROM python:3.13.0-bullseye
|
||||||
|
|
||||||
ENV PYTHONBUFFERED=1
|
ENV PYTHONBUFFERED=1
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
@ -6,12 +6,8 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
COPY . /code/
|
COPY . /code/
|
||||||
ADD . /code/
|
ADD . /code/
|
||||||
COPY start.sh /code/
|
COPY scripts/ /code/scripts/
|
||||||
RUN chmod +x /code/start.sh
|
RUN chmod +x /code/scripts/start.sh
|
||||||
|
|
||||||
# Fix permissions with /tmp
|
|
||||||
RUN chown root:root /tmp
|
|
||||||
RUN chmod 1777 /tmp
|
|
||||||
|
|
||||||
# Install packages
|
# Install packages
|
||||||
RUN apt update && apt install -y graphviz libgraphviz-dev graphviz-dev wget zip chromium chromium-driver firefox-esr
|
RUN apt update && apt install -y graphviz libgraphviz-dev graphviz-dev wget zip chromium chromium-driver firefox-esr
|
||||||
|
@ -26,4 +22,4 @@ RUN chmod +x /usr/bin/geckodriver
|
||||||
# Expose port 8000 for the web server
|
# Expose port 8000 for the web server
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
ENTRYPOINT [ "/code/start.sh" ]
|
ENTRYPOINT [ "/code/scripts/start.sh" ]
|
43
Pipfile
43
Pipfile
|
@ -1,43 +0,0 @@
|
||||||
[[source]]
|
|
||||||
url = "https://pypi.org/simple"
|
|
||||||
verify_ssl = true
|
|
||||||
name = "pypi"
|
|
||||||
|
|
||||||
[packages]
|
|
||||||
django = "*"
|
|
||||||
djangorestframework = "*"
|
|
||||||
python-dotenv = "*"
|
|
||||||
whitenoise = "*"
|
|
||||||
djoser = "*"
|
|
||||||
django-cors-headers = "*"
|
|
||||||
drf-spectacular = {version = "*", extras = ["sidecar"]}
|
|
||||||
django-extra-fields = "*"
|
|
||||||
pillow = "*"
|
|
||||||
psycopg2 = "*"
|
|
||||||
django-simple-history = "*"
|
|
||||||
django-unfold = "*"
|
|
||||||
django-resized = "*"
|
|
||||||
stripe = "*"
|
|
||||||
celery = "*"
|
|
||||||
selenium = "*"
|
|
||||||
undetected-chromedriver = "*"
|
|
||||||
2captcha-python = "*"
|
|
||||||
python-whois = "*"
|
|
||||||
django-celery-beat = "*"
|
|
||||||
flower = "*"
|
|
||||||
kombu = "*"
|
|
||||||
redis = "*"
|
|
||||||
django-storages = "*"
|
|
||||||
django-extensions = "*"
|
|
||||||
django-celery-results = "*"
|
|
||||||
pygraphviz = "*"
|
|
||||||
gunicorn = "*"
|
|
||||||
django-silk = "*"
|
|
||||||
django-redis = "*"
|
|
||||||
granian = "*"
|
|
||||||
black = "*"
|
|
||||||
|
|
||||||
[dev-packages]
|
|
||||||
|
|
||||||
[requires]
|
|
||||||
python_version = "3.11"
|
|
1407
Pipfile.lock
generated
1407
Pipfile.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
|
||||||
from .models import CustomUser
|
from .models import CustomUser
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
from django.db import models
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
|
||||||
from django.urls import reverse
|
|
||||||
from django_resized import ResizedImageField
|
|
||||||
from django.utils import timezone
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils import timezone
|
||||||
|
from django_resized import ResizedImageField
|
||||||
|
|
||||||
|
|
||||||
class CustomUser(AbstractUser):
|
class CustomUser(AbstractUser):
|
||||||
# first_name inherited from base user class
|
# first_name inherited from base user class
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
from djoser.serializers import UserSerializer as BaseUserSerializer
|
|
||||||
from rest_framework.serializers import ModelSerializer
|
|
||||||
from rest_framework import serializers
|
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
from drf_extra_fields.fields import Base64ImageField
|
|
||||||
from user_groups.serializers import SimpleUserGroupSerializer
|
|
||||||
from django.core.cache import cache
|
|
||||||
from django.core import exceptions as django_exceptions
|
|
||||||
from rest_framework.settings import api_settings
|
|
||||||
from django.contrib.auth.password_validation import validate_password
|
from django.contrib.auth.password_validation import validate_password
|
||||||
|
from django.core import exceptions as django_exceptions
|
||||||
|
from django.core.cache import cache
|
||||||
|
from djoser.serializers import UserSerializer as BaseUserSerializer
|
||||||
|
from rest_framework import serializers
|
||||||
|
from rest_framework.serializers import ImageField, ModelSerializer
|
||||||
|
from rest_framework.settings import api_settings
|
||||||
|
from user_groups.serializers import SimpleUserGroupSerializer
|
||||||
|
|
||||||
# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here
|
# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here
|
||||||
|
|
||||||
|
@ -19,7 +18,7 @@ class SimpleCustomUserSerializer(ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class CustomUserSerializer(BaseUserSerializer):
|
class CustomUserSerializer(BaseUserSerializer):
|
||||||
avatar = Base64ImageField()
|
avatar = ImageField()
|
||||||
|
|
||||||
class Meta(BaseUserSerializer.Meta):
|
class Meta(BaseUserSerializer.Meta):
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from config.settings import ROOT_DIR, SEED_DATA, get_secret
|
||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from config.settings import SEED_DATA, ROOT_DIR, get_secret
|
from django_celery_beat.models import CrontabSchedule, PeriodicTask
|
||||||
from django_celery_beat.models import PeriodicTask, CrontabSchedule
|
|
||||||
from .models import CustomUser
|
from .models import CustomUser
|
||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
# Function to fill in users table with test data on dev/staging
|
# Function to fill in users table with test data on dev/staging
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path, include
|
|
||||||
from rest_framework.routers import DefaultRouter
|
|
||||||
from accounts import views
|
from accounts import views
|
||||||
|
from django.urls import include, path
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register(r"users", views.CustomUserViewSet, basename="users")
|
router.register(r"users", views.CustomUserViewSet, basename="users")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import re
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class UppercaseValidator(object):
|
class UppercaseValidator(object):
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
from rest_framework import status
|
|
||||||
from accounts.models import CustomUser
|
|
||||||
from accounts import serializers
|
from accounts import serializers
|
||||||
from rest_framework.decorators import action
|
from accounts.models import CustomUser
|
||||||
from rest_framework.response import Response
|
|
||||||
from djoser.conf import settings
|
|
||||||
from djoser.views import UserViewSet as DjoserUserViewSet
|
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
|
from django.core.cache import cache
|
||||||
from djoser import signals
|
from djoser import signals
|
||||||
from djoser.compat import get_user_email
|
from djoser.compat import get_user_email
|
||||||
from django.core.cache import cache
|
from djoser.conf import settings
|
||||||
|
from djoser.views import UserViewSet as DjoserUserViewSet
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
|
||||||
class CustomUserViewSet(DjoserUserViewSet):
|
class CustomUserViewSet(DjoserUserViewSet):
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
from config.settings import DEBUG, MEDIA_ROOT, SERVE_MEDIA
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
from django.contrib import admin
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
from django.urls import path, include
|
from django.urls import include, path
|
||||||
from drf_spectacular.views import (
|
from drf_spectacular.views import (
|
||||||
SpectacularAPIView,
|
SpectacularAPIView,
|
||||||
SpectacularRedocView,
|
SpectacularRedocView,
|
||||||
SpectacularSwaggerView,
|
SpectacularSwaggerView,
|
||||||
)
|
)
|
||||||
from django.contrib import admin
|
|
||||||
from config.settings import DEBUG, SERVE_MEDIA, MEDIA_ROOT
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("accounts/", include("accounts.urls")),
|
path("accounts/", include("accounts.urls")),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.urls import path
|
|
||||||
from billing import views
|
from billing import views
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.BillingHistoryView.as_view()),
|
path("", views.BillingHistoryView.as_view()),
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from rest_framework import status
|
from datetime import datetime
|
||||||
from rest_framework.views import APIView
|
|
||||||
from rest_framework.response import Response
|
import stripe
|
||||||
from rest_framework.permissions import IsAuthenticated
|
|
||||||
from config.settings import STRIPE_SECRET_KEY
|
from config.settings import STRIPE_SECRET_KEY
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from datetime import datetime
|
from rest_framework import status
|
||||||
import stripe
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
# Make sure to set your secret key
|
# Make sure to set your secret key
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from celery import Celery
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
# Set the default Django settings module for the 'celery' program.
|
# Set the default Django settings module for the 'celery' program.
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
import os
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dotenv import load_dotenv, find_dotenv # Python dotenv
|
|
||||||
import os
|
from dotenv import find_dotenv, load_dotenv # Python dotenv
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
# Backend folder (/backend)
|
# Backend folder (/backend)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.urls import path, include
|
from django.urls import include, path
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("api/v1/", include("api.urls")),
|
path("api/v1/", include("api.urls")),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from djoser import email
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from djoser import email
|
||||||
|
|
||||||
|
|
||||||
class ActivationEmail(email.ActivationEmail):
|
class ActivationEmail(email.ActivationEmail):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from unfold.admin import ModelAdmin
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin
|
||||||
|
|
||||||
from .models import Notification
|
from .models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from rest_framework import serializers
|
|
||||||
from notifications.models import Notification
|
from notifications.models import Notification
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
class NotificationSerializer(serializers.ModelSerializer):
|
class NotificationSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.dispatch import receiver
|
|
||||||
from django.db.models.signals import post_save
|
|
||||||
from notifications.models import Notification
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from django.db.models.signals import post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
from notifications.models import Notification
|
||||||
|
|
||||||
# Template for running actions after user have paid for a subscription
|
# Template for running actions after user have paid for a subscription
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.urls import path, include
|
from django.urls import include, path
|
||||||
from notifications.views import NotificationViewSet
|
from notifications.views import NotificationViewSet
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from rest_framework import viewsets
|
from django.core.cache import cache
|
||||||
from notifications.models import Notification
|
from notifications.models import Notification
|
||||||
from notifications.serializers import NotificationSerializer
|
from notifications.serializers import NotificationSerializer
|
||||||
|
from rest_framework import viewsets
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from django.core.cache import cache
|
|
||||||
|
|
||||||
|
|
||||||
class NotificationViewSet(viewsets.ModelViewSet):
|
class NotificationViewSet(viewsets.ModelViewSet):
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from payments import views
|
from payments import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("checkout_session/", views.StripeCheckoutView.as_view()),
|
path("checkout_session/", views.StripeCheckoutView.as_view()),
|
||||||
path("webhook/", views.stripe_webhook_view, name="Stripe Webhook"),
|
path("webhook/", views.stripe_webhook_view, name="Stripe Webhook"),
|
||||||
|
|
|
@ -1,31 +1,32 @@
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import stripe
|
||||||
|
from accounts.models import CustomUser
|
||||||
from config.settings import (
|
from config.settings import (
|
||||||
|
FRONTEND_ADDRESS,
|
||||||
|
FRONTEND_PORT,
|
||||||
STRIPE_SECRET_KEY,
|
STRIPE_SECRET_KEY,
|
||||||
STRIPE_SECRET_WEBHOOK,
|
STRIPE_SECRET_WEBHOOK,
|
||||||
URL_SCHEME,
|
URL_SCHEME,
|
||||||
FRONTEND_ADDRESS,
|
|
||||||
FRONTEND_PORT,
|
|
||||||
)
|
|
||||||
from rest_framework.permissions import IsAuthenticated
|
|
||||||
from rest_framework.views import APIView
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from rest_framework import status
|
|
||||||
import logging
|
|
||||||
import stripe
|
|
||||||
from subscriptions.models import SubscriptionPlan, UserSubscription
|
|
||||||
from accounts.models import CustomUser
|
|
||||||
from rest_framework.decorators import api_view
|
|
||||||
from subscriptions.tasks import get_user_subscription
|
|
||||||
import json
|
|
||||||
from emails.templates import (
|
|
||||||
SubscriptionAvailedEmail,
|
|
||||||
SubscriptionRefundedEmail,
|
|
||||||
SubscriptionCancelledEmail,
|
|
||||||
)
|
)
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from payments.serializers import CheckoutSerializer
|
from django.http import HttpResponse
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from drf_spectacular.utils import extend_schema
|
from drf_spectacular.utils import extend_schema
|
||||||
|
from emails.templates import (
|
||||||
|
SubscriptionAvailedEmail,
|
||||||
|
SubscriptionCancelledEmail,
|
||||||
|
SubscriptionRefundedEmail,
|
||||||
|
)
|
||||||
|
from payments.serializers import CheckoutSerializer
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from subscriptions.models import SubscriptionPlan, UserSubscription
|
||||||
|
from subscriptions.tasks import get_user_subscription
|
||||||
|
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from unfold.admin import ModelAdmin
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import SearchResult
|
from unfold.admin import ModelAdmin
|
||||||
from unfold.contrib.filters.admin import RangeDateFilter
|
from unfold.contrib.filters.admin import RangeDateFilter
|
||||||
|
|
||||||
|
from .models import SearchResult
|
||||||
|
|
||||||
|
|
||||||
@admin.register(SearchResult)
|
@admin.register(SearchResult)
|
||||||
class SearchResultAdmin(ModelAdmin):
|
class SearchResultAdmin(ModelAdmin):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
|
||||||
from .models import SearchResult
|
from .models import SearchResult
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +7,7 @@ from .models import SearchResult
|
||||||
autoretry_for=(Exception,), retry_kwargs={"max_retries": 0, "countdown": 5}
|
autoretry_for=(Exception,), retry_kwargs={"max_retries": 0, "countdown": 5}
|
||||||
)
|
)
|
||||||
def create_search_result(title, link):
|
def create_search_result(title, link):
|
||||||
if SearchResult.objects.filter(title=title, link=link).exists():
|
if SearchResult.objects.filter(title=title).exists():
|
||||||
return "SearchResult entry already exists"
|
return "SearchResult entry already exists"
|
||||||
else:
|
else:
|
||||||
SearchResult.objects.create(title=title, link=link)
|
SearchResult.objects.create(title=title, link=link)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.db import models
|
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
from user_groups.models import UserGroup
|
from django.db import models
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
from user_groups.models import UserGroup
|
||||||
|
|
||||||
|
|
||||||
class StripePrice(models.Model):
|
class StripePrice(models.Model):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from rest_framework import serializers
|
|
||||||
from subscriptions.models import SubscriptionPlan, UserSubscription, StripePrice
|
|
||||||
from accounts.serializers import SimpleCustomUserSerializer
|
from accounts.serializers import SimpleCustomUserSerializer
|
||||||
|
from rest_framework import serializers
|
||||||
|
from subscriptions.models import StripePrice, SubscriptionPlan, UserSubscription
|
||||||
|
|
||||||
|
|
||||||
class SimpleStripePriceSerializer(serializers.ModelSerializer):
|
class SimpleStripePriceSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from django.dispatch import receiver
|
|
||||||
from django.db.models.signals import post_migrate, post_save
|
|
||||||
from .models import UserSubscription, StripePrice, SubscriptionPlan
|
|
||||||
from django.core.cache import cache
|
|
||||||
from config.settings import STRIPE_SECRET_KEY
|
|
||||||
import stripe
|
import stripe
|
||||||
|
from config.settings import STRIPE_SECRET_KEY
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.db.models.signals import post_migrate, post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from .models import StripePrice, SubscriptionPlan, UserSubscription
|
||||||
|
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ from celery import shared_task
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def get_user_subscription(user_id):
|
def get_user_subscription(user_id):
|
||||||
from subscriptions.models import UserSubscription
|
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
|
from subscriptions.models import UserSubscription
|
||||||
|
|
||||||
USER = CustomUser.objects.get(id=user_id)
|
USER = CustomUser.objects.get(id=user_id)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path, include
|
from django.urls import include, path
|
||||||
from subscriptions import views
|
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
from subscriptions import views
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register(r"plans", views.SubscriptionPlanViewset, basename="Subscription Plans")
|
router.register(r"plans", views.SubscriptionPlanViewset, basename="Subscription Plans")
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
from django.core.cache import cache
|
||||||
|
from rest_framework import viewsets
|
||||||
|
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||||
|
from subscriptions.models import SubscriptionPlan, UserSubscription
|
||||||
from subscriptions.serializers import (
|
from subscriptions.serializers import (
|
||||||
SubscriptionPlanSerializer,
|
SubscriptionPlanSerializer,
|
||||||
UserSubscriptionSerializer,
|
UserSubscriptionSerializer,
|
||||||
)
|
)
|
||||||
from subscriptions.models import SubscriptionPlan, UserSubscription
|
|
||||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
||||||
from rest_framework import viewsets
|
|
||||||
from django.core.cache import cache
|
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionPlanViewset(viewsets.ModelViewSet):
|
class SubscriptionPlanViewset(viewsets.ModelViewSet):
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from unfold.admin import ModelAdmin
|
from unfold.admin import ModelAdmin
|
||||||
from .models import UserGroup
|
|
||||||
from unfold.contrib.filters.admin import RangeDateFilter
|
from unfold.contrib.filters.admin import RangeDateFilter
|
||||||
|
|
||||||
|
from .models import UserGroup
|
||||||
|
|
||||||
|
|
||||||
@admin.register(UserGroup)
|
@admin.register(UserGroup)
|
||||||
class UserGroupAdmin(ModelAdmin):
|
class UserGroupAdmin(ModelAdmin):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import stripe
|
||||||
|
from config.settings import STRIPE_SECRET_KEY
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from config.settings import STRIPE_SECRET_KEY
|
|
||||||
import stripe
|
|
||||||
|
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from .models import UserGroup
|
from .models import UserGroup
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
from subscriptions.models import SubscriptionPlan
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import stripe
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
from .models import UserGroup
|
from config.settings import ROOT_DIR, STRIPE_SECRET_KEY
|
||||||
from subscriptions.tasks import get_user_group_subscription
|
|
||||||
from django.db.models.signals import m2m_changed, post_migrate
|
from django.db.models.signals import m2m_changed, post_migrate
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from config.settings import STRIPE_SECRET_KEY, ROOT_DIR
|
from subscriptions.models import SubscriptionPlan
|
||||||
import os
|
from subscriptions.tasks import get_user_group_subscription
|
||||||
import json
|
|
||||||
import stripe
|
from .models import UserGroup
|
||||||
|
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
from search_results.tasks import create_search_result
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
from webdriver.utils import (
|
from webdriver.utils import (
|
||||||
setup_webdriver,
|
|
||||||
selenium_action_template,
|
|
||||||
google_search,
|
|
||||||
get_element,
|
get_element,
|
||||||
get_elements,
|
get_elements,
|
||||||
|
google_search,
|
||||||
|
selenium_action_template,
|
||||||
|
setup_webdriver,
|
||||||
)
|
)
|
||||||
from selenium.webdriver.common.by import By
|
|
||||||
from search_results.tasks import create_search_result
|
|
||||||
|
|
||||||
|
|
||||||
# Task template
|
# Task template
|
||||||
|
|
|
@ -2,21 +2,20 @@
|
||||||
Settings file to hold constants and functions
|
Settings file to hold constants and functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
|
||||||
|
import undetected_chromedriver as uc
|
||||||
|
from config.settings import CAPTCHA_TESTING, USE_PROXY, get_secret
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver import FirefoxOptions
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
from config.settings import get_secret
|
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver import FirefoxOptions
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from selenium import webdriver
|
|
||||||
import undetected_chromedriver as uc
|
|
||||||
from config.settings import USE_PROXY, CAPTCHA_TESTING
|
|
||||||
from config.settings import get_secret
|
|
||||||
from twocaptcha import TwoCaptcha
|
from twocaptcha import TwoCaptcha
|
||||||
from whois import whois
|
from whois import whois
|
||||||
from whois.parser import PywhoisError
|
from whois.parser import PywhoisError
|
||||||
import os
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
def take_snapshot(driver, filename="dump.png"):
|
def take_snapshot(driver, filename="dump.png"):
|
||||||
|
@ -249,7 +248,7 @@ def execute_selenium_elements(driver, timeout, elements):
|
||||||
element["default"]["key"],
|
element["default"]["key"],
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print(f"Failed to find primary element")
|
print(f"Failed to find primary element")
|
||||||
# If that fails, try to get the failover one
|
# If that fails, try to get the failover one
|
||||||
print("Trying to find legacy element")
|
print("Trying to find legacy element")
|
||||||
|
|
6
pyproject.toml
Normal file
6
pyproject.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
||||||
|
|
||||||
|
[tool.autoflake]
|
||||||
|
check = true
|
||||||
|
imports = ["django", "requests", "urllib3"]
|
131
requirements.txt
131
requirements.txt
|
@ -1,110 +1,107 @@
|
||||||
-i https://pypi.org/simple
|
-i https://pypi.org/simple
|
||||||
2captcha-python==1.2.5
|
2captcha-python==1.5.0
|
||||||
amqp==5.2.0; python_version >= '3.6'
|
amqp==5.2.0; python_version >= '3.6'
|
||||||
asgiref==3.8.1; python_version >= '3.8'
|
asgiref==3.8.1; python_version >= '3.8'
|
||||||
async-timeout==4.0.3; python_full_version < '3.11.3'
|
async-timeout==4.0.3; python_full_version < '3.11.3'
|
||||||
attrs==23.2.0; python_version >= '3.7'
|
attrs==24.2.0; python_version >= '3.7'
|
||||||
autobahn==23.6.2; python_version >= '3.9'
|
autobahn==24.4.2; python_version >= '3.9'
|
||||||
automat==22.10.0
|
automat==24.8.1
|
||||||
autopep8==2.1.0; python_version >= '3.8'
|
autopep8==2.3.1; python_version >= '3.8'
|
||||||
billiard==4.2.0; python_version >= '3.7'
|
billiard==4.2.1; python_version >= '3.7'
|
||||||
celery==5.4.0
|
celery==5.4.0
|
||||||
certifi==2024.2.2; python_version >= '3.6'
|
certifi==2024.8.30; python_version >= '3.6'
|
||||||
cffi==1.16.0;
|
cffi==1.17.1;
|
||||||
charset-normalizer==3.3.2; python_full_version >= '3.7.0'
|
charset-normalizer==3.4.0; python_full_version >= '3.7.0'
|
||||||
click==8.1.7; python_version >= '3.7'
|
click==8.1.7; python_version >= '3.7'
|
||||||
click-didyoumean==0.3.1; python_full_version >= '3.6.2'
|
click-didyoumean==0.3.1; python_full_version >= '3.6.2'
|
||||||
click-plugins==1.1.1
|
click-plugins==1.1.1
|
||||||
click-repl==0.3.0; python_version >= '3.6'
|
click-repl==0.3.0; python_version >= '3.6'
|
||||||
colorama==0.4.6;
|
colorama==0.4.6;
|
||||||
constantly==23.10.4; python_version >= '3.8'
|
constantly==23.10.4; python_version >= '3.8'
|
||||||
cron-descriptor==1.4.3
|
cron-descriptor==1.4.5
|
||||||
cryptography==42.0.7; python_version >= '3.7'
|
cryptography==43.0.3; python_version >= '3.7'
|
||||||
defusedxml==0.8.0rc2; python_version >= '3.6'
|
defusedxml==0.8.0rc2; python_version >= '3.6'
|
||||||
django==5.0.6
|
django==5.1.2
|
||||||
django-celery-beat==2.6.0
|
django-celery-beat==2.7.0
|
||||||
django-celery-results==2.5.1
|
django-celery-results==2.5.1
|
||||||
django-cors-headers==4.3.1
|
django-cors-headers==4.6.0
|
||||||
django-extensions==3.2.3
|
django-extensions==3.2.3
|
||||||
django-extra-fields==3.0.2
|
|
||||||
django-redis==5.4.0
|
django-redis==5.4.0
|
||||||
django-resized==1.0.2
|
django-resized==1.0.3
|
||||||
django-silk==5.1.0
|
django-silk==5.2.0
|
||||||
django-simple-history==3.5.0
|
django-simple-history==3.7.0
|
||||||
django-storages==1.14.3
|
django-storages==1.14.4
|
||||||
django-templated-mail==1.1.1
|
django-templated-mail==1.1.1
|
||||||
django-timezone-field==6.1.0; python_version >= '3.8' and python_version < '4.0'
|
django-timezone-field==7.0; python_version >= '3.8' and python_version < '4.0'
|
||||||
django-unfold==0.22.0
|
django-unfold==0.40.0
|
||||||
djangorestframework==3.15.1
|
djangorestframework==3.15.2
|
||||||
djangorestframework-simplejwt==5.3.1; python_version >= '3.8'
|
djangorestframework-simplejwt==5.3.1; python_version >= '3.8'
|
||||||
djoser==2.2.2
|
djoser==2.2.3
|
||||||
drf-spectacular[sidecar]==0.27.2
|
drf-spectacular[sidecar]==0.27.2
|
||||||
drf-spectacular-sidecar==2024.5.1
|
drf-spectacular-sidecar==2024.7.1
|
||||||
flower==2.0.1
|
flower==2.0.1
|
||||||
gprof2dot==2022.7.29; python_version >= '2.7'
|
gprof2dot==2024.6.6; python_version >= '2.7'
|
||||||
granian==1.4.1
|
|
||||||
h11==0.14.0; python_version >= '3.7'
|
h11==0.14.0; python_version >= '3.7'
|
||||||
humanize==4.9.0; python_version >= '3.8'
|
humanize==4.11.0; python_version >= '3.8'
|
||||||
hyperlink==21.0.0
|
hyperlink==21.0.0
|
||||||
idna==3.7; python_version >= '3.5'
|
idna==3.10; python_version >= '3.5'
|
||||||
incremental==22.10.0
|
incremental==24.7.2
|
||||||
inflection==0.5.1; python_version >= '3.5'
|
inflection==0.5.1; python_version >= '3.5'
|
||||||
jsonschema==4.22.0; python_version >= '3.8'
|
jsonschema==4.23.0; python_version >= '3.8'
|
||||||
jsonschema-specifications==2023.12.1; python_version >= '3.8'
|
jsonschema-specifications==2024.10.1; python_version >= '3.8'
|
||||||
kombu==5.3.7
|
kombu==5.4.2
|
||||||
msgpack==1.0.8; python_version >= '3.8'
|
msgpack==1.1.0; python_version >= '3.8'
|
||||||
oauthlib==3.2.2; python_version >= '3.6'
|
oauthlib==3.2.2; python_version >= '3.6'
|
||||||
outcome==1.3.0.post0; python_version >= '3.7'
|
outcome==1.3.0.post0; python_version >= '3.7'
|
||||||
packaging==24.0; python_version >= '3.7'
|
packaging==24.1; python_version >= '3.7'
|
||||||
pillow==10.3.0
|
pillow==11.0.0
|
||||||
prometheus-client==0.20.0; python_version >= '3.8'
|
prometheus-client==0.21.0; python_version >= '3.8'
|
||||||
prompt-toolkit==3.0.43; python_full_version >= '3.7.0'
|
prompt-toolkit==3.0.48; python_full_version >= '3.7.0'
|
||||||
psycopg2==2.9.9
|
psycopg2-binary==2.9.10; platform_system == 'Linux'
|
||||||
pyasn1==0.6.0; python_version >= '3.8'
|
pyasn1==0.6.1; python_version >= '3.8'
|
||||||
pyasn1-modules==0.4.0; python_version >= '3.8'
|
pyasn1-modules==0.4.1; python_version >= '3.8'
|
||||||
pycodestyle==2.11.1; python_version >= '3.8'
|
pycodestyle==2.12.1; python_version >= '3.8'
|
||||||
pycparser==2.22; python_version >= '3.8'
|
pycparser==2.22; python_version >= '3.8'
|
||||||
pygraphviz==1.13
|
pygraphviz==1.14; platform_system == 'Linux'
|
||||||
pyjwt==2.8.0; python_version >= '3.7'
|
pyjwt==2.9.0; python_version >= '3.7'
|
||||||
pyopenssl==24.1.0
|
pyopenssl==24.2.1
|
||||||
pysocks==1.7.1
|
pysocks==1.7.1
|
||||||
python-crontab==3.0.0
|
python-crontab==3.2.0
|
||||||
python-dateutil==2.9.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
python-dateutil==2.9.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||||
python-dotenv==1.0.1
|
python-dotenv==1.0.1
|
||||||
python-whois==0.9.4
|
python-whois==0.9.4
|
||||||
python3-openid==3.2.0
|
python3-openid==3.2.0
|
||||||
pytz==2024.1
|
pytz==2024.2
|
||||||
pyyaml==6.0.1; python_version >= '3.6'
|
pyyaml==6.0.2; python_version >= '3.6'
|
||||||
redis==5.0.4
|
redis==5.2.0 #
|
||||||
referencing==0.35.1; python_version >= '3.8'
|
referencing==0.35.1; python_version >= '3.8'
|
||||||
requests==2.31.0; python_version >= '3.7'
|
requests==2.32.3; python_version >= '3.7'
|
||||||
requests-oauthlib==2.0.0; python_version >= '3.4'
|
requests-oauthlib==2.0.0; python_version >= '3.4'
|
||||||
rpds-py==0.18.1; python_version >= '3.8'
|
rpds-py==0.20.0; python_version >= '3.8'
|
||||||
selenium==4.20.0
|
selenium==4.26.0
|
||||||
service-identity==24.1.0
|
service-identity==24.2.0
|
||||||
setuptools==69.5.1; python_version >= '3.8'
|
setuptools==75.3.0; python_version >= '3.8'
|
||||||
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||||
sniffio==1.3.1; python_version >= '3.7'
|
sniffio==1.3.1; python_version >= '3.7'
|
||||||
social-auth-app-django==5.4.1; python_version >= '3.8'
|
social-auth-app-django==5.4.2; python_version >= '3.8'
|
||||||
social-auth-core==4.5.4; python_version >= '3.8'
|
social-auth-core==4.5.4; python_version >= '3.8'
|
||||||
sortedcontainers==2.4.0
|
sortedcontainers==2.4.0
|
||||||
sqlparse==0.5.0; python_version >= '3.8'
|
sqlparse==0.5.1; python_version >= '3.8'
|
||||||
stripe==9.6.0
|
stripe==11.2.0
|
||||||
tornado==6.4; python_version >= '3.8'
|
tornado==6.4.1; python_version >= '3.8'
|
||||||
trio==0.25.0; python_version >= '3.8'
|
trio==0.27.0; python_version >= '3.8'
|
||||||
trio-websocket==0.11.1; python_version >= '3.7'
|
trio-websocket==0.11.1; python_version >= '3.7'
|
||||||
twisted[tls]==24.3.0; python_full_version >= '3.8.0'
|
twisted[tls]==24.10.0; python_full_version >= '3.8.0'
|
||||||
twisted-iocpsupport==1.0.4; platform_system == 'Windows'
|
|
||||||
txaio==23.1.1; python_version >= '3.7'
|
txaio==23.1.1; python_version >= '3.7'
|
||||||
typing-extensions==4.11.0; python_version >= '3.8'
|
typing-extensions==4.12.2; python_version >= '3.8'
|
||||||
tzdata==2024.1; python_version >= '2'
|
tzdata==2024.2; python_version >= '2'
|
||||||
undetected-chromedriver==3.5.5
|
undetected-chromedriver==3.5.5
|
||||||
uritemplate==4.1.1; python_version >= '3.6'
|
uritemplate==4.1.1; python_version >= '3.6'
|
||||||
urllib3[socks]==2.2.1; python_version >= '3.8'
|
urllib3[socks]==2.2.3; python_version >= '3.8'
|
||||||
vine==5.1.0; python_version >= '3.6'
|
vine==5.1.0; python_version >= '3.6'
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
websockets==12.0; python_version >= '3.8'
|
websockets==13.1; python_version >= '3.8'
|
||||||
whitenoise==6.6.0
|
whitenoise==6.8.2
|
||||||
wsproto==1.2.0; python_full_version >= '3.7.0'
|
wsproto==1.2.0; python_full_version >= '3.7.0'
|
||||||
zope-interface==6.3; python_version >= '3.7'
|
zope-interface==7.1.1; python_version >= '3.7'
|
||||||
gunicorn==22.0.0
|
gunicorn==23.0.0
|
||||||
|
|
|
@ -13,9 +13,7 @@ if [ "$RUN_TYPE" = "web" ]; then
|
||||||
if [ "$BACKEND_DEBUG" = 'True' ]; then
|
if [ "$BACKEND_DEBUG" = 'True' ]; then
|
||||||
python manage.py runserver "0.0.0.0:8000"
|
python manage.py runserver "0.0.0.0:8000"
|
||||||
else
|
else
|
||||||
# Feel free to replace the WSGI server here with something else
|
gunicorn --workers 8 --bind 0.0.0.0:8000 config.wsgi:application # Gunicorn
|
||||||
# gunicorn --workers 8 --bind 0.0.0.0:8000 config.wsgi:application # Gunicorn
|
|
||||||
python -m granian --host 0.0.0.0 --port 8000 --workers 8 --interface wsgi config.wsgi:application # Granian
|
|
||||||
fi
|
fi
|
||||||
elif [ "$RUN_TYPE" = "worker" ]; then
|
elif [ "$RUN_TYPE" = "worker" ]; then
|
||||||
celery -A config worker -l INFO -E --concurrency 1
|
celery -A config worker -l INFO -E --concurrency 1
|
Loading…
Reference in a new issue