initial
This commit is contained in:
		
							
								
								
									
										53
									
								
								.deploy/deploy-dev.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								.deploy/deploy-dev.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										53
									
								
								.deploy/deploy-prod.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								.deploy/deploy-prod.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
venv
 | 
			
		||||
.idea
 | 
			
		||||
							
								
								
									
										46
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										7
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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"]
 | 
			
		||||
							
								
								
									
										12
									
								
								entrypoint.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								entrypoint.py
									
									
									
									
									
										Normal file
									
								
							@@ -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!")
 | 
			
		||||
							
								
								
									
										0
									
								
								helpers/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								helpers/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										31
									
								
								helpers/jokes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								helpers/jokes.py
									
									
									
									
									
										Normal file
									
								
							@@ -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("<p>")[1].split("</p>")[0].replace("<br />", "")
 | 
			
		||||
            if '<a href="random">' 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)
 | 
			
		||||
							
								
								
									
										22
									
								
								helpers/mongo.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								helpers/mongo.py
									
									
									
									
									
										Normal file
									
								
							@@ -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()
 | 
			
		||||
							
								
								
									
										25
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							@@ -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()
 | 
			
		||||
							
								
								
									
										2
									
								
								nginx/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								nginx/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
FROM nginx
 | 
			
		||||
COPY nginx.conf /etc/nginx/nginx.conf
 | 
			
		||||
							
								
								
									
										12
									
								
								nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
events {}
 | 
			
		||||
 | 
			
		||||
http {
 | 
			
		||||
    server {
 | 
			
		||||
        listen      1238;
 | 
			
		||||
 | 
			
		||||
        location / {
 | 
			
		||||
            proxy_pass http://api:5000/;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								processor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								processor.py
									
									
									
									
									
										Normal file
									
								
							@@ -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()
 | 
			
		||||
							
								
								
									
										7
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										7
									
								
								settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								settings.py
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
		Reference in New Issue
	
	Block a user