mirror of
				https://github.com/task-17-lct/backend.git
				synced 2025-10-28 06:31:02 +03:00 
			
		
		
		
	add files
This commit is contained in:
		
						commit
						a939867ff5
					
				
							
								
								
									
										10
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| orconfig | ||||
| .gitattributes | ||||
| .github | ||||
| .gitignore | ||||
| .gitlab-ci.yml | ||||
| .idea | ||||
| .pre-commit-config.yaml | ||||
| .readthedocs.yml | ||||
| .travis.yml | ||||
| venv | ||||
							
								
								
									
										27
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| # http://editorconfig.org | ||||
| 
 | ||||
| root = true | ||||
| 
 | ||||
| [*] | ||||
| charset = utf-8 | ||||
| end_of_line = lf | ||||
| insert_final_newline = true | ||||
| trim_trailing_whitespace = true | ||||
| 
 | ||||
| [*.{py,rst,ini}] | ||||
| indent_style = space | ||||
| indent_size = 4 | ||||
| 
 | ||||
| [*.{html,css,scss,json,yml,xml}] | ||||
| indent_style = space | ||||
| indent_size = 2 | ||||
| 
 | ||||
| [*.md] | ||||
| trim_trailing_whitespace = false | ||||
| 
 | ||||
| [Makefile] | ||||
| indent_style = tab | ||||
| 
 | ||||
| [nginx.conf] | ||||
| indent_style = space | ||||
| indent_size = 2 | ||||
							
								
								
									
										4
									
								
								.env.template
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.env.template
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/passfinder | ||||
| CELERY_BROKER_URL=redis://localhost:6379/0 | ||||
| REDIS_URL=redis://localhost:6379/1 | ||||
| USE_DOCKER=no | ||||
							
								
								
									
										25
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| # Source files | ||||
| # ============ | ||||
| *.pxd    text diff=python | ||||
| *.py     text diff=python | ||||
| *.py3    text diff=python | ||||
| *.pyw    text diff=python | ||||
| *.pyx    text diff=python | ||||
| *.pyz    text diff=python | ||||
| *.pyi    text diff=python | ||||
| 
 | ||||
| # Binary files | ||||
| # ============ | ||||
| *.db     binary | ||||
| *.p      binary | ||||
| *.pkl    binary | ||||
| *.pickle binary | ||||
| *.pyc    binary export-ignore | ||||
| *.pyo    binary export-ignore | ||||
| *.pyd    binary | ||||
| 
 | ||||
| # Jupyter notebook | ||||
| *.ipynb  text eol=lf | ||||
| 
 | ||||
| # ignore static | ||||
| passfinder/static/** linguist-vendored | ||||
							
								
								
									
										333
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,333 @@ | |||
| ### Python template | ||||
| # Byte-compiled / optimized / DLL files | ||||
| __pycache__/ | ||||
| *.py[cod] | ||||
| *$py.class | ||||
| 
 | ||||
| # C extensions | ||||
| *.so | ||||
| 
 | ||||
| # Distribution / packaging | ||||
| .Python | ||||
| build/ | ||||
| develop-eggs/ | ||||
| dist/ | ||||
| downloads/ | ||||
| eggs/ | ||||
| .eggs/ | ||||
| lib/ | ||||
| lib64/ | ||||
| parts/ | ||||
| sdist/ | ||||
| var/ | ||||
| wheels/ | ||||
| *.egg-info/ | ||||
| .installed.cfg | ||||
| *.egg | ||||
| 
 | ||||
| # PyInstaller | ||||
| #  Usually these files are written by a python script from a template | ||||
| #  before PyInstaller builds the exe, so as to inject date/other infos into it. | ||||
| *.manifest | ||||
| *.spec | ||||
| 
 | ||||
| # Installer logs | ||||
| pip-log.txt | ||||
| pip-delete-this-directory.txt | ||||
| 
 | ||||
| # Unit test / coverage reports | ||||
| htmlcov/ | ||||
| .tox/ | ||||
| .coverage | ||||
| .coverage.* | ||||
| .cache | ||||
| nosetests.xml | ||||
| coverage.xml | ||||
| *.cover | ||||
| .hypothesis/ | ||||
| 
 | ||||
| # Translations | ||||
| *.mo | ||||
| *.pot | ||||
| 
 | ||||
| # Django stuff: | ||||
| staticfiles/ | ||||
| 
 | ||||
| # Sphinx documentation | ||||
| docs/_build/ | ||||
| 
 | ||||
| # PyBuilder | ||||
| target/ | ||||
| 
 | ||||
| # pyenv | ||||
| .python-version | ||||
| 
 | ||||
| # celery beat schedule file | ||||
| celerybeat-schedule | ||||
| 
 | ||||
| # Environments | ||||
| .venv | ||||
| venv/ | ||||
| ENV/ | ||||
| 
 | ||||
| # Rope project settings | ||||
| .ropeproject | ||||
| 
 | ||||
| # mkdocs documentation | ||||
| /site | ||||
| 
 | ||||
| # mypy | ||||
| .mypy_cache/ | ||||
| 
 | ||||
| 
 | ||||
| ### Node template | ||||
| # Logs | ||||
| logs | ||||
| *.log | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
| 
 | ||||
| # Runtime data | ||||
| pids | ||||
| *.pid | ||||
| *.seed | ||||
| *.pid.lock | ||||
| 
 | ||||
| # Directory for instrumented libs generated by jscoverage/JSCover | ||||
| lib-cov | ||||
| 
 | ||||
| # Coverage directory used by tools like istanbul | ||||
| coverage | ||||
| 
 | ||||
| # nyc test coverage | ||||
| .nyc_output | ||||
| 
 | ||||
| # Bower dependency directory (https://bower.io/) | ||||
| bower_components | ||||
| 
 | ||||
| # node-waf configuration | ||||
| .lock-wscript | ||||
| 
 | ||||
| # Compiled binary addons (http://nodejs.org/api/addons.html) | ||||
| build/Release | ||||
| 
 | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| jspm_packages/ | ||||
| 
 | ||||
| # Typescript v1 declaration files | ||||
| typings/ | ||||
| 
 | ||||
| # Optional npm cache directory | ||||
| .npm | ||||
| 
 | ||||
| # Optional eslint cache | ||||
| .eslintcache | ||||
| 
 | ||||
| # Optional REPL history | ||||
| .node_repl_history | ||||
| 
 | ||||
| # Output of 'npm pack' | ||||
| *.tgz | ||||
| 
 | ||||
| # Yarn Integrity file | ||||
| .yarn-integrity | ||||
| 
 | ||||
| 
 | ||||
| ### Linux template | ||||
| *~ | ||||
| 
 | ||||
| # temporary files which can be created if a process still has a handle open of a deleted file | ||||
| .fuse_hidden* | ||||
| 
 | ||||
| # KDE directory preferences | ||||
| .directory | ||||
| 
 | ||||
| # Linux trash folder which might appear on any partition or disk | ||||
| .Trash-* | ||||
| 
 | ||||
| # .nfs files are created when an open file is removed but is still being accessed | ||||
| .nfs* | ||||
| 
 | ||||
| 
 | ||||
| ### VisualStudioCode template | ||||
| .vscode/* | ||||
| !.vscode/settings.json | ||||
| !.vscode/tasks.json | ||||
| !.vscode/launch.json | ||||
| !.vscode/extensions.json | ||||
| *.code-workspace | ||||
| 
 | ||||
| # Local History for Visual Studio Code | ||||
| .history/ | ||||
| 
 | ||||
| 
 | ||||
| # Provided default Pycharm Run/Debug Configurations should be tracked by git | ||||
| # In case of local modifications made by Pycharm, use update-index command | ||||
| # for each changed file, like this: | ||||
| # git update-index --assume-unchanged .idea/passfinder.iml | ||||
| ### JetBrains template | ||||
| # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm | ||||
| # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||||
| 
 | ||||
| # User-specific stuff: | ||||
| .idea/**/workspace.xml | ||||
| .idea/**/tasks.xml | ||||
| .idea/dictionaries | ||||
| 
 | ||||
| # Sensitive or high-churn files: | ||||
| .idea/**/dataSources/ | ||||
| .idea/**/dataSources.ids | ||||
| .idea/**/dataSources.xml | ||||
| .idea/**/dataSources.local.xml | ||||
| .idea/**/sqlDataSources.xml | ||||
| .idea/**/dynamic.xml | ||||
| .idea/**/uiDesigner.xml | ||||
| 
 | ||||
| # Gradle: | ||||
| .idea/**/gradle.xml | ||||
| .idea/**/libraries | ||||
| 
 | ||||
| # CMake | ||||
| cmake-build-debug/ | ||||
| 
 | ||||
| # Mongo Explorer plugin: | ||||
| .idea/**/mongoSettings.xml | ||||
| 
 | ||||
| ## File-based project format: | ||||
| *.iws | ||||
| 
 | ||||
| ## Plugin-specific files: | ||||
| 
 | ||||
| # IntelliJ | ||||
| out/ | ||||
| 
 | ||||
| # mpeltonen/sbt-idea plugin | ||||
| .idea_modules/ | ||||
| 
 | ||||
| # JIRA plugin | ||||
| atlassian-ide-plugin.xml | ||||
| 
 | ||||
| # Cursive Clojure plugin | ||||
| .idea/replstate.xml | ||||
| 
 | ||||
| # Crashlytics plugin (for Android Studio and IntelliJ) | ||||
| com_crashlytics_export_strings.xml | ||||
| crashlytics.properties | ||||
| crashlytics-build.properties | ||||
| fabric.properties | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ### Windows template | ||||
| # Windows thumbnail cache files | ||||
| Thumbs.db | ||||
| ehthumbs.db | ||||
| ehthumbs_vista.db | ||||
| 
 | ||||
| # Dump file | ||||
| *.stackdump | ||||
| 
 | ||||
| # Folder config file | ||||
| Desktop.ini | ||||
| 
 | ||||
| # Recycle Bin used on file shares | ||||
| $RECYCLE.BIN/ | ||||
| 
 | ||||
| # Windows Installer files | ||||
| *.cab | ||||
| *.msi | ||||
| *.msm | ||||
| *.msp | ||||
| 
 | ||||
| # Windows shortcuts | ||||
| *.lnk | ||||
| 
 | ||||
| 
 | ||||
| ### macOS template | ||||
| # General | ||||
| *.DS_Store | ||||
| .AppleDouble | ||||
| .LSOverride | ||||
| 
 | ||||
| # Icon must end with two \r | ||||
| Icon | ||||
| 
 | ||||
| # Thumbnails | ||||
| ._* | ||||
| 
 | ||||
| # Files that might appear in the root of a volume | ||||
| .DocumentRevisions-V100 | ||||
| .fseventsd | ||||
| .Spotlight-V100 | ||||
| .TemporaryItems | ||||
| .Trashes | ||||
| .VolumeIcon.icns | ||||
| .com.apple.timemachine.donotpresent | ||||
| 
 | ||||
| # Directories potentially created on remote AFP share | ||||
| .AppleDB | ||||
| .AppleDesktop | ||||
| Network Trash Folder | ||||
| Temporary Items | ||||
| .apdisk | ||||
| 
 | ||||
| 
 | ||||
| ### SublimeText template | ||||
| # Cache files for Sublime Text | ||||
| *.tmlanguage.cache | ||||
| *.tmPreferences.cache | ||||
| *.stTheme.cache | ||||
| 
 | ||||
| # Workspace files are user-specific | ||||
| *.sublime-workspace | ||||
| 
 | ||||
| # Project files should be checked into the repository, unless a significant | ||||
| # proportion of contributors will probably not be using Sublime Text | ||||
| # *.sublime-project | ||||
| 
 | ||||
| # SFTP configuration file | ||||
| sftp-config.json | ||||
| 
 | ||||
| # Package control specific files | ||||
| Package Control.last-run | ||||
| Package Control.ca-list | ||||
| Package Control.ca-bundle | ||||
| Package Control.system-ca-bundle | ||||
| Package Control.cache/ | ||||
| Package Control.ca-certs/ | ||||
| Package Control.merged-ca-bundle | ||||
| Package Control.user-ca-bundle | ||||
| oscrypto-ca-bundle.crt | ||||
| bh_unicode_properties.cache | ||||
| 
 | ||||
| # Sublime-github package stores a github token in this file | ||||
| # https://packagecontrol.io/packages/sublime-github | ||||
| GitHub.sublime-settings | ||||
| 
 | ||||
| 
 | ||||
| ### Vim template | ||||
| # Swap | ||||
| [._]*.s[a-v][a-z] | ||||
| [._]*.sw[a-p] | ||||
| [._]s[a-v][a-z] | ||||
| [._]sw[a-p] | ||||
| 
 | ||||
| # Session | ||||
| Session.vim | ||||
| 
 | ||||
| # Temporary | ||||
| .netrwhist | ||||
| 
 | ||||
| # Auto-generated tag files | ||||
| tags | ||||
| 
 | ||||
| ### Project template | ||||
| passfinder/media/ | ||||
| 
 | ||||
| .pytest_cache/ | ||||
| 
 | ||||
| .ipython/ | ||||
| .env | ||||
| .idea | ||||
							
								
								
									
										39
									
								
								.pre-commit-config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								.pre-commit-config.yaml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| exclude: "^docs/|/migrations/" | ||||
| default_stages: [commit] | ||||
| 
 | ||||
| repos: | ||||
|   - repo: https://github.com/pre-commit/pre-commit-hooks | ||||
|     rev: v4.4.0 | ||||
|     hooks: | ||||
|       - id: trailing-whitespace | ||||
|       - id: end-of-file-fixer | ||||
|       - id: check-yaml | ||||
| 
 | ||||
|   - repo: https://github.com/asottile/pyupgrade | ||||
|     rev: v3.3.1 | ||||
|     hooks: | ||||
|       - id: pyupgrade | ||||
|         args: [--py310-plus] | ||||
| 
 | ||||
|   - repo: https://github.com/psf/black | ||||
|     rev: 22.12.0 | ||||
|     hooks: | ||||
|       - id: black | ||||
| 
 | ||||
|   - repo: https://github.com/PyCQA/isort | ||||
|     rev: 5.11.4 | ||||
|     hooks: | ||||
|       - id: isort | ||||
| 
 | ||||
|   - repo: https://github.com/PyCQA/flake8 | ||||
|     rev: 6.0.0 | ||||
|     hooks: | ||||
|       - id: flake8 | ||||
|         args: ["--config=setup.cfg"] | ||||
|         additional_dependencies: [flake8-isort] | ||||
| 
 | ||||
| # sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date | ||||
| ci: | ||||
|   autoupdate_schedule: weekly | ||||
|   skip: [] | ||||
|   submodules: false | ||||
							
								
								
									
										14
									
								
								.pylintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.pylintrc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| [MASTER] | ||||
| load-plugins=pylint_django, pylint_celery | ||||
| django-settings-module=config.settings.local | ||||
| [FORMAT] | ||||
| max-line-length=120 | ||||
| 
 | ||||
| [MESSAGES CONTROL] | ||||
| disable=missing-docstring,invalid-name | ||||
| 
 | ||||
| [DESIGN] | ||||
| max-parents=13 | ||||
| 
 | ||||
| [TYPECHECK] | ||||
| generated-members=REQUEST,acl_users,aq_parent,"[a-zA-Z]+_set{1,2}",save,delete | ||||
							
								
								
									
										40
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| # Pass Finder | ||||
| 
 | ||||
| 
 | ||||
| ## Basic Commands | ||||
| 
 | ||||
| ### Runserver | ||||
| 
 | ||||
|     $ ./manage.py runserver_plus | ||||
| 
 | ||||
| ### Type checks | ||||
| 
 | ||||
| Running type checks with mypy: | ||||
| 
 | ||||
|     $ mypy passfinder | ||||
| 
 | ||||
| #### Running tests with pytest | ||||
| 
 | ||||
|     $ pytest | ||||
| 
 | ||||
| ### Setting Up Your Users | ||||
| 
 | ||||
| -   To create a **superuser account**, use this command: | ||||
| 
 | ||||
|         $ python manage.py createsuperuser | ||||
| 
 | ||||
| ### Celery | ||||
| 
 | ||||
| This app comes with Celery. | ||||
| 
 | ||||
| To run a celery worker: | ||||
| 
 | ||||
| ``` bash | ||||
| cd passfinder | ||||
| celery -A config.celery_app worker -l info | ||||
| ``` | ||||
| 
 | ||||
| Please note: For Celery's import magic to work, it is important *where* the celery commands are run. If you are in the same folder with *manage.py*, you should be right. | ||||
| 
 | ||||
| 
 | ||||
| made with [cookiecutter-django](https://github.com/Alexander-D-Karpov/cookiecutter-django) | ||||
							
								
								
									
										75
									
								
								compose/local/django/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								compose/local/django/Dockerfile
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| ARG PYTHON_VERSION=3.11-slim | ||||
| 
 | ||||
| # define an alias for the specfic python version used in this file. | ||||
| FROM python:${PYTHON_VERSION} as python | ||||
| 
 | ||||
| # Python build stage | ||||
| FROM python as python-build-stage | ||||
| 
 | ||||
| ARG BUILD_ENVIRONMENT=local | ||||
| 
 | ||||
| # Install apt packages | ||||
| RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||
|   # dependencies for building Python packages | ||||
|   build-essential \ | ||||
|   # psycopg2 dependencies | ||||
|   libpq-dev | ||||
| 
 | ||||
| 
 | ||||
| # Python 'run' stage | ||||
| FROM python as python-run-stage | ||||
| 
 | ||||
| ARG BUILD_ENVIRONMENT=local | ||||
| ARG APP_HOME=/app | ||||
| 
 | ||||
| ENV PYTHONUNBUFFERED 1 | ||||
| ENV PYTHONDONTWRITEBYTECODE 1 | ||||
| ENV BUILD_ENV ${BUILD_ENVIRONMENT} | ||||
| 
 | ||||
| WORKDIR ${APP_HOME} | ||||
| 
 | ||||
| # Install required system dependencies | ||||
| RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||
|   # psycopg2 dependencies | ||||
|   libpq-dev \ | ||||
|   # Translations dependencies | ||||
|   gettext \ | ||||
|   # cleaning up unused files | ||||
|   && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ | ||||
|   && rm -rf /var/lib/apt/lists/* | ||||
| 
 | ||||
| RUN pip install poetry | ||||
| 
 | ||||
| # Configuring poetry | ||||
| RUN poetry config virtualenvs.create false | ||||
| COPY pyproject.toml poetry.lock / | ||||
| 
 | ||||
| # Installing requirements | ||||
| RUN poetry install | ||||
| 
 | ||||
| 
 | ||||
| COPY ./compose/production/django/entrypoint /entrypoint | ||||
| RUN sed -i 's/\r$//g' /entrypoint | ||||
| RUN chmod +x /entrypoint | ||||
| 
 | ||||
| COPY ./compose/local/django/start /start | ||||
| RUN sed -i 's/\r$//g' /start | ||||
| RUN chmod +x /start | ||||
| 
 | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/worker/start /start-celeryworker | ||||
| RUN sed -i 's/\r$//g' /start-celeryworker | ||||
| RUN chmod +x /start-celeryworker | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/beat/start /start-celerybeat | ||||
| RUN sed -i 's/\r$//g' /start-celerybeat | ||||
| RUN chmod +x /start-celerybeat | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/flower/start /start-flower | ||||
| RUN sed -i 's/\r$//g' /start-flower | ||||
| RUN chmod +x /start-flower | ||||
| 
 | ||||
| # copy application code to WORKDIR | ||||
| COPY . ${APP_HOME} | ||||
| 
 | ||||
| ENTRYPOINT ["/entrypoint"] | ||||
							
								
								
									
										8
									
								
								compose/local/django/celery/beat/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								compose/local/django/celery/beat/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| rm -f './celerybeat.pid' | ||||
| exec watchfiles celery.__main__.main --args '-A config.celery_app beat -l INFO' | ||||
							
								
								
									
										8
									
								
								compose/local/django/celery/flower/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								compose/local/django/celery/flower/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| 
 | ||||
| exec watchfiles celery.__main__.main \ | ||||
|     --args \ | ||||
|     "-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\"" | ||||
							
								
								
									
										7
									
								
								compose/local/django/celery/worker/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								compose/local/django/celery/worker/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| exec watchfiles celery.__main__.main --args '-A config.celery_app worker -l INFO' | ||||
							
								
								
									
										9
									
								
								compose/local/django/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								compose/local/django/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| python manage.py migrate | ||||
| exec python manage.py runserver_plus 0.0.0.0:8000 | ||||
							
								
								
									
										81
									
								
								compose/production/django/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								compose/production/django/Dockerfile
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| ARG PYTHON_VERSION=3.11-slim | ||||
| 
 | ||||
| # define an alias for the specfic python version used in this file. | ||||
| FROM python:${PYTHON_VERSION} as python | ||||
| 
 | ||||
| # Python build stage | ||||
| FROM python as python-build-stage | ||||
| 
 | ||||
| ARG BUILD_ENVIRONMENT=production | ||||
| 
 | ||||
| # Install apt packages | ||||
| RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||
|   # dependencies for building Python packages | ||||
|   build-essential \ | ||||
|   # psycopg2 dependencies | ||||
|   libpq-dev | ||||
| 
 | ||||
| 
 | ||||
| # Python 'run' stage | ||||
| FROM python as python-run-stage | ||||
| 
 | ||||
| ARG BUILD_ENVIRONMENT=production | ||||
| ARG APP_HOME=/app | ||||
| 
 | ||||
| ENV PYTHONUNBUFFERED 1 | ||||
| ENV PYTHONDONTWRITEBYTECODE 1 | ||||
| ENV BUILD_ENV ${BUILD_ENVIRONMENT} | ||||
| 
 | ||||
| WORKDIR ${APP_HOME} | ||||
| 
 | ||||
| # Install required system dependencies | ||||
| RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||
|   # psycopg2 dependencies | ||||
|   libpq-dev \ | ||||
|   # Translations dependencies | ||||
|   gettext \ | ||||
|   # cleaning up unused files | ||||
|   && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ | ||||
|   && rm -rf /var/lib/apt/lists/* | ||||
| 
 | ||||
| RUN addgroup --system django \ | ||||
|     && adduser --system --ingroup django django | ||||
| 
 | ||||
| RUN pip install poetry | ||||
| 
 | ||||
| # Configuring poetry | ||||
| RUN poetry config virtualenvs.create false | ||||
| COPY pyproject.toml poetry.lock / | ||||
| 
 | ||||
| # Installing requirements | ||||
| RUN poetry install | ||||
| 
 | ||||
| 
 | ||||
| COPY ./compose/production/django/entrypoint /entrypoint | ||||
| RUN sed -i 's/\r$//g' /entrypoint | ||||
| RUN chmod +x /entrypoint | ||||
| 
 | ||||
| COPY ./compose/local/django/start /start | ||||
| RUN sed -i 's/\r$//g' /start | ||||
| RUN chmod +x /start | ||||
| 
 | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/worker/start /start-celeryworker | ||||
| RUN sed -i 's/\r$//g' /start-celeryworker | ||||
| RUN chmod +x /start-celeryworker | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/beat/start /start-celerybeat | ||||
| RUN sed -i 's/\r$//g' /start-celerybeat | ||||
| RUN chmod +x /start-celerybeat | ||||
| 
 | ||||
| COPY ./compose/local/django/celery/flower/start /start-flower | ||||
| RUN sed -i 's/\r$//g' /start-flower | ||||
| RUN chmod +x /start-flower | ||||
| 
 | ||||
| # copy application code to WORKDIR | ||||
| COPY --chown=django:django . ${APP_HOME} | ||||
| 
 | ||||
| # make django owner of the WORKDIR directory as well. | ||||
| RUN chown django:django ${APP_HOME} | ||||
| 
 | ||||
| USER django | ||||
							
								
								
									
										8
									
								
								compose/production/django/celery/beat/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								compose/production/django/celery/beat/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| exec celery -A config.celery_app beat -l INFO | ||||
							
								
								
									
										11
									
								
								compose/production/django/celery/flower/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								compose/production/django/celery/flower/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| exec celery \ | ||||
|     -A config.celery_app \ | ||||
|     -b "${CELERY_BROKER_URL}" \ | ||||
|     flower \ | ||||
|     --basic_auth="${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}" | ||||
							
								
								
									
										8
									
								
								compose/production/django/celery/worker/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								compose/production/django/celery/worker/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| exec celery -A config.celery_app worker -l INFO | ||||
							
								
								
									
										49
									
								
								compose/production/django/entrypoint
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								compose/production/django/entrypoint
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # N.B. If only .env files supported variable expansion... | ||||
| export CELERY_BROKER_URL="${REDIS_URL}" | ||||
| 
 | ||||
| 
 | ||||
| if [ -z "${POSTGRES_USER}" ]; then | ||||
|     base_postgres_image_default_user='postgres' | ||||
|     export POSTGRES_USER="${base_postgres_image_default_user}" | ||||
| fi | ||||
| export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}" | ||||
| 
 | ||||
| python << END | ||||
| import sys | ||||
| import time | ||||
| 
 | ||||
| import psycopg2 | ||||
| 
 | ||||
| suggest_unrecoverable_after = 30 | ||||
| start = time.time() | ||||
| 
 | ||||
| while True: | ||||
|     try: | ||||
|         psycopg2.connect( | ||||
|             dbname="${POSTGRES_DB}", | ||||
|             user="${POSTGRES_USER}", | ||||
|             password="${POSTGRES_PASSWORD}", | ||||
|             host="${POSTGRES_HOST}", | ||||
|             port="${POSTGRES_PORT}", | ||||
|         ) | ||||
|         break | ||||
|     except psycopg2.OperationalError as error: | ||||
|         sys.stderr.write("Waiting for PostgreSQL to become available...\n") | ||||
| 
 | ||||
|         if time.time() - start > suggest_unrecoverable_after: | ||||
|             sys.stderr.write("  This is taking longer than expected. The following exception may be indicative of an unrecoverable error: '{}'\n".format(error)) | ||||
| 
 | ||||
|     time.sleep(1) | ||||
| END | ||||
| 
 | ||||
| >&2 echo 'PostgreSQL is available' | ||||
| 
 | ||||
| exec "$@" | ||||
							
								
								
									
										9
									
								
								compose/production/django/start
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								compose/production/django/start
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| python /app/manage.py collectstatic --noinput | ||||
| exec /usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app | ||||
							
								
								
									
										6
									
								
								compose/production/postgres/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								compose/production/postgres/Dockerfile
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| FROM postgres:14 | ||||
| 
 | ||||
| COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance | ||||
| RUN chmod +x /usr/local/bin/maintenance/* | ||||
| RUN mv /usr/local/bin/maintenance/* /usr/local/bin \ | ||||
|     && rmdir /usr/local/bin/maintenance | ||||
|  | @ -0,0 +1,5 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| BACKUP_DIR_PATH='/backups' | ||||
| BACKUP_FILE_PREFIX='backup' | ||||
|  | @ -0,0 +1,12 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| countdown() { | ||||
|     declare desc="A simple countdown. Source: https://superuser.com/a/611582" | ||||
|     local seconds="${1}" | ||||
|     local d=$(($(date +%s) + "${seconds}")) | ||||
|     while [ "$d" -ge `date +%s` ]; do | ||||
|         echo -ne "$(date -u --date @$(($d - `date +%s`)) +%H:%M:%S)\r"; | ||||
|         sleep 0.1 | ||||
|     done | ||||
| } | ||||
							
								
								
									
										41
									
								
								compose/production/postgres/maintenance/_sourced/messages.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								compose/production/postgres/maintenance/_sourced/messages.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| message_newline() { | ||||
|     echo | ||||
| } | ||||
| 
 | ||||
| message_debug() | ||||
| { | ||||
|     echo -e "DEBUG: ${@}" | ||||
| } | ||||
| 
 | ||||
| message_welcome() | ||||
| { | ||||
|     echo -e "\e[1m${@}\e[0m" | ||||
| } | ||||
| 
 | ||||
| message_warning() | ||||
| { | ||||
|     echo -e "\e[33mWARNING\e[0m: ${@}" | ||||
| } | ||||
| 
 | ||||
| message_error() | ||||
| { | ||||
|     echo -e "\e[31mERROR\e[0m: ${@}" | ||||
| } | ||||
| 
 | ||||
| message_info() | ||||
| { | ||||
|     echo -e "\e[37mINFO\e[0m: ${@}" | ||||
| } | ||||
| 
 | ||||
| message_suggestion() | ||||
| { | ||||
|     echo -e "\e[33mSUGGESTION\e[0m: ${@}" | ||||
| } | ||||
| 
 | ||||
| message_success() | ||||
| { | ||||
|     echo -e "\e[32mSUCCESS\e[0m: ${@}" | ||||
| } | ||||
							
								
								
									
										16
									
								
								compose/production/postgres/maintenance/_sourced/yes_no.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								compose/production/postgres/maintenance/_sourced/yes_no.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| yes_no() { | ||||
|     declare desc="Prompt for confirmation. \$\"\{1\}\": confirmation message." | ||||
|     local arg1="${1}" | ||||
| 
 | ||||
|     local response= | ||||
|     read -r -p "${arg1} (y/[n])? " response | ||||
|     if [[ "${response}" =~ ^[Yy]$ ]] | ||||
|     then | ||||
|         exit 0 | ||||
|     else | ||||
|         exit 1 | ||||
|     fi | ||||
| } | ||||
							
								
								
									
										38
									
								
								compose/production/postgres/maintenance/backup
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								compose/production/postgres/maintenance/backup
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| ### Create a database backup. | ||||
| ### | ||||
| ### Usage: | ||||
| ###     $ docker-compose -f <environment>.yml (exec |run --rm) postgres backup | ||||
| 
 | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| working_dir="$(dirname ${0})" | ||||
| source "${working_dir}/_sourced/constants.sh" | ||||
| source "${working_dir}/_sourced/messages.sh" | ||||
| 
 | ||||
| 
 | ||||
| message_welcome "Backing up the '${POSTGRES_DB}' database..." | ||||
| 
 | ||||
| 
 | ||||
| if [[ "${POSTGRES_USER}" == "postgres" ]]; then | ||||
|     message_error "Backing up as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| export PGHOST="${POSTGRES_HOST}" | ||||
| export PGPORT="${POSTGRES_PORT}" | ||||
| export PGUSER="${POSTGRES_USER}" | ||||
| export PGPASSWORD="${POSTGRES_PASSWORD}" | ||||
| export PGDATABASE="${POSTGRES_DB}" | ||||
| 
 | ||||
| backup_filename="${BACKUP_FILE_PREFIX}_$(date +'%Y_%m_%dT%H_%M_%S').sql.gz" | ||||
| pg_dump | gzip > "${BACKUP_DIR_PATH}/${backup_filename}" | ||||
| 
 | ||||
| 
 | ||||
| message_success "'${POSTGRES_DB}' database backup '${backup_filename}' has been created and placed in '${BACKUP_DIR_PATH}'." | ||||
							
								
								
									
										22
									
								
								compose/production/postgres/maintenance/backups
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								compose/production/postgres/maintenance/backups
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| ### View backups. | ||||
| ### | ||||
| ### Usage: | ||||
| ###     $ docker-compose -f <environment>.yml (exec |run --rm) postgres backups | ||||
| 
 | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| working_dir="$(dirname ${0})" | ||||
| source "${working_dir}/_sourced/constants.sh" | ||||
| source "${working_dir}/_sourced/messages.sh" | ||||
| 
 | ||||
| 
 | ||||
| message_welcome "These are the backups you have got:" | ||||
| 
 | ||||
| ls -lht "${BACKUP_DIR_PATH}" | ||||
							
								
								
									
										55
									
								
								compose/production/postgres/maintenance/restore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								compose/production/postgres/maintenance/restore
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| 
 | ||||
| ### Restore database from a backup. | ||||
| ### | ||||
| ### Parameters: | ||||
| ###     <1> filename of an existing backup. | ||||
| ### | ||||
| ### Usage: | ||||
| ###     $ docker-compose -f <environment>.yml (exec |run --rm) postgres restore <1> | ||||
| 
 | ||||
| 
 | ||||
| set -o errexit | ||||
| set -o pipefail | ||||
| set -o nounset | ||||
| 
 | ||||
| 
 | ||||
| working_dir="$(dirname ${0})" | ||||
| source "${working_dir}/_sourced/constants.sh" | ||||
| source "${working_dir}/_sourced/messages.sh" | ||||
| 
 | ||||
| 
 | ||||
| if [[ -z ${1+x} ]]; then | ||||
|     message_error "Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again." | ||||
|     exit 1 | ||||
| fi | ||||
| backup_filename="${BACKUP_DIR_PATH}/${1}" | ||||
| if [[ ! -f "${backup_filename}" ]]; then | ||||
|     message_error "No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| message_welcome "Restoring the '${POSTGRES_DB}' database from the '${backup_filename}' backup..." | ||||
| 
 | ||||
| if [[ "${POSTGRES_USER}" == "postgres" ]]; then | ||||
|     message_error "Restoring as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| export PGHOST="${POSTGRES_HOST}" | ||||
| export PGPORT="${POSTGRES_PORT}" | ||||
| export PGUSER="${POSTGRES_USER}" | ||||
| export PGPASSWORD="${POSTGRES_PASSWORD}" | ||||
| export PGDATABASE="${POSTGRES_DB}" | ||||
| 
 | ||||
| message_info "Dropping the database..." | ||||
| dropdb "${PGDATABASE}" | ||||
| 
 | ||||
| message_info "Creating a new database..." | ||||
| createdb --owner="${POSTGRES_USER}" | ||||
| 
 | ||||
| message_info "Applying the backup to the new database..." | ||||
| gunzip -c "${backup_filename}" | psql "${POSTGRES_DB}" | ||||
| 
 | ||||
| message_success "The '${POSTGRES_DB}' database has been restored from the '${backup_filename}' backup." | ||||
							
								
								
									
										5
									
								
								compose/production/traefik/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								compose/production/traefik/Dockerfile
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| FROM traefik:v2.2.11 | ||||
| RUN mkdir -p /etc/traefik/acme \ | ||||
|   && touch /etc/traefik/acme/acme.json \ | ||||
|   && chmod 600 /etc/traefik/acme/acme.json | ||||
| COPY ./compose/production/traefik/traefik.yml /etc/traefik | ||||
							
								
								
									
										75
									
								
								compose/production/traefik/traefik.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								compose/production/traefik/traefik.yml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| log: | ||||
|   level: INFO | ||||
| 
 | ||||
| entryPoints: | ||||
|   web: | ||||
|     # http | ||||
|     address: ":80" | ||||
|     http: | ||||
|       # https://docs.traefik.io/routing/entrypoints/#entrypoint | ||||
|       redirections: | ||||
|         entryPoint: | ||||
|           to: web-secure | ||||
| 
 | ||||
|   web-secure: | ||||
|     # https | ||||
|     address: ":443" | ||||
| 
 | ||||
|   flower: | ||||
|     address: ":5555" | ||||
| 
 | ||||
| certificatesResolvers: | ||||
|   letsencrypt: | ||||
|     # https://docs.traefik.io/master/https/acme/#lets-encrypt | ||||
|     acme: | ||||
|       email: "sanspie@akarpov.ru" | ||||
|       storage: /etc/traefik/acme/acme.json | ||||
|       # https://docs.traefik.io/master/https/acme/#httpchallenge | ||||
|       httpChallenge: | ||||
|         entryPoint: web | ||||
| 
 | ||||
| http: | ||||
|   routers: | ||||
|     web-secure-router: | ||||
|       rule: "Host(`akarpov.ru`) || Host(`www.akarpov.ru`)" | ||||
|       entryPoints: | ||||
|         - web-secure | ||||
|       middlewares: | ||||
|         - csrf | ||||
|       service: django | ||||
|       tls: | ||||
|         # https://docs.traefik.io/master/routing/routers/#certresolver | ||||
|         certResolver: letsencrypt | ||||
| 
 | ||||
|     flower-secure-router: | ||||
|       rule: "Host(`akarpov.ru`)" | ||||
|       entryPoints: | ||||
|         - flower | ||||
|       service: flower | ||||
|       tls: | ||||
|         # https://docs.traefik.io/master/routing/routers/#certresolver | ||||
|         certResolver: letsencrypt | ||||
| 
 | ||||
|   middlewares: | ||||
|     csrf: | ||||
|       # https://docs.traefik.io/master/middlewares/headers/#hostsproxyheaders | ||||
|       # https://docs.djangoproject.com/en/dev/ref/csrf/#ajax | ||||
|       headers: | ||||
|         hostsProxyHeaders: ["X-CSRFToken"] | ||||
| 
 | ||||
|   services: | ||||
|     django: | ||||
|       loadBalancer: | ||||
|         servers: | ||||
|           - url: http://django:5000 | ||||
| 
 | ||||
|     flower: | ||||
|       loadBalancer: | ||||
|         servers: | ||||
|           - url: http://flower:5555 | ||||
| 
 | ||||
| providers: | ||||
|   # https://docs.traefik.io/master/providers/file/ | ||||
|   file: | ||||
|     filename: /etc/traefik/traefik.yml | ||||
|     watch: true | ||||
							
								
								
									
										5
									
								
								config/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								config/__init__.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| # This will make sure the app is always imported when | ||||
| # Django starts so that shared_task will use this app. | ||||
| from .celery_app import app as celery_app | ||||
| 
 | ||||
| __all__ = ("celery_app",) | ||||
							
								
								
									
										24
									
								
								config/api_router.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								config/api_router.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| from django.urls import path, include | ||||
| from rest_framework.routers import DefaultRouter | ||||
| from passfinder.recomendations.api.views import TinderView, PersonalRecommendation, OnboardingViewset | ||||
| from passfinder.users.api.views import ( | ||||
|     UserViewSet, | ||||
|     CreateUserPreferenceApiView, | ||||
|     ListUserFavoritePointsApiView, | ||||
| ) | ||||
| 
 | ||||
| router = DefaultRouter() | ||||
| 
 | ||||
| router.register("tinder", TinderView) | ||||
| router.register("recommendations", PersonalRecommendation) | ||||
| router.register("user", UserViewSet) | ||||
| router.register('onboarding', OnboardingViewset) | ||||
| 
 | ||||
| app_name = "api" | ||||
| urlpatterns = [ | ||||
|     path("", include("passfinder.events.api.urls")), | ||||
|     path("auth/", include("passfinder.users.api.urls")), | ||||
|     path("user/preference", CreateUserPreferenceApiView.as_view()), | ||||
|     path("user/favorite", ListUserFavoritePointsApiView.as_view()), | ||||
| ] | ||||
| urlpatterns += router.urls | ||||
							
								
								
									
										17
									
								
								config/celery_app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								config/celery_app.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| import os | ||||
| 
 | ||||
| from celery import Celery | ||||
| 
 | ||||
| # set the default Django settings module for the 'celery' program. | ||||
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") | ||||
| 
 | ||||
| app = Celery("passfinder") | ||||
| 
 | ||||
| # Using a string here means the worker doesn't have to serialize | ||||
| # the configuration object to child processes. | ||||
| # - namespace='CELERY' means all celery-related configuration keys | ||||
| #   should have a `CELERY_` prefix. | ||||
| app.config_from_object("django.conf:settings", namespace="CELERY") | ||||
| 
 | ||||
| # Load task modules from all registered Django app configs. | ||||
| app.autodiscover_tasks() | ||||
							
								
								
									
										0
									
								
								config/settings/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								config/settings/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										365
									
								
								config/settings/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										365
									
								
								config/settings/base.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,365 @@ | |||
| """ | ||||
| Base settings to build other settings files upon. | ||||
| """ | ||||
| import warnings | ||||
| from datetime import timedelta | ||||
| from pathlib import Path | ||||
| 
 | ||||
| import environ | ||||
| import structlog | ||||
| from urllib3.connectionpool import InsecureRequestWarning | ||||
| 
 | ||||
| ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent | ||||
| # passfinder/ | ||||
| APPS_DIR = ROOT_DIR / "passfinder" | ||||
| 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 / ".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 = "Europe/Moscow" | ||||
| # 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-tz | ||||
| USE_TZ = True | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths | ||||
| LOCALE_PATHS = [str(ROOT_DIR / "locale")] | ||||
| 
 | ||||
| # DATABASES | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#databases | ||||
| DATABASES = { | ||||
|     "default": env.db( | ||||
|         "DATABASE_URL", "postgres://postgres:Ilvas2006@localhost:5432/passfinder" | ||||
|     ) | ||||
| } | ||||
| DATABASES["default"]["ATOMIC_REQUESTS"] = True | ||||
| # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-DEFAULT_AUTO_FIELD | ||||
| DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" | ||||
| 
 | ||||
| # 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", | ||||
|     "django.forms", | ||||
| ] | ||||
| THIRD_PARTY_APPS = [ | ||||
|     "django_celery_beat", | ||||
|     "rest_framework", | ||||
|     "rest_framework.authtoken", | ||||
|     "corsheaders", | ||||
|     "drf_spectacular", | ||||
|     "location_field", | ||||
|     "polymorphic", | ||||
|     "django_clickhouse", | ||||
| ] | ||||
| 
 | ||||
| LOCAL_APPS = ["passfinder.users", "passfinder.events", "passfinder.recomendations"] | ||||
| # 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": "passfinder.contrib.sites.migrations"} | ||||
| 
 | ||||
| # AUTHENTICATION | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends | ||||
| AUTHENTICATION_BACKENDS = [ | ||||
|     "django.contrib.auth.backends.ModelBackend", | ||||
| ] | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model | ||||
| AUTH_USER_MODEL = "users.User" | ||||
| 
 | ||||
| # 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", | ||||
|     "corsheaders.middleware.CorsMiddleware", | ||||
|     "whitenoise.middleware.WhiteNoiseMiddleware", | ||||
|     "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.common.BrokenLinkEmailsMiddleware", | ||||
|     "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 / "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/#dirs | ||||
|         "DIRS": [str(APPS_DIR / "templates")], | ||||
|         # https://docs.djangoproject.com/en/dev/ref/settings/#app-dirs | ||||
|         "APP_DIRS": True, | ||||
|         "OPTIONS": { | ||||
|             # 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", | ||||
|             ], | ||||
|         }, | ||||
|     } | ||||
| ] | ||||
| 
 | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#form-renderer | ||||
| FORM_RENDERER = "django.forms.renderers.TemplatesSetting" | ||||
| 
 | ||||
| # FIXTURES | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs | ||||
| FIXTURE_DIRS = (str(APPS_DIR / "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" | ||||
| 
 | ||||
| # ADMIN | ||||
| # ------------------------------------------------------------------------------ | ||||
| # Django Admin URL. | ||||
| ADMIN_URL = "admin/" | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#admins | ||||
| ADMINS = [("""sanspie""", "sanspie@akarpov.ru")] | ||||
| # 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": { | ||||
|         "json_formatter": { | ||||
|             "()": structlog.stdlib.ProcessorFormatter, | ||||
|             "processor": structlog.processors.JSONRenderer(), | ||||
|         }, | ||||
|         "plain_console": { | ||||
|             "()": structlog.stdlib.ProcessorFormatter, | ||||
|             "processor": structlog.dev.ConsoleRenderer(), | ||||
|         }, | ||||
|         "key_value": { | ||||
|             "()": structlog.stdlib.ProcessorFormatter, | ||||
|             "processor": structlog.processors.KeyValueRenderer( | ||||
|                 key_order=["timestamp", "level", "event", "logger"] | ||||
|             ), | ||||
|         }, | ||||
|     }, | ||||
|     "handlers": { | ||||
|         "console": { | ||||
|             "class": "logging.StreamHandler", | ||||
|             "formatter": "plain_console", | ||||
|         }, | ||||
|         "json_file": { | ||||
|             "class": "logging.handlers.WatchedFileHandler", | ||||
|             "filename": "logs/json.log", | ||||
|             "formatter": "json_formatter", | ||||
|         }, | ||||
|         "flat_line_file": { | ||||
|             "class": "logging.handlers.WatchedFileHandler", | ||||
|             "filename": "logs/flat_line.log", | ||||
|             "formatter": "key_value", | ||||
|         }, | ||||
|     }, | ||||
|     "loggers": { | ||||
|         "django_structlog": { | ||||
|             "handlers": ["console", "flat_line_file", "json_file"], | ||||
|             "level": "INFO", | ||||
|         }, | ||||
|         # Make sure to replace the following logger's name for yours | ||||
|         "django_structlog_demo_project": { | ||||
|             "handlers": ["console", "flat_line_file", "json_file"], | ||||
|             "level": "INFO", | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| structlog.configure( | ||||
|     processors=[ | ||||
|         structlog.contextvars.merge_contextvars, | ||||
|         structlog.stdlib.filter_by_level, | ||||
|         structlog.processors.TimeStamper(fmt="iso"), | ||||
|         structlog.stdlib.add_logger_name, | ||||
|         structlog.stdlib.add_log_level, | ||||
|         structlog.stdlib.PositionalArgumentsFormatter(), | ||||
|         structlog.processors.StackInfoRenderer(), | ||||
|         structlog.processors.format_exc_info, | ||||
|         structlog.processors.UnicodeDecoder(), | ||||
|         structlog.stdlib.ProcessorFormatter.wrap_for_formatter, | ||||
|     ], | ||||
|     logger_factory=structlog.stdlib.LoggerFactory(), | ||||
|     cache_logger_on_first_use=True, | ||||
| ) | ||||
| # CELERY | ||||
| # -------------------------------------------------------------------------------------------------- | ||||
| CELERY_REDIS_HOST = env("CELERY_REDIS_HOST", default="127.0.0.1") | ||||
| CELERY_REDIS_PORT = env.int("CELERY_REDIS_PORT", default=6379) | ||||
| CELERY_REDIS_USER = env("CELERY_REDIS_USER", default=None) | ||||
| CELERY_REDIS_PASSWORD = env("CELERY_REDIS_PASSWORD", default=None) | ||||
| CELERY_REDIS_DB = env("CELERY_REDIS_DB", default=0) | ||||
| 
 | ||||
| CELERY_REDIS_SSL = env.bool("CELERY_REDIS_SSL", default=False) | ||||
| CELERY_BROKER_URL = env("CELERY_BROKER_URL", default="") | ||||
| CELERY_TASK_SERIALIZER = "json" | ||||
| CELERY_ACCEPT_CONTENT = ["application/json"] | ||||
| CELERY_ENABLE_UTC = True | ||||
| 
 | ||||
| CELERY_BEAT_SCHEDULE = { | ||||
|     "clickhouse_auto_sync": { | ||||
|         "task": "django_clickhouse.tasks.clickhouse_auto_sync", | ||||
|         "schedule": timedelta(seconds=5), | ||||
|         "options": {"expires": 1}, | ||||
|     }, | ||||
| } | ||||
| # DRF | ||||
| # ------------------------------------------------------------------------------- | ||||
| # django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/ | ||||
| REST_FRAMEWORK = { | ||||
|     "DEFAULT_AUTHENTICATION_CLASSES": ( | ||||
|         "rest_framework_simplejwt.authentication.JWTAuthentication", | ||||
|     ), | ||||
|     "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), | ||||
|     "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", | ||||
| } | ||||
| 
 | ||||
| # django-cors-headers - https://github.com/adamchainz/django-cors-headers#setup | ||||
| CORS_URLS_REGEX = r"^/api/.*$" | ||||
| 
 | ||||
| # By Default swagger ui is available only to admin user(s). You can change permission classes to change that | ||||
| # See more configuration options at https://drf-spectacular.readthedocs.io/en/latest/settings.html#settings | ||||
| SPECTACULAR_SETTINGS = { | ||||
|     "TITLE": "Pass Finder API", | ||||
|     "DESCRIPTION": "Documentation of API endpoints of Pass Finder", | ||||
|     "VERSION": "1.0.0", | ||||
|     "SERVE_PERMISSIONS": [], | ||||
|     "SERVERS": [ | ||||
|         {"url": "https://dev2.akarpov.ru", "description": "Production server"}, | ||||
|         {"url": "http://127.0.0.1:8000", "description": "Local Development server"}, | ||||
|     ], | ||||
| } | ||||
| 
 | ||||
| LOCATION_FIELD = { | ||||
|     "map.provider": "openstreetmap", | ||||
|     "search.provider": "nominatim", | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| SIMPLE_JWT = { | ||||
|     "ACCESS_TOKEN_LIFETIME": timedelta(days=30), | ||||
|     "REFRESH_TOKEN_LIFETIME": timedelta(weeks=50), | ||||
| } | ||||
| 
 | ||||
| # CLICKHOUSE | ||||
| # ------------------------------------------------------------------------------ | ||||
| CLICKHOUSE_DATABASES = { | ||||
|     "default": { | ||||
|         "db_url": env("CLICKHOUSE_URL", default="http://localhost:8123"), | ||||
|         "db_name": env("CLICKHOUSE_DB", default="default"), | ||||
|         "username": env("CLICKHOUSE_USER", default="default"), | ||||
|         "password": env("CLICKHOUSE_PASSWORD", default="default"), | ||||
|         "verify_ssl_cert": False, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| warnings.filterwarnings("ignore", category=InsecureRequestWarning) | ||||
| 
 | ||||
| CLICKHOUSE_REDIS_CONFIG = { | ||||
|     "host": env("CLICKHOUSE_REDIS_HOST", default="127.0.0.1"), | ||||
|     "port": env("CLICKHOUSE_REDIS_PORT", default=6379), | ||||
|     "db": env("CLICKHOUSE_REDIS_DB", default=0), | ||||
|     "username": env("CLICKHOUSE_REDIS_USER", default=None), | ||||
|     "password": env("CLICKHOUSE_REDIS_PASSWORD", default=None), | ||||
|     "socket_timeout": 10, | ||||
| } | ||||
							
								
								
									
										61
									
								
								config/settings/local.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								config/settings/local.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| 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="dh0qndI7XExEDZIdMDh2VPHbW9VNq0jsjsI2ImR9EyDQfNMYudHUaJswMggfhotG", | ||||
| ) | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts | ||||
| ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "dev2.akarpov.ru", "0e06-92-100-146-65.ngrok-free.app"] | ||||
| CORS_ORIGIN_ALLOW_ALL = True | ||||
| 
 | ||||
| # CACHES | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#caches | ||||
| CACHES = { | ||||
|     "default": { | ||||
|         "BACKEND": "django.core.cache.backends.locmem.LocMemCache", | ||||
|         "LOCATION": "", | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| # WhiteNoise | ||||
| # ------------------------------------------------------------------------------ | ||||
| # http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development | ||||
| INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS  # noqa F405 | ||||
| 
 | ||||
| 
 | ||||
| # 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 += [".".join(ip.split(".")[:-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 | ||||
| # Celery | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.celeryq.dev/en/stable/userguide/configuration.html#task-eager-propagates | ||||
| CELERY_TASK_EAGER_PROPAGATES = True | ||||
| # Your stuff... | ||||
| # ------------------------------------------------------------------------------ | ||||
							
								
								
									
										115
									
								
								config/settings/production.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								config/settings/production.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| 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=["akarpov.ru"]) | ||||
| 
 | ||||
| # DATABASES | ||||
| # ------------------------------------------------------------------------------ | ||||
| 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. | ||||
|             # https://github.com/jazzband/django-redis#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 | ||||
| SECURE_HSTS_SECONDS = 518400 | ||||
| # 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 | ||||
| ) | ||||
| 
 | ||||
| # STATIC | ||||
| # ------------------------ | ||||
| STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" | ||||
| # MEDIA | ||||
| # ------------------------------------------------------------------------------ | ||||
| 
 | ||||
| # ADMIN | ||||
| # ------------------------------------------------------------------------------ | ||||
| # Django Admin URL regex. | ||||
| ADMIN_URL = env("DJANGO_ADMIN_URL") | ||||
| # 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, | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # django-rest-framework | ||||
| # ------------------------------------------------------------------------------- | ||||
| # Tools that generate code samples can use SERVERS to point to the correct domain | ||||
| SPECTACULAR_SETTINGS["SERVERS"] = [  # noqa F405 | ||||
|     {"url": "https://akarpov.ru", "description": "Production server"} | ||||
| ] | ||||
							
								
								
									
										33
									
								
								config/settings/test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								config/settings/test.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| """ | ||||
| With these settings, tests run faster. | ||||
| """ | ||||
| 
 | ||||
| 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", | ||||
|     default="rGnf9bzlf7cNN2Sq64P0jc3Za3VTMMYxPnehFudBB4g5N9p51h63HQQRFoiDFvNV", | ||||
| ) | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#test-runner | ||||
| TEST_RUNNER = "django.test.runner.DiscoverRunner" | ||||
| 
 | ||||
| # PASSWORDS | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers | ||||
| PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] | ||||
| 
 | ||||
| # EMAIL | ||||
| # ------------------------------------------------------------------------------ | ||||
| # https://docs.djangoproject.com/en/dev/ref/settings/#email-backend | ||||
| EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" | ||||
| 
 | ||||
| # DEBUGGING FOR TEMPLATES | ||||
| # ------------------------------------------------------------------------------ | ||||
| TEMPLATES[0]["OPTIONS"]["debug"] = True  # type: ignore # noqa F405 | ||||
| 
 | ||||
| # Your stuff... | ||||
| # ------------------------------------------------------------------------------ | ||||
							
								
								
									
										31
									
								
								config/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								config/urls.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| from django.conf import settings | ||||
| from django.conf.urls.static import static | ||||
| from django.contrib import admin | ||||
| from django.urls import include, path | ||||
| from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     # Django Admin, use {% url 'admin:index' %} | ||||
|     path(settings.ADMIN_URL, admin.site.urls), | ||||
|     # User management | ||||
|     # Your stuff: custom urls includes go here | ||||
| ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) | ||||
| # API URLS | ||||
| urlpatterns += [ | ||||
|     # API base url | ||||
|     path("api/", include("config.api_router")), | ||||
|     path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"), | ||||
|     path( | ||||
|         "api/docs/", | ||||
|         SpectacularSwaggerView.as_view(url_name="api-schema"), | ||||
|         name="api-docs", | ||||
|     ), | ||||
| ] | ||||
| 
 | ||||
| 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. | ||||
|     if "debug_toolbar" in settings.INSTALLED_APPS: | ||||
|         import debug_toolbar | ||||
| 
 | ||||
|         urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns | ||||
							
								
								
									
										38
									
								
								config/wsgi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								config/wsgi.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| """ | ||||
| WSGI config for Pass Finder 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 pathlib import Path | ||||
| 
 | ||||
| from django.core.wsgi import get_wsgi_application | ||||
| 
 | ||||
| # This allows easy placement of apps within the interior | ||||
| # passfinder directory. | ||||
| ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent | ||||
| sys.path.append(str(ROOT_DIR / "passfinder")) | ||||
| # 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) | ||||
							
								
								
									
										1
									
								
								data/bulvary.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/bulvary.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| [{"_id": {"$oid": "61c07987c53ae811d6e6b829"}, "dictionary_data": {"youtube_videos": [], "russpass_recommendation": false, "aac_images": [], "disable_sessionids_autoupdate": false, "information_pages": [], "type_audio_guide": [], "sessionIds": [], "social_buttons": [], "images": [{"source": {"id": "63da16a3961d4400a3ac475f"}}, {"source": {"id": "63da16a6961d4400a3ac476b"}}], "image_explore_preview": [{"source": {"id": "63da16a0961d4400a3ac4757"}}], "image_detailed_page_main": [], "tags_main_screen": ["5e4aa3aca7edd0687c4688e1"], "aac_tags": [], "duration": "30", "purchase_method": "free", "ticket_price": "0", "is_can_buy": false, "galereya": [], "recommendation_prime": [], "timetable_by_place": [], "schedule": [], "without_schedule": false, "description": "\u0421\u0430\u043c\u0430\u044f \u0441\u0442\u0430\u0440\u0430\u044f \u0438 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0411\u0443\u043b\u044c\u0432\u0430\u0440\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u044c\u0446\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0435 \u043f\u043b\u043e\u0449\u0430\u0434\u0438 \u2014 \u041d\u0438\u043a\u0438\u0442\u0441\u043a\u0438\u0445 \u0412\u043e\u0440\u043e\u0442 \u0438 \u041f\u0443\u0448\u043a\u0438\u043d\u0441\u043a\u0443\u044e. \u0422\u0432\u0435\u0440\u0441\u043a\u043e\u0439 \u0431\u0443\u043b\u044c\u0432\u0430\u0440 \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 1796 \u0433\u043e\u0434\u0443: \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u0441\u043a\u043e\u0440\u043e \u0441\u0442\u0430\u043b \u0446\u0435\u043d\u0442\u0440\u043e\u043c \u0441\u0432\u0435\u0442\u0441\u043a\u043e\u0439 \u0436\u0438\u0437\u043d\u0438 \u043c\u043e\u0441\u043a\u043e\u0432\u0441\u043a\u0438\u0445 \u0434\u0432\u043e\u0440\u044f\u043d. \u0411\u044b\u0432\u0430\u043b \u0437\u0434\u0435\u0441\u044c \u0438 \u041f\u0443\u0448\u043a\u0438\u043d: \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u0422\u0432\u0435\u0440\u0441\u043a\u043e\u043c \u0431\u0443\u043b\u044c\u0432\u0430\u0440\u0435 \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0441\u0442\u043e\u044f\u043b \u043f\u0430\u043c\u044f\u0442\u043d\u0438\u043a \u043f\u043e\u044d\u0442\u0443, \u043f\u043e\u043a\u0430 \u0432 1950 \u0433\u043e\u0434\u0443 \u0435\u0433\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u043e\u0441\u0435\u0434\u043d\u044e\u044e \u041f\u0443\u0448\u043a\u0438\u043d\u0441\u043a\u0443\u044e \u043f\u043b\u043e\u0449\u0430\u0434\u044c. \n", "region": "5d08e36dad3a9a001701b95b", "is_priority": false, "sort": 60, "tags": ["6124b391020892001197dfcf"], "cg_recommendations": [], "place": ["61c079d3c53ae811d6e6b8db"], "restaurants": [], "city": "5bbe8a8a9e7fcb000f78a92d", "event_type": "5ebe69313740700019205cfe", "title": "\u0422\u0432\u0435\u0440\u0441\u043a\u043e\u0439 \u0431\u0443\u043b\u044c\u0432\u0430\u0440", "import_denied": false}}] | ||||
							
								
								
									
										61864
									
								
								data/cities.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61864
									
								
								data/cities.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										84
									
								
								data/cities_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								data/cities_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| { | ||||
|   id:{ | ||||
|     $oid: str  // id объекта коллекции | ||||
|   }, | ||||
|   dictionary_data: {  // собственно наполнение словарей | ||||
|     _id: str  // нет | ||||
|     aliases: list // Псевдонимы | ||||
|     cg_images: list // Обложка CityGuide / Alfa travel | ||||
|     city: str // идентификатор города | ||||
|     country: list // идентификатор страны | ||||
|     description: str // описание | ||||
|     description_title: str // заголовок | ||||
|     external_id: str // внешний идентификатор  | ||||
|     gallery: list // Галерея изображений | ||||
|     geo_data {  | ||||
|       center_distance: float  // расстояние до центра | ||||
|       coordinates: [  // Координаты (широта и долгота) | ||||
|         #.##,  // широта | ||||
|         #.##  // долгота | ||||
|       ] | ||||
|       type: str //  Тип геоданных (по умолчанию: points) | ||||
|     } | ||||
|     google_place { | ||||
|       use_manual_schedule: bool // Использовать google расписание  | ||||
|     } | ||||
|     hp_images: list // HP Картинки | ||||
|     icon: [ // Иконка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [ // Основное изображений | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool // импорт запрещен | ||||
|     is_priority: bool // приоритет | ||||
|     list_image: list // идентификаторы и источники файлов изображений | ||||
|     on_map: list // Город на карте | ||||
|     rating: int // Рейтинг | ||||
|     region: str // Регион | ||||
|     short_description: str // Краткое описание | ||||
|     sort: int // Порядковый номер сортировки | ||||
|     source: str // Источник данных | ||||
|     timezone: str  // часовой пояс | ||||
|     title: str // Название | ||||
|     title_dative: str // Название в винительном падеже | ||||
|     title_genitive: str // Название в родительном падеже | ||||
|     travel_line_id: str // Идентификатор города в справочнике на стороне travelline (TravelLine ID) | ||||
|     weather_sync: bool  // Признак синхронизации погоды | ||||
|     working_time: { | ||||
|       days: { | ||||
|         Mon: { | ||||
|           closed: bool // Нерабочий день Понедельник | ||||
|         } | ||||
|         Tue: { | ||||
|           closed: bool // Нерабочий день Вторник | ||||
|         } | ||||
|         Wed: { | ||||
|           closed: bool // Нерабочий день Среда | ||||
|         } | ||||
|         Thu: { | ||||
|           closed: bool // Нерабочий день Четверг | ||||
|         } | ||||
|         Fri: { | ||||
|           closed: bool // Нерабочий день Пятница | ||||
|         } | ||||
|         Sat: { | ||||
|           closed: bool // Нерабочий день Суббота | ||||
|         } | ||||
|         Sun: { | ||||
|           closed: bool // Нерабочий день Воскресенье | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     ya_id: str // Идентификатор города в справочнике на стороне Яндекс | ||||
|     сoat_of_arms: list  // Герб | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								data/concerts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/concerts.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/dostoprimechatelnosti.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/dostoprimechatelnosti.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										126
									
								
								data/events_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								data/events_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| { | ||||
|   _id:{ | ||||
|     $oid: str  // id объекта коллекции | ||||
|   }, | ||||
|   dictionary_data: {  // собственно наполнение коллекций | ||||
|     _id: str  // нет | ||||
|     aac_images: list  // ААЦ Изображения | ||||
|     aac_tags: list  // AAC Тэги | ||||
|     about_booking: str  // Дополнительная информация о покупке билета | ||||
|     age: str  // Возрастное ограничение | ||||
|     billing_product_id: int  // Идентификатор продукта в биллинге | ||||
|     booking_link: str  // Ссылка на покупку билета | ||||
|     cg_announcement: str  // Краткое описание события | ||||
|     cg_recommendations: list  // CG: Рекомендации членов клуба Prime | ||||
|     city: str  // id города (справочник cities) | ||||
|     creator: str  // Кто создал запись | ||||
|     description: str  // Описание | ||||
|     disable_sessionids_autoupdate: bool  // Не обновлять автоматически sessionIds | ||||
|     discover_moscow_link: str  // ссылка на Discover.Moscow | ||||
|     duration: str  // Продолжительность, мин | ||||
|     event_type: str  // Тип события | ||||
|     galereya: list  // Галерея | ||||
|     id_izi_travel: str  // Идентификатор izi.travel | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображение обложки | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     information_pages: list  // Информационные страницы | ||||
|     is_can_buy: bool  // Можно купить | ||||
|     is_priority: bool  // Приоритетное событие | ||||
|     link_source: str  // Ссылка на источник события | ||||
|     parser_source: str  // Источник импорта | ||||
|     partner: str  // Партнер | ||||
|     partner_type: str  // Тип партнера | ||||
|     payment_method: str  // Метод покупки | ||||
|     place: list  // Площадка проведения события (справочник places) | ||||
|     pravila-soglasovaniya: bool  // Правила согласования | ||||
|     purchase_addtitional_info: str  // Дополнительная информация к стоимости | ||||
|     purchase_method: str  // Метод покупки (старый) | ||||
|     recommendation_prime: list  // City Guide Рекомендации | ||||
|     region: str  // Регион | ||||
|     remote_event_id: str  // нет | ||||
|     remote_place_id: str  // нет | ||||
|     restaurants: list  // Рестораны проведения события | ||||
|     rp_price_id: int  // Идентификатор тарифа в биллинге | ||||
|     russpass_recommendation: bool  // RUSSPASS рекомендует | ||||
|     schedule: [  // Расписание | ||||
|       { | ||||
|         title: str  // заголовок | ||||
|         start: { | ||||
|           $date: str // Дата и время начала | ||||
|         }, | ||||
|         end: { | ||||
|           $date: str // Дата и время окончания | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     schedule_description: str  // Дополнительная информация к расписанию | ||||
|     scheduleUpdatedByPlace: bool  // нет | ||||
|     sessionId: str  // sessionId | ||||
|     sessionIds: [  // sessionIds | ||||
|             { | ||||
|         id: str  // id сессии | ||||
|         startTime: str  //  Дата время начала | ||||
|         endTime: str  //  Дата время окончания | ||||
|         timezone: str  //  Временная зона | ||||
|         isAllDay: bool  // Длитяс ли весь день | ||||
|             } | ||||
|     ] | ||||
|     social_buttons: list  // Кнопки социальных сетей | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     tags: list  // Тэги | ||||
|     tags_main_screen: list  // Тэг главного экрана | ||||
|     ticket_price: str  // Стоимость билета | ||||
|     timetable_by_place: [  // Расписание и сессии по площадкам(Yandex Afisha) | ||||
|       { | ||||
|         placeId: str  // id места (справочник places) | ||||
|         sessionIds: [ | ||||
|           { | ||||
|             id: str  // id сессии | ||||
|             startTime: str  //  Дата время начала | ||||
|             endTime: str  //  Дата время окончания | ||||
|             timezone: str  //  Временная зона | ||||
|             isAllDay: bool  // Длитяс ли весь день | ||||
|           } | ||||
|         ] | ||||
|         schedule: [  // Расписание | ||||
|           { | ||||
|             title: str  // заголовок | ||||
|             start: { | ||||
|               $date: str // Дата и время начала | ||||
|             } | ||||
|             end: { | ||||
|               $date: str // Дата и время окончания | ||||
|             } | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|        | ||||
|     ] | ||||
|     title: str  // Заголовок | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|     without_schedule: bool  // Событие без расписания | ||||
|     ya_id: str  // Идентификатор города в справочнике на стороне Яндекс | ||||
|     youtube_video_url: str  // Ссылка на видео в Youtube | ||||
|     youtube_videos: list  // YouTube ролики | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								data/excursii.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/excursii.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										100
									
								
								data/excursions_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								data/excursions_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   }, | ||||
|   dictionary_data: { | ||||
|     audioguide: bool  // наличие аудиогида | ||||
|     campaign: list  // id кампании (акции) | ||||
|     city: str  // идентификатор города  | ||||
|     description: str  // описание | ||||
|     duration: str  // длительность минуты | ||||
|     duration_hours: float  // длительность часы | ||||
|     duration_string: str  // длительность часы | ||||
|     event_type: str  // тип события | ||||
|     excursion_form: str  // Способ передвижения | ||||
|     excursion_type: str  // Тип экскурсии | ||||
|     html_file: list  // html файл | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью картитнки | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Список изображений | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     information_pages: list  // Информационные страницы | ||||
|     is_can_buy: bool  // Возможность покупки | ||||
|     is_priority: bool  // Признак приоритета | ||||
|     language: list  // Язык проведения | ||||
|     min_age: str  // Минимальный возраст | ||||
|     minGroupCount: str  // Минимальное количество группы | ||||
|     parser_source: str  // Источник импорта | ||||
|     partner: str  // Партнер | ||||
|     partner_logo: list  // Логотипы партнёра | ||||
|     pravila-soglasovaniya: bool // Правила согласования | ||||
|     price: int  // Цена от  | ||||
|     program: str  // Программа экскурсий | ||||
|     region: str  // Регион | ||||
|     route: [  // Основные события | ||||
|       { | ||||
|         title: str  // заголовок | ||||
|         day_contents: {  // события, посещения внутри дня | ||||
|           dictionaries: list  // Используемые словари | ||||
|           selected: [  // события / рестораны и прочие участвующие | ||||
|             { | ||||
|               id: str | ||||
|               active: bool | ||||
|             } | ||||
|           ] | ||||
|           active: list  // список активностей | ||||
|         } | ||||
|         events: [  // список событий | ||||
|           { | ||||
|             title: str | ||||
|             images: [ | ||||
|               { | ||||
|                 source: { | ||||
|                   id: str | ||||
|                 } | ||||
|               } | ||||
|             ] | ||||
|             geo_data: { | ||||
|               coordinates: [] | ||||
|             } | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|     russpass_recommendation: bool  // Признак значка "RUSSPASS рекомендует" true / false | ||||
|     schedule_excursion: str  // Расписание проведения экскурсии | ||||
|     season_end: date  // Дата конца сезона | ||||
|     season_start: date  // Дата начала сезона | ||||
|     short_description: str  // Краткое описание экскурсий | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     tags: list  // Тэги дополнительные | ||||
|     tags_main_screen: list  //   Тэг главного экрана | ||||
|     title: str  // Заголовок | ||||
|     tour_composition: [  // Состав экскурсии | ||||
|       { | ||||
|         title: str | ||||
|         list: list | ||||
|       } | ||||
|     ] | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|     without_schedule: bool  // Признак, показывающий, отсутствует расписание у активности: true, false | ||||
|   } | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								data/ext.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/ext.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										104
									
								
								data/hotels_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								data/hotels_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | |||
| { | ||||
|   _id:{ | ||||
|     $oid: str  // id объекта коллекции | ||||
|   }, | ||||
|   dictionary_data: { | ||||
|     address: str  // адрес отеля | ||||
|     arrival_time: str  // Время заезда | ||||
|     beach_services: list  // Список услуг отеля связанных с пляжным отдыхом | ||||
|     city: str  // Город | ||||
|     common_services: list  // Список общих услуг отеля | ||||
|     departure_time: str  // Время выезда | ||||
|     description: str  // Описание отеля | ||||
|     email: str  // Контактный email | ||||
|     entertainment_services: list  // Список услуг отеля связанных с развлечением | ||||
|     facility_services: list  // Список общих удобств отеля | ||||
|     fitness_services: list  // Список услуг отеля связанных со здоровьем и красотой | ||||
|     geo_data: { | ||||
|       center_distance: float  // расстояние до центра города | ||||
|       coordinates: [  // Координаты (широта и долгота) | ||||
|         #.##,  // широта | ||||
|         #.##  // долгота | ||||
|       ] | ||||
|       type: str  // Тип координат | ||||
|     } | ||||
|     google_place: {  // информация из Google | ||||
|        meta: {  // доп информация | ||||
|         formatted_address: str  // Адрес Google | ||||
|         update_time: str  // дата и время последнего обновления | ||||
|       } | ||||
|     } | ||||
|     hotel_rooms: {  // наличие типов комнат | ||||
|       active: list  // список активных комнат | ||||
|       dictionaries: list  // id словаря который описывает комнаты | ||||
|       selected: [  // все доступные комнаты | ||||
|         { | ||||
|           id: str | ||||
|           active: bool | ||||
|         } | ||||
|       ]   | ||||
|     } | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображения | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     import_denied_reason: str  // Причина отклонения модератором | ||||
|     integration_id: str  // id интеграции | ||||
|     meals: list  // услуги питания | ||||
|     parser_source: str  // Условный код внешней системы откуда было загружено событие Yandex Afisha – ya/afisha; infotech  – INFOTECH; LeClick– leclick/restaurants; LKP Личный кабинет партнёров | ||||
|     partner: str  // id партнёра | ||||
|     partner_is_not_moderated: bool  // Партнёр не проходил модерацию | ||||
|     partner_system_type: str  // Наименование системы партнера | ||||
|     phones: list  // Контактные телефоны | ||||
|     region: str  // Регион | ||||
|     rooms: [  // Список объектов содержащий информацию о номерах | ||||
|       { | ||||
|         name: str  // Название комнат  | ||||
|         description: str  // Описание комнат | ||||
|         images: list  // Изображения комнат | ||||
|         integration_id: str  // id интеграции | ||||
|         rate_plans: [  // Тарифы комнаты | ||||
|           { | ||||
|             integration_id: str // id интеграции | ||||
|             name: str  // Наименование тарифа | ||||
|             description: str  // Описание тарифа | ||||
|             currency: str  // Валюта тарифа | ||||
|             services: list  // Услуги тарифа | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|     russpass_recommendation: bool  // Признак значка "RUSSPASS рекомендует" true / false | ||||
|     services: [  // Услуги отеля | ||||
|       { | ||||
|         name: str  // Название услуги | ||||
|         description: str  // Описание услуги | ||||
|         kind: str  // Тип услуги | ||||
|         mealPlanCode: str  // Код услуги питания | ||||
|         integration_id: str  // id интеграции | ||||
|       } | ||||
|     ] | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     stars: str  // Звёзд отеля | ||||
|     time_zone: str  // Временная зона | ||||
|     title: str  // Название | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								data/images.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/images.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/kino.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/kino.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/museum.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/museum.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| [{"_id": {"$oid": "64107fe599c33f2daae19203"}, "dictionary_data": {"youtube_videos": [], "russpass_recommendation": false, "aac_images": [], "parser_source": "LKP", "disable_sessionids_autoupdate": false, "information_pages": [], "type_audio_guide": [], "sessionIds": [], "social_buttons": [], "partner": "63ff5a8fd40834b15998dcf9", "images": [], "image_explore_preview": [{"source": {"id": "6422a74bcfc508abfb3fe7e8"}}, {"source": {"id": "6422a750cfc508abfb3fe7f8"}}, {"source": {"id": "6422a758cfc508abfb3fe804"}}], "image_detailed_page_main": [], "tags_main_screen": [], "aac_tags": [], "duration": "60", "ticket_price": "500", "is_can_buy": true, "galereya": [], "recommendation_prime": [], "age": "0+", "timetable_by_place": [], "schedule": [], "without_schedule": false, "description": "\u0412 \u00ab\u041e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043f\u0430\u0440\u0444\u044e\u043c\u0435\u0440\u043d\u043e\u0439 \u043b\u0430\u0431\u043e\u0440\u0430\u0442\u043e\u0440\u0438\u0438\u00bb \u0434\u0443\u0445\u0438 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0438\u0441\u0442\u043e\u0440\u0438\u0438, \u043d\u043e \u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0430\u043c\u0438 \u0438 \u0433\u0435\u0440\u043e\u044f\u043c\u0438 \u0441\u043f\u0435\u043a\u0442\u0430\u043a\u043b\u0435\u0439. \u0422\u0430\u043a\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f - \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u0438\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0438\u0437\u043c\u0443 \u0430\u0440\u043e\u043c\u0430\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0437\u0438\u0440\u0443\u044e\u0442 \u0441\u0430\u043c\u044b\u0435 \u043f\u043e\u0442\u0430\u0451\u043d\u043d\u044b\u0435 \u0437\u043e\u043d\u044b \u0434\u0443\u0448\u0438 \u0438 \u0442\u0435\u043b\u0430, \u043f\u0440\u043e\u0431\u0443\u0436\u0434\u0430\u044f \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u044e, \u043e\u0436\u0438\u0432\u043b\u044f\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u043e\u043d\u044f\u0442\u0435\u043b\u044c\u043d\u044b\u0435, \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435, \u0441\u043b\u0443\u0445\u043e\u0432\u044b\u0435 \u0438 \u0442\u0430\u043a\u0442\u0438\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b. \u041f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u0444\u044e\u043c\u0435\u0440\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u0443\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u043a\u0440\u0443\u0433\u043e\u0437\u043e\u0440\u0430 \u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043c\u0438\u0440\u043e\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c. ", "is_priority": false, "tags": [], "cg_recommendations": [], "place": ["641081162a94483af923a496"], "restaurants": [], "city": "5bbf0e5f729bd4000fe02d5e", "event_type": "63eb49a688c02c9c01208394", "title": "\u0422\u0435\u0430\u0442\u0440 \u0430\u0440\u043e\u043c\u0430\u0442\u043e\u0432", "import_denied": false}}] | ||||
							
								
								
									
										1
									
								
								data/only_cords.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/only_cords.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										15392
									
								
								data/osm/apartment.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15392
									
								
								data/osm/apartment.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										113888
									
								
								data/osm/artwork.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113888
									
								
								data/osm/artwork.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										803412
									
								
								data/osm/attraction.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										803412
									
								
								data/osm/attraction.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										100900
									
								
								data/osm/bars.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100900
									
								
								data/osm/bars.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										905482
									
								
								data/osm/cafes.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										905482
									
								
								data/osm/cafes.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										122011
									
								
								data/osm/chalet.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122011
									
								
								data/osm/chalet.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										6834
									
								
								data/osm/gallery.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6834
									
								
								data/osm/gallery.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										64484
									
								
								data/osm/hostel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64484
									
								
								data/osm/hostel.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										195593
									
								
								data/osm/hostel_2.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195593
									
								
								data/osm/hostel_2.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										694300
									
								
								data/osm/hotels.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										694300
									
								
								data/osm/hotels.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										41589
									
								
								data/osm/motel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41589
									
								
								data/osm/motel.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										264923
									
								
								data/osm/museum.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264923
									
								
								data/osm/museum.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34692
									
								
								data/osm/other.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34692
									
								
								data/osm/other.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										316960
									
								
								data/osm/restaurants.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316960
									
								
								data/osm/restaurants.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3067934
									
								
								data/osm/shops.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3067934
									
								
								data/osm/shops.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										74340
									
								
								data/osm/theme_park.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74340
									
								
								data/osm/theme_park.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										79998
									
								
								data/osm/viewpoint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79998
									
								
								data/osm/viewpoint.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34176
									
								
								data/osm/zoo.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34176
									
								
								data/osm/zoo.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										757844
									
								
								data/places.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										757844
									
								
								data/places.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										278
									
								
								data/places_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								data/places_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,278 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     address: str  // адрес места | ||||
|     cg_recommendations: list  // CG: Рекомендации членов клуба Prime | ||||
|     chain: list  // Сеть | ||||
|     city: list  // Город | ||||
|     country: list  // идентификатор страны (дублирует strana) | ||||
|     creator: str  // Кто создал запись | ||||
|     description: str  // Описание места | ||||
|     district: list  // Список районов из выборки | ||||
|     emails: list[str]  // Контактные email-ы | ||||
|     exter_spot_id: int  // Идентификатор площадки в ЕБС | ||||
|     external_id: str  // id места из внешней системы | ||||
|     geo_data: { | ||||
|       center_distance: float  // расстояние до центра города | ||||
|       coordinates: [  // Координаты (широта и долгота) | ||||
|         #.##,  // широта | ||||
|         #.##  // долгота | ||||
|       ] | ||||
|       type: str  // Тип координат | ||||
|     } | ||||
|     google_place: {  // Google Place | ||||
|       meta: { | ||||
|         formatted_address: str  // Адрес Google | ||||
|         international_phone_number: str  // Номер телефона | ||||
|         place_id: str  // id места из внешней системы | ||||
|         update_time: str  // дата и время последнего обновления | ||||
|         vicinity: str  // "около" | ||||
|         website: str  // сайт места | ||||
|       } | ||||
|       schedule_google: {  // Расписание google | ||||
|         all: { | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         days: {  // Объекты дней недели | ||||
|           Sun: {  // Воскресенье | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Mon: {  // Понедельник | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Tue: {  // Вторник | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Wed: {  // Среда | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Thu: {  // Четверг | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Fri: {  // Пятница | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Sat: {  // Суббота | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       use_manual_schedule: bool  // Применять ручное расписание | ||||
|     } | ||||
|     holding: str  // Холдинг | ||||
|     hotels_types: list  // Тип отеля | ||||
|     hp_images: list  // HP Изображения | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображения | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     import_denied_reason: str  // Причина отклонения модератором | ||||
|     is_showed_in_placeslist: bool  // Отображать в списке площадок | ||||
|     metro: list  // список id станций метро | ||||
|     parser_source: str  // Условный код внешней системы откуда было загружено событие Yandex Afisha – ya/afisha; infotech  – INFOTECH; LeClick– leclick/restaurants; LKP Личный кабинет партнёров | ||||
|     partner: list  // id партнёра | ||||
|     partner_subtype: list  // Подтип партнера ПП | ||||
|     partner_system: list  // Партнерская система | ||||
|     partner_type: str  // Тип партнера | ||||
|     phones: list  // Контактные телефоны | ||||
|     place_note: str  // Доп информация | ||||
|     post_code: str  // Почтовый индекс | ||||
|     pravila-soglasovaniya: bool  // Правила согласования | ||||
|     privileges_prime: list  // Привилегии Prime | ||||
|     promo: list  // Условный код промо слова | ||||
|     region: str  // Регион | ||||
|     remote_place_id: str  // нет | ||||
|     route_description: str  // Описание для пути, проходящего | ||||
|     short_title: str  // Короткое название | ||||
|     sites: list  // web сайты | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     source: str  // Источник данных | ||||
|     strana: list  // идентификатор страны (дублирует country) | ||||
|     tags: list  // Тэги дополнительные | ||||
|     tags_main_screen: list  // Тэги главного экрана | ||||
|     testovaya-ploshadkakf: str  // Тестовая площадкаКФ | ||||
|     tet: {  // Тет | ||||
|       coordinates: list | ||||
|     } | ||||
|     title: str  // Название | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|     working_time: {  // График работы площадки | ||||
|       all: { | ||||
|         breaks: [  // перерывы | ||||
|           { | ||||
|             startTime: str  // время начала перерыва | ||||
|             endTime: str  // время конца перерыва  | ||||
|           } | ||||
|         ] | ||||
|         closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|         endTime: str  // Время окончания работы | ||||
|         startTime: str  // Время начала работы | ||||
|       } | ||||
|       days: {  // Объекты дней недели | ||||
|         Sun: {  // Воскресенье | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Mon: {  // Понедельник | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Tue: {  // Вторник | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Wed: {  // Среда | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Thu: {  // Четверг | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Fri: {  // Пятница | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Sat: {  // Суббота | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     working_time_description: str  // Примечание ко времени работы | ||||
|     ya_afisha_id: str  // Yandex Afisha ID | ||||
|   } | ||||
| } | ||||
							
								
								
									
										18430
									
								
								data/regions.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18430
									
								
								data/regions.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										54
									
								
								data/regions_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								data/regions_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     city: list  // Список городов | ||||
|     coat_of_arms: list  // Герб (аналог: сoat_of_arms) | ||||
|     code_ott_avia_from: str  // Код региона откуда (города) в onetwotrip для авиабилетов | ||||
|     code_ott_avia_to: str  // Код региона куда (города) в onetwotrip для авиабилетов | ||||
|     code_ott_rzd_from: str  // Код региона откуда (города) в onetwotrip жд билетов | ||||
|     code_ott_rzd_to: str  // Код региона куда (города) в onetwotrip жд билетов | ||||
|     country: str  // Страна | ||||
|     description: str  // Детальное описание | ||||
|     description_title: str  // Заголовок детального описания | ||||
|     external_id: str  // Внешний ID | ||||
|     gallery: list  // Галерея изображений | ||||
|     icon: [  // Иконка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Основное изображение | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     map_info: str  // Информация для карты | ||||
|     on_map: [  // Регион на карте | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     price_hotel: int  // Цена билета за ночь (отель) | ||||
|     short_description: str  // Краткое описание | ||||
|     showcase_cards: list  // Активности на витрине региона | ||||
|     showcase_description: str  // Описание на витрине региона | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     time_zone: list  // Часовой пояс | ||||
|     title: str  // Заголовок | ||||
|     title_accusative: str  // Название в винительном падеже | ||||
|     title_dative: str  // Название в дательном падеже | ||||
|     title_genitive: str  // Название в родительном падеже | ||||
|     travel_line_id: str  // TravelLine ID | ||||
|     url: str  // Официальный адрес сайт региона/ОИВа | ||||
|     сoat_of_arms: list  // Герб (аналог: coat_of_arms) | ||||
|   } | ||||
| } | ||||
							
								
								
									
										261892
									
								
								data/restaurants.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261892
									
								
								data/restaurants.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										288
									
								
								data/restaurants_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								data/restaurants_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,288 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     _id: str  // нет | ||||
|     address: str  // Адрес | ||||
|     avg_price_level: str  // Уровень цен | ||||
|     avg_time_visit: int  // Среднее время посещения, мин | ||||
|     bill: int  // Средний чек | ||||
|     can_reserve: bool  // Доступен для бронирования | ||||
|     cg_recommendations: list  // Рекомендации членов клуба Prime | ||||
|     chain: list  // Сеть | ||||
|     children: list  // Дети | ||||
|     city: list  // Город | ||||
|     country: list  // Страна | ||||
|     cuisines: list  // Кухни | ||||
|     description: str  // Описание | ||||
|     district: list  // Район | ||||
|     emails: list  // Электронные почты | ||||
|     external_id: str  // Внешний ID | ||||
|     external_status: int  // нет | ||||
|     geo_data: { | ||||
|       center_distance: float  // расстояние до центра города | ||||
|       coordinates: [  // Координаты (широта и долгота) | ||||
|         #.##,  // широта | ||||
|         #.##  // долгота | ||||
|       ] | ||||
|       type: str  // Тип координат | ||||
|     } | ||||
|     google_place: {  // Google Place | ||||
|       meta: { | ||||
|         formatted_address: str  // Адрес Google | ||||
|         international_phone_number: str  // Номер телефона | ||||
|         place_id: str  // id места из внешней системы | ||||
|         update_time: str  // дата и время последнего обновления | ||||
|         vicinity: str  // "около" | ||||
|         website: str  // сайт места | ||||
|       } | ||||
|       schedule_google: {  // Расписание google | ||||
|         all: { | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         days: {  // Объекты дней недели | ||||
|           Sun: {  // Воскресенье | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Mon: {  // Понедельник | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Tue: {  // Вторник | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Wed: {  // Среда | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Thu: {  // Четверг | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Fri: {  // Пятница | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|           Sat: {  // Суббота | ||||
|             breaks: [  // перерывы | ||||
|               { | ||||
|                 startTime: str  // время начала перерыва | ||||
|                 endTime: str  // время конца перерыва  | ||||
|               } | ||||
|             ] | ||||
|             closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|             endTime: str  // Время окончания работы | ||||
|             startTime: str  // Время начала работы | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       use_manual_schedule: bool  // Применять ручное расписание | ||||
|     } | ||||
|     guides: list  // Гиды | ||||
|     holding: str  // Холдинг | ||||
|     hp_images: list  // Изображения Hotel Prime | ||||
|     icons: [  // Тэги ресторана (Особенности) | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображения | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images360: list  // 360 изображения | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     menu_type: list  // Тип меню | ||||
|     metro: list  // Метро | ||||
|     parser_source: str  // Источник импорта | ||||
|     partner: str  // Партнер | ||||
|     partner_subtype: list  // Подтип партнера ПП | ||||
|     partner_type: list  // Тип партнера | ||||
|     phones: list  // Телефоны | ||||
|     post_code: str  // Почтовый индекс | ||||
|     promo: list  // Промоакции | ||||
|     rating_prime: str  // Рейтинг Prime | ||||
|     region: str  // Регион | ||||
|     remote_id: str  // ID Ресторана | ||||
|     remote_status: int  // нет | ||||
|     rest_id: str // нет | ||||
|     rest_services: list  // Услуги ресторанов | ||||
|     route_description: str  // Как добраться | ||||
|     russpass_recommendation: bool  // RUSSPASS рекомендует | ||||
|     short_description: str  // Краткое описание | ||||
|     showcase_filter: list  // Фильтрация по витринам | ||||
|     sites: list  // web сайты | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     source: str  // нет | ||||
|     subcategories: list  // Подкатегория | ||||
|     tags: list  // Тэги основные (фильтр) | ||||
|     tags_main_screen: list  // Тэг главного экрана | ||||
|     title: str  // Название | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|     working_time: {  // График работы площадки | ||||
|       all: { | ||||
|         breaks: [  // перерывы | ||||
|           { | ||||
|             startTime: str  // время начала перерыва | ||||
|             endTime: str  // время конца перерыва  | ||||
|           } | ||||
|         ] | ||||
|         closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|         endTime: str  // Время окончания работы | ||||
|         startTime: str  // Время начала работы | ||||
|       } | ||||
|       days: {  // Объекты дней недели | ||||
|         Sun: {  // Воскресенье | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Mon: {  // Понедельник | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Tue: {  // Вторник | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Wed: {  // Среда | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Thu: {  // Четверг | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Fri: {  // Пятница | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|         Sat: {  // Суббота | ||||
|           breaks: [  // перерывы | ||||
|             { | ||||
|               startTime: str  // время начала перерыва | ||||
|               endTime: str  // время конца перерыва  | ||||
|             } | ||||
|           ] | ||||
|           closed: bool  // Закрыта ли на целый день активность или нет; true - закрыто | ||||
|           endTime: str  // Время окончания работы | ||||
|           startTime: str  // Время начала работы | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     working_time_description: str  // Примечание ко времени работы | ||||
|   } | ||||
| } | ||||
							
								
								
									
										670
									
								
								data/routes.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										670
									
								
								data/routes.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,670 @@ | |||
| [ | ||||
|   { | ||||
|     "_id": { | ||||
|       "$oid": "63ce792cb792256419d55e28" | ||||
|     }, | ||||
|     "dictionary_data": { | ||||
|       "type_audio_guide": [], | ||||
|       "region": "5d08e36dad3a9a001701b95b", | ||||
|       "information_pages": [ | ||||
|         "5ed7a8a9070b700019e2d3cc", | ||||
|         "5ed7aaed7437c000194f1972" | ||||
|       ], | ||||
|       "image_explore_preview": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce70b1b792256419d51be2" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "image_detailed_page_main": [], | ||||
|       "tags_main_screen": [ | ||||
|         "5e4aa3aca7edd0687c4688e1" | ||||
|       ], | ||||
|       "rp_price_id": 39665, | ||||
|       "images": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce7095b792256419d51b90" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce7099b792256419d51b94" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce709db792256419d51ba7" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce70a2b792256419d51baa" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce70a6b792256419d51bbf" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce70a9b792256419d51bca" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "63ce70adb792256419d51bd8" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "route": { | ||||
|         "dictionaries": [ | ||||
|           "5a673061e97c730010ac6281" | ||||
|         ], | ||||
|         "selected": [ | ||||
|           { | ||||
|             "id": "5f146cfa448801001847422d", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5f2bfb47a0eff200185761cc", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e67af0ea4ba9e001a93240f", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a45826e00001944d0ee", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561770826e00001944d02c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619e8826e00001944d0d0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5617c6826e00001944d042", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619a6826e00001944d0c2", | ||||
|             "active": true | ||||
|           } | ||||
|         ], | ||||
|         "active": [ | ||||
|           "5f146cfa448801001847422d", | ||||
|           "5f2bfb47a0eff200185761cc", | ||||
|           "5e67af0ea4ba9e001a93240f", | ||||
|           "5e561a45826e00001944d0ee", | ||||
|           "5e561770826e00001944d02c", | ||||
|           "5e5619e8826e00001944d0d0", | ||||
|           "5e5617c6826e00001944d042", | ||||
|           "5e5619a6826e00001944d0c2" | ||||
|         ] | ||||
|       }, | ||||
|       "description": "Moscow CityPass Express ― это новый формат карты гостя столицы. В ее стоимость включены увлекательные экскурсии и бесплатное посещение интереснейших мест города, а срок действия составляет целых 30 дней. Туристы смогут познакомиться с главными достопримечательностями Москвы во время путешествия на двухэтажном автобусе, побывать на стадионе «Лужники» и прокатиться по канатной дороге, полюбоваться панорамными видами на мегаполис со смотровой площадки в сталинской высотке, прогуляться по «Зарядью» в компании гида и посетить музеи, которые известны на весь мир. Получить карту Moscow CityPass Express можно в Музее советских игровых автоматов.\n", | ||||
|       "sort": 60, | ||||
|       "time": "90", | ||||
|       "packet_price": 5100, | ||||
|       "route_tags": [], | ||||
|       "city": "5bbe8a8a9e7fcb000f78a92d", | ||||
|       "import_denied": false, | ||||
|       "title": "Moscow CityPass Express" | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "_id": { | ||||
|       "$oid": "5e58fffb7849960019a7e18a" | ||||
|     }, | ||||
|     "dictionary_data": { | ||||
|       "is_priority": false, | ||||
|       "is_can_buy": false, | ||||
|       "type_audio_guide": [], | ||||
|       "region": "5d08e36dad3a9a001701b95b", | ||||
|       "information_pages": [ | ||||
|         "5ed7a8a9070b700019e2d3cc", | ||||
|         "5ed7aaed7437c000194f1972" | ||||
|       ], | ||||
|       "short_description": "Пластиковая смарт карта Moscow CityPass откроет двери всех главных достопримечательностей столицы! ", | ||||
|       "image_explore_preview": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "623982ee994c9997315b6917" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "image_detailed_page_main": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "705a663b-41c4-430f-abf9-814f493c0c52", | ||||
|             "avg": "rgba(125, 136, 148, 0.4)" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "tags_main_screen": [ | ||||
|         "5e4aa3aca7edd0687c4688e1" | ||||
|       ], | ||||
|       "billing_product_id": 3507, | ||||
|       "rp_price_id": 6301, | ||||
|       "images": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "635fce9512bcf2bb9a7508b9" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "635fce9912bcf2bb9a7508d3" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "route": { | ||||
|         "active": [ | ||||
|           "5e561615826e00001944cfe2", | ||||
|           "5e561627826e00001944cfe6", | ||||
|           "5e561760826e00001944d027", | ||||
|           "5e561768826e00001944d029", | ||||
|           "5e561770826e00001944d02c", | ||||
|           "5e561784826e00001944d030", | ||||
|           "5e561815826e00001944d067", | ||||
|           "5e56181d826e00001944d069", | ||||
|           "5e56193a826e00001944d0ac", | ||||
|           "5e5617b9826e00001944d03e", | ||||
|           "5e5617e5826e00001944d04b", | ||||
|           "5e561800826e00001944d05e", | ||||
|           "5e5617c6826e00001944d042", | ||||
|           "5e561948826e00001944d0b0", | ||||
|           "5e561964826e00001944d0b4", | ||||
|           "5e56169d826e00001944cfff", | ||||
|           "5e5619ad826e00001944d0c4", | ||||
|           "5e5619f0826e00001944d0d2", | ||||
|           "5e5619a6826e00001944d0c2", | ||||
|           "5e56199a826e00001944d0c0", | ||||
|           "5e5618b5826e00001944d08b", | ||||
|           "5e561729826e00001944d01c", | ||||
|           "5e561950826e00001944d0b2", | ||||
|           "5e5619e8826e00001944d0d0", | ||||
|           "5e5616b4826e00001944d005", | ||||
|           "5e5616ac826e00001944d003", | ||||
|           "5e5616a5826e00001944d001", | ||||
|           "5e561941826e00001944d0ae", | ||||
|           "5e5616e6826e00001944d00f", | ||||
|           "5e561636826e00001944cfea", | ||||
|           "5e5619d9826e00001944d0cc", | ||||
|           "5e5619c4826e00001944d0ca", | ||||
|           "5e5619bc826e00001944d0c8", | ||||
|           "5e5619b4826e00001944d0c6", | ||||
|           "5e56196c826e00001944d0b6", | ||||
|           "5e561974826e00001944d0b8", | ||||
|           "5e56197b826e00001944d0ba", | ||||
|           "5e56198a826e00001944d0be", | ||||
|           "5e561898826e00001944d087", | ||||
|           "5e56171a826e00001944d017", | ||||
|           "5e561982826e00001944d0bc", | ||||
|           "5e561a38826e00001944d0ec", | ||||
|           "5e561a4e826e00001944d0f0", | ||||
|           "5e561759826e00001944d025", | ||||
|           "5e561a45826e00001944d0ee", | ||||
|           "5e561a5e826e00001944d0f4", | ||||
|           "5e561a56826e00001944d0f2", | ||||
|           "5e561a26826e00001944d0e8" | ||||
|         ], | ||||
|         "dictionaries": [ | ||||
|           "5bb51b424390424300d06a41", | ||||
|           "5a673061e97c730010ac6281" | ||||
|         ], | ||||
|         "selected": [ | ||||
|           { | ||||
|             "id": "5e561615826e00001944cfe2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561627826e00001944cfe6", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561760826e00001944d027", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561768826e00001944d029", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5617a2826e00001944d03a", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561770826e00001944d02c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561784826e00001944d030", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561815826e00001944d067", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56181d826e00001944d069", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56193a826e00001944d0ac", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5617b9826e00001944d03e", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5617e5826e00001944d04b", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561800826e00001944d05e", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5617c6826e00001944d042", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561948826e00001944d0b0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561964826e00001944d0b4", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56169d826e00001944cfff", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619ad826e00001944d0c4", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619f0826e00001944d0d2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619a6826e00001944d0c2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56199a826e00001944d0c0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5618b5826e00001944d08b", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561729826e00001944d01c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561950826e00001944d0b2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619e8826e00001944d0d0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5616b4826e00001944d005", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5616ac826e00001944d003", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5616a5826e00001944d001", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561941826e00001944d0ae", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5616e6826e00001944d00f", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561636826e00001944cfea", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619d9826e00001944d0cc", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619c4826e00001944d0ca", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619bc826e00001944d0c8", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619b4826e00001944d0c6", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56196c826e00001944d0b6", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561974826e00001944d0b8", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56197b826e00001944d0ba", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56198a826e00001944d0be", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561898826e00001944d087", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56171a826e00001944d017", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561982826e00001944d0bc", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5619e1826e00001944d0ce", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a38826e00001944d0ec", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a4e826e00001944d0f0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561759826e00001944d025", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a45826e00001944d0ee", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a5e826e00001944d0f4", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a56826e00001944d0f2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561a26826e00001944d0e8", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e56162f826e00001944cfe8", | ||||
|             "active": false | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "description": "Пластиковая смарт карта Moscow CityPass откроет двери всех главных достопримечательностей столицы! Экскурсии по суше и воде, проход в музеи без очередей, скидки в ресторанах и 15 поездок на общественном транспорте — и все это бесплатно! В турпакет включены более 40 достопримечательностей и 6 экскурсионных туров разных форматов. Скучать не придется! \n\nИспользуя карту Moscow CityPass, вы можете посетить каждый объект программы, но не более одного раза, в течение срока действия карты (кроме билетов на City Sightseeing Bus. Они бывают нескольких видов на 24, 48 и 72 часа. Вы можете выходить и заходить обратно на любой из остановок неограниченное количество раз в течение срока действия билета).", | ||||
|       "sort": 96, | ||||
|       "time": "48", | ||||
|       "packet_price": 6500, | ||||
|       "route_tags": [ | ||||
|         "5e4fa298d067450019abf839", | ||||
|         "5e4f9f18d067450019abf806", | ||||
|         "5e4fa278d067450019abf834", | ||||
|         "5e4fa0a4d067450019abf81c", | ||||
|         "5ec3ee769bee8c001946a9a7", | ||||
|         "5ec3ee40bfdeb400197cbe8e" | ||||
|       ], | ||||
|       "city": "5bbe8a8a9e7fcb000f78a92d", | ||||
|       "import_denied": false, | ||||
|       "title": "Moscow CityPass на 2 дня" | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "_id": { | ||||
|       "$oid": "5e5902357849960019a7e25e" | ||||
|     }, | ||||
|     "dictionary_data": { | ||||
|       "type_audio_guide": [], | ||||
|       "region": "5d08e36dad3a9a001701b94c", | ||||
|       "information_pages": [ | ||||
|         "5ed7a8a9070b700019e2d3cc", | ||||
|         "5f132560448801001846dfc0" | ||||
|       ], | ||||
|       "service_count": null, | ||||
|       "activity_count": null, | ||||
|       "short_description": "Карта гостя Санкт-Петербурга, ключ к главным достопримечательностям города и не только!", | ||||
|       "image_explore_preview": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "6351452112bcf2bb9a0c8e7c" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "image_detailed_page_main": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "5f16ea774488010018484d59" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "tags_main_screen": [ | ||||
|         "5e4aa3aca7edd0687c4688e1" | ||||
|       ], | ||||
|       "rp_price_id": 7101, | ||||
|       "images": [ | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "635fc95f12bcf2bb9a748e5c" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "source": { | ||||
|             "id": "635fc96412bcf2bb9a748e60" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "route": { | ||||
|         "active": [ | ||||
|           "5c1ce09d514196d20547020e", | ||||
|           "5e5615db826e00001944cfd2", | ||||
|           "5e5615e9826e00001944cfd6", | ||||
|           "5e55a62a826e00001944c86c", | ||||
|           "5e5e331d2fc00200193460d3", | ||||
|           "5e561606826e00001944cfe0", | ||||
|           "5e5615ff826e00001944cfde", | ||||
|           "5e5e473d2fc00200193461b6", | ||||
|           "5e5e531e2fc00200193461f4", | ||||
|           "5e5e49822fc00200193461c2", | ||||
|           "5e5e4bf42fc00200193461d1", | ||||
|           "5e5e561a2fc002001934620c", | ||||
|           "5e5e45052fc00200193461a1", | ||||
|           "5e55a346b333bd0019d18d2c", | ||||
|           "5e5e29d82fc0020019346078", | ||||
|           "5e5615e1826e00001944cfd4", | ||||
|           "5e5d676d88e8040019cda132", | ||||
|           "5e5e42982fc0020019346184", | ||||
|           "5e5615f8826e00001944cfdc", | ||||
|           "5e5e6903ccb7de00197f8abd", | ||||
|           "5e5e5e45ccb7de00197f8aa3", | ||||
|           "5e5e6e30ccb7de00197f8aec", | ||||
|           "5e590ac47849960019a7e44b", | ||||
|           "5e590a777849960019a7e445", | ||||
|           "5e57735d2c129400197af134", | ||||
|           "5f130fb1448801001846dec8", | ||||
|           "5e5e6fe8ccb7de00197f8af3" | ||||
|         ], | ||||
|         "dictionaries": [ | ||||
|           "5bb51b424390424300d06a41", | ||||
|           "5a673061e97c730010ac6281" | ||||
|         ], | ||||
|         "selected": [ | ||||
|           { | ||||
|             "id": "5c1ce09d514196d20547020e", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e40f22fc0020019346173", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5615db826e00001944cfd2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5615e9826e00001944cfd6", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e55a62a826e00001944c86c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e267b2fc002001934603b", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e2e422fc0020019346090", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e30fc2fc00200193460c8", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e331d2fc00200193460d3", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e561606826e00001944cfe0", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5615ff826e00001944cfde", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e473d2fc00200193461b6", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e531e2fc00200193461f4", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e49822fc00200193461c2", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e4bf42fc00200193461d1", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e561a2fc002001934620c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e218d2fc002001934601a", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e45052fc00200193461a1", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e55a346b333bd0019d18d2c", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e29d82fc0020019346078", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5615e1826e00001944cfd4", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5d676d88e8040019cda132", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e42982fc0020019346184", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5615f8826e00001944cfdc", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e6903ccb7de00197f8abd", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e5e45ccb7de00197f8aa3", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e59098f7849960019a7e435", | ||||
|             "active": false | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e6e30ccb7de00197f8aec", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e590ac47849960019a7e44b", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e590a777849960019a7e445", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e57735d2c129400197af134", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5f130fb1448801001846dec8", | ||||
|             "active": true | ||||
|           }, | ||||
|           { | ||||
|             "id": "5e5e6fe8ccb7de00197f8af3", | ||||
|             "active": true | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "description": "St. Petersburg CityPass — это карта гостя Санкт-Петербурга, ключ к главным достопримечательностям города и не только! Комплект состоит из путеводителя с отрывными билетами на двух языках (русский, английский) и карты города. Вас ждет доступ к 23 музеям, 6 увлекательных разноформатных экскурсий и многое другое! Это просто, удобно и экономно! \n\nОбратите внимание, что после приобретения St. Petersburg CityPass, вы получаете путеводитель с отрывными билетами. В течение срока действия CityPass вы можете один раз посетить все музеи и экскурсии (кроме билетов на City Sightseeing Bus. Они бывают нескольких видов на 24, 48 и 72 часа. Вы можете выходить и заходить обратно на любой из остановок неограниченное количество раз в течение срока действия билета). CityPass действует с момента первого прохода в музей, автобус или на борт корабля. Скидками и специальными предложениями можно воспользоваться и после окончания срока действия CityPass!", | ||||
|       "sort": 90, | ||||
|       "time": "48", | ||||
|       "packet_price": 5500, | ||||
|       "route_tags": [], | ||||
|       "city": "5bbf0e5f729bd4000fe02d5e", | ||||
|       "import_denied": false, | ||||
|       "pravila-soglasovaniya": false, | ||||
|       "title": "St.-Petersburg CityPass на 2 дня" | ||||
|     } | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										56
									
								
								data/routes_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								data/routes_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     billing_product_id: int  // Идентификатор продукта в биллинге | ||||
|     city: str  // Город | ||||
|     description: str  // Описание | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображение | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     information_pages: list  // Информационные страницы | ||||
|     is_can_buy: bool  // нет | ||||
|     is_priority: bool  // нет | ||||
|     packet_price: int  // Стоимость пакета | ||||
|     pravila-soglasovaniya: bool  // Правила согласования | ||||
|     region: str  // Регион | ||||
|     route: {  // Маршрут | ||||
|       active: list  // список активностей | ||||
|       dictionaries: list  // Используемые словари | ||||
|       selected: [  // события / рестораны и прочие участвующие | ||||
|         { | ||||
|           id: str | ||||
|           active: bool | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|     route_tags: list  // Тэги маршрута | ||||
|     rp_price_id: int  // Идентификатор тарифа в биллинге | ||||
|     short_description: str  // Краткое описание | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     tags_main_screen: list  // Тэг главного экрана | ||||
|     time: str  // Продолжительность, мин | ||||
|     title: str  // Заголовок | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								data/spektatli.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/spektatli.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/teatr.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/teatr.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| [{"_id": {"$oid": "64107fe599c33f2daae19203"}, "dictionary_data": {"youtube_videos": [], "russpass_recommendation": false, "aac_images": [], "parser_source": "LKP", "disable_sessionids_autoupdate": false, "information_pages": [], "type_audio_guide": [], "sessionIds": [], "social_buttons": [], "partner": "63ff5a8fd40834b15998dcf9", "images": [], "image_explore_preview": [{"source": {"id": "6422a74bcfc508abfb3fe7e8"}}, {"source": {"id": "6422a750cfc508abfb3fe7f8"}}, {"source": {"id": "6422a758cfc508abfb3fe804"}}], "image_detailed_page_main": [], "tags_main_screen": [], "aac_tags": [], "duration": "60", "ticket_price": "500", "is_can_buy": true, "galereya": [], "recommendation_prime": [], "age": "0+", "timetable_by_place": [], "schedule": [], "without_schedule": false, "description": "\u0412 \u00ab\u041e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043f\u0430\u0440\u0444\u044e\u043c\u0435\u0440\u043d\u043e\u0439 \u043b\u0430\u0431\u043e\u0440\u0430\u0442\u043e\u0440\u0438\u0438\u00bb \u0434\u0443\u0445\u0438 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0438\u0441\u0442\u043e\u0440\u0438\u0438, \u043d\u043e \u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0430\u043c\u0438 \u0438 \u0433\u0435\u0440\u043e\u044f\u043c\u0438 \u0441\u043f\u0435\u043a\u0442\u0430\u043a\u043b\u0435\u0439. \u0422\u0430\u043a\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f - \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u0438\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0438\u0437\u043c\u0443 \u0430\u0440\u043e\u043c\u0430\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0437\u0438\u0440\u0443\u044e\u0442 \u0441\u0430\u043c\u044b\u0435 \u043f\u043e\u0442\u0430\u0451\u043d\u043d\u044b\u0435 \u0437\u043e\u043d\u044b \u0434\u0443\u0448\u0438 \u0438 \u0442\u0435\u043b\u0430, \u043f\u0440\u043e\u0431\u0443\u0436\u0434\u0430\u044f \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u044e, \u043e\u0436\u0438\u0432\u043b\u044f\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u043e\u043d\u044f\u0442\u0435\u043b\u044c\u043d\u044b\u0435, \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435, \u0441\u043b\u0443\u0445\u043e\u0432\u044b\u0435 \u0438 \u0442\u0430\u043a\u0442\u0438\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b. \u041f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u0444\u044e\u043c\u0435\u0440\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u0443\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u043a\u0440\u0443\u0433\u043e\u0437\u043e\u0440\u0430 \u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043c\u0438\u0440\u043e\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c. ", "is_priority": false, "tags": [], "cg_recommendations": [], "place": ["641081162a94483af923a496"], "restaurants": [], "city": "5bbf0e5f729bd4000fe02d5e", "event_type": "63eb49a688c02c9c01208394", "title": "\u0422\u0435\u0430\u0442\u0440 \u0430\u0440\u043e\u043c\u0430\u0442\u043e\u0432", "import_denied": false}}] | ||||
							
								
								
									
										20988
									
								
								data/tours.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20988
									
								
								data/tours.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										92
									
								
								data/tours_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								data/tours_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     city: str  // Город | ||||
|     complexity: str  // Cложность | ||||
|     days: int  // Количество дней | ||||
|     description: str  // Описание | ||||
|     hotel_stars: str  // Звезды отеля | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображения | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     included: str  // В стоимость включено | ||||
|     is_can_buy: bool  // Можно купить | ||||
|     language: str  // Язык проведения | ||||
|     min_age: str  // Возрастное ограничение | ||||
|     minGroupCount: str  // Группа | ||||
|     nights: int  // Количество ночей | ||||
|     paid_separately: str  // Оплачивается дополнительно | ||||
|     partner: str  // Партнер | ||||
|     pravila-soglasovaniya: bool  // Правила согласования | ||||
|     price: str  // Стоимость | ||||
|     program: str  // Программа | ||||
|     region: str  // Регион | ||||
|     route: [  // Программа тура | ||||
|       { | ||||
|         title: str  // заголовок | ||||
|         day_contents: {  // события, посещения внутри дня | ||||
|           dictionaries: list  // Используемые словари | ||||
|           selected: [  // события / рестораны и прочие участвующие | ||||
|             { | ||||
|               id: str | ||||
|               active: bool | ||||
|             } | ||||
|           ] | ||||
|           active: list  // список активностей | ||||
|         } | ||||
|         events: [  // список событий | ||||
|           { | ||||
|             title: str | ||||
|             images: [ | ||||
|               { | ||||
|                 source: { | ||||
|                   id: str | ||||
|                 } | ||||
|               } | ||||
|             ] | ||||
|             geo_data: { | ||||
|               coordinates: [] | ||||
|             } | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|     russpass_recommendation: bool  // RUSSPASS рекомендует | ||||
|     season_end: str  // Конец сезона | ||||
|     season_start: str  // Начало сезона | ||||
|     short_description: str  // Краткое описание | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     tags: list  // Тэги | ||||
|     tags_main_screen: list  // Тэг главного экрана | ||||
|     title: str  // Заголовок | ||||
|     tour_composition: [  // Состав тура | ||||
|       { | ||||
|         title: str | ||||
|         list: list | ||||
|       } | ||||
|     ] | ||||
|     tour_type: str  // Тип тура | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|   } | ||||
| } | ||||
							
								
								
									
										29729
									
								
								data/tracks.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29729
									
								
								data/tracks.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										78
									
								
								data/tracks_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								data/tracks_description.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,78 @@ | |||
| { | ||||
|   _id: { | ||||
|     $oid: str  // id объекта коллекции | ||||
|   } | ||||
|   dictionary_data: { | ||||
|     city: str  // Город | ||||
|     days_count: int  // Длительность (дни) | ||||
|     description: str  // Полное описание | ||||
|     duration_hours: int  // Общее время прохождения маршрута (часы) | ||||
|     image_detailed_page_main: [  // Главная картинка | ||||
|       { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     image_explore_preview: [  // Превью для Explore | ||||
|     { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     images: [  // Изображения | ||||
|     { | ||||
|         source: { | ||||
|           id: str  // id картинки в бд | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     import_denied: bool  // Отклонено модератором | ||||
|     information_pages: list  // Информационные страницы | ||||
|     price: int  // Стоимость маршрута | ||||
|     region: str  // Регион | ||||
|     route: [  // Маршрут по дням | ||||
|       { | ||||
|         title: str  // заголовок | ||||
|         day_contents: {  // события, посещения внутри дня | ||||
|           dictionaries: list  // Используемые словари | ||||
|           selected: [  // события / рестораны и прочие участвующие | ||||
|             { | ||||
|               id: str | ||||
|               active: bool | ||||
|             } | ||||
|           ] | ||||
|           active: list  // список активностей | ||||
|         } | ||||
|         recommended_hotels: list | ||||
|         descriptions: {  // Описания | ||||
|           'active_id': {  // id из day_contents | ||||
|             description: str  // Описание для данного элемента маршрута (может быть отлично от данных объекта) | ||||
|             duration_custom_for_this_route: int  // Продолжительность для данного элемента маршрута (может быть отлична от данных объекта) | ||||
|           } | ||||
|         } | ||||
|         translated_data: { | ||||
|           'language': {  // 2-х буквенное описание языка | ||||
|             descriptions: {  // Описания | ||||
|               'active_id': {  // id из day_contents | ||||
|                 description: str  // Описание для данного элемента маршрута (может быть отлично от данных объекта) | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|     russpass_recommendation: bool  // RUSSPASS рекомендует | ||||
|     short_description: str  // Краткое описание | ||||
|     sort: int  // Порядковый номер сортировки | ||||
|     tags: list  // Тэги | ||||
|     tags_main_screen: list  // Тэги главного экрана | ||||
|     title: str  // Заголовок | ||||
|     total_activity_price: int  // Суммарная цена на активности | ||||
|     type: str  // Тип маршрута | ||||
|     type_audio_guide: list  // Тип аудиогида | ||||
|     video_link: str  // Ссылка на видео | ||||
|     video_url_detail: str  // Ссылка на видео на странице маршрута | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								data/yarmarki.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/yarmarki.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										0
									
								
								data4.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								data4.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										68
									
								
								local.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								local.yml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| version: '3' | ||||
| 
 | ||||
| volumes: | ||||
|   passfinder_local_postgres_data: {} | ||||
|   passfinder_local_postgres_data_backups: {} | ||||
| 
 | ||||
| services: | ||||
|   django: &django | ||||
|     build: | ||||
|       context: . | ||||
|       dockerfile: ./compose/local/django/Dockerfile | ||||
|     image: passfinder_local_django | ||||
|     container_name: passfinder_local_django | ||||
|     depends_on: | ||||
|       - postgres | ||||
|       - redis | ||||
|     volumes: | ||||
|       - .:/app:z | ||||
|     env_file: | ||||
|       - ./.envs/.local/.django | ||||
|       - ./.envs/.local/.postgres | ||||
|     ports: | ||||
|       - "8000:8000" | ||||
|     command: /start | ||||
| 
 | ||||
|   postgres: | ||||
|     build: | ||||
|       context: . | ||||
|       dockerfile: ./compose/production/postgres/Dockerfile | ||||
|     image: passfinder_production_postgres | ||||
|     container_name: passfinder_local_postgres | ||||
|     volumes: | ||||
|       - passfinder_local_postgres_data:/var/lib/postgresql/data | ||||
|       - passfinder_local_postgres_data_backups:/backups | ||||
|     env_file: | ||||
|       - ./.envs/.local/.postgres | ||||
| 
 | ||||
|   redis: | ||||
|     image: redis:6 | ||||
|     container_name: passfinder_local_redis | ||||
| 
 | ||||
|   celeryworker: | ||||
|     <<: *django | ||||
|     image: passfinder_local_celeryworker | ||||
|     container_name: passfinder_local_celeryworker | ||||
|     depends_on: | ||||
|       - redis | ||||
|       - postgres | ||||
|     ports: [] | ||||
|     command: /start-celeryworker | ||||
| 
 | ||||
|   celerybeat: | ||||
|     <<: *django | ||||
|     image: passfinder_local_celerybeat | ||||
|     container_name: passfinder_local_celerybeat | ||||
|     depends_on: | ||||
|       - redis | ||||
|       - postgres | ||||
|     ports: [] | ||||
|     command: /start-celerybeat | ||||
| 
 | ||||
|   flower: | ||||
|     <<: *django | ||||
|     image: passfinder_local_flower | ||||
|     container_name: passfinder_local_flower | ||||
|     ports: | ||||
|       - "5555:5555" | ||||
|     command: /start-flower | ||||
							
								
								
									
										6
									
								
								locale/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								locale/README.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| Translations | ||||
| ============ | ||||
| 
 | ||||
| Translations will be placed in this folder when running:: | ||||
| 
 | ||||
|     python manage.py makemessages | ||||
							
								
								
									
										31
									
								
								manage.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								manage.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| #!/usr/bin/env python | ||||
| import os | ||||
| import sys | ||||
| from pathlib import Path | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "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 | ||||
|     # passfinder directory. | ||||
|     current_path = Path(__file__).parent.resolve() | ||||
|     sys.path.append(str(current_path / "passfinder")) | ||||
| 
 | ||||
|     execute_from_command_line(sys.argv) | ||||
							
								
								
									
										57
									
								
								parsers/attractions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								parsers/attractions.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from passfinder.events.models import Region, Event | ||||
| 
 | ||||
| with open("data/pos-attr.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| reggg = { | ||||
|     "г. Санкт-Петербург": "Санкт-Петербург", | ||||
|     "г. Москва": "Москва", | ||||
|     "г. Севастополь": "Севастополь", | ||||
|     "Республика Адыгея (Адыгея)": "Республика Адыгея", | ||||
|     "Чувашская Республика - Чувашия": "Чувашская Республика", | ||||
|     "Республика Татарстан (Татарстан)": "Республика Татарстан", | ||||
|     "Республика Северная Осетия - Алания": "Республика Северная Осетия – Алания", | ||||
|     "Ханты-Мансийский автономный округ - Югра": "Ханты-Мансийский автономный округ — Югра", | ||||
| } | ||||
| rett = [] | ||||
| ret = [] | ||||
| for infff in data: | ||||
|     info = infff["general"] | ||||
|     if info["address"] and "mapPosition" in info["address"]: | ||||
|         r_name = ( | ||||
|             reggg[info["region"]["value"]] | ||||
|             if info["region"]["value"] in reggg | ||||
|             else info["region"]["value"] | ||||
|         ) | ||||
|         res = { | ||||
|             "title": info["name"], | ||||
|             "parser_source": "mkrf.ru", | ||||
|             # "region": Region.objects.get(title=r_name), | ||||
|             "lat": info["address"]["mapPosition"]["coordinates"][0], | ||||
|             "lon": info["address"]["mapPosition"]["coordinates"][1], | ||||
|             "address": info["address"]["fullAddress"], | ||||
|             "type": "attraction", | ||||
|             "extra_kwargs": {"objectType": info["objectType"]["value"]}, | ||||
|         } | ||||
|         if "typologies" in info: | ||||
|             res["extra_kwargs"]["typologies"] = [x["value"] for x in info["typologies"]] | ||||
| 
 | ||||
|         if "securityInfo" in info or "borderInfo" in info: | ||||
|             for ev in Event.objects.filter( | ||||
|                 title=info["name"], | ||||
|                 address=res["address"], | ||||
|                 lat=res["lat"], | ||||
|                 lon=res["lon"], | ||||
|             ): | ||||
|                 ev.extra_kwargs = res["extra_kwargs"] | ||||
|                 ev.save() | ||||
| 
 | ||||
|         ret.append(res) | ||||
| 
 | ||||
| 
 | ||||
| def get_att(): | ||||
|     return ret | ||||
							
								
								
									
										89
									
								
								parsers/bulvari.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								parsers/bulvari.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region, Place | ||||
| 
 | ||||
| with open("data/bulvary.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     al = True | ||||
|     d = {} | ||||
|     info = r["dictionary_data"] | ||||
|     d["type"] = "boulevard" | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["description"] = info["description"] | ||||
|     if "parser_source" in info: | ||||
|         d["parser_source"] = info["parser_source"] | ||||
|     if "sort" in info: | ||||
|         d["sort"] = int(info["sort"]) | ||||
|     if "is_can_buy" in info: | ||||
|         d["can_buy"] = info["is_can_buy"] | ||||
|     if "priority" in info: | ||||
|         d["priority"] = int(info["priority"]) | ||||
|     if "duration" in info: | ||||
|         d["duration"] = int(info["duration"]) | ||||
|     if "ticket_price" in info: | ||||
|         d["ticket_price"] = int(info["ticket_price"]) | ||||
|     if "schedule" in info: | ||||
|         d["schedule"] = info["schedule"] | ||||
| 
 | ||||
|     if "payment_method" in info: | ||||
|         d["payment_method"] = info["payment_method"] | ||||
|     elif "purchase_method" in info: | ||||
|         d["payment_method"] = info["purchase_method"] | ||||
|     if "age" in info: | ||||
|         d["age"] = info["age"] | ||||
|     if "booking_link" in info: | ||||
|         d["booking_link"] = info["booking_link"] | ||||
|     if "discover_moscow_link" in info: | ||||
|         d["discover_moscow_link"] = info["discover_moscow_link"] | ||||
|     if info["city"]: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if info["region"]: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if info["place"]: | ||||
|         try: | ||||
|             d["place"] = Place.objects.get(oid=info["place"][0]) | ||||
|         except Place.DoesNotExist: | ||||
|             ... | ||||
| 
 | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         if "place" in d: | ||||
|             d["location"] = d["place"].location | ||||
|         else: | ||||
|             al = False | ||||
| 
 | ||||
|     media = [] | ||||
|     for m in info["images"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     for m in info["galereya"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
|     else: | ||||
|         print(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_bulvari(): | ||||
|     return result | ||||
							
								
								
									
										27
									
								
								parsers/city.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								parsers/city.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| with open("data/cities.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     d = {} | ||||
|     info = r["dictionary_data"] | ||||
|     d["id"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     if "region" in info: | ||||
|         d["region"] = info["region"] | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
| 
 | ||||
|     result.append(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_cities(): | ||||
|     return result | ||||
							
								
								
									
										89
									
								
								parsers/concert.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								parsers/concert.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region, Place | ||||
| 
 | ||||
| with open("data/concerts.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     al = True | ||||
|     d = {} | ||||
|     d["type"] = "concert" | ||||
|     info = r["dictionary_data"] | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["description"] = info["description"] | ||||
|     if "parser_source" in info: | ||||
|         d["parser_source"] = info["parser_source"] | ||||
|     if "sort" in info: | ||||
|         d["sort"] = int(info["sort"]) | ||||
|     if "is_can_buy" in info: | ||||
|         d["can_buy"] = info["is_can_buy"] | ||||
|     if "priority" in info: | ||||
|         d["priority"] = int(info["priority"]) | ||||
|     if "duration" in info: | ||||
|         d["duration"] = int(info["duration"]) | ||||
|     if "ticket_price" in info: | ||||
|         d["ticket_price"] = int(info["ticket_price"]) | ||||
|     if "schedule" in info: | ||||
|         d["schedule"] = info["schedule"] | ||||
| 
 | ||||
|     if "payment_method" in info: | ||||
|         d["payment_method"] = info["payment_method"] | ||||
|     elif "purchase_method" in info: | ||||
|         d["payment_method"] = info["purchase_method"] | ||||
|     if "age" in info: | ||||
|         d["age"] = info["age"] | ||||
|     if "booking_link" in info: | ||||
|         d["booking_link"] = info["booking_link"] | ||||
|     if "discover_moscow_link" in info: | ||||
|         d["discover_moscow_link"] = info["discover_moscow_link"] | ||||
|     if info["city"]: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if "region" in info: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if info["place"]: | ||||
|         try: | ||||
|             d["place"] = Place.objects.get(oid=info["place"][0]) | ||||
|         except Place.DoesNotExist: | ||||
|             ... | ||||
| 
 | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         if "place" in d: | ||||
|             d["location"] = d["place"].location | ||||
|         else: | ||||
|             al = False | ||||
| 
 | ||||
|     media = [] | ||||
|     for m in info["images"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     for m in info["galereya"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
|     else: | ||||
|         pprint(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_concert(): | ||||
|     return result | ||||
							
								
								
									
										89
									
								
								parsers/dostoprimechatelnost.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								parsers/dostoprimechatelnost.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region, Place | ||||
| 
 | ||||
| with open("data/dostoprimechatelnosti.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     al = True | ||||
|     d = {} | ||||
|     d["type"] = "attraction" | ||||
|     info = r["dictionary_data"] | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["description"] = info["description"] | ||||
|     if "parser_source" in info: | ||||
|         d["parser_source"] = info["parser_source"] | ||||
|     if "sort" in info: | ||||
|         d["sort"] = int(info["sort"]) | ||||
|     if "is_can_buy" in info: | ||||
|         d["can_buy"] = info["is_can_buy"] | ||||
|     if "priority" in info: | ||||
|         d["priority"] = int(info["priority"]) | ||||
|     if "duration" in info: | ||||
|         d["duration"] = int(info["duration"]) | ||||
|     if "ticket_price" in info: | ||||
|         d["ticket_price"] = int(info["ticket_price"]) | ||||
|     if "schedule" in info: | ||||
|         d["schedule"] = info["schedule"] | ||||
| 
 | ||||
|     if "payment_method" in info: | ||||
|         d["payment_method"] = info["payment_method"] | ||||
|     elif "purchase_method" in info: | ||||
|         d["payment_method"] = info["purchase_method"] | ||||
|     if "age" in info: | ||||
|         d["age"] = info["age"] | ||||
|     if "booking_link" in info: | ||||
|         d["booking_link"] = info["booking_link"] | ||||
|     if "discover_moscow_link" in info: | ||||
|         d["discover_moscow_link"] = info["discover_moscow_link"] | ||||
|     if info["city"]: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if info["region"]: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if info["place"]: | ||||
|         try: | ||||
|             d["place"] = Place.objects.get(oid=info["place"][0]) | ||||
|         except Place.DoesNotExist: | ||||
|             ... | ||||
| 
 | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         if "place" in d: | ||||
|             d["location"] = d["place"].location | ||||
|         else: | ||||
|             al = False | ||||
| 
 | ||||
|     media = [] | ||||
|     for m in info["images"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     for m in info["galereya"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
|     else: | ||||
|         pprint(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_dostoprimechatelnost(): | ||||
|     return result | ||||
							
								
								
									
										89
									
								
								parsers/excursii.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								parsers/excursii.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region, Place | ||||
| 
 | ||||
| with open("data/excursii.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     al = True | ||||
|     d = {} | ||||
|     d["type"] = "excursion" | ||||
|     info = r["dictionary_data"] | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["description"] = info["description"] | ||||
|     if "parser_source" in info: | ||||
|         d["parser_source"] = info["parser_source"] | ||||
|     if "sort" in info: | ||||
|         d["sort"] = int(info["sort"]) | ||||
|     if "is_can_buy" in info: | ||||
|         d["can_buy"] = info["is_can_buy"] | ||||
|     if "priority" in info: | ||||
|         d["priority"] = int(info["priority"]) | ||||
|     if "duration" in info: | ||||
|         d["duration"] = int(info["duration"]) | ||||
|     if "ticket_price" in info: | ||||
|         d["ticket_price"] = int(info["ticket_price"]) | ||||
|     if "schedule" in info: | ||||
|         d["schedule"] = info["schedule"] | ||||
| 
 | ||||
|     if "payment_method" in info: | ||||
|         d["payment_method"] = info["payment_method"] | ||||
|     elif "purchase_method" in info: | ||||
|         d["payment_method"] = info["purchase_method"] | ||||
|     if "age" in info: | ||||
|         d["age"] = info["age"] | ||||
|     if "booking_link" in info: | ||||
|         d["booking_link"] = info["booking_link"] | ||||
|     if "discover_moscow_link" in info: | ||||
|         d["discover_moscow_link"] = info["discover_moscow_link"] | ||||
|     if info["city"]: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if "region" in info: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if info["place"]: | ||||
|         try: | ||||
|             d["place"] = Place.objects.get(oid=info["place"][0]) | ||||
|         except Place.DoesNotExist: | ||||
|             ... | ||||
| 
 | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         if "place" in d: | ||||
|             d["location"] = d["place"].location | ||||
|         else: | ||||
|             al = False | ||||
| 
 | ||||
|     media = [] | ||||
|     for m in info["images"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     for m in info["galereya"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
|     else: | ||||
|         pprint(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_excursion(): | ||||
|     return result | ||||
							
								
								
									
										67
									
								
								parsers/extract_mus.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								parsers/extract_mus.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| import os | ||||
| import json | ||||
| 
 | ||||
| import requests | ||||
| 
 | ||||
| from urllib.parse import urlparse | ||||
| from bs4 import BeautifulSoup | ||||
| 
 | ||||
| result = [] | ||||
| 
 | ||||
| url = "http://vrm.museum.ru/mus/list.asp?by=alpha" | ||||
| response = requests.get(url) | ||||
| soup = BeautifulSoup(response.text, "html.parser") | ||||
| t = soup.find_all("tr") | ||||
| for j in range(20, len(t)): | ||||
|     try: | ||||
|         el = t[j] | ||||
|         l = str(el.find_all(href=True)[0]).split('"')[1] | ||||
|         link = "http://vrm.museum.ru" + l | ||||
|         response = requests.get(link) | ||||
|         name = BeautifulSoup( | ||||
|             [x for x in response.text.splitlines() if f"http://www.museum.ru{l}" in x][ | ||||
|                 0 | ||||
|             ], | ||||
|             "html.parser", | ||||
|         ).text | ||||
|         soup2 = BeautifulSoup(response.text, "html.parser") | ||||
|         data2 = [] | ||||
|         for table in soup2.find_all("table"): | ||||
|             rows = table.find_all("tr") | ||||
|             data = [] | ||||
|             for row in rows: | ||||
|                 cols = row.find_all("td") | ||||
|                 cols = [ele.text.strip() for ele in cols] | ||||
|                 data.append([ele for ele in cols if ele]) | ||||
|             data2 += data | ||||
| 
 | ||||
|         data3 = {} | ||||
|         for row in data2: | ||||
|             if len(row) > 0: | ||||
|                 rec = [] | ||||
|                 for el in row: | ||||
|                     rec += el.split(":") | ||||
|                 if len(rec) > 1: | ||||
|                     c_name = " ".join(rec[0].split()) | ||||
|                     desc = " ".join(" ".join(rec[1:]).split()) | ||||
|                     data3[c_name] = desc | ||||
| 
 | ||||
|         images = [] | ||||
|         img_tags = soup2.find_all("img") | ||||
|         urls = [img["src"] for img in img_tags] | ||||
|         add = { | ||||
|             "name": name, | ||||
|             "urls": [x for x in urls if "asp" in x], | ||||
|             "link": link, | ||||
|         } | data3 | ||||
|         result.append(add) | ||||
|         print(name) | ||||
|     except Exception as e: | ||||
|         print(e) | ||||
|     print(j, "/", len(t)) | ||||
| 
 | ||||
|     with open("ext.json", "w", encoding="utf-16") as f: | ||||
|         json.dump({"links": result}, f, ensure_ascii=False, indent=4) | ||||
| 
 | ||||
| with open("ext.json", "w", encoding="utf-16") as f: | ||||
|     json.dump({"links": result}, f, ensure_ascii=False, indent=4) | ||||
							
								
								
									
										63
									
								
								parsers/hotel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								parsers/hotel.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region | ||||
| 
 | ||||
| with open("data/hotels.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     d = {} | ||||
|     al = True | ||||
|     info = r["dictionary_data"] | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["address"] = info["address"] | ||||
|     if "stars" in info and info["stars"]: | ||||
|         d["stars"] = int(info["stars"]) | ||||
| 
 | ||||
|     if "city" in info: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if "region" in info: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         al = False | ||||
|     if "rooms" in info: | ||||
|         d["rooms"] = info["rooms"] | ||||
| 
 | ||||
|     phones = [] | ||||
|     if "phones" in info: | ||||
|         for phone in info["phones"]: | ||||
|             phones.append( | ||||
|                 {"hotel": d["oid"], "name": phone["name"], "number": phone["number"]} | ||||
|             ) | ||||
|     if phones: | ||||
|         d["phones"] = phones | ||||
| 
 | ||||
|     media = [] | ||||
|     if "images" in info: | ||||
|         for m in info["images"]: | ||||
|             media.append({"file": m["source"]["id"], "type": "image"}) | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_hotel(): | ||||
|     return result | ||||
							
								
								
									
										89
									
								
								parsers/movie.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								parsers/movie.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| from django.contrib.gis.geos import Point | ||||
| 
 | ||||
| from passfinder.events.models import City, Region, Place | ||||
| 
 | ||||
| with open("data/kino.json") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| 
 | ||||
| result = [] | ||||
| for r in data: | ||||
|     al = True | ||||
|     d = {} | ||||
|     d["type"] = "movie" | ||||
|     info = r["dictionary_data"] | ||||
|     d["oid"] = r["_id"]["$oid"] | ||||
|     d["title"] = info["title"] | ||||
|     d["description"] = info["description"] | ||||
|     if "parser_source" in info: | ||||
|         d["parser_source"] = info["parser_source"] | ||||
|     if "sort" in info: | ||||
|         d["sort"] = int(info["sort"]) | ||||
|     if "is_can_buy" in info: | ||||
|         d["can_buy"] = info["is_can_buy"] | ||||
|     if "priority" in info: | ||||
|         d["priority"] = int(info["priority"]) | ||||
|     if "duration" in info: | ||||
|         d["duration"] = int(info["duration"]) | ||||
|     if "ticket_price" in info: | ||||
|         d["ticket_price"] = int(info["ticket_price"]) | ||||
|     if "schedule" in info: | ||||
|         d["schedule"] = info["schedule"] | ||||
| 
 | ||||
|     if "payment_method" in info: | ||||
|         d["payment_method"] = info["payment_method"] | ||||
|     elif "purchase_method" in info: | ||||
|         d["payment_method"] = info["purchase_method"] | ||||
|     if "age" in info: | ||||
|         d["age"] = info["age"] | ||||
|     if "booking_link" in info: | ||||
|         d["booking_link"] = info["booking_link"] | ||||
|     if "discover_moscow_link" in info: | ||||
|         d["discover_moscow_link"] = info["discover_moscow_link"] | ||||
|     if info["city"]: | ||||
|         try: | ||||
|             d["city"] = City.objects.get(oid=info["city"]) | ||||
|         except City.DoesNotExist: | ||||
|             ... | ||||
|     if "region" in info: | ||||
|         try: | ||||
|             d["region"] = Region.objects.get(oid=info["region"]) | ||||
|         except Region.DoesNotExist: | ||||
|             ... | ||||
|     if info["place"]: | ||||
|         try: | ||||
|             d["place"] = Place.objects.get(oid=info["place"][0]) | ||||
|         except Place.DoesNotExist: | ||||
|             ... | ||||
| 
 | ||||
|     if "geo_data" in info and info["geo_data"]["coordinates"]: | ||||
|         d["location"] = Point( | ||||
|             info["geo_data"]["coordinates"][0], info["geo_data"]["coordinates"][1] | ||||
|         ) | ||||
|     else: | ||||
|         if "place" in d: | ||||
|             d["location"] = d["place"].location | ||||
|         else: | ||||
|             al = False | ||||
| 
 | ||||
|     media = [] | ||||
|     for m in info["images"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     for m in info["galereya"]: | ||||
|         media.append({"file": m["source"]["id"], "type": "image"}) | ||||
| 
 | ||||
|     if media: | ||||
|         d["media"] = media | ||||
| 
 | ||||
|     if al: | ||||
|         result.append(d) | ||||
|     else: | ||||
|         pprint(d) | ||||
| 
 | ||||
| 
 | ||||
| def get_movie(): | ||||
|     return result | ||||
							
								
								
									
										58
									
								
								parsers/mus_load.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								parsers/mus_load.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| import json | ||||
| from pprint import pprint | ||||
| 
 | ||||
| with open("data/ext.json", "r", encoding="utf-16") as f: | ||||
|     data = json.load(f) | ||||
| 
 | ||||
| with open("data/only_cords.json", "r") as f: | ||||
|     data2 = json.load(f) | ||||
| 
 | ||||
| ret = [] | ||||
| 
 | ||||
| 
 | ||||
| for j in range(len(data2)): | ||||
|     info = data["links"][j] | ||||
|     pos = data2[j] | ||||
| 
 | ||||
|     if "cords" in pos: | ||||
|         p_name = [x for x in info.keys() if "плата" in x.lower() or "цена" in x.lower()] | ||||
| 
 | ||||
|         res = { | ||||
|             "sort": j, | ||||
|             "type": "museum", | ||||
|             "parser_source": "museum.ru", | ||||
|             "title": info["name"], | ||||
|             "lat": pos["cords"][0], | ||||
|             "lon": pos["cords"][1], | ||||
|         } | ||||
|         if p_name and info[p_name[0]] != "См. здесь": | ||||
|             for n in p_name: | ||||
|                 m = [] | ||||
|                 if "руб" in info[n]: | ||||
|                     ppp = info[n].split() | ||||
|                     for ind, eee in enumerate(ppp): | ||||
|                         if "руб" in eee: | ||||
|                             try: | ||||
|                                 val = int(ppp[ind - 1]) | ||||
|                                 m.append(val) | ||||
|                             except Exception: | ||||
|                                 try: | ||||
|                                     val = int(ppp[ind + 1]) | ||||
|                                     m.append(val) | ||||
|                                 except Exception: | ||||
|                                     ... | ||||
|                     if m: | ||||
|                         res["ticket_price"] = max(m) | ||||
|                     break | ||||
| 
 | ||||
|         if "Режим работы" in info and info["Режим работы"] != "См. здесь": | ||||
|             res["schedule"] = {"plain": info["Режим работы"]} | ||||
| 
 | ||||
|         if "Описание" in info: | ||||
|             res["description"] = info["Описание"] | ||||
| 
 | ||||
|         ret.append(res) | ||||
| 
 | ||||
| 
 | ||||
| def get_mus(): | ||||
|     return ret | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user