Basic api stuff and bot exec
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
"""
|
||||
Base settings to build other settings files upon.
|
||||
"""
|
||||
|
||||
import environ
|
||||
|
||||
ROOT_DIR = (
|
||||
environ.Path(__file__) - 3
|
||||
) # (geeksbot_v2/config/settings/base.py - 3 = geeksbot_v2/)
|
||||
APPS_DIR = ROOT_DIR
|
||||
|
||||
env = environ.Env()
|
||||
|
||||
READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=True)
|
||||
if READ_DOT_ENV_FILE:
|
||||
# OS environment variables take precedence over variables from .env
|
||||
env.read_env(str(ROOT_DIR.path(".env")))
|
||||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = env.bool("DJANGO_DEBUG", False)
|
||||
# Local time zone. Choices are
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# though not all of them may be available with every OS.
|
||||
# In Windows, this must be set to your system time zone.
|
||||
TIME_ZONE = "America/Anchorage"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
|
||||
LANGUAGE_CODE = "en-us"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
|
||||
SITE_ID = 1
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
|
||||
USE_I18N = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
|
||||
USE_L10N = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
|
||||
USE_TZ = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths
|
||||
LOCALE_PATHS = [ROOT_DIR.path("locale")]
|
||||
|
||||
# DATABASES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||
DATABASES = {"default": env.db("DATABASE_URL")}
|
||||
DATABASES["default"]["ATOMIC_REQUESTS"] = True
|
||||
|
||||
# URLS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
|
||||
ROOT_URLCONF = "config.urls"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
|
||||
WSGI_APPLICATION = "config.wsgi.application"
|
||||
|
||||
# APPS
|
||||
# ------------------------------------------------------------------------------
|
||||
DJANGO_APPS = [
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.sites",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
# "django.contrib.humanize", # Handy template tags
|
||||
"django.contrib.admin",
|
||||
]
|
||||
THIRD_PARTY_APPS = [
|
||||
"crispy_forms",
|
||||
"allauth",
|
||||
"allauth.account",
|
||||
"allauth.socialaccount",
|
||||
"allauth.socialaccount.providers.discord",
|
||||
"rest_framework",
|
||||
"rest_framework.authtoken",
|
||||
]
|
||||
|
||||
LOCAL_APPS = [
|
||||
"geeksbot_v2.users.apps.UsersConfig",
|
||||
"geeksbot_v2.guilds.apps.GuildsConfig",
|
||||
"geeksbot_v2.dmessages.apps.MessagesConfig",
|
||||
"geeksbot_v2.patreon.apps.PatreonConfig",
|
||||
"geeksbot_v2.rcon.apps.RconConfig",
|
||||
# Your stuff: custom apps go here
|
||||
]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
||||
|
||||
# MIGRATIONS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
|
||||
MIGRATION_MODULES = {"sites": "geeksbot_v2.contrib.sites.migrations"}
|
||||
|
||||
# AUTHENTICATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
"allauth.account.auth_backends.AuthenticationBackend",
|
||||
]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
|
||||
AUTH_USER_MODEL = "users.User"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
|
||||
LOGIN_REDIRECT_URL = "users:redirect"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
|
||||
LOGIN_URL = "account_login"
|
||||
|
||||
# PASSWORDS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||
PASSWORD_HASHERS = [
|
||||
# https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
|
||||
"django.contrib.auth.hashers.Argon2PasswordHasher",
|
||||
"django.contrib.auth.hashers.PBKDF2PasswordHasher",
|
||||
"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
|
||||
"django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
|
||||
]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
|
||||
},
|
||||
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
|
||||
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
|
||||
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
|
||||
]
|
||||
|
||||
# MIDDLEWARE
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
# STATIC
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
|
||||
STATIC_ROOT = str(ROOT_DIR("staticfiles"))
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#static-url
|
||||
STATIC_URL = "/static/"
|
||||
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
|
||||
STATICFILES_DIRS = [str(APPS_DIR.path("static"))]
|
||||
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
||||
STATICFILES_FINDERS = [
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
]
|
||||
|
||||
# MEDIA
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#media-root
|
||||
MEDIA_ROOT = str(APPS_DIR("media"))
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
|
||||
MEDIA_URL = "/media/"
|
||||
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
TEMPLATES = [
|
||||
{
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
|
||||
"DIRS": [str(APPS_DIR.path("templates"))],
|
||||
"OPTIONS": {
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
|
||||
# https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
|
||||
"loaders": [
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
],
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.template.context_processors.i18n",
|
||||
"django.template.context_processors.media",
|
||||
"django.template.context_processors.static",
|
||||
"django.template.context_processors.tz",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
|
||||
CRISPY_TEMPLATE_PACK = "bootstrap4"
|
||||
|
||||
# FIXTURES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
|
||||
FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
|
||||
|
||||
# SECURITY
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly
|
||||
CSRF_COOKIE_HTTPONLY = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options
|
||||
X_FRAME_OPTIONS = "DENY"
|
||||
|
||||
# EMAIL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
EMAIL_BACKEND = env(
|
||||
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend"
|
||||
)
|
||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#email-timeout
|
||||
EMAIL_TIMEOUT = 5
|
||||
|
||||
# ADMIN
|
||||
# ------------------------------------------------------------------------------
|
||||
# Django Admin URL.
|
||||
ADMIN_URL = "admin/"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
||||
ADMINS = [("""Dustin Pianalto""", "dusty.p@geeksbot.app")]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
||||
MANAGERS = ADMINS
|
||||
|
||||
# LOGGING
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||
# See https://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "%(levelname)s %(asctime)s %(module)s "
|
||||
"%(process)d %(thread)d %(message)s"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose",
|
||||
}
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
}
|
||||
|
||||
# django-allauth
|
||||
# ------------------------------------------------------------------------------
|
||||
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", False)
|
||||
SOCIAL_ACCOUNT_ALLOW_REGISTRATION = env.bool('DJANGO_SOCIAL_ACCOUNT_ALLOW_REGISTRATION', True)
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
ACCOUNT_AUTHENTICATION_METHOD = "username"
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
ACCOUNT_EMAIL_REQUIRED = False
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
ACCOUNT_EMAIL_VERIFICATION = "optional"
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
ACCOUNT_ADAPTER = "geeksbot_v2.users.adapters.AccountAdapter"
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
SOCIALACCOUNT_ADAPTER = "geeksbot_v2.users.adapters.SocialAccountAdapter"
|
||||
|
||||
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
],
|
||||
"DEFAULT_RENDERER_CLASSES": [
|
||||
"rest_framework.renderers.JSONRenderer",
|
||||
],
|
||||
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
|
||||
"PAGE_SIZE": 100,
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
from .base import * # noqa
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env(
|
||||
"DJANGO_SECRET_KEY",
|
||||
default="j67xnBm5ZQ7SAQwhvaMnD4WAW1EeEFVQx0KxBOyHRMYCR4LV0rVkuslZJs1rtPUE",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
"LOCATION": "",
|
||||
}
|
||||
}
|
||||
|
||||
# EMAIL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
EMAIL_BACKEND = env(
|
||||
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
|
||||
EMAIL_HOST = "localhost"
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
|
||||
EMAIL_PORT = 1025
|
||||
|
||||
# django-debug-toolbar
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
|
||||
INSTALLED_APPS += ["debug_toolbar"] # noqa F405
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
|
||||
MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] # noqa F405
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
|
||||
DEBUG_TOOLBAR_CONFIG = {
|
||||
"DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"],
|
||||
"SHOW_TEMPLATE_CONTEXT": True,
|
||||
}
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
|
||||
INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
|
||||
if env("USE_DOCKER") == "yes":
|
||||
import socket
|
||||
|
||||
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
|
||||
INTERNAL_IPS += [ip[:-1] + "1" for ip in ips]
|
||||
|
||||
# django-extensions
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
||||
INSTALLED_APPS += ["django_extensions"] # noqa F405
|
||||
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,155 @@
|
||||
from .base import * # noqa
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env("DJANGO_SECRET_KEY")
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["geeksbot.app"])
|
||||
|
||||
# DATABASES
|
||||
# ------------------------------------------------------------------------------
|
||||
DATABASES["default"] = env.db("DATABASE_URL") # noqa F405
|
||||
DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405
|
||||
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": env("REDIS_URL"),
|
||||
"OPTIONS": {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
# Mimicing memcache behavior.
|
||||
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
|
||||
"IGNORE_EXCEPTIONS": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
# SECURITY
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect
|
||||
SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
|
||||
SESSION_COOKIE_SECURE = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
|
||||
CSRF_COOKIE_SECURE = True
|
||||
# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds
|
||||
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
|
||||
SECURE_HSTS_SECONDS = 60
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
|
||||
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
|
||||
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
|
||||
# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
|
||||
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
|
||||
)
|
||||
|
||||
# MEDIA
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
|
||||
(
|
||||
"django.template.loaders.cached.Loader",
|
||||
[
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
# EMAIL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
|
||||
DEFAULT_FROM_EMAIL = env(
|
||||
"DJANGO_DEFAULT_FROM_EMAIL", default="geeksbot <noreply@geeksbot.app>"
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#server-email
|
||||
SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
|
||||
EMAIL_SUBJECT_PREFIX = env(
|
||||
"DJANGO_EMAIL_SUBJECT_PREFIX", default="[geeksbot]"
|
||||
)
|
||||
|
||||
# ADMIN
|
||||
# ------------------------------------------------------------------------------
|
||||
# Django Admin URL regex.
|
||||
ADMIN_URL = env("DJANGO_ADMIN_URL")
|
||||
|
||||
# Anymail (Mailgun)
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
|
||||
INSTALLED_APPS += ["anymail"] # noqa F405
|
||||
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
|
||||
# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
|
||||
ANYMAIL = {
|
||||
"MAILGUN_API_KEY": env("MAILGUN_API_KEY"),
|
||||
"MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"),
|
||||
"MAILGUN_API_URL": env("MAILGUN_API_URL", default="https://api.mailgun.net/v3"),
|
||||
}
|
||||
|
||||
# Collectfast
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://github.com/antonagestam/collectfast#installation
|
||||
INSTALLED_APPS = ["collectfast"] + INSTALLED_APPS # noqa F405
|
||||
AWS_PRELOAD_METADATA = True
|
||||
|
||||
# LOGGING
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||
# See https://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "%(levelname)s %(asctime)s %(module)s "
|
||||
"%(process)d %(thread)d %(message)s"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"mail_admins": {
|
||||
"level": "ERROR",
|
||||
"filters": ["require_debug_false"],
|
||||
"class": "django.utils.log.AdminEmailHandler",
|
||||
},
|
||||
"console": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose",
|
||||
},
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
"loggers": {
|
||||
"django.request": {
|
||||
"handlers": ["mail_admins"],
|
||||
"level": "ERROR",
|
||||
"propagate": True,
|
||||
},
|
||||
"django.security.DisallowedHost": {
|
||||
"level": "ERROR",
|
||||
"handlers": ["console", "mail_admins"],
|
||||
"propagate": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
With these settings, tests run faster.
|
||||
"""
|
||||
|
||||
from .base import * # noqa
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = False
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env(
|
||||
"DJANGO_SECRET_KEY",
|
||||
default="f2z33VJdMTuS8AHpyHr1p2AAR9daYVQFMLEqBGxEP2aZLmtBpRVudyOrhK1DL9Ov",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner
|
||||
TEST_RUNNER = "django.test.runner.DiscoverRunner"
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
"LOCATION": "",
|
||||
}
|
||||
}
|
||||
|
||||
# PASSWORDS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
|
||||
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
|
||||
(
|
||||
"django.template.loaders.cached.Loader",
|
||||
[
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
# EMAIL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
||||
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,47 @@
|
||||
from django.conf import settings
|
||||
from django.urls import include, path
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.views.generic import TemplateView
|
||||
from django.views import defaults as default_views
|
||||
|
||||
urlpatterns = [
|
||||
path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
|
||||
path(
|
||||
"about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
|
||||
),
|
||||
# Django Admin, use {% url 'admin:index' %}
|
||||
path(settings.ADMIN_URL, admin.site.urls),
|
||||
# User management
|
||||
path("users/", include("geeksbot_v2.users.urls", namespace="users")),
|
||||
path("accounts/", include("allauth.urls")),
|
||||
# Your stuff: custom urls includes go here
|
||||
path("api/users", include("geeksbot_v2.users.api_urls", namespace="users_api")),
|
||||
path("api/guilds", include("geeksbot_v2.guilds.api_urls", namespace="guilds_api"))
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
if settings.DEBUG:
|
||||
# This allows the error pages to be debugged during development, just visit
|
||||
# these url in browser to see how these error pages look like.
|
||||
urlpatterns += [
|
||||
path(
|
||||
"400/",
|
||||
default_views.bad_request,
|
||||
kwargs={"exception": Exception("Bad Request!")},
|
||||
),
|
||||
path(
|
||||
"403/",
|
||||
default_views.permission_denied,
|
||||
kwargs={"exception": Exception("Permission Denied")},
|
||||
),
|
||||
path(
|
||||
"404/",
|
||||
default_views.page_not_found,
|
||||
kwargs={"exception": Exception("Page not Found")},
|
||||
),
|
||||
path("500/", default_views.server_error),
|
||||
]
|
||||
if "debug_toolbar" in settings.INSTALLED_APPS:
|
||||
import debug_toolbar
|
||||
|
||||
urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns
|
||||
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
WSGI config for geeksbot project.
|
||||
|
||||
This module contains the WSGI application used by Django's development server
|
||||
and any production WSGI deployments. It should expose a module-level variable
|
||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
||||
this application via the ``WSGI_APPLICATION`` setting.
|
||||
|
||||
Usually you will have the standard Django WSGI application here, but it also
|
||||
might make sense to replace the whole Django WSGI application with a custom one
|
||||
that later delegates to the Django one. For example, you could introduce WSGI
|
||||
middleware here, or combine a Django application with an application of another
|
||||
framework.
|
||||
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
# This allows easy placement of apps within the interior
|
||||
# geeksbot_v2 directory.
|
||||
app_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
|
||||
)
|
||||
sys.path.append(os.path.join(app_path, "geeksbot_v2"))
|
||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
application = get_wsgi_application()
|
||||
# Apply WSGI middleware here.
|
||||
# from helloworld.wsgi import HelloWorldApplication
|
||||
# application = HelloWorldApplication(application)
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Message
|
||||
from .models import GuildInfo
|
||||
from .models import AdminRequest
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Message)
|
||||
admin.site.register(GuildInfo)
|
||||
admin.site.register(AdminRequest)
|
||||
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class MessagesConfig(AppConfig):
|
||||
name = 'geeksbot_v2.dmessages'
|
||||
verbose_name = _("DMessages")
|
||||
@@ -0,0 +1,64 @@
|
||||
# Generated by Django 2.2.4 on 2019-09-16 05:23
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.postgres.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('guilds', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Message',
|
||||
fields=[
|
||||
('id', models.CharField(max_length=30, primary_key=True, serialize=False)),
|
||||
('channel', models.CharField(max_length=30)),
|
||||
('created_at', models.DateTimeField()),
|
||||
('modified_at', models.DateTimeField(null=True)),
|
||||
('deleted_at', models.DateTimeField(null=True)),
|
||||
('content', models.CharField(max_length=2000)),
|
||||
('previous_content', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=2000), size=None)),
|
||||
('tagged_users', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), size=None)),
|
||||
('tagged_channels', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), size=None)),
|
||||
('tagged_roles', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), size=None)),
|
||||
('tagged_everyone', models.BooleanField()),
|
||||
('embeds', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), size=None)),
|
||||
('previous_embeds', django.contrib.postgres.fields.ArrayField(base_field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), size=None), size=None)),
|
||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='GuildInfo',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.PositiveSmallIntegerField()),
|
||||
('text', models.TextField(max_length=1980)),
|
||||
('format', models.PositiveSmallIntegerField()),
|
||||
('channel', models.CharField(max_length=30)),
|
||||
('message_number', models.PositiveSmallIntegerField()),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
('message', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dmessages.Message')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AdminRequest',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('completed', models.BooleanField()),
|
||||
('requested_at', models.DateTimeField()),
|
||||
('completed_at', models.DateTimeField()),
|
||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dmessages.Message')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,58 @@
|
||||
from django.db import models
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
from geeksbot_v2.users.models import User
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
id = models.CharField(max_length=30, primary_key=True)
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE)
|
||||
channel = models.CharField(max_length=30)
|
||||
created_at = models.DateTimeField()
|
||||
modified_at = models.DateTimeField(null=True)
|
||||
deleted_at = models.DateTimeField(null=True)
|
||||
content = models.CharField(max_length=2000)
|
||||
previous_content = ArrayField(models.CharField(max_length=2000))
|
||||
tagged_users = ArrayField(models.CharField(max_length=30))
|
||||
tagged_channels = ArrayField(models.CharField(max_length=30))
|
||||
tagged_roles = ArrayField(models.CharField(max_length=30))
|
||||
tagged_everyone = models.BooleanField()
|
||||
embeds = ArrayField(models.TextField())
|
||||
previous_embeds = ArrayField(ArrayField(models.TextField()))
|
||||
|
||||
def __str__(self):
|
||||
return (f'{self.created_at} | '
|
||||
f'{self.author.id}'
|
||||
f'{" | Modified" if self.modified_at else ""}'
|
||||
f'{" | Deleted" if self.deleted_at else ""}')
|
||||
|
||||
|
||||
class GuildInfo(models.Model):
|
||||
message = models.ForeignKey(
|
||||
Message, on_delete=models.CASCADE, blank=True, null=True
|
||||
)
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE)
|
||||
type = models.PositiveSmallIntegerField()
|
||||
text = models.TextField(max_length=1980)
|
||||
format = models.PositiveSmallIntegerField()
|
||||
channel = models.CharField(max_length=30)
|
||||
message_number = models.PositiveSmallIntegerField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.text[:25]}"
|
||||
|
||||
|
||||
class AdminRequest(models.Model):
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE)
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
message = models.ForeignKey(Message, on_delete=models.CASCADE)
|
||||
completed = models.BooleanField()
|
||||
requested_at = models.DateTimeField()
|
||||
completed_at = models.DateTimeField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.requested_at} | By {self.author.id}"
|
||||
@@ -0,0 +1,22 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Message
|
||||
from .models import GuildInfo
|
||||
from .models import AdminRequest
|
||||
|
||||
|
||||
class MessageSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Message
|
||||
fields = "__all__"
|
||||
|
||||
class GuildInfoSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = GuildInfo
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class AdminRequestSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = AdminRequest
|
||||
fields = "__all__"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
if [ -z "${POSTGRES_USER}" ]; then
|
||||
base_postgres_image_default_user='postgres'
|
||||
export POSTGRES_USER="${base_postgres_image_default_user}"
|
||||
fi
|
||||
|
||||
postgres_ready() {
|
||||
python << END
|
||||
import sys
|
||||
|
||||
import psycopg2
|
||||
|
||||
try:
|
||||
psycopg2.connect(
|
||||
dbname="${POSTGRES_DB}",
|
||||
user="${POSTGRES_USER}",
|
||||
password="${POSTGRES_PASSWORD}",
|
||||
host="${POSTGRES_HOST}",
|
||||
port="${POSTGRES_PORT}",
|
||||
)
|
||||
except psycopg2.OperationalError:
|
||||
sys.exit(-1)
|
||||
sys.exit(0)
|
||||
|
||||
END
|
||||
}
|
||||
until postgres_ready; do
|
||||
>&2 echo 'Waiting for PostgreSQL to become available...'
|
||||
sleep 1
|
||||
done
|
||||
>&2 echo 'PostgreSQL is available'
|
||||
|
||||
python manage.py collectstatic --noinput
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
|
||||
/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
from geeksbot_v2.guilds.models import Role
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Guild)
|
||||
admin.site.register(Role)
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import GuildsAPI
|
||||
|
||||
app_name = "users_api"
|
||||
urlpatterns = [
|
||||
path("/", view=GuildsAPI.as_view(), name="list")
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class GuildsConfig(AppConfig):
|
||||
name = 'geeksbot_v2.guilds'
|
||||
verbose_name = _("Guilds")
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 2.2.4 on 2019-09-16 05:23
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Guild',
|
||||
fields=[
|
||||
('id', models.CharField(max_length=30, primary_key=True, serialize=False)),
|
||||
('admin_chat', models.CharField(max_length=30)),
|
||||
('new_patron_message', models.TextField(blank=True, max_length=1000)),
|
||||
('default_channel', models.CharField(max_length=30)),
|
||||
('new_patron_channel', models.CharField(max_length=30)),
|
||||
('prefixes', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=10), size=None)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Role',
|
||||
fields=[
|
||||
('id', models.CharField(max_length=30, primary_key=True, serialize=False)),
|
||||
('type', models.PositiveSmallIntegerField()),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 2.2.4 on 2019-09-17 05:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guilds', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='guild',
|
||||
name='admin_chat',
|
||||
field=models.CharField(blank=True, max_length=30, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='guild',
|
||||
name='new_patron_channel',
|
||||
field=models.CharField(blank=True, max_length=30, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='guild',
|
||||
name='new_patron_message',
|
||||
field=models.TextField(blank=True, max_length=1000, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
from django.db import models
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Guild(models.Model):
|
||||
id = models.CharField(max_length=30, primary_key=True)
|
||||
admin_chat = models.CharField(max_length=30, blank=True, null=True)
|
||||
new_patron_message = models.TextField(max_length=1000, blank=True, null=True)
|
||||
default_channel = models.CharField(max_length=30)
|
||||
new_patron_channel = models.CharField(max_length=30, blank=True, null=True)
|
||||
prefixes = ArrayField(models.CharField(max_length=10))
|
||||
|
||||
def __str__(self):
|
||||
return self.id
|
||||
|
||||
|
||||
class Role(models.Model):
|
||||
id = models.CharField(max_length=30, primary_key=True)
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE, null=False)
|
||||
type = models.PositiveSmallIntegerField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.id}"
|
||||
@@ -0,0 +1,16 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
from geeksbot_v2.guilds.models import Role
|
||||
|
||||
|
||||
class GuildSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Guild
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class RoleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ["id", "guild", "type"]
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,51 @@
|
||||
import os
|
||||
|
||||
from django.shortcuts import render
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from geeksbot_v2.utils.api_utils import PaginatedAPIView
|
||||
from .models import Guild
|
||||
from .serializers import GuildSerializer
|
||||
|
||||
# Create your views here.
|
||||
|
||||
# API Views
|
||||
|
||||
|
||||
class GuildsAPI(PaginatedAPIView):
|
||||
def get(self, request, format=None):
|
||||
users = Guild.objects.all()
|
||||
page = self.paginate_queryset(users)
|
||||
if page is not None:
|
||||
serialized_users = GuildSerializer(users, many=True)
|
||||
return self.get_paginated_response(serialized_users.data)
|
||||
|
||||
serialized_users = GuildSerializer(users, many=True)
|
||||
return Response(serialized_users.data)
|
||||
|
||||
def post(self, request, format=None):
|
||||
data = dict(request.data)
|
||||
print(data)
|
||||
id = data.get('id')
|
||||
default_channel = data.get('default_channel')
|
||||
if not (id and default_channel):
|
||||
return Response({'msg': 'id and default_channel are required'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
admin_chat = data.get('admin_chat')
|
||||
new_patron_message = data.get('new_patron_message')
|
||||
default_prefix = os.environ['DISCORD_DEFAULT_PREFIX']
|
||||
prefixes = data.get('prefixes', [default_prefix, ])
|
||||
print(prefixes)
|
||||
|
||||
guild = Guild(
|
||||
id=id[0] if isinstance(id, list) else id,
|
||||
default_channel=default_channel[0] if isinstance(default_channel, list) else default_channel,
|
||||
prefixes=prefixes,
|
||||
admin_chat=admin_chat[0] if isinstance(admin_chat, list) else admin_chat,
|
||||
new_patron_message=new_patron_message[0] if isinstance(new_patron_message, list) else new_patron_message
|
||||
)
|
||||
guild.save()
|
||||
|
||||
return Response(GuildSerializer(guild).data, status=status.HTTP_201_CREATED)
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "geeksbot_v2.config.settings.local")
|
||||
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError:
|
||||
# The above import may fail for some other reason. Ensure that the
|
||||
# issue is really that Django is missing to avoid masking other
|
||||
# exceptions on Python 2.
|
||||
try:
|
||||
import django # noqa
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
)
|
||||
|
||||
raise
|
||||
|
||||
# This allows easy placement of apps within the interior
|
||||
# geeksbot_v2 directory.
|
||||
current_path = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(os.path.join(current_path, "geeksbot_v2"))
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.contrib import admin
|
||||
|
||||
|
||||
from .models import PatreonCreator
|
||||
from .models import PatreonTier
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(PatreonCreator)
|
||||
admin.site.register(PatreonTier)
|
||||
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class PatreonConfig(AppConfig):
|
||||
name = 'geeksbot_v2.patreon'
|
||||
verbose_name = _("Patreon")
|
||||
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 2.2.4 on 2019-09-16 05:23
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('guilds', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PatreonCreator',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('creator', models.CharField(max_length=50)),
|
||||
('link', models.CharField(max_length=100)),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PatreonTier',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('description', models.TextField()),
|
||||
('amount', models.IntegerField(null=True)),
|
||||
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='patreon.PatreonCreator')),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Role')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
from django.db import models
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
from geeksbot_v2.guilds.models import Role
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class PatreonCreator(models.Model):
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE, null=False)
|
||||
creator = models.CharField(max_length=50, null=False)
|
||||
link = models.CharField(max_length=100, null=False)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.creator}"
|
||||
|
||||
|
||||
class PatreonTier(models.Model):
|
||||
creator = models.ForeignKey(PatreonCreator, on_delete=models.CASCADE)
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=50)
|
||||
description = models.TextField()
|
||||
role = models.ForeignKey(Role, on_delete=models.CASCADE)
|
||||
amount = models.IntegerField(null=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.creator.creator} | {self.name}"
|
||||
@@ -0,0 +1,16 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from geeksbot_v2.patreon.models import PatreonCreator
|
||||
from geeksbot_v2.patreon.models import PatreonTier
|
||||
|
||||
|
||||
class PatreonCreatorSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = PatreonCreator
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class PatreonTierSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = PatreonTier
|
||||
fields = "__all__"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import RconServer
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(RconServer)
|
||||
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class RconConfig(AppConfig):
|
||||
name = 'geeksbot_v2.rcon'
|
||||
verbose_name = _("Rcon")
|
||||
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 2.2.4 on 2019-09-16 05:23
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('guilds', '0001_initial'),
|
||||
('dmessages', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='RconServer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('ip', models.GenericIPAddressField()),
|
||||
('port', models.PositiveIntegerField()),
|
||||
('password', models.CharField(max_length=50)),
|
||||
('monitor_chat', models.BooleanField()),
|
||||
('monitor_chat_channel', models.CharField(blank=True, max_length=30)),
|
||||
('alerts_channel', models.CharField(blank=True, max_length=30)),
|
||||
('info_channel', models.CharField(blank=True, max_length=30)),
|
||||
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='guilds.Guild')),
|
||||
('info_message', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dmessages.Message')),
|
||||
('settings_message', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dmessages.Message')),
|
||||
('whitelist', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
from django.db import models
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
from geeksbot_v2.dmessages.models import Message
|
||||
from geeksbot_v2.users.models import User
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class RconServer(models.Model):
|
||||
guild = models.ForeignKey(Guild, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=50)
|
||||
ip = models.GenericIPAddressField()
|
||||
port = models.PositiveIntegerField()
|
||||
password = models.CharField(max_length=50)
|
||||
monitor_chat = models.BooleanField()
|
||||
monitor_chat_channel = models.CharField(max_length=30, blank=True)
|
||||
alerts_channel = models.CharField(max_length=30, blank=True)
|
||||
info_channel = models.CharField(max_length=30, blank=True)
|
||||
info_message = models.ForeignKey(
|
||||
Message, on_delete=models.CASCADE, related_name="+", blank=True
|
||||
)
|
||||
settings_message = models.ForeignKey(
|
||||
Message, on_delete=models.CASCADE, related_name="+", blank=True
|
||||
)
|
||||
whitelist = models.ManyToManyField(User, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.guild.id} | {self.name}"
|
||||
@@ -0,0 +1,9 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from geeksbot_v2.rcon.models import RconServer
|
||||
|
||||
|
||||
class RconServerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = RconServer
|
||||
fields = "__all__"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -59,10 +59,6 @@
|
||||
<a class="nav-link" href="{% url 'account_logout' %}">{% trans "Sign Out" %}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
{# URL provided by django-allauth/account/urls.py #}
|
||||
<a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
{# URL provided by django-allauth/account/urls.py #}
|
||||
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% trans "Sign In" %}</a>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
{% if object.name %}
|
||||
<p>{{ object.name }}</p>
|
||||
{% endif %}
|
||||
{{ user.id }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,15 +2,34 @@ from typing import Any
|
||||
|
||||
from allauth.account.adapter import DefaultAccountAdapter
|
||||
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||
from allauth.account.utils import user_email, user_username, user_field
|
||||
from allauth.utils import valid_email_or_none
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest
|
||||
|
||||
|
||||
class AccountAdapter(DefaultAccountAdapter):
|
||||
def is_open_for_signup(self, request: HttpRequest):
|
||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", False)
|
||||
|
||||
|
||||
class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||
def is_open_for_signup(self, request: HttpRequest, sociallogin: Any):
|
||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
||||
return getattr(settings, "SOCIAL_ACCOUNT_ALLOW_REGISTRATION", True)
|
||||
|
||||
def populate_user(self, request, sociallogin, data):
|
||||
# print(sociallogin.account.extra_data)
|
||||
first_name = data.get('first_name')
|
||||
last_name = data.get('last_name')
|
||||
name = data.get('name')
|
||||
id = sociallogin.account.extra_data.get('id')
|
||||
user = sociallogin.user
|
||||
user_username(user, data.get('username', ''))
|
||||
user_email(user, valid_email_or_none(data.get('email')) or '')
|
||||
name_parts = (name or '').partition(' ')
|
||||
user_field(user, 'first_name', first_name or name_parts[0])
|
||||
user_field(user, 'last_name', last_name or name_parts[2])
|
||||
user_field(user, 'id', id or '')
|
||||
user_field(user, 'avatar', sociallogin.account.extra_data.get('avatar', ''))
|
||||
user_field(user, 'discriminator', sociallogin.account.extra_data.get('discriminator', ''))
|
||||
return user
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth import admin as auth_admin
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from geeksbot_v2.users.forms import UserChangeForm, UserCreationForm
|
||||
|
||||
User = get_user_model()
|
||||
from .forms import UserChangeForm
|
||||
from .models import User
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class UserAdmin(auth_admin.UserAdmin):
|
||||
|
||||
model = User
|
||||
form = UserChangeForm
|
||||
add_form = UserCreationForm
|
||||
fieldsets = (("User", {"fields": ("name",)}),) + auth_admin.UserAdmin.fieldsets
|
||||
list_display = ["username", "name", "is_superuser"]
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from geeksbot_v2.users.views import UsersAPI
|
||||
|
||||
app_name = "users_api"
|
||||
urlpatterns = [
|
||||
path("users/", view=UsersAPI.as_view(), name="list")
|
||||
]
|
||||
@@ -1,30 +1,8 @@
|
||||
from django.contrib.auth import get_user_model, forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth import forms
|
||||
|
||||
User = get_user_model()
|
||||
from .models import User
|
||||
|
||||
|
||||
class UserChangeForm(forms.UserChangeForm):
|
||||
class Meta(forms.UserChangeForm.Meta):
|
||||
model = User
|
||||
|
||||
|
||||
class UserCreationForm(forms.UserCreationForm):
|
||||
|
||||
error_message = forms.UserCreationForm.error_messages.update(
|
||||
{"duplicate_username": _("This username has already been taken.")}
|
||||
)
|
||||
|
||||
class Meta(forms.UserCreationForm.Meta):
|
||||
model = User
|
||||
|
||||
def clean_username(self):
|
||||
username = self.cleaned_data["username"]
|
||||
|
||||
try:
|
||||
User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
return username
|
||||
|
||||
raise ValidationError(self.error_messages["duplicate_username"])
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
import django.contrib.auth.models
|
||||
import django.contrib.auth.validators
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [("auth", "0008_alter_user_username_max_length")]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="User",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("password", models.CharField(max_length=128, verbose_name="password")),
|
||||
(
|
||||
"last_login",
|
||||
models.DateTimeField(
|
||||
blank=True, null=True, verbose_name="last login"
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_superuser",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
||||
verbose_name="superuser status",
|
||||
),
|
||||
),
|
||||
(
|
||||
"username",
|
||||
models.CharField(
|
||||
error_messages={
|
||||
"unique": "A user with that username already exists."
|
||||
},
|
||||
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||
max_length=150,
|
||||
unique=True,
|
||||
validators=[
|
||||
django.contrib.auth.validators.UnicodeUsernameValidator()
|
||||
],
|
||||
verbose_name="username",
|
||||
),
|
||||
),
|
||||
(
|
||||
"first_name",
|
||||
models.CharField(
|
||||
blank=True, max_length=30, verbose_name="first name"
|
||||
),
|
||||
),
|
||||
(
|
||||
"last_name",
|
||||
models.CharField(
|
||||
blank=True, max_length=150, verbose_name="last name"
|
||||
),
|
||||
),
|
||||
(
|
||||
"email",
|
||||
models.EmailField(
|
||||
blank=True, max_length=254, verbose_name="email address"
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_staff",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Designates whether the user can log into this admin site.",
|
||||
verbose_name="staff status",
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_active",
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
|
||||
verbose_name="active",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date_joined",
|
||||
models.DateTimeField(
|
||||
default=django.utils.timezone.now, verbose_name="date joined"
|
||||
),
|
||||
),
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
blank=True, max_length=255, verbose_name="Name of User"
|
||||
),
|
||||
),
|
||||
(
|
||||
"groups",
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
||||
related_name="user_set",
|
||||
related_query_name="user",
|
||||
to="auth.Group",
|
||||
verbose_name="groups",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user_permissions",
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="Specific permissions for this user.",
|
||||
related_name="user_set",
|
||||
related_query_name="user",
|
||||
to="auth.Permission",
|
||||
verbose_name="user permissions",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name_plural": "users",
|
||||
"verbose_name": "user",
|
||||
"abstract": False,
|
||||
},
|
||||
managers=[("objects", django.contrib.auth.models.UserManager())],
|
||||
)
|
||||
]
|
||||
@@ -2,6 +2,20 @@ from django.contrib.auth.models import AbstractUser
|
||||
from django.db.models import CharField
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db import models
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.conf import settings
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from geeksbot_v2.guilds.models import Guild
|
||||
|
||||
|
||||
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
|
||||
def create_auth_token(sender, instance=None, created=False, **kwargs):
|
||||
if created:
|
||||
Token.objects.create(user=instance)
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
@@ -9,6 +23,28 @@ class User(AbstractUser):
|
||||
# First Name and Last Name do not cover name patterns
|
||||
# around the globe.
|
||||
name = CharField(_("Name of User"), blank=True, max_length=255)
|
||||
id = models.CharField(max_length=30, primary_key=True)
|
||||
discord_username = models.CharField(max_length=100, null=True)
|
||||
previous_discord_usernames = ArrayField(models.CharField(max_length=100), blank=True, null=True)
|
||||
discriminator = models.IntegerField(null=True)
|
||||
previous_discriminators = ArrayField(models.IntegerField(), blank=True, null=True)
|
||||
guilds = models.ManyToManyField(Guild, blank=True, null=True)
|
||||
steam_id = models.CharField(max_length=30, blank=True, null=True)
|
||||
animated = models.BooleanField(blank=True, null=True)
|
||||
avatar = models.CharField(max_length=100, blank=True, null=True)
|
||||
bot = models.BooleanField(blank=True, null=True)
|
||||
banned = models.BooleanField(default=False)
|
||||
logging_enabled = models.BooleanField(default=True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("users:detail", kwargs={"username": self.username})
|
||||
|
||||
|
||||
class UserLog(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
time = models.DateTimeField()
|
||||
action = models.IntegerField()
|
||||
description = models.CharField(max_length=100)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.time} | {self.user.id} | {self.action}"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from geeksbot_v2.users.models import User
|
||||
from geeksbot_v2.users.models import UserLog
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class UserLogSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = UserLog
|
||||
fields = "__all__"
|
||||
@@ -4,6 +4,14 @@ from django.urls import reverse
|
||||
from django.views.generic import DetailView, RedirectView, UpdateView
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
from geeksbot_v2.users.serializers import UserSerializer
|
||||
from geeksbot_v2.users.serializers import UserLogSerializer
|
||||
from geeksbot_v2.users.models import UserLog
|
||||
from geeksbot_v2.utils.api_utils import PaginatedAPIView
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@@ -14,6 +22,11 @@ class UserDetailView(LoginRequiredMixin, DetailView):
|
||||
slug_field = "username"
|
||||
slug_url_kwarg = "username"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
context = self.get_context_data(object=self.object, user=request.user)
|
||||
return self.render_to_response(context)
|
||||
|
||||
|
||||
user_detail_view = UserDetailView.as_view()
|
||||
|
||||
@@ -48,3 +61,49 @@ class UserRedirectView(LoginRequiredMixin, RedirectView):
|
||||
|
||||
|
||||
user_redirect_view = UserRedirectView.as_view()
|
||||
|
||||
# API Views
|
||||
|
||||
|
||||
class UsersAPI(PaginatedAPIView):
|
||||
def get(self, request, guild, format=None):
|
||||
users = User.objects.filter(guilds__id=guild)
|
||||
page = self.paginate_queryset(users)
|
||||
if page is not None:
|
||||
serialized_users = UserSerializer(users, many=True)
|
||||
return self.get_paginated_response(serialized_users.data)
|
||||
|
||||
serialized_users = UserSerializer(users, many=True)
|
||||
return Response(serialized_users.data)
|
||||
|
||||
|
||||
class UserDetail(APIView):
|
||||
def get(self, request, guild, id, format=None):
|
||||
user = User.objects.filter(guilds__id=guild).get(id=id)
|
||||
return Response(UserSerializer(user).data)
|
||||
|
||||
|
||||
class UserLogList(PaginatedAPIView):
|
||||
def get(self, request, user, action=None, format=None):
|
||||
if action:
|
||||
user_logs = (
|
||||
UserLog.objects.filter(user=user)
|
||||
.filter(action=action)
|
||||
.order_by("-time")
|
||||
)
|
||||
else:
|
||||
user_logs = UserLog.objects.filter(user=user).order_by("-time")
|
||||
|
||||
page = self.paginate_queryset(user_logs)
|
||||
if page is not None:
|
||||
serialized_logs = UserLogSerializer(page, many=True)
|
||||
return self.get_paginated_response(serialized_logs.data)
|
||||
|
||||
serialized_logs = UserLogSerializer(user_logs, many=True)
|
||||
return Response(serialized_logs.data)
|
||||
|
||||
|
||||
class UserLogDetail(APIView):
|
||||
def get(self, request, id, format=None):
|
||||
user_log = UserLog.objects.get(id=id)
|
||||
return Response(UserLogSerializer(user_log).data)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.settings import api_settings
|
||||
|
||||
|
||||
class PaginatedAPIView(APIView):
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
|
||||
@property
|
||||
def paginator(self):
|
||||
"""
|
||||
The paginator instance associated with the view, or `None`.
|
||||
"""
|
||||
if not hasattr(self, "_paginator"):
|
||||
if self.pagination_class is None:
|
||||
self._paginator = None
|
||||
else:
|
||||
self._paginator = self.pagination_class()
|
||||
return self._paginator
|
||||
|
||||
def paginate_queryset(self, queryset):
|
||||
"""
|
||||
Return a single page of results, or `None` if pagination is disabled.
|
||||
"""
|
||||
if self.paginator is None:
|
||||
return None
|
||||
return self.paginator.paginate_queryset(queryset, self.request, view=self)
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
"""
|
||||
Return a paginated style `Response` object for the given output data.
|
||||
"""
|
||||
assert self.paginator is not None
|
||||
return self.paginator.get_paginated_response(data)
|
||||
Reference in New Issue
Block a user