Skip to content

Commit

Permalink
Vk callback (#23)
Browse files Browse the repository at this point in the history
## Изменения
Добавил возможность читать сообщения от ВК

## Детали
Для добавления ВК группы нужно создать ее через АПИ, передав секретный
ключ, после чего сохранить настройки в группе в интерфейсе ВК

## Check-List
<!-- Проставьте x в квадратные скобки в нужных пунктах. Example: [x] -->
- [x] Вы проверили свой код перед отправкой запроса?
- [ ] Вы написали тесты к реализованным функциям?
- [x] Вы не забыли применить форматирование `black` и `isort` для
_Back-End_ или `Prettier` для _Front-End_?
  • Loading branch information
dyakovri authored Aug 19, 2023
1 parent d0b645b commit a4ee995
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 4 deletions.
32 changes: 32 additions & 0 deletions migrations/versions/9d98c1e9c864_vk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""vk
Revision ID: 9d98c1e9c864
Revises: 57c72962d2b4
Create Date: 2023-08-19 15:53:19.787309
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '9d98c1e9c864'
down_revision = '57c72962d2b4'
branch_labels = None
depends_on = None


def upgrade():
op.create_table('vk_groups',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('group_id', sa.Integer(), nullable=False),
sa.Column('confirmation_token', sa.String(), nullable=False),
sa.Column('secret_key', sa.String(), nullable=False),
sa.Column('create_ts', sa.DateTime(), nullable=False),
sa.Column('update_ts', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('id')
)


def downgrade():
op.drop_table('vk_groups')
4 changes: 2 additions & 2 deletions social/handlers_github/profcomff_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def issue_opened(event):
projectId=PROJECT_NODE_ID,
itemId=project_item_id,
fieldId=DEADLINE_FIELD_NODE_ID,
newDate=new_deadline_date
newDate=new_deadline_date,
)
logging.debug("Deadline change response: %s", r)

Expand All @@ -81,6 +81,6 @@ def issue_opened(event):
projectId=PROJECT_NODE_ID,
itemId=project_item_id,
fieldId=TAKEN_FIELD_NODE_ID,
newDate=new_taken_date
newDate=new_taken_date,
)
logging.debug("Taken change response: %s", r)
2 changes: 1 addition & 1 deletion social/handlers_telegram/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_application():

# Хэндлеры конкретных чатов
register_handlers(app)

return app


Expand Down
2 changes: 1 addition & 1 deletion social/handlers_telegram/handlers_viribus.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
Приятно познакомиться, [{name}](tg://user?id={id})! Мы здесь, чтобы обсуждать всё, что связано с IT.
Какие темы в IT тебя больше всего интересуют и где ты узнал(а) о нас?
"""
""",
]


Expand Down
5 changes: 5 additions & 0 deletions social/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .vk import VkGroups
from .webhook_storage import WebhookStorage


__all__ = ['WebhookStorage', 'VkGroups']
15 changes: 15 additions & 0 deletions social/models/vk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from datetime import datetime

import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column

from .base import Base


class VkGroups(Base):
id: Mapped[int] = mapped_column(sa.Integer, primary_key=True)
group_id: Mapped[int] = mapped_column(sa.Integer)
confirmation_token: Mapped[str] = mapped_column(sa.String)
secret_key: Mapped[str] = mapped_column(sa.String)
create_ts: Mapped[datetime] = mapped_column(sa.DateTime, default=datetime.utcnow)
update_ts: Mapped[datetime] = mapped_column(sa.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
1 change: 1 addition & 0 deletions social/models/webhook_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class WebhookSystems(str, Enum):
TELEGRAM = 'telegram'
GITHUB = 'github'
VK = 'vk'


class WebhookStorage(Base):
Expand Down
2 changes: 2 additions & 0 deletions social/routes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from .github import router as github_rourer
from .telegram import router as telegram_rourer
from .vk import router as vk_rourer


settings = get_settings()
Expand Down Expand Up @@ -52,3 +53,4 @@ async def shutdown():

app.include_router(github_rourer)
app.include_router(telegram_rourer)
app.include_router(vk_rourer)
77 changes: 77 additions & 0 deletions social/routes/vk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import logging

from auth_lib.fastapi import UnionAuth
from fastapi import APIRouter, Depends, Request
from fastapi.responses import PlainTextResponse
from fastapi_sqlalchemy import db
from pydantic import BaseModel, ConfigDict

from social.handlers_telegram import get_application
from social.models.vk import VkGroups
from social.models.webhook_storage import WebhookStorage, WebhookSystems
from social.settings import get_settings
from social.utils.string import random_string


router = APIRouter(prefix="/vk", tags=['vk'])
settings = get_settings()
logger = logging.getLogger(__name__)
application = get_application()


class VkGroupCreate(BaseModel):
confirmation_token: str
change_secret_key: bool = False


class VkGroupCreateResponse(BaseModel):
group_id: int
secret_key: str

model_config = ConfigDict(from_attributes=True)


@router.post('', tags=["webhooks"])
async def vk_webhook(request: Request):
"""Принимает любой POST запрос от VK"""
request_data = await request.json()
logger.debug(request_data)
group_id = request_data["group_id"] # Fail if no group
group = db.session.query(VkGroups).where(VkGroups.group_id == group_id).one() # Fail if no settings

# Проверка на создание нового вебхука со страничка ВК
if request_data.get("type", "") == "confirmation":
return PlainTextResponse(group.confirmation_token)

if request_data.get("secret") != group.secret_key:
raise Exception("Not a valid secret")

db.session.add(
WebhookStorage(
system=WebhookSystems.VK,
message=request_data,
)
)
db.session.commit()

return


@router.put('/{group_id}')
def create_or_replace_group(
group_id: int, group_info: VkGroupCreate, _=Depends(UnionAuth(["social.vk_group.create"]))
) -> VkGroupCreateResponse:
group = db.session.query(VkGroups).where(VkGroups.group_id == group_id).one_or_none()
if group is None:
group = VkGroups()
db.session.add(group)
group.group_id = group_id
group.secret_key = random_string(32)

if group_info.change_secret_key:
group.secret_key = random_string(32)

group.confirmation_token = group_info.confirmation_token

db.session.commit()
return group
6 changes: 6 additions & 0 deletions social/utils/string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import random
import string


def random_string(N: int):
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=N))

0 comments on commit a4ee995

Please sign in to comment.