initial
This commit is contained in:
commit
149c251bfa
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)
|
Loading…
Reference in New Issue
Block a user