├── .flake8
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── AUTHORS
├── LICENSE
├── MANIFEST.in
├── README.md
├── demo
├── README.md
├── demo
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── poetry.lock
├── pyproject.toml
└── templates
│ └── default_urlconf.html
├── django_spam
├── __init__.py
├── apps.py
├── enums.py
├── urls.py
└── utils.py
├── poetry.lock
├── pyproject.toml
├── runtests.py
├── setup.py
└── tests
├── __init__.py
├── settings.py
├── test_enums.py
├── test_spam.py
├── test_utils.py
└── urls.py
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length=110
3 | ignore=F403,F405,W605,W503,E203,E231
4 | exclude=setup.py,__init__.py,.eggs,runtests.py
5 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: lint and test
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - develop
8 |
9 | jobs:
10 | lint-and-test:
11 | runs-on: ubuntu-18.04
12 | strategy:
13 | # By default, GitHub will maximize the number of jobs run in parallel
14 | # depending on the available runners on GitHub-hosted virtual machines.
15 | # max-parallel: 8
16 | fail-fast: false
17 | matrix:
18 | python-version:
19 | - "3.4"
20 | - "3.5"
21 | - "3.6"
22 | - "3.7"
23 | - "3.8"
24 | - "3.9"
25 | django-version:
26 | - "2.0"
27 | - "2.1"
28 | - "2.2" # LTS
29 | - "3.0"
30 | - "3.1"
31 | - "3.2" # LTS
32 | exclude:
33 | # Python 3.4 is not compatible with Django 2.0+
34 | - python-version: "3.4"
35 | django-version: "2.1"
36 | - python-version: "3.4"
37 | django-version: "2.2"
38 | - python-version: "3.4"
39 | django-version: "3.0"
40 | - python-version: "3.4"
41 | django-version: "3.1"
42 | - python-version: "3.4"
43 | django-version: "3.2"
44 | # Python 3.5 is not compatible with Django 2.2+
45 | - python-version: "3.5"
46 | django-version: "3.0"
47 | - python-version: "3.5"
48 | django-version: "3.1"
49 | - python-version: "3.5"
50 | django-version: "3.2"
51 | # Python 3.8 is compatible with Django 2.2+
52 | - python-version: "3.8"
53 | django-version: "2.0"
54 | - python-version: "3.8"
55 | django-version: "2.1"
56 | # Python 3.9 is compatible with Django 3.1+
57 | - python-version: "3.9"
58 | django-version: "2.0"
59 | - python-version: "3.9"
60 | django-version: "2.1"
61 | - python-version: "3.9"
62 | django-version: "2.2"
63 | - python-version: "3.9"
64 | django-version: "3.0"
65 |
66 | steps:
67 | - uses: actions/checkout@v2
68 |
69 | - name: Set up Python ${{ matrix.python-version }}
70 | uses: actions/setup-python@v2
71 | with:
72 | python-version: ${{ matrix.python-version }}
73 |
74 | - name: Upgrade pip version
75 | run: |
76 | python -m pip install -U pip
77 |
78 | - name: Upgrade django version
79 | run: |
80 | python -m pip install "Django~=${{ matrix.django-version }}.0"
81 |
82 | - name: Python and Django versions
83 | run: |
84 | echo "Python ${{ matrix.python-version }} -> Django ${{ matrix.django-version }}"
85 | python --version
86 | echo "Django: `django-admin --version`"
87 |
88 | - name: run tests
89 | run: |
90 | python -m pip install coverage
91 | coverage run --source=django_spam setup.py test
92 | coverage report
93 | coverage xml -o coverage.xml
94 |
95 | - name: Codecov
96 | if: success()
97 | uses: codecov/codecov-action@v2
98 | with:
99 | file: coverage.xml
100 | flags: unittests
101 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | .coverage
5 |
6 | # Distribution / packaging
7 | .Python
8 | env/
9 | bin/
10 | build/
11 | develop-eggs/
12 | dist/
13 | *eggs/
14 | lib/
15 | lib64/
16 | parts/
17 | sdist/
18 | var/
19 | *.egg-info/
20 | .installed.cfg
21 | *.egg
22 | demo/django_spam
23 | .vscode
24 | *.sqlite3
25 |
26 | # Installer logs
27 | pip-log.txt
28 | pip-delete-this-directory.txt
29 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | http://github.com/Tivix/django-spam/contributors
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Tivix, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include AUTHORS
2 | include LICENSE
3 | include MANIFEST.in
4 | include README.md
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | django-spam
2 | ===========
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Inspired by this Nick Craver tweet https://twitter.com/nick_craver/status/720062942960623616
15 |
16 | We all hate bots, lets admit it. Especially the ones that try to gain access to our most secret endpoints. Well we have an easy
17 | solution for your django application. django_spam simply adds common admin urls to url conf so when bots (or human
18 | for that matter) try and access them, they will get redirected...
19 |
20 |
21 | | | Django 2.0 | Django 2.1 | Django 2.2 | Django 3.0 | Django 3.1 | Django 3.2 |
22 | | -- | -- | -- | -- | -- | -- | -- |
23 | | Python 3.4 | :heavy_check_mark: | | | | | |
24 | | Python 3.5 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | |
25 | | Python 3.6 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
26 | | Python 3.7 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
27 | | Python 3.8 | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
28 | | Python 3.9 | | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
29 |
30 |
31 | ## Installation / Usage
32 | ```python
33 | pip install django-spam
34 | ```
35 |
36 | Add to apps list:
37 | ```python
38 | INSTALLED_APPS = [
39 | '...',
40 | 'django_spam',
41 | '...'
42 | ]
43 | ```
44 |
45 | django_spam ships with some default endpoints bots might try to hit. If you would like to add extra routes, simply add
46 | a ``SPAM_ROUTES`` variable to your settings file that contains a list of extra endpoints you would like
47 | to add. *no leading slashes*
48 | ```python
49 | SPAM_ROUTES = [
50 | 'admin.php',
51 | 'admin/login.php',
52 | 'administrator/index.php',
53 | 'index.php',
54 | '...',
55 | ]
56 | ```
57 |
58 | Include ``django_spam.urls`` to root url file:
59 | ```python
60 |
61 | '...'
62 | path('', include('django_spam.urls')),
63 | '...',
64 | ```
65 |
66 | If for some odd reason you need to exclude routes, define ``EXCLUDED_ROUTES`` in settings. *no leading slashes*
67 |
68 | ```python
69 | EXCLUDED_ROUTES = [
70 | 'admin.php',
71 | 'index.php'
72 | ]
73 | ```
74 |
75 | ## Demo
76 | See [here](demo/README.md)
77 |
78 | ## Development
79 | This project uses [Poetry](https://python-poetry.org/docs/#osx--linux--bashonwindows-install-instructions) to manage dev environment. Once installed:
80 | 1. Clone and `cd` into repo
81 | 2. install packages with `poetry install`
82 | 3. black `poetry run black .`
83 | 4. flake8 `poetry run flake8`
84 | 5. test `poetry run coverage run --source=django_spam setup.py test`
85 |
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | ## Demo using django-spam
2 |
3 | This demo is provided as a convenience feature to allow potential users to try the app straight from the app repo without having to create a django project.
4 |
5 | It can also be used to develop the app in place.
6 |
7 | To run this example, follow these instructions:
8 |
9 | 1. Navigate to the `demo` directory
10 |
11 | 2. Install required packages with Poetry.
12 |
13 | poetry install
14 |
15 | 3. Make and apply migrations
16 |
17 | poetry run python manage.py makemigrations
18 |
19 | poetry run python manage.py migrate
20 |
21 | 4. Run the server
22 |
23 | poetry run python manage.py runserver
24 |
25 | 5. Access from the browser at `http://127.0.0.1:8000` to view homepage
26 |
27 | 6. Visit a `SPAM_ROUTES` eg `http://127.0.0.1:8000/admin/login.asp`
28 |
--------------------------------------------------------------------------------
/demo/demo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tivix/django-spam/c975de8777b3c8c08e63cbaeef7b84af00f10620/demo/demo/__init__.py
--------------------------------------------------------------------------------
/demo/demo/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for demo project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.11.8.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.11/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = "demo-key"
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | "django.contrib.admin",
35 | "django.contrib.auth",
36 | "django.contrib.contenttypes",
37 | "django.contrib.sessions",
38 | "django.contrib.messages",
39 | "django.contrib.staticfiles",
40 | "django_spam",
41 | ]
42 |
43 | MIDDLEWARE = [
44 | "django.middleware.security.SecurityMiddleware",
45 | "django.contrib.sessions.middleware.SessionMiddleware",
46 | "django.middleware.common.CommonMiddleware",
47 | "django.middleware.csrf.CsrfViewMiddleware",
48 | "django.contrib.auth.middleware.AuthenticationMiddleware",
49 | "django.contrib.messages.middleware.MessageMiddleware",
50 | "django.middleware.clickjacking.XFrameOptionsMiddleware",
51 | ]
52 |
53 | ROOT_URLCONF = "demo.urls"
54 |
55 | TEMPLATES = [
56 | {
57 | "BACKEND": "django.template.backends.django.DjangoTemplates",
58 | "DIRS": ["templates"],
59 | "APP_DIRS": True,
60 | "OPTIONS": {
61 | "context_processors": [
62 | "django.template.context_processors.debug",
63 | "django.template.context_processors.request",
64 | "django.contrib.auth.context_processors.auth",
65 | "django.contrib.messages.context_processors.messages",
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = "demo.wsgi.application"
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
76 |
77 | DATABASES = {
78 | "default": {
79 | "ENGINE": "django.db.backends.sqlite3",
80 | "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
81 | }
82 | }
83 |
84 |
85 | # Internationalization
86 | # https://docs.djangoproject.com/en/1.11/topics/i18n/
87 |
88 | LANGUAGE_CODE = "en-us"
89 |
90 | TIME_ZONE = "UTC"
91 |
92 | USE_I18N = True
93 |
94 | USE_L10N = True
95 |
96 | USE_TZ = True
97 |
98 |
99 | # Static files (CSS, JavaScript, Images)
100 | # https://docs.djangoproject.com/en/1.11/howto/static-files/
101 |
102 | STATIC_URL = "/static/"
103 |
--------------------------------------------------------------------------------
/demo/demo/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, include
2 | from django.contrib import admin
3 | from django.views.generic import TemplateView
4 |
5 |
6 | urlpatterns = [
7 | path("admin/", admin.site.urls),
8 | path("", TemplateView.as_view(template_name="default_urlconf.html")),
9 | path("", include("django_spam.urls")),
10 | ]
11 |
--------------------------------------------------------------------------------
/demo/demo/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for demo project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/demo/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 |
6 | if __name__ == "__main__":
7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
8 |
9 | from django.core.management import execute_from_command_line
10 |
11 | execute_from_command_line(sys.argv)
12 |
--------------------------------------------------------------------------------
/demo/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "asgiref"
3 | version = "3.4.1"
4 | description = "ASGI specs, helper code, and adapters"
5 | category = "main"
6 | optional = false
7 | python-versions = ">=3.6"
8 |
9 | [package.extras]
10 | tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
11 |
12 | [[package]]
13 | name = "django"
14 | version = "3.2.7"
15 | description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
16 | category = "main"
17 | optional = false
18 | python-versions = ">=3.6"
19 |
20 | [package.dependencies]
21 | asgiref = ">=3.3.2,<4"
22 | pytz = "*"
23 | sqlparse = ">=0.2.2"
24 |
25 | [package.extras]
26 | argon2 = ["argon2-cffi (>=19.1.0)"]
27 | bcrypt = ["bcrypt"]
28 |
29 | [[package]]
30 | name = "django-spam"
31 | version = "1.0.0"
32 | description = "Django application that redirects spam bots to '10 hours of' videos"
33 | category = "main"
34 | optional = false
35 | python-versions = "^3.9"
36 | develop = true
37 |
38 | [package.source]
39 | type = "directory"
40 | url = ".."
41 |
42 | [[package]]
43 | name = "pytz"
44 | version = "2021.1"
45 | description = "World timezone definitions, modern and historical"
46 | category = "main"
47 | optional = false
48 | python-versions = "*"
49 |
50 | [[package]]
51 | name = "sqlparse"
52 | version = "0.4.2"
53 | description = "A non-validating SQL parser."
54 | category = "main"
55 | optional = false
56 | python-versions = ">=3.5"
57 |
58 | [metadata]
59 | lock-version = "1.1"
60 | python-versions = "3.9"
61 | content-hash = "3465f4fa47d1362bce3242be6e480ae22de47be7239ae7cb7670dd931b0f7006"
62 |
63 | [metadata.files]
64 | asgiref = [
65 | {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
66 | {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
67 | ]
68 | django = [
69 | {file = "Django-3.2.7-py3-none-any.whl", hash = "sha256:e93c93565005b37ddebf2396b4dc4b6913c1838baa82efdfb79acedd5816c240"},
70 | {file = "Django-3.2.7.tar.gz", hash = "sha256:95b318319d6997bac3595517101ad9cc83fe5672ac498ba48d1a410f47afecd2"},
71 | ]
72 | django-spam = []
73 | pytz = [
74 | {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
75 | {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
76 | ]
77 | sqlparse = [
78 | {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"},
79 | {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"},
80 | ]
81 |
--------------------------------------------------------------------------------
/demo/pyproject.toml:
--------------------------------------------------------------------------------
1 |
2 | [tool.poetry]
3 | name = "django-spam demo"
4 | version = "1.0.0"
5 | description = "A demo using django-spam."
6 | authors = ["nick.kelly@tivix.com"]
7 |
8 | [tool.poetry.dependencies]
9 | python = "3.9"
10 | django = "^3.0"
11 | django_spam = { path = "../", develop = true}
12 |
13 | [tool.poetry.dev-dependencies]
14 |
15 | [build-system]
16 | requires = ["poetry>=0.12"]
17 | build-backend = "poetry.masonry.api"
18 |
--------------------------------------------------------------------------------
/demo/templates/default_urlconf.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 | {% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
4 |
5 |
6 |
7 | {% translate "The install worked successfully! Congratulations!" %}
8 |
9 |
10 |
201 |
202 |
203 |
209 |
210 |
221 | {% translate "The install worked successfully! Congratulations!" %}
222 | {% blocktranslate %}You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs.{% endblocktranslate %}
223 |
224 |
253 |
254 |
255 |
--------------------------------------------------------------------------------
/django_spam/__init__.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 |
3 | from django_spam.enums import SPAM_ENUMS
4 |
5 | from django_spam.utils import Colour
6 |
7 |
8 | # common endpoints bots like (w/o leading slash)
9 | SPAM_ROUTES = [
10 | # asp/x
11 | "admin.aspx",
12 | "admin.asp",
13 | "admin/account.html",
14 | "admin/login.asp",
15 | "admin_login.asp",
16 | "admin_login.aspx",
17 | "administartorlogin.aspx",
18 | "administrator_login.asp",
19 | "administrator_login.aspx",
20 | "login/administrator.aspx",
21 | "login/admin.asp",
22 | # php
23 | "admin.php",
24 | "admin/login.php",
25 | "admin_area/index.php",
26 | "administrator/index.php",
27 | "index.php",
28 | "siteadmin/index.php",
29 | "siteadmin/login.php",
30 | "wp-admin/admin-ajax.php",
31 | "wp-admin/post-new.php",
32 | "wp-admin/options-link.php",
33 | "wp-admin/includes/themes.php",
34 | "wp-login.php",
35 | # html
36 | "admin/account.html",
37 | "admin/admin.html",
38 | "admin/index.html",
39 | "admin/login.html",
40 | ]
41 |
42 | # '10 hours of'...
43 | SPAM_URLS = [spam for spam in SPAM_ENUMS]
44 |
45 | # check if any settings vars have been included to add to the
46 | # list of routes or urls
47 | if hasattr(settings, "SPAM_ROUTES"):
48 | SPAM_ROUTES += settings.SPAM_ROUTES
49 |
50 |
51 | # check for excluded routes
52 | if hasattr(settings, "EXCLUDED_ROUTES"):
53 | for route in settings.EXCLUDED_ROUTES:
54 | if route in SPAM_ROUTES:
55 | SPAM_ROUTES.remove(route)
56 | else:
57 | print(
58 | Colour.text(
59 | 'Warning: "' + route + '" is not included in django_spam.SPAM_ROUTES.',
60 | "warn",
61 | )
62 | )
63 |
64 | # NOTE: temp disbaling custom routes
65 | # if hasattr(settings, "SPAM_URLS"):
66 | # SPAM_URLS += settings.SPAM_URLS
67 |
--------------------------------------------------------------------------------
/django_spam/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class DjangoSpamConfig(AppConfig):
5 | name = "django_spam"
6 |
--------------------------------------------------------------------------------
/django_spam/enums.py:
--------------------------------------------------------------------------------
1 | class SpamBase:
2 | name = ""
3 | url = ""
4 |
5 | def __init__(self):
6 | raise NotImplementedError
7 |
8 | @classmethod
9 | def to_readable(cls) -> str:
10 | return cls.name.lower().replace(" ", "_")
11 |
12 |
13 | class VaderBreathing(SpamBase):
14 | name = "Darth Vader Breathing"
15 | url = "https://www.youtube.com/watch?v=un8FAjXWOBY"
16 |
17 |
18 | class Yodelling(SpamBase):
19 | name = "Yodelling"
20 | url = "https://www.youtube.com/watch?v=Lxt0_YrQs0M"
21 |
22 |
23 | class MulletGuy(SpamBase):
24 | name = "Whistling Mullet Guy"
25 | url = "https://www.youtube.com/watch?v=Sbhoym9yzVQ"
26 |
27 |
28 | class ScreamingGuy(SpamBase):
29 | name = "Screaming Guy"
30 | url = "https://www.youtube.com/watch?v=CRcYlE3i_-4"
31 |
32 |
33 | class FaceSong(SpamBase):
34 | name = "Awesome Face Song"
35 | url = "https://www.youtube.com/watch?v=WNeni1lbzgY"
36 |
37 |
38 | class ScreamingSheep(SpamBase):
39 | name = "Screaming Sheep"
40 | url = "https://www.youtube.com/watch?v=SjHUb7NSrNk"
41 |
42 |
43 | class SaxGuy(SpamBase):
44 | name = "Epic Sax Guy"
45 | url = "https://www.youtube.com/watch?v=kxopViU98Xo"
46 |
47 |
48 | class CrabRave(SpamBase):
49 | name = "Crab Rave"
50 | url = "https://www.youtube.com/watch?v=-50NdPawLVY"
51 |
52 |
53 | class WiiMusic(SpamBase):
54 | name = "Wii Theme Music"
55 | url = "https://www.youtube.com/watch?v=Twi92KYddW4"
56 |
57 |
58 | class NyonCat(SpamBase):
59 | name = "Nyon Cat"
60 | url = "https://www.youtube.com/watch?v=wZZ7oFKsKzY"
61 |
62 |
63 | class Asmr(SpamBase):
64 | name = "ASMR"
65 | url = "https://www.youtube.com/watch?v=jbAy9MwBR-I"
66 |
67 |
68 | class HeMan(SpamBase):
69 | name = "He-man Heyeayea"
70 | url = "https://www.youtube.com/watch?v=eh7lp9umG2I"
71 |
72 |
73 | SPAM_ENUMS = [
74 | VaderBreathing,
75 | Yodelling,
76 | MulletGuy,
77 | ScreamingGuy,
78 | FaceSong,
79 | ScreamingSheep,
80 | SaxGuy,
81 | CrabRave,
82 | WiiMusic,
83 | NyonCat,
84 | Asmr,
85 | HeMan,
86 | ]
87 |
--------------------------------------------------------------------------------
/django_spam/urls.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | from django.urls import path
4 | from django.views.generic.base import RedirectView
5 |
6 | from django_spam import SPAM_ROUTES
7 | from django_spam import SPAM_ENUMS
8 |
9 |
10 | urlpatterns = list()
11 |
12 | for spam_route in SPAM_ROUTES:
13 | enum = random.choice(SPAM_ENUMS)
14 | urlpatterns.append(
15 | path(
16 | spam_route,
17 | RedirectView.as_view(url=enum.url),
18 | name=enum.to_readable(),
19 | )
20 | )
21 |
--------------------------------------------------------------------------------
/django_spam/utils.py:
--------------------------------------------------------------------------------
1 | class Colour:
2 | """
3 | Color output in terminal so warnings/errors stick out.
4 | """
5 |
6 | HEADER = "\033[95m"
7 | OKBLUE = "\033[94m"
8 | OKGREEN = "\033[92m"
9 | WARNING = "\033[93m"
10 | FAIL = "\033[91m"
11 | ENDC = "\033[0m"
12 | BOLD = "\033[1m"
13 | UNDERLINE = "\033[4m"
14 |
15 | def __init__(self):
16 | raise NotImplementedError
17 |
18 | @classmethod
19 | def text(cls, txt: str, status: str = None) -> str:
20 | """colorize specific text
21 |
22 | :param txt: text printed to console
23 | :param status: the type of status depends on the color
24 |
25 | :return: colorized text string
26 | """
27 | if status == "fail":
28 | return cls.FAIL + txt + cls.ENDC
29 | elif status == "ok":
30 | return cls.OKGREEN + txt + cls.ENDC
31 | elif status == "warn":
32 | return cls.WARNING + txt + cls.ENDC
33 | else:
34 | return txt
35 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "appdirs"
3 | version = "1.4.4"
4 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
5 | category = "dev"
6 | optional = false
7 | python-versions = "*"
8 |
9 | [[package]]
10 | name = "black"
11 | version = "20.8b1"
12 | description = "The uncompromising code formatter."
13 | category = "dev"
14 | optional = false
15 | python-versions = ">=3.6"
16 |
17 | [package.dependencies]
18 | appdirs = "*"
19 | click = ">=7.1.2"
20 | mypy-extensions = ">=0.4.3"
21 | pathspec = ">=0.6,<1"
22 | regex = ">=2020.1.8"
23 | toml = ">=0.10.1"
24 | typed-ast = ">=1.4.0"
25 | typing-extensions = ">=3.7.4"
26 |
27 | [package.extras]
28 | colorama = ["colorama (>=0.4.3)"]
29 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
30 |
31 | [[package]]
32 | name = "click"
33 | version = "8.0.1"
34 | description = "Composable command line interface toolkit"
35 | category = "dev"
36 | optional = false
37 | python-versions = ">=3.6"
38 |
39 | [package.dependencies]
40 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
41 |
42 | [[package]]
43 | name = "colorama"
44 | version = "0.4.4"
45 | description = "Cross-platform colored terminal text."
46 | category = "dev"
47 | optional = false
48 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
49 |
50 | [[package]]
51 | name = "coverage"
52 | version = "5.5"
53 | description = "Code coverage measurement for Python"
54 | category = "dev"
55 | optional = false
56 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
57 |
58 | [package.extras]
59 | toml = ["toml"]
60 |
61 | [[package]]
62 | name = "flake8"
63 | version = "3.9.2"
64 | description = "the modular source code checker: pep8 pyflakes and co"
65 | category = "dev"
66 | optional = false
67 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
68 |
69 | [package.dependencies]
70 | mccabe = ">=0.6.0,<0.7.0"
71 | pycodestyle = ">=2.7.0,<2.8.0"
72 | pyflakes = ">=2.3.0,<2.4.0"
73 |
74 | [[package]]
75 | name = "mccabe"
76 | version = "0.6.1"
77 | description = "McCabe checker, plugin for flake8"
78 | category = "dev"
79 | optional = false
80 | python-versions = "*"
81 |
82 | [[package]]
83 | name = "mypy-extensions"
84 | version = "0.4.3"
85 | description = "Experimental type system extensions for programs checked with the mypy typechecker."
86 | category = "dev"
87 | optional = false
88 | python-versions = "*"
89 |
90 | [[package]]
91 | name = "pathspec"
92 | version = "0.9.0"
93 | description = "Utility library for gitignore style pattern matching of file paths."
94 | category = "dev"
95 | optional = false
96 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
97 |
98 | [[package]]
99 | name = "pycodestyle"
100 | version = "2.7.0"
101 | description = "Python style guide checker"
102 | category = "dev"
103 | optional = false
104 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
105 |
106 | [[package]]
107 | name = "pyflakes"
108 | version = "2.3.1"
109 | description = "passive checker of Python programs"
110 | category = "dev"
111 | optional = false
112 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
113 |
114 | [[package]]
115 | name = "regex"
116 | version = "2021.9.24"
117 | description = "Alternative regular expression module, to replace re."
118 | category = "dev"
119 | optional = false
120 | python-versions = "*"
121 |
122 | [[package]]
123 | name = "toml"
124 | version = "0.10.2"
125 | description = "Python Library for Tom's Obvious, Minimal Language"
126 | category = "dev"
127 | optional = false
128 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
129 |
130 | [[package]]
131 | name = "typed-ast"
132 | version = "1.4.3"
133 | description = "a fork of Python 2 and 3 ast modules with type comment support"
134 | category = "dev"
135 | optional = false
136 | python-versions = "*"
137 |
138 | [[package]]
139 | name = "typing-extensions"
140 | version = "3.10.0.2"
141 | description = "Backported and Experimental Type Hints for Python 3.5+"
142 | category = "dev"
143 | optional = false
144 | python-versions = "*"
145 |
146 | [metadata]
147 | lock-version = "1.1"
148 | python-versions = "^3.9"
149 | content-hash = "fbb03c7e4ae3cf6d930db3363a42815e9a414055c641b7bdf239375df60bad5d"
150 |
151 | [metadata.files]
152 | appdirs = [
153 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
154 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
155 | ]
156 | black = [
157 | {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
158 | ]
159 | click = [
160 | {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
161 | {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
162 | ]
163 | colorama = [
164 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
165 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
166 | ]
167 | coverage = [
168 | {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
169 | {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"},
170 | {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"},
171 | {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"},
172 | {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"},
173 | {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"},
174 | {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"},
175 | {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"},
176 | {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"},
177 | {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"},
178 | {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"},
179 | {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"},
180 | {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"},
181 | {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"},
182 | {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"},
183 | {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"},
184 | {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"},
185 | {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"},
186 | {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"},
187 | {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"},
188 | {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"},
189 | {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"},
190 | {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"},
191 | {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"},
192 | {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"},
193 | {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"},
194 | {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"},
195 | {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"},
196 | {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"},
197 | {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"},
198 | {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"},
199 | {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"},
200 | {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"},
201 | {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"},
202 | {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"},
203 | {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"},
204 | {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"},
205 | {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"},
206 | {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"},
207 | {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"},
208 | {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"},
209 | {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"},
210 | {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"},
211 | {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"},
212 | {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"},
213 | {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"},
214 | {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"},
215 | {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"},
216 | {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"},
217 | {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"},
218 | {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"},
219 | {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"},
220 | ]
221 | flake8 = [
222 | {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
223 | {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
224 | ]
225 | mccabe = [
226 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
227 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
228 | ]
229 | mypy-extensions = [
230 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
231 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
232 | ]
233 | pathspec = [
234 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
235 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
236 | ]
237 | pycodestyle = [
238 | {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
239 | {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
240 | ]
241 | pyflakes = [
242 | {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
243 | {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
244 | ]
245 | regex = [
246 | {file = "regex-2021.9.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0628ed7d6334e8f896f882a5c1240de8c4d9b0dd7c7fb8e9f4692f5684b7d656"},
247 | {file = "regex-2021.9.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3baf3eaa41044d4ced2463fd5d23bf7bd4b03d68739c6c99a59ce1f95599a673"},
248 | {file = "regex-2021.9.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c000635fd78400a558bd7a3c2981bb2a430005ebaa909d31e6e300719739a949"},
249 | {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:295bc8a13554a25ad31e44c4bedabd3c3e28bba027e4feeb9bb157647a2344a7"},
250 | {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0e3f59d3c772f2c3baaef2db425e6fc4149d35a052d874bb95ccfca10a1b9f4"},
251 | {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aea4006b73b555fc5bdb650a8b92cf486d678afa168cf9b38402bb60bf0f9c18"},
252 | {file = "regex-2021.9.24-cp310-cp310-win32.whl", hash = "sha256:09eb62654030f39f3ba46bc6726bea464069c29d00a9709e28c9ee9623a8da4a"},
253 | {file = "regex-2021.9.24-cp310-cp310-win_amd64.whl", hash = "sha256:8d80087320632457aefc73f686f66139801959bf5b066b4419b92be85be3543c"},
254 | {file = "regex-2021.9.24-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7e3536f305f42ad6d31fc86636c54c7dafce8d634e56fef790fbacb59d499dd5"},
255 | {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c31f35a984caffb75f00a86852951a337540b44e4a22171354fb760cefa09346"},
256 | {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7cb25adba814d5f419733fe565f3289d6fa629ab9e0b78f6dff5fa94ab0456"},
257 | {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:85c61bee5957e2d7be390392feac7e1d7abd3a49cbaed0c8cee1541b784c8561"},
258 | {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c94722bf403b8da744b7d0bb87e1f2529383003ceec92e754f768ef9323f69ad"},
259 | {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6adc1bd68f81968c9d249aab8c09cdc2cbe384bf2d2cb7f190f56875000cdc72"},
260 | {file = "regex-2021.9.24-cp36-cp36m-win32.whl", hash = "sha256:2054dea683f1bda3a804fcfdb0c1c74821acb968093d0be16233873190d459e3"},
261 | {file = "regex-2021.9.24-cp36-cp36m-win_amd64.whl", hash = "sha256:7783d89bd5413d183a38761fbc68279b984b9afcfbb39fa89d91f63763fbfb90"},
262 | {file = "regex-2021.9.24-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b15dc34273aefe522df25096d5d087abc626e388a28a28ac75a4404bb7668736"},
263 | {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10a7a9cbe30bd90b7d9a1b4749ef20e13a3528e4215a2852be35784b6bd070f0"},
264 | {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb9f5844db480e2ef9fce3a72e71122dd010ab7b2920f777966ba25f7eb63819"},
265 | {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:17310b181902e0bb42b29c700e2c2346b8d81f26e900b1328f642e225c88bce1"},
266 | {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bba1f6df4eafe79db2ecf38835c2626dbd47911e0516f6962c806f83e7a99ae"},
267 | {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:821e10b73e0898544807a0692a276e539e5bafe0a055506a6882814b6a02c3ec"},
268 | {file = "regex-2021.9.24-cp37-cp37m-win32.whl", hash = "sha256:9c371dd326289d85906c27ec2bc1dcdedd9d0be12b543d16e37bad35754bde48"},
269 | {file = "regex-2021.9.24-cp37-cp37m-win_amd64.whl", hash = "sha256:1e8d1898d4fb817120a5f684363b30108d7b0b46c7261264b100d14ec90a70e7"},
270 | {file = "regex-2021.9.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a5c2250c0a74428fd5507ae8853706fdde0f23bfb62ee1ec9418eeacf216078"},
271 | {file = "regex-2021.9.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8aec4b4da165c4a64ea80443c16e49e3b15df0f56c124ac5f2f8708a65a0eddc"},
272 | {file = "regex-2021.9.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:650c4f1fc4273f4e783e1d8e8b51a3e2311c2488ba0fcae6425b1e2c248a189d"},
273 | {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2cdb3789736f91d0b3333ac54d12a7e4f9efbc98f53cb905d3496259a893a8b3"},
274 | {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e61100200fa6ab7c99b61476f9f9653962ae71b931391d0264acfb4d9527d9c"},
275 | {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c268e78d175798cd71d29114b0a1f1391c7d011995267d3b62319ec1a4ecaa1"},
276 | {file = "regex-2021.9.24-cp38-cp38-win32.whl", hash = "sha256:658e3477676009083422042c4bac2bdad77b696e932a3de001c42cc046f8eda2"},
277 | {file = "regex-2021.9.24-cp38-cp38-win_amd64.whl", hash = "sha256:a731552729ee8ae9c546fb1c651c97bf5f759018fdd40d0e9b4d129e1e3a44c8"},
278 | {file = "regex-2021.9.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86f9931eb92e521809d4b64ec8514f18faa8e11e97d6c2d1afa1bcf6c20a8eab"},
279 | {file = "regex-2021.9.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcbbc9cfa147d55a577d285fd479b43103188855074552708df7acc31a476dd9"},
280 | {file = "regex-2021.9.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29385c4dbb3f8b3a55ce13de6a97a3d21bd00de66acd7cdfc0b49cb2f08c906c"},
281 | {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c50a6379763c733562b1fee877372234d271e5c78cd13ade5f25978aa06744db"},
282 | {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f74b6d8f59f3cfb8237e25c532b11f794b96f5c89a6f4a25857d85f84fbef11"},
283 | {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c4d83d21d23dd854ffbc8154cf293f4e43ba630aa9bd2539c899343d7f59da3"},
284 | {file = "regex-2021.9.24-cp39-cp39-win32.whl", hash = "sha256:95e89a8558c8c48626dcffdf9c8abac26b7c251d352688e7ab9baf351e1c7da6"},
285 | {file = "regex-2021.9.24-cp39-cp39-win_amd64.whl", hash = "sha256:835962f432bce92dc9bf22903d46c50003c8d11b1dc64084c8fae63bca98564a"},
286 | {file = "regex-2021.9.24.tar.gz", hash = "sha256:6266fde576e12357b25096351aac2b4b880b0066263e7bc7a9a1b4307991bb0e"},
287 | ]
288 | toml = [
289 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
290 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
291 | ]
292 | typed-ast = [
293 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
294 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
295 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
296 | {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
297 | {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
298 | {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
299 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
300 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
301 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
302 | {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
303 | {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
304 | {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
305 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
306 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
307 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
308 | {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
309 | {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
310 | {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
311 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
312 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
313 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
314 | {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
315 | {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
316 | {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
317 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
318 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
319 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
320 | {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
321 | {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
322 | {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
323 | ]
324 | typing-extensions = [
325 | {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"},
326 | {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"},
327 | {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
328 | ]
329 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "django-spam"
3 | version = "2.0.1"
4 | description = "Django application that redirects spam bots to '10 hours of' videos"
5 | authors = ["Nick Kelly "]
6 | readme = "README.md"
7 | homepage = "https://github.com/Tivix/django-spam"
8 | repository = "https://github.com/Tivix/django-spam"
9 |
10 | [tool.poetry.dependencies]
11 | python = "^3.9"
12 |
13 | [tool.poetry.dev-dependencies]
14 | flake8 = "^3.9.2"
15 | black = "20.8b1"
16 | coverage = "^5.5"
17 |
18 | [tool.black]
19 | line-length = 110
20 | include = '\.pyi?$'
21 | exclude = '''
22 | /(
23 | \.git
24 | | \.hg
25 | | \.mypy_cache
26 | | \.tox
27 | | \.venv
28 | | _build
29 | | build
30 | | dist
31 | )/
32 | '''
33 |
34 | [build-system]
35 | requires = ["poetry-core>=1.0.0"]
36 | build-backend = "poetry.core.masonry.api"
37 |
--------------------------------------------------------------------------------
/runtests.py:
--------------------------------------------------------------------------------
1 | # This file mainly exists to allow python setup.py test to work.
2 | import os
3 | import sys
4 |
5 | os.environ["DJANGO_SETTINGS_MODULE"] = "tests.settings"
6 | test_dir = os.path.join(os.path.dirname(__file__), "tests")
7 | sys.path.insert(0, test_dir)
8 |
9 | import django
10 | from django.test.utils import get_runner
11 | from django.conf import settings
12 |
13 |
14 | def runtests():
15 | TestRunner = get_runner(settings)
16 | test_runner = TestRunner(verbosity=1, interactive=True)
17 | if hasattr(django, "setup"):
18 | django.setup()
19 | failures = test_runner.run_tests(["tests"])
20 | sys.exit(bool(failures))
21 |
22 |
23 | if __name__ == "__main__":
24 | runtests()
25 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | try:
5 | from setuptools import setup, find_packages
6 | from setuptools.command.test import test
7 | except ImportError:
8 | from ez_setup import use_setuptools
9 |
10 | use_setuptools()
11 | from setuptools import setup, find_packages
12 | from setuptools.command.test import test
13 |
14 |
15 | import os
16 |
17 |
18 | here = os.path.dirname(os.path.abspath(__file__))
19 | f = open(os.path.join(here, "README.md"))
20 | long_description = f.read().strip()
21 | f.close()
22 |
23 | setup(
24 | name="django_spam",
25 | version="2.0.1",
26 | author="Nick Kelly",
27 | author_email="nick.kelly@tivix.com",
28 | url="http://github.com/Tivix/django-spam",
29 | description="Redirecting bots to utilize their time better...",
30 | packages=find_packages(exclude=("tests*",)),
31 | long_description=long_description,
32 | long_description_content_type="text/markdown",
33 | keywords="django spam",
34 | zip_safe=False,
35 | include_package_data=True,
36 | py_modules=["django_spam"],
37 | test_suite="runtests.runtests",
38 | install_requires=[
39 | "Django>=2.0.0",
40 | ],
41 | classifiers=[
42 | "Framework :: Django",
43 | "Framework :: Django :: 2.0",
44 | "Framework :: Django :: 2.1",
45 | "Framework :: Django :: 2.2",
46 | "Framework :: Django :: 3.0",
47 | "Framework :: Django :: 3.1",
48 | "Intended Audience :: Developers",
49 | "Intended Audience :: System Administrators",
50 | "Operating System :: OS Independent",
51 | "Topic :: Software Development",
52 | ],
53 | )
54 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tivix/django-spam/c975de8777b3c8c08e63cbaeef7b84af00f10620/tests/__init__.py
--------------------------------------------------------------------------------
/tests/settings.py:
--------------------------------------------------------------------------------
1 | import os.path
2 |
3 | INSTALLED_APPS = [
4 | "django.contrib.auth",
5 | "django.contrib.contenttypes",
6 | "django.contrib.sessions",
7 | "django.contrib.sites",
8 | # 'tests',
9 | # 'django_spam'
10 | ]
11 |
12 | MIDDLEWARE_CLASSES = (
13 | "django.contrib.sessions.middleware.SessionMiddleware",
14 | "django.middleware.common.CommonMiddleware",
15 | "django.middleware.csrf.CsrfViewMiddleware",
16 | "django.contrib.auth.middleware.AuthenticationMiddleware",
17 | "django.contrib.messages.middleware.MessageMiddleware",
18 | "django.middleware.clickjacking.XFrameOptionsMiddleware",
19 | )
20 |
21 | SITE_ID = 1
22 | SECRET_KEY = "fake-key"
23 |
24 | ROOT_URLCONF = "tests.urls"
25 |
26 | SPAM_ROUTES = [
27 | "testadmin.php",
28 | ]
29 |
30 | EXCLUDED_ROUTES = [
31 | "index.php",
32 | ]
33 |
34 | DEBUG = True
35 |
36 | STATIC_URL = "/static/"
37 |
38 | DATABASES = {
39 | "default": {
40 | "ENGINE": "django.db.backends.sqlite3",
41 | "NAME": os.path.join(os.path.dirname(__file__), "database.db"),
42 | }
43 | }
44 |
45 | TEMPLATES = [
46 | {
47 | "BACKEND": "django.template.backends.django.DjangoTemplates",
48 | "DIRS": [],
49 | "APP_DIRS": True,
50 | "OPTIONS": {
51 | "context_processors": [
52 | "django.template.context_processors.debug",
53 | "django.template.context_processors.request",
54 | "django.contrib.auth.context_processors.auth",
55 | "django.contrib.messages.context_processors.messages",
56 | ],
57 | },
58 | },
59 | ]
60 |
--------------------------------------------------------------------------------
/tests/test_enums.py:
--------------------------------------------------------------------------------
1 | from django_spam.enums import SpamBase
2 |
3 | from django.test import TestCase
4 |
5 |
6 | class DjangoSpamEnumsTestCase(TestCase):
7 | def test_not_implemented_error(self):
8 | with self.assertRaises(NotImplementedError):
9 | SpamBase()
10 |
--------------------------------------------------------------------------------
/tests/test_spam.py:
--------------------------------------------------------------------------------
1 | import random
2 | import sys
3 | from io import StringIO
4 | from importlib import reload
5 |
6 | from django.conf import settings
7 | from django.test import TestCase, override_settings
8 |
9 | from django_spam import SPAM_ROUTES
10 |
11 |
12 | class DjangoSpamTestCase(TestCase):
13 | def test_redirect_random_route(self):
14 | response = self.client.get("/" + random.choice(SPAM_ROUTES))
15 | self.assertEqual(response.status_code, 302)
16 |
17 | def test_add_spam_routes_in_settings(self):
18 | spam_routes = getattr(settings, "SPAM_ROUTES", [])
19 | response = self.client.get("/" + spam_routes[-1])
20 | self.assertEqual(response.status_code, 302)
21 |
22 | def test_excluded_routes(self):
23 | excluded_routes = getattr(settings, "EXCLUDED_ROUTES", [])
24 | response = self.client.get("/" + excluded_routes[-1])
25 | self.assertEqual(response.status_code, 200)
26 |
27 | @override_settings(
28 | EXCLUDED_ROUTES=[
29 | "notinlist.html",
30 | ]
31 | )
32 | def test_excluded_routes_contains_non_existent_spam_route(self):
33 | # create string object, redirect to stdout, reload package, then reset redirect
34 | capturedOutput = StringIO()
35 | sys.stdout = capturedOutput
36 | import django_spam
37 |
38 | reload(django_spam)
39 | sys.stdout = sys.__stdout__
40 |
41 | captured_output = capturedOutput.getvalue()
42 | self.assertIn("Warning:", captured_output) and self.assertIn(
43 | "is not included in django_spam.SPAM_ROUTES.", captured_output
44 | )
45 |
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | from django_spam.utils import Colour
2 |
3 | from django.test import TestCase
4 |
5 |
6 | class DjangoSpamUtilsTestCase(TestCase):
7 | """
8 | We use assertIn due to unicode preceding and trailing text...for
9 | visual clarity.
10 | """
11 |
12 | def test_fail_text(self):
13 | fail_text = Colour.text("Fail text.", "fail")
14 | self.assertIn("Fail text.", fail_text)
15 |
16 | def test_ok_text(self):
17 | ok_text = Colour.text("Ok text.", "ok")
18 | self.assertIn("Ok text.", ok_text)
19 |
20 | def test_warn_text(self):
21 | warn_text = Colour.text("Warn text.", "warn")
22 | self.assertIn("Warn text.", warn_text)
23 |
24 | def test_no_status_text(self):
25 | warn_text = Colour.text("Warn text.") # pylint: disable=no-value-for-parameter
26 | self.assertIn("Warn text.", warn_text)
27 |
28 | def test_not_implemented_error(self):
29 | with self.assertRaises(NotImplementedError):
30 | Colour()
31 |
--------------------------------------------------------------------------------
/tests/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, include
2 | from django.http import HttpResponse
3 |
4 |
5 | urlpatterns = [
6 | path("", include("django_spam.urls")),
7 | path("index.php", lambda request: HttpResponse("Hello World!")),
8 | ]
9 |
--------------------------------------------------------------------------------