commit 149c251bfa26e2f8a24a057fb6832d8e9bc3c232 Author: Administrator Date: Mon Oct 3 16:32:43 2022 +0300 initial diff --git a/.deploy/deploy-dev.yaml b/.deploy/deploy-dev.yaml new file mode 100644 index 0000000..dfb7257 --- /dev/null +++ b/.deploy/deploy-dev.yaml @@ -0,0 +1,53 @@ +version: "3.4" + + +services: + + b-jokes-nginx: + image: mathwave/sprint-repo:b-jokes-nginx + networks: + - b-jokes-net + - b-jokes-nginx + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + + api: + image: mathwave/sprint-repo:b-jokes + networks: + - b-jokes-net + environment: + MONGO_HOST: "mongo.develop.sprinthub.ru" + DB_PASSWORD: $MONGO_PASSWORD_DEV + command: api + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + + poll: + image: mathwave/sprint-repo:b-jokes + environment: + MONGO_HOST: "mongo.develop.sprinthub.ru" + DB_PASSWORD: $MONGO_PASSWORD_DEV + command: poll + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + +networks: + b-jokes-net: + driver: overlay + b-jokes-nginx: + external: true diff --git a/.deploy/deploy-prod.yaml b/.deploy/deploy-prod.yaml new file mode 100644 index 0000000..f6af589 --- /dev/null +++ b/.deploy/deploy-prod.yaml @@ -0,0 +1,53 @@ +version: "3.4" + + +services: + + b-jokes-nginx: + image: mathwave/sprint-repo:b-jokes-nginx + networks: + - b-jokes-net + - b-jokes-nginx + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + + api: + image: mathwave/sprint-repo:b-jokes + networks: + - b-jokes-net + environment: + MONGO_HOST: "mongo.sprinthub.ru" + DB_PASSWORD: $MONGO_PASSWORD_PROD + command: api + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + + poll: + image: mathwave/sprint-repo:b-jokes + environment: + MONGO_HOST: "mongo.sprinthub.ru" + DB_PASSWORD: $MONGO_PASSWORD_PROD + command: poll + deploy: + mode: replicated + restart_policy: + condition: any + update_config: + parallelism: 1 + order: start-first + +networks: + b-jokes-net: + driver: overlay + b-jokes-nginx: + external: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82195aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +venv +.idea \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..03ae9f8 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,46 @@ +stages: + - build + - deploy-dev + - deploy-prod + +build: + stage: build + tags: + - dev + before_script: + - docker login -u mathwave -p $DOCKERHUB_PASSWORD + script: + - docker build -t mathwave/sprint-repo:b-jokes . + - docker push mathwave/sprint-repo:b-jokes + - docker build -t mathwave/sprint-repo:b-jokes-nginx nginx + - docker push mathwave/sprint-repo:b-jokes-nginx + +.deploy: + before_script: + - docker login -u mathwave -p $DOCKERHUB_PASSWORD + - docker network create -d overlay --attachable b-jokes-nginx || true + +deploy-dev: + extends: + - .deploy + stage: deploy-dev + tags: + - dev + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + when: on_success + - when: manual + script: + - docker stack deploy -c ./.deploy/deploy-dev.yaml b-jokes + +deploy-prod: + extends: + - .deploy + stage: deploy-prod + tags: + - prod + only: + - master + when: manual + script: + - docker stack deploy -c ./.deploy/deploy-prod.yaml b-jokes diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1f1cffe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.10 +RUN mkdir /usr/src/app +WORKDIR /usr/src/app +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt +COPY . . +ENTRYPOINT ["python", "entrypoint.py"] \ No newline at end of file diff --git a/entrypoint.py b/entrypoint.py new file mode 100644 index 0000000..ad18016 --- /dev/null +++ b/entrypoint.py @@ -0,0 +1,12 @@ +import sys + +import main +from helpers import jokes + +arg = sys.argv[-1] +if arg == "poll": + jokes.poll_jokes() +elif arg == "api": + main.run() +else: + raise NotImplementedError("No arg specified!") diff --git a/helpers/__init__.py b/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/helpers/jokes.py b/helpers/jokes.py new file mode 100644 index 0000000..9de243a --- /dev/null +++ b/helpers/jokes.py @@ -0,0 +1,31 @@ +from time import sleep + +from requests import get + +from helpers.mongo import mongo + + +def fetch_jokes(): + i = 1 + while True: + info = get(f"https://baneks.ru/{i}") + if info.status_code == 200: + print(i) + content = info.text + anek = content.split("

")[1].split("

")[0].replace("
", "") + if '' in anek: + break + if mongo.jokes_collection.find_one({"id": i}) is None: + mongo.jokes_collection.insert_one({ + "id": i, + "text": anek + }) + i += 1 + + +def poll_jokes(): + while True: + print("start fetching jokes") + fetch_jokes() + print("finished fetching jokes") + sleep(60 * 60 * 24) diff --git a/helpers/mongo.py b/helpers/mongo.py new file mode 100644 index 0000000..c51adf8 --- /dev/null +++ b/helpers/mongo.py @@ -0,0 +1,22 @@ +from functools import cached_property + +import pymongo + +import settings + + +class Mongo: + def __init__(self): + url = f"mongodb://{settings.MONGO_USER}:{settings.MONGO_PASSWORD}@{settings.MONGO_HOST}:27017/" + self.client = pymongo.MongoClient(url) + self.database = self.client.get_database("b-jokes") + + def __getitem__(self, item): + return self.database.get_collection(item) + + @cached_property + def jokes_collection(self): + return self["jokes"] + + +mongo = Mongo() diff --git a/main.py b/main.py new file mode 100644 index 0000000..3dd5a1d --- /dev/null +++ b/main.py @@ -0,0 +1,25 @@ +import json + +from flask import Flask, request + +from processor import Processor + + +def run(): + app = Flask(__name__) + + @app.route('/', methods=['POST']) + def main(): + req = request.json + processor = Processor(req) + response = { + "version": req['version'], + "session": req['session'], + "response": { + "end_session": False + } + } + response['response'].update(processor.process()) + return response + + app.run() diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..0d947da --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx +COPY nginx.conf /etc/nginx/nginx.conf \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..8fbe45f --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,12 @@ +events {} + +http { + server { + listen 1238; + + location / { + proxy_pass http://api:5000/; + } + + } +} \ No newline at end of file diff --git a/processor.py b/processor.py new file mode 100644 index 0000000..0bb258d --- /dev/null +++ b/processor.py @@ -0,0 +1,36 @@ +from functools import cached_property + + +class Processor: + def __init__(self, data: dict): + self.data = data + self.user_id = data['session']['user']['user_id'] + self.message = data['request']['original_utterance'] + + def next(self): + ... + + def save(self): + ... + + def finish(self): + return { + "text": "Пока-пока, заходи еще", + "end_session": True + } + + @cached_property + def handlers(self) -> dict: + return { + "следующий": self.next, + "сохрани": self.save, + "закончить": self.finish + } + + def process(self) -> dict: + action = self.handlers.get(self.message) + if action is None: + return { + "text": f"Я не понимаю этой команды. Я могу выполнить только действия: {', '.join(self.handlers.keys())}" + } + return action() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ce3ed4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +click==8.1.3 +Flask==2.2.2 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.1 +pymongo==4.2.0 +Werkzeug==2.2.2 diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..800b90b --- /dev/null +++ b/settings.py @@ -0,0 +1,7 @@ +import os + + +MONGO_USER = os.getenv("MONGO_USER", "mongo") +MONGO_PASSWORD = os.getenv("MONGO_PASSWORD", "password") +MONGO_HOST = os.getenv("MONGO_HOST", "localhost") +DIALOG_ID = os.getenv("DIALOG_ID", None)