apps.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import os
  2. import sys
  3. import platform
  4. from typing import List, ClassVar
  5. from pathlib import Path
  6. from pydantic import InstanceOf, Field
  7. from django.conf import settings
  8. from plugantic.base_plugin import BasePlugin
  9. from plugantic.base_configset import BaseConfigSet, ConfigSectionName
  10. from plugantic.base_hook import BaseHook
  11. ###################### Config ##########################
  12. class ShellConfig(BaseConfigSet):
  13. section: ClassVar[ConfigSectionName] = 'SHELL_CONFIG'
  14. DEBUG: bool = Field(default=False)
  15. IS_TTY: bool = Field(default=sys.stdout.isatty())
  16. USE_COLOR: bool = Field(default=lambda c: c.IS_TTY)
  17. SHOW_PROGRESS: bool = Field(default=lambda c: (c.IS_TTY and platform.system() != 'darwin')) # progress bars are buggy on mac, disable for now
  18. IN_DOCKER: bool = Field(default=False)
  19. IN_QEMU: bool = Field(default=False)
  20. PUID: int = Field(default=os.getuid())
  21. PGID: int = Field(default=os.getgid())
  22. SHELL_CONFIG = ShellConfig()
  23. class StorageConfig(BaseConfigSet):
  24. section: ClassVar[ConfigSectionName] = 'STORAGE_CONFIG'
  25. OUTPUT_PERMISSIONS: str = Field(default='644')
  26. RESTRICT_FILE_NAMES: str = Field(default='windows')
  27. ENFORCE_ATOMIC_WRITES: bool = Field(default=True)
  28. STORAGE_CONFIG = StorageConfig()
  29. class GeneralConfig(BaseConfigSet):
  30. section: ClassVar[ConfigSectionName] = 'GENERAL_CONFIG'
  31. TAG_SEPARATOR_PATTERN: str = Field(default=r'[,]')
  32. GENERAL_CONFIG = GeneralConfig()
  33. class ServerConfig(BaseConfigSet):
  34. section: ClassVar[ConfigSectionName] = 'SERVER_CONFIG'
  35. SECRET_KEY: str = Field(default=None)
  36. BIND_ADDR: str = Field(default=lambda: ['127.0.0.1:8000', '0.0.0.0:8000'][SHELL_CONFIG.IN_DOCKER])
  37. ALLOWED_HOSTS: str = Field(default='*')
  38. CSRF_TRUSTED_ORIGINS: str = Field(default=lambda c: 'http://localhost:8000,http://127.0.0.1:8000,http://0.0.0.0:8000,http://{}'.format(c.BIND_ADDR))
  39. SNAPSHOTS_PER_PAGE: int = Field(default=40)
  40. FOOTER_INFO: str = Field(default='Content is hosted for personal archiving purposes only. Contact server owner for any takedown requests.')
  41. CUSTOM_TEMPLATES_DIR: Path = Field(default=None)
  42. PUBLIC_INDEX: bool = Field(default=True)
  43. PUBLIC_SNAPSHOTS: bool = Field(default=True)
  44. PUBLIC_ADD_VIEW: bool = Field(default=False)
  45. ADMIN_USERNAME: str = Field(default=None)
  46. ADMIN_PASSWORD: str = Field(default=None)
  47. REVERSE_PROXY_USER_HEADER: str = Field(default='Remote-User')
  48. REVERSE_PROXY_WHITELIST: str = Field(default='')
  49. LOGOUT_REDIRECT_URL: str = Field(default='/')
  50. PREVIEW_ORIGINALS: bool = Field(default=True)
  51. SERVER_CONFIG = ServerConfig()
  52. class ArchivingConfig(BaseConfigSet):
  53. section: ClassVar[ConfigSectionName] = 'ARCHIVING_CONFIG'
  54. ONLY_NEW: bool = Field(default=True)
  55. TIMEOUT: int = Field(default=60)
  56. MEDIA_TIMEOUT: int = Field(default=3600)
  57. MEDIA_MAX_SIZE: str = Field(default='750m')
  58. RESOLUTION: str = Field(default='1440,2000')
  59. CHECK_SSL_VALIDITY: bool = Field(default=True)
  60. USER_AGENT: str = Field(default='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)')
  61. COOKIES_FILE: Path | None = Field(default=None)
  62. URL_DENYLIST: str = Field(default=r'\.(css|js|otf|ttf|woff|woff2|gstatic\.com|googleapis\.com/css)(\?.*)?$', alias='URL_BLACKLIST')
  63. URL_ALLOWLIST: str | None = Field(default=None, alias='URL_WHITELIST')
  64. # GIT_DOMAINS: str = Field(default='github.com,bitbucket.org,gitlab.com,gist.github.com,codeberg.org,gitea.com,git.sr.ht')
  65. # WGET_USER_AGENT: str = Field(default=lambda c: c['USER_AGENT'] + ' wget/{WGET_VERSION}')
  66. # CURL_USER_AGENT: str = Field(default=lambda c: c['USER_AGENT'] + ' curl/{CURL_VERSION}')
  67. # CHROME_USER_AGENT: str = Field(default=lambda c: c['USER_AGENT'])
  68. # CHROME_USER_DATA_DIR: str | None = Field(default=None)
  69. # CHROME_TIMEOUT: int = Field(default=0)
  70. # CHROME_HEADLESS: bool = Field(default=True)
  71. # CHROME_SANDBOX: bool = Field(default=lambda: not SHELL_CONFIG.IN_DOCKER)
  72. ARCHIVING_CONFIG = ArchivingConfig()
  73. class SearchBackendConfig(BaseConfigSet):
  74. section: ClassVar[ConfigSectionName] = 'SEARCH_BACKEND_CONFIG'
  75. USE_INDEXING_BACKEND: bool = Field(default=True)
  76. USE_SEARCHING_BACKEND: bool = Field(default=True)
  77. SEARCH_BACKEND_ENGINE: str = Field(default='ripgrep')
  78. SEARCH_BACKEND_HOST_NAME: str = Field(default='localhost')
  79. SEARCH_BACKEND_PORT: int = Field(default=1491)
  80. SEARCH_BACKEND_PASSWORD: str = Field(default='SecretPassword')
  81. SEARCH_PROCESS_HTML: bool = Field(default=True)
  82. SEARCH_BACKEND_CONFIG = SearchBackendConfig()
  83. class CorePlugin(BasePlugin):
  84. app_label: str = 'core'
  85. verbose_name: str = 'Core'
  86. hooks: List[InstanceOf[BaseHook]] = [
  87. SHELL_CONFIG,
  88. GENERAL_CONFIG,
  89. STORAGE_CONFIG,
  90. SERVER_CONFIG,
  91. ARCHIVING_CONFIG,
  92. SEARCH_BACKEND_CONFIG,
  93. ]
  94. PLUGIN = CorePlugin()
  95. PLUGIN.register(settings)
  96. DJANGO_APP = PLUGIN.AppConfig