56 Commits
main ... v1.0.1

Author SHA1 Message Date
gav
1274909088 Update '.drone.yml' 2022-09-12 14:41:25 +07:00
gav
bd3b859add Update '.drone.yml' 2022-09-12 14:37:10 +07:00
gav
6fa27c175f Update '.drone.yml' 2022-09-12 14:19:18 +07:00
gav
530c9c96fd Update '.drone.yml' 2022-09-12 13:25:04 +07:00
gav
0c3ac88812 Update '.drone.yml' 2022-05-08 13:50:42 +07:00
gav
ad9dce9a89 Update '.drone.yml' 2022-05-08 13:49:28 +07:00
gav
65531336ad Update '.drone.yml' 2022-05-08 13:39:26 +07:00
gav
169e9c36a9 Update '.drone.yml' 2022-05-08 13:37:54 +07:00
gav
9d8d1d0fdd Update '.drone.yml' 2022-05-08 13:33:43 +07:00
gav
bd82a7c1a7 Update '.drone.yml' 2022-05-08 13:33:12 +07:00
gav
fc50d21ab2 Update '.drone.yml' 2022-05-08 13:32:03 +07:00
gav
ce4c89aa8d Update '.drone.yml' 2022-05-08 13:29:20 +07:00
gav
b6b6d0e6aa Update '.drone.yml' 2022-05-08 13:28:04 +07:00
gav
bf36286307 Update '.drone.yml' 2022-05-08 13:22:48 +07:00
gav
7113f914c5 Update '.drone.yml' 2022-05-08 13:14:03 +07:00
gav
b686d39818 Update '.drone.yml' 2022-05-08 13:13:46 +07:00
gav
166b2bd8ef Update '.drone.yml' 2022-05-08 13:13:25 +07:00
gav
f9217fd736 Update '.drone.yml' 2022-05-08 13:11:32 +07:00
gav
26ac8ddc90 Update '.drone.yml' 2022-05-08 13:05:29 +07:00
gav
2c18fec1f6 Update '.drone.yml' 2022-05-08 13:02:32 +07:00
gav
08fc8f56e7 Update '.drone.yml' 2022-05-08 13:01:39 +07:00
gav
f26f7cce37 Update '.drone.yml' 2022-05-08 02:36:30 +07:00
b313b15686 Test fix nft_svc 2022-05-08 01:11:56 +07:00
aacb413176 Some fix 2022-05-08 01:06:05 +07:00
efc711cd3b Added jpeg to png converted images 2022-05-08 01:02:04 +07:00
b77f1bc13d Remove jpeg's 2022-05-08 00:49:08 +07:00
55f17606d6 Merge branch 'main' of https://gitea.gavt45.ru/gav/es-bot 2022-05-08 00:44:41 +07:00
e0c9aad35a Update pictures 2022-05-08 00:44:19 +07:00
gav
8c558f7bc0 Merge pull request 'Job of fucking copywriter!!!' (#4) from text-edition into main
Reviewed-on: gav/es-bot#4
Reviewed-by: gav <a@a.aa>
2022-05-05 12:13:54 +07:00
gav
a66fde985f Merge branch 'main' into text-edition 2022-05-05 12:13:24 +07:00
f97a8286b7 Updated gitignore 2022-05-05 12:12:27 +07:00
1dfd81de31 Merge branch 'main' of https://gitea.gavt45.ru/gav/es-bot 2022-05-05 12:11:40 +07:00
20eaea722f added images and updated svc 2022-05-05 12:11:20 +07:00
ee834376db Job of fucking copywriter!!! 2022-05-04 22:05:35 +07:00
gav
ca6ac97e33 Merge pull request 'Job of fucking copiwriter!!!' (#3) from text-edition into main
Reviewed-on: gav/es-bot#3
Reviewed-by: gav <a@a.aa>
2022-05-04 21:03:34 +07:00
be430673f1 Job of fucking copiwriter!!! 2022-05-04 21:02:03 +07:00
gav
2dc6327fe1 Merge pull request 'text-edition' (#2) from text-edition into main
Reviewed-on: gav/es-bot#2
2022-05-04 20:44:44 +07:00
221ff51d3d Text edited 2022-05-04 20:43:53 +07:00
0fc4d0df82 Text edited 2022-05-04 19:59:59 +07:00
fe897a596c Merge pull request 'Text edited' (#1) from text-edition into main
Reviewed-on: gav/es-bot#1
Reviewed-by: dshestakova <d.shestakova2@g.nsu.ru>
2022-05-04 16:58:04 +07:00
2bc65d37dd Merge branch 'main' into text-edition 2022-05-04 16:56:46 +07:00
98136d93a2 Text edited 2022-05-04 16:34:01 +07:00
cc206ff358 Fixed keyboard and added man page 2022-05-03 21:06:32 +07:00
9065115927 Fixed bug in image gen 2022-05-03 11:18:05 +07:00
db629bb804 Update nft svc 2022-05-03 11:04:21 +07:00
0649bb445c Fixed circular import in nft_util 2022-05-01 12:42:22 +07:00
c5d18e56d5 Fix port of image_gen 2022-05-01 02:38:58 +07:00
08e7f4ee93 Fixed group add event 2022-05-01 02:36:51 +07:00
65ed6f9fa6 Added persistence 2022-05-01 02:00:20 +07:00
d9c9f8f131 Upd readme 2022-05-01 01:58:48 +07:00
80584dbaf9 MVP 2022-05-01 01:56:47 +07:00
gav
56adc16b04 Add '.drone.yml' 2022-05-01 01:22:43 +07:00
gav
f2e6e27179 Delete '.drone.ci' 2022-05-01 01:22:21 +07:00
gav
a54eeaf625 Update 'README.md' 2022-05-01 01:21:24 +07:00
gav
80b464baf5 Add '.drone.ci' 2022-05-01 01:20:33 +07:00
e1bd7234ed MVP 2022-05-01 00:57:58 +07:00
119 changed files with 823 additions and 110 deletions

58
.drone.yml Normal file
View File

@ -0,0 +1,58 @@
# ---
# kind: pipeline
# type: docker
# name: deploy-to-docker-vm
# clone:
# disable: true
# steps:
# - name: greeting
# image: appleboy/drone-ssh
# settings:
# host:
# from_secret: docker_host
# username:
# from_secret: docker_user
# key:
# from_secret: docker_privkey
# port: 2200
# script:
# - whoami
# - uname -a
# - mkdir -p deploy; cd deploy
# - git clone https://gitea.gavt45.ru/gav/es-bot.git
# - cd es-bot
# - git checkout main
# - docker-compose build
# when:
# branch:
# - main
# ---
# kind: pipeline
# type: docker
# name: test-secrets-pipeline
# steps:
# - name: test-secrets
# image: alpine
# environment:
# HOST:
# from_secret: docker_host
# commands:
# - env
kind: pipeline
type: docker
name: default
steps:
- name: docker
image: plugins/docker
settings:
auto_tag: true
registry: registry.gavt45.ru
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: registry.gavt45.ru/es-bot

3
.env
View File

@ -1,3 +0,0 @@
PG_USER=pg
PG_PASS=pg
PG_OUTBOUND_PORT=5432

5
.env.sample Normal file
View File

@ -0,0 +1,5 @@
PG_USER=pg
PG_PASS=<password>
PG_OUTBOUND_PORT=5432
GROUP_ID=<group id>
TOKEN=<token>

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text

5
.gitignore vendored
View File

@ -1 +1,6 @@
*__pycache__* *__pycache__*
tmp
.env
docker-compose-dev.yml
*.DS_Store*
.idea/

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM python:3.9
ENV DB_ADDR localhost:5432
ENV GROUP_ID group_id
ENV NFT_ADDR http://localhost:5001
ENV PASS pg
ENV REDIS_ADDR localhost
ENV TMP_DIR ./tmp
ENV TOKEN token
WORKDIR /app
RUN mkdir -p /app/tmp
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY . /app
CMD ["python3", "main.py"]

View File

@ -1,3 +1,13 @@
# es-bot # es-bot
todo (пока лень) [![Build Status](https://droneci.gavt45.ru/api/badges/gav/es-bot/status.svg)](https://droneci.gavt45.ru/gav/es-bot)
## Deploy
```shell
$ cp .env.example .env
```
Change variables as you need and then:
```shell
$ docker-compose up -d
```

View File

@ -1,2 +1,5 @@
from .menu import menu_router from .menu import menu_router
from .test import test_router from .test import test_router
from .teacher import teacher_router
from .student import student_router
from .man import man_router

19
blueprints/man.py Normal file
View File

@ -0,0 +1,19 @@
from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler, PayloadContainsFilter, BotEvent, \
EventTypeFilter
from vkwave.types.bot_events import BotEventType
import locales
man_router = DefaultRouter()
@man_router.registrar.with_decorator(
EventTypeFilter(BotEventType.MESSAGE_NEW.value),
PayloadContainsFilter("man"),
)
async def man_menu(event: BotEvent):
sevent = SimpleBotEvent(event)
return await sevent.answer(
message=locales.MAN,
keyboard=locales.MAN_KB.get_keyboard(),
)

View File

@ -1,12 +1,29 @@
from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler, EventTypeFilter
from vkwave.types.bot_events import BotEventType
import locales import locales
menu_router = DefaultRouter() menu_router = DefaultRouter()
@simple_bot_message_handler(menu_router,) @menu_router.registrar.with_decorator(
EventTypeFilter(BotEventType.MESSAGE_NEW.value),
)
async def menu(event: SimpleBotEvent): async def menu(event: SimpleBotEvent):
return await event.answer( sevent = SimpleBotEvent(event)
return await sevent.answer(
message=locales.MENU, message=locales.MENU,
keyboard=locales.MENU_KB.get_keyboard(), keyboard=locales.MENU_KB.get_keyboard(),
) )
@menu_router.registrar.with_decorator(
EventTypeFilter(BotEventType.GROUP_JOIN.value),
)
async def menu(event: SimpleBotEvent):
return await event.api_ctx.messages.send(
keyboard=locales.MENU_KB.get_keyboard(),
peer_id=event.object.object.user_id,
message=locales.MENU,
random_id=0
)

19
blueprints/student.py Normal file
View File

@ -0,0 +1,19 @@
from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler, PayloadContainsFilter, BotEvent, \
EventTypeFilter
from vkwave.types.bot_events import BotEventType
import locales
student_router = DefaultRouter()
@student_router.registrar.with_decorator(
EventTypeFilter(BotEventType.MESSAGE_NEW.value),
PayloadContainsFilter("student"),
)
async def student_menu(event: BotEvent):
sevent = SimpleBotEvent(event)
return await sevent.answer(
message=locales.ST_MENU,
keyboard=locales.ST_KB.get_keyboard(),
)

19
blueprints/teacher.py Normal file
View File

@ -0,0 +1,19 @@
from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler, PayloadContainsFilter, BotEvent, \
EventTypeFilter
from vkwave.types.bot_events import BotEventType
import locales
teacher_router = DefaultRouter()
@teacher_router.registrar.with_decorator(
EventTypeFilter(BotEventType.MESSAGE_NEW.value),
PayloadContainsFilter("teacher"),
)
async def teacher_menu(event: BotEvent):
sevent = SimpleBotEvent(event)
return await sevent.answer(
message=locales.TC_MENU,
keyboard=locales.TC_KB.get_keyboard(),
)

View File

@ -1,46 +1,25 @@
import json import json
import logging import logging
import random
from vkwave.bots import DefaultRouter, SimpleBotEvent, simple_bot_message_handler, PayloadFilter, PayloadContainsFilter, \ from vkwave.bots import DefaultRouter, SimpleBotEvent, PayloadContainsFilter
PhotoUploader from vkwave.bots import Keyboard
from vkwave.bots import Keyboard, ButtonColor
from vkwave.bots import EventTypeFilter, BotEvent from vkwave.bots import EventTypeFilter, BotEvent
from vkwave.types.bot_events import BotEventType from vkwave.types.bot_events import BotEventType
from vkwave.bots.fsm import FiniteStateMachine, StateFilter, ForWhat, State, ANY_STATE
import locales import locales
from config import Config from config import Config
from db import DB from db import DB
from db.db import TestResult
from locales import INPUT_NAME_TEXT
from util.redis_db import RedisDB
# MENU_KB.add_row() from util.nft_util import get_image
# MENU_KB.add_text_button(text="Профиль", payload={"command": "profile"}, color=ButtonColor.SECONDARY)
# MENU_KB.add_row()
# MENU_KB.add_text_button(text="Бонус", payload={"command": "bonus"}, color=ButtonColor.POSITIVE)
# from nft_things.NftSender import NFTSender
test_router = DefaultRouter() test_router = DefaultRouter()
test_router.registrar.add_default_filter( EMPTY_KB = '{"buttons": [], "inline": false, "one_time": false}'
EventTypeFilter(BotEventType.MESSAGE_NEW.value)) # we don't want to write it in all handlers.
# # exiting from poll (works on any state)
# @test_router.registrar.with_decorator(
# lambda event: event.object.object.message.text == "exit",
# StateFilter(fsm=fsm, state=ANY_STATE, for_what=ForWhat.FOR_USER)
# )
# async def simple_handler(event: BotEvent):
# # Check if we have the user in database
# if await fsm.get_data(event, for_what=ForWhat.FOR_USER) is not None:
# await fsm.finish(event=event, for_what=ForWhat.FOR_USER)
# return "You are quited!"
@test_router.registrar.with_decorator( @test_router.registrar.with_decorator(
PayloadContainsFilter("test"),# for state in States.questions[:-1]] EventTypeFilter(BotEventType.MESSAGE_NEW.value),
PayloadContainsFilter("test"),
) )
async def main_part_handle(event: BotEvent): async def main_part_handle(event: BotEvent):
user_id = event.object.object.message.from_id user_id = event.object.object.message.from_id
@ -50,8 +29,7 @@ async def main_part_handle(event: BotEvent):
state_idx = int(payload["test"]) state_idx = int(payload["test"])
logging.debug(f"State index: {state_idx}") logging.debug(f"State index: {state_idx}")
q_res = payload['q'] if 'q' in payload else event.object.object.message.text
q_res = payload['q'] if 'q' in payload else None
logging.debug(f"Qres: {q_res}") logging.debug(f"Qres: {q_res}")
# extra_state_data works as fsm.add_data(..., state_data={"name": event.object.object.message.text}) # extra_state_data works as fsm.add_data(..., state_data={"name": event.object.object.message.text})
@ -61,17 +39,28 @@ async def main_part_handle(event: BotEvent):
DB().update_test_result(user_id, question=state_idx, answer=q_res) DB().update_test_result(user_id, question=state_idx, answer=q_res)
if state_idx + 1 < len(locales.questions): if state_idx + 1 < len(locales.questions):
return await botevent.answer( RedisDB().set_state(user_id, state_idx + 1)
message=locales.questions[state_idx + 1][0], kb = locales.questions[state_idx + 1][1]
keyboard=locales.questions[state_idx + 1][1].get_keyboard(), if kb:
) return await botevent.answer(
message=locales.questions[state_idx + 1][0],
keyboard=kb.get_keyboard(),
)
else:
return await botevent.answer(
message=locales.questions[state_idx + 1][0],
payload=json.dumps({"test": state_idx + 1}),
keyboard=EMPTY_KB, # try to remove keyboard
)
else: else:
# todo add task to send user an image here # todo add task to send user an image here
# Config().nft_sender.add_task() # Config().nft_sender.add_task()
RedisDB().del_state(user_id)
logging.warn("Sending attach!") logging.warn("Sending attach!")
big_attachment = await Config().uploader.get_attachments_from_paths( big_attachment = await Config().uploader.get_attachments_from_paths(
peer_id=user_id, peer_id=user_id,
file_paths=["img.jpg"], file_paths=[get_image(user_id)],
) )
await Config().api_ctx.messages.send( await Config().api_ctx.messages.send(
user_id=user_id, attachment=big_attachment, random_id=0 user_id=user_id, attachment=big_attachment, random_id=0
@ -80,21 +69,3 @@ async def main_part_handle(event: BotEvent):
message=locales.LAST_MESSAGE, message=locales.LAST_MESSAGE,
keyboard=locales.LAST_MESSAGE_KB.get_keyboard(), keyboard=locales.LAST_MESSAGE_KB.get_keyboard(),
) )
# @test_router.registrar.with_decorator(
# StateFilter(fsm=fsm, state=MyState.age, for_what=ForWhat.FOR_USER),
# )
# async def simple_handler(event: BotEvent):
# if not event.object.object.message.text.isdigit():
# return f"Please, send only positive numbers!"
# await fsm.add_data(
# event=event,
# for_what=ForWhat.FOR_USER,
# state_data={"age": event.object.object.message.text},
# )
# user_data = await fsm.get_data(event=event, for_what=ForWhat.FOR_USER)
#
# # finish poll and delete the user
# # `fsm.finish` will do it
# await fsm.finish(event=event, for_what=ForWhat.FOR_USER)
# return f"Your data - {user_data}"

View File

@ -1,4 +1,7 @@
import os import os
from vkwave.bots import PhotoUploader
from util import Singleton from util import Singleton
@ -9,8 +12,13 @@ class Config(metaclass=Singleton):
PG_USER = os.environ["USER"] PG_USER = os.environ["USER"]
PG_PASS = os.environ["PASS"] PG_PASS = os.environ["PASS"]
PG_ADDR = os.environ["DB_ADDR"] PG_ADDR = os.environ["DB_ADDR"]
REDIS_ADDR = os.environ["REDIS_ADDR"]
NFT_SVC_ADDR = os.environ["NFT_ADDR"]
TMP_DIR = os.environ["TMP_DIR"]
def __init__(self): def __init__(self):
self.api_ctx = None self.api_ctx = None
self.uploader = None self.uploader: PhotoUploader = None

View File

@ -64,10 +64,19 @@ class DB(metaclass=Singleton):
def update_test_result(self, user_id: int, question: int, answer: str): def update_test_result(self, user_id: int, question: int, answer: str):
user = self._session.query(Candidate).filter(Candidate.id == user_id).first() user = self._session.query(Candidate).filter(Candidate.id == user_id).first()
user.test_result[0].answers.append(QuestionAnswer(question=question, answer=answer)) for i, ans in enumerate(user.test_result[0].answers):
if ans.question == question:
logging.debug(f"Update test result: {question} {answer}")
user.test_result[0].answers[i].answer = answer
break
else:
logging.warn(f"New test result: {question} {answer}")
user.test_result[0].answers.append(QuestionAnswer(question=question, answer=answer))
self._session.commit() self._session.commit()
def add_candidate(self, candidate: Candidate): def add_candidate(self, candidate: Candidate):
if self._session.query(Candidate).filter(Candidate.id == candidate.id).first() is not None:
return
tres = TestResult(answers=[]) tres = TestResult(answers=[])
candidate.test_result = [tres] candidate.test_result = [tres]
self._session.add(candidate) self._session.add(candidate)

View File

@ -1,5 +1,30 @@
version: "2" version: "2"
services: services:
image_gen:
build:
context: ./nft_svc
dockerfile: Dockerfile
ports:
- 5001:5000
bot:
build:
context: .
dockerfile: Dockerfile
environment:
- DB_ADDR=pgdb:5432
- GROUP_ID=${GROUP_ID}
- NFT_ADDR=http://image_gen:5000
- PASS=${PG_PASS}
- REDIS_ADDR=redis
- TMP_DIR=./tmp
- TOKEN=${TOKEN}
- USER=${PG_USER}
depends_on:
- pgdb
- redis
- image_gen
pgdb: pgdb:
image: 'postgres:12' image: 'postgres:12'
restart: always restart: always
@ -8,7 +33,18 @@ services:
- POSTGRES_PASSWORD=${PG_PASS} - POSTGRES_PASSWORD=${PG_PASS}
- POSTGRES_DB=db - POSTGRES_DB=db
- PGDATA=/var/lib/postgresql/data/pgdata - PGDATA=/var/lib/postgresql/data/pgdata
# volumes: volumes:
# - ${PG_MNT}:/var/lib/postgresql/data - bot_pg_data:/var/lib/postgresql/data
ports: # ports:
- ${PG_OUTBOUND_PORT}:5432 # - ${PG_OUTBOUND_PORT}:5432
redis:
image: "redis:alpine"
command: redis-server --appendonly yes --appendfsync everysec
# ports:
# - 6379:6379
volumes:
- bot_redis_data:/data
volumes:
bot_pg_data:
bot_redis_data:

BIN
img.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 131 B

View File

@ -1,10 +1,72 @@
from vkwave.bots import Keyboard, ButtonColor from vkwave.bots import Keyboard, ButtonColor
# menu # menu
MENU = "Привет!" MENU = """С помощью бота вы можете:
&#9881; пройти тест и получить индивидуальный NFT-талисман, сгенерированный специально для вас нейросетью;
&#9881; вступить в чат абитуриентов, студентов и преподавателей;
&#9881; пообщаться со студентом (можно выбрать с кем);
&#9881; пообщаться с руководителем ИШ или преподавателем (можно выбрать с кем)."""
MENU_KB = Keyboard() MENU_KB = Keyboard()
MENU_KB.add_text_button(text="Пройти тест!", payload={"test": "-1"}, color=ButtonColor.POSITIVE) MENU_KB.add_text_button(text="Пройти тест", payload={"test": "-1"}, color=ButtonColor.POSITIVE)
MENU_KB.add_link_button(text="Общий чатик", link="https://vk.me/join/AJQ1dw97/SBEQYIyQdZfG69y") MENU_KB.add_link_button(text="Чат абитуриентов", link="https://vk.me/join/AJQ1dw97/SBEQYIyQdZfG69y")
MENU_KB.add_row()
MENU_KB.add_text_button(text="Пообщаться со студентом", payload={"student": "1"}, color=ButtonColor.PRIMARY)
MENU_KB.add_row()
MENU_KB.add_text_button(text="Пообщаться с преподавателем", payload={"teacher": "1"}, color=ButtonColor.PRIMARY)
# MENU_KB.add_row()
# MENU_KB.add_text_button(text="АЧе делать?", payload={"man": "1"}, color=ButtonColor.PRIMARY)
# Student menu
ST_MENU = """Если вы ходите узнать про жизнь студента Инженерной школы, то можете написать этим ребятам:
*fossa_mar (Даша Пискеева), 2 курс;
*shestakova__d (Даша Шестакова), 2 курс;
*cleverbitch (Лиза Булгакова), 2 курс;
*brainkiller78 (Данил Тищенко), 1 курс;
*skazaniyk (Дмитрий Хамутский), 1 курс;
*kirik229 (Анжела Шадрина), 2 курс;
*dinazavrrrik (Назар Коновалов), 1 курс;
*tenikeev (Тимур Еникеев), 1 курс.
"""
ST_KB = Keyboard()
ST_KB.add_link_button(text="Даша Пискеева", link="https://vk.com/fossa_mar")
ST_KB.add_link_button(text="Даша Шестакова", link="https://vk.com/shestakova__d")
ST_KB.add_row()
ST_KB.add_link_button(text="Лиза Булгакова", link="https://vk.com/cleverbitch")
ST_KB.add_link_button(text="Данил Тищенко", link="https://vk.com/brainkiller78")
ST_KB.add_row()
ST_KB.add_link_button(text="Дмитрий Хамутский", link="https://vk.com/skazaniyk")
ST_KB.add_link_button(text="Анжела Шадрина", link="https://vk.com/kirik229")
ST_KB.add_row()
ST_KB.add_link_button(text="Назар Коновалов", link="https://vk.com/dinazavrrrik")
ST_KB.add_link_button(text="Тимур Еникеев", link="https://vk.com/tenikeev")
ST_KB.add_row()
ST_KB.add_text_button(text="Вернуться на главную", payload={}, color=ButtonColor.NEGATIVE)
# Teacher menu
TC_MENU = """Вы можете написать преподавателям и руководителям Инженерной школы:
*anastasia.v.karpenko (Анастасия Валерьевна Карпенко) — руководитель ИШ, преподаватель «Математической логики» и «Основ проектной деятельности»;
*krkaushan (Кристина Андреевна Насыбуллова) — заместитель декана по 2 курсу;
*id11073597 (Тимур Ринатович Насыбуллов) — преподаватель «Алгебры и геометрии» и «Теории функций комплексного переменного»;
*yury_efremenko (Ефременко Юрий Даниилович) — заместитель декана по набору, преподаватель «Алгебры и геометрии»."""
TC_KB = Keyboard()
TC_KB.add_link_button(text="Анастасия Валерьевна", link="https://vk.com/anastasia.v.karpenko")
TC_KB.add_link_button(text="Кристина Андреевна", link="https://vk.com/krkaushan")
TC_KB.add_row()
TC_KB.add_link_button(text="Тимур Ринатович", link="https://vk.com/id11073597")
TC_KB.add_link_button(text="Юрий Даниилович", link="https://vk.com/yury_efremenko")
TC_KB.add_row()
TC_KB.add_text_button(text="Вернуться на главную", payload={}, color=ButtonColor.NEGATIVE)
# Manual
MAN = """Если вы хотите пройти тест - нажми на соответствующую кнопку.
Если вы абитуриент, и хотите узнать больше про инженерную школу, то вы можете пообщаться со студентами или преподавателями!
Для этого нажмите на кнопку “Диалог со студентом” или “Диалог с преподавателем”.
Также вы можете узнать про нас из соцсетей - для этого нажмите на кнопку “Таплинк”.
Если вы хотите пообщаться с другими абитуриентами - нажми на кнопку “Неформальный чат”.
Приятного пользования!"""
MAN_KB = Keyboard()
MAN_KB.add_text_button(text="ХОЧУ ДОМОЙ!!!!!!!!!!!!!!!", payload={}, color=ButtonColor.NEGATIVE)
# TEST Questions # TEST Questions
INPUT_NAME_TEXT = "Пожалуйста, введите имя:" INPUT_NAME_TEXT = "Пожалуйста, введите имя:"
@ -12,54 +74,75 @@ INPUT_NAME_TEXT = "Пожалуйста, введите имя:"
# 1 # 1
WHAT_ENGINEER_ARE_YOU = "Кто ты из инженеров?" WHAT_ENGINEER_ARE_YOU = "Кто ты из инженеров?"
WHAT_ENGINEER_ARE_YOU_KB = Keyboard() WHAT_ENGINEER_ARE_YOU_KB = Keyboard()
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Маск", payload={"q": "Маск", "test": "0"}, color=ButtonColor.PRIMARY) WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Илон Маск", payload={"q": "Илон Маск"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Рогозин", payload={"q": "Рогозин", "test": "0"}, color=ButtonColor.PRIMARY) WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Дмитрий Рогозин", payload={"q": "Дмитрий Рогозин"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Тесла", payload={"q": "Тесла", "test": "0"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_row() WHAT_ENGINEER_ARE_YOU_KB.add_row()
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Кулибин", payload={"q": "Кулибин", "test": "0"}, color=ButtonColor.PRIMARY) WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Никола Тесла", payload={"q": "Никола Тесла"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Калашников", payload={"q": "Калашников", "test": "0"}, color=ButtonColor.PRIMARY) WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Иван Кулибин", payload={"q": "Иван Кулибин"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Кондратюк", payload={"q": "Кондратюк", "test": "0"}, color=ButtonColor.PRIMARY) WHAT_ENGINEER_ARE_YOU_KB.add_row()
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Михаил Калашников", payload={"q": "Михаил Калашников"}, color=ButtonColor.PRIMARY)
WHAT_ENGINEER_ARE_YOU_KB.add_text_button(text="Юрий Кондратюк", payload={"q": "Юрий Кондратюк"}, color=ButtonColor.PRIMARY)
# 2 # 2
PROG_LANG = "Какой ЯП нравится?" PROG_LANG = "Какой язык программирования вы чаще всего используете?"
PROG_LANG_KB = Keyboard() PROG_LANG_KB = Keyboard()
PROG_LANG_KB.add_text_button(text="Python", payload={"q": "Python", "test": "1"}, color=ButtonColor.PRIMARY) PROG_LANG_KB.add_text_button(text="Python", payload={"q": "Python"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="Pascal", payload={"q": "Pascal", "test": "1"}, color=ButtonColor.PRIMARY) PROG_LANG_KB.add_text_button(text="Pascal", payload={"q": "Pascal"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="C/C++", payload={"q": "ccpp", "test": "1"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_row() PROG_LANG_KB.add_row()
PROG_LANG_KB.add_text_button(text="JS", payload={"q": "JS", "test": "1"}, color=ButtonColor.PRIMARY) PROG_LANG_KB.add_text_button(text="C/C++", payload={"q": "ccpp"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="HTML+CSS", payload={"q": "HTMLCSS", "test": "1"}, color=ButtonColor.PRIMARY) PROG_LANG_KB.add_text_button(text="JS", payload={"q": "JS"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="Haskel", payload={"q": "Haskel", "test": "1"}, color=ButtonColor.PRIMARY) PROG_LANG_KB.add_row()
PROG_LANG_KB.add_text_button(text="HTML+CSS", payload={"q": "HTMLCSS"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="Haskel", payload={"q": "Haskel"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_row()
PROG_LANG_KB.add_text_button(text="Java", payload={"q": "Java"}, color=ButtonColor.PRIMARY)
PROG_LANG_KB.add_text_button(text="Я не программирую", payload={"q": "Я не программирую"}, color=ButtonColor.PRIMARY)
# 3 # 3
FAV_THEME = "Какой предмет нравится?" FAV_THEME = "Какая школьная дисциплина нравится вам больше?"
FAV_THEME_KB = Keyboard() FAV_THEME_KB = Keyboard()
FAV_THEME_KB.add_text_button(text="Матеша", payload={"q": "Матеша", "test": "2"}, color=ButtonColor.PRIMARY) FAV_THEME_KB.add_text_button(text="Математика", payload={"q": "Математика"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_text_button(text="Русский/Литра", payload={"q": "русскийлитра", "test": "2"}, color=ButtonColor.PRIMARY) FAV_THEME_KB.add_text_button(text="Русский/Литература", payload={"q": "русскийлитра"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_text_button(text="Инфа", payload={"q": "Инфа", "test": "2"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_row() FAV_THEME_KB.add_row()
FAV_THEME_KB.add_text_button(text="Физика", payload={"q": "Физика", "test": "2"}, color=ButtonColor.PRIMARY) FAV_THEME_KB.add_text_button(text="Информатика/программирование", payload={"q": "Инфа"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_text_button(text="другое", payload={"q": "other", "test": "2"}, color=ButtonColor.PRIMARY) FAV_THEME_KB.add_text_button(text="Физика", payload={"q": "Физика"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_row()
FAV_THEME_KB.add_text_button(text="История/обществознание", payload={"q": "Инфа"}, color=ButtonColor.PRIMARY)
FAV_THEME_KB.add_text_button(text="Другой", payload={"q": "other"}, color=ButtonColor.PRIMARY)
# 4 # 4
EGE = "Как готовился к ЕГЭ?" EGE = "Как вы готовитесь к ЕГЭ?"
EGE_KB = Keyboard() EGE_KB = Keyboard()
EGE_KB.add_text_button(text="В школе", payload={"q": "школа", "test": "3"}, color=ButtonColor.PRIMARY) EGE_KB.add_text_button(text="В школе", payload={"q": "школа"}, color=ButtonColor.PRIMARY)
EGE_KB.add_text_button(text="online", payload={"q": "online", "test": "3"}, color=ButtonColor.PRIMARY) EGE_KB.add_text_button(text="В онлайн-школе", payload={"q": "online"}, color=ButtonColor.PRIMARY)
EGE_KB.add_text_button(text="репетитор", payload={"q": "репетитор", "test": "3"}, color=ButtonColor.PRIMARY) EGE_KB.add_text_button(text="С репетитором", payload={"q": "репетитор"}, color=ButtonColor.PRIMARY)
EGE_KB.add_row() EGE_KB.add_row()
EGE_KB.add_text_button(text="Сам", payload={"q": "Сам", "test": "3"}, color=ButtonColor.PRIMARY) EGE_KB.add_text_button(text="Самостоятельно", payload={"q": "Сам"}, color=ButtonColor.PRIMARY)
EGE_KB.add_text_button(text="wtf?", payload={"q": "wtf", "test": "3"}, color=ButtonColor.PRIMARY) EGE_KB.add_text_button(text="А? Какие экзамены?", payload={"q": "А? Какие экзамены?"}, color=ButtonColor.PRIMARY)
# 5
TRANS_ENGINEER_COUNT = "Сколько нужно инженеров, чтобы запустить трансляцию в Телемосте?"
TRANS_ENGINEER_COUNT_KB = Keyboard()
TRANS_ENGINEER_COUNT_KB.add_text_button(text="1", payload={"q": "1"}, color=ButtonColor.PRIMARY)
TRANS_ENGINEER_COUNT_KB.add_text_button(text="2", payload={"q": "2"}, color=ButtonColor.PRIMARY)
TRANS_ENGINEER_COUNT_KB.add_text_button(text="5", payload={"q": "5"}, color=ButtonColor.PRIMARY)
# 6
ZODIAC = "Кто вы по знаку зодиака?"
# ZODIAC_KB = Keyboard()
# # 7
# CONTACT = "Введите почту или ник в телеграмме, по которому мы сможем прислать вам результаты"
# last # last
LAST_MESSAGE = "Спасибо, что прошел тест!" LAST_MESSAGE = "Теперь у вас есть ваш персональный NFT-талисман! Он поможет вам при сдаче экзаменов и поступлении в желаемый университет &#127775;"
LAST_MESSAGE_KB = Keyboard() LAST_MESSAGE_KB = Keyboard()
LAST_MESSAGE_KB.add_text_button(text="Вернуться на главную", payload={}, color=ButtonColor.POSITIVE) LAST_MESSAGE_KB.add_text_button(text="Вернуться на главную", payload={}, color=ButtonColor.POSITIVE)
questions = [ questions = [
(WHAT_ENGINEER_ARE_YOU, WHAT_ENGINEER_ARE_YOU_KB), (WHAT_ENGINEER_ARE_YOU, WHAT_ENGINEER_ARE_YOU_KB),
(PROG_LANG, PROG_LANG_KB), (PROG_LANG, PROG_LANG_KB),
(FAV_THEME, FAV_THEME_KB), (FAV_THEME, FAV_THEME_KB),
(EGE, EGE_KB), (EGE, EGE_KB),
(TRANS_ENGINEER_COUNT, TRANS_ENGINEER_COUNT_KB),
(ZODIAC, None),
# (CONTACT, None),
] ]

13
main.py
View File

@ -3,29 +3,28 @@ import logging
from vkwave.bots import SimpleLongPollBot, PhotoUploader from vkwave.bots import SimpleLongPollBot, PhotoUploader
from blueprints import ( from blueprints import (
menu_router, test_router, menu_router, test_router, student_router, teacher_router, man_router,
) )
from config import Config from config import Config
from middlewares import UserMiddleware from middlewares import UserMiddleware
# from nft_things.NftSender import NFTSender # from nft_things.NftSender import NFTSender
from middlewares.test_state_middleware import TestStateMiddleware
logging.basicConfig(level="DEBUG") logging.basicConfig(level="DEBUG")
bot = SimpleLongPollBot(Config.TOKEN, group_id=Config.GROUP_ID) bot = SimpleLongPollBot(Config.TOKEN, group_id=Config.GROUP_ID)
# nft_sender = NFTSender(bot.api_context)
# nft_sender.start()
uploader = PhotoUploader(bot.api_context) uploader = PhotoUploader(bot.api_context)
Config().api_ctx = bot.api_context Config().api_ctx = bot.api_context
Config().uploader = uploader Config().uploader = uploader
bot.middleware_manager.add_middleware(UserMiddleware()) bot.middleware_manager.add_middleware(UserMiddleware())
bot.middleware_manager.add_middleware(TestStateMiddleware())
bot.dispatcher.add_router(test_router) bot.dispatcher.add_router(test_router)
# bot.dispatcher.add_router(games_router) bot.dispatcher.add_router(student_router)
# bot.dispatcher.add_router(coin_flip_router) bot.dispatcher.add_router(teacher_router)
# bot.dispatcher.add_router(bonus_router) bot.dispatcher.add_router(man_router)
# регаем последним чтобы сначала проверялись все остальные команды # регаем последним чтобы сначала проверялись все остальные команды
bot.dispatcher.add_router(menu_router) bot.dispatcher.add_router(menu_router)

View File

@ -0,0 +1,31 @@
import json
import logging
from vkwave.bots import BaseMiddleware, BotEvent, MiddlewareResult, SimpleBotEvent, Storage
from vkwave.bots.storage.types import Key
from vkwave.types.bot_events import MessageNewObject
from db import DB, Candidate
from util.redis_db import RedisDB
storage = Storage()
class TestStateMiddleware(BaseMiddleware):
async def pre_process_event(self, event: BotEvent) -> MiddlewareResult:
if isinstance(event.object.object, MessageNewObject):
user_id = event.object.object.message.from_id
else:
return MiddlewareResult(True)
redis_test_state = RedisDB().get_state(user_id)
logging.debug(event.object.object.message.payload)
payload_json = json.loads(event.object.object.message.payload) if event.object.object.message.payload else {}
if 'test' not in payload_json.keys() and (
redis_test_state != None):
logging.debug(f"User {user_id} is in state: {redis_test_state}")
payload_json["test"] = int(redis_test_state)
event.object.object.message.payload = json.dumps(payload_json)
return MiddlewareResult(True)

View File

@ -1,19 +1,33 @@
import logging import logging
from vkwave.bots import BaseMiddleware, BotEvent, MiddlewareResult, SimpleBotEvent from vkwave.bots import BaseMiddleware, BotEvent, MiddlewareResult, SimpleBotEvent
from vkwave.types.bot_events import GroupJoinObject, MessageNewObject
from vkwave.types.objects import UsersUser
from db import DB, Candidate from db import DB, Candidate
async def get_user(api_ctx, user_id):
raw_user = (
await api_ctx.api_request("users.get", {"user_ids": user_id})
)["response"][0]
return UsersUser(**raw_user)
class UserMiddleware(BaseMiddleware): class UserMiddleware(BaseMiddleware):
async def pre_process_event(self, event: BotEvent) -> MiddlewareResult: async def pre_process_event(self, event: BotEvent) -> MiddlewareResult:
db = DB() db = DB()
botevent = SimpleBotEvent(event)
user_id = event.object.object.message.from_id if isinstance(event.object.object, GroupJoinObject):
user_id = event.object.object.user_id
elif isinstance(event.object.object, MessageNewObject):
user_id = event.object.object.message.from_id
else:
return MiddlewareResult(True)
user = db.get_user(user_id) user = db.get_user(user_id)
if not user: if not user:
user_info = await botevent.get_user() user_info = await get_user(event.api_ctx, user_id)
logging.debug(f"Got user info: {user_info}") logging.debug(f"Got user info: {user_info}")
user = Candidate(id=user_id, sex=user_info.sex, name=user_info.first_name, last_name=user_info.last_name) user = Candidate(id=user_id, sex=user_info.sex, name=user_info.first_name, last_name=user_info.last_name)
db.add_candidate(user) db.add_candidate(user)

14
nft_svc/Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM python:3.9
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY . /app
EXPOSE 5000
ENTRYPOINT [ "flask" ]
CMD ["run", "--host=0.0.0.0", "--port=5000"]

46
nft_svc/app.py Normal file
View File

@ -0,0 +1,46 @@
import io
import random
import os
from PIL import Image
from flask import Flask, request, jsonify
import matplotlib.image as mpimg
import base64
app = Flask(__name__)
IMAGE_PATH = 'pics'
def open_image_as_array(path):
return mpimg.imread(path)
def get_encoded_img(arr):
img = Image.fromarray(arr)
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='PNG')
encoded_img = base64.encodebytes(img_byte_arr.getvalue()).decode('ascii')
return str(encoded_img)
@app.route('/getImage', methods=['GET'])
def get_image():
# print(random.choice(os.listdir(IMAGE_PATH)))
file = os.path.join(IMAGE_PATH, random.choice(os.listdir(IMAGE_PATH)))
# buffered = io.BytesIO()
# image.save(buffered, format="JPEG")
# img_str = base64.b64encode(buffered.getvalue())
image = base64.encodebytes(open(file, 'rb').read()).decode('ascii')
return jsonify({
"code": 0,
"image": image,
"first_time": 1
})
def start_app():
app.run()
if __name__ == '__main__':
start_app()

View File

@ -0,0 +1,10 @@
# Gunicorn config variables
loglevel = "info"
errorlog = "-" # stderr
accesslog = "-" # stdout
worker_tmp_dir = "/dev/shm"
graceful_timeout = 120
timeout = 120
keepalive = 5
threads = 4
workers = 4

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More