feat: переименование доменной области
This commit is contained in:
@@ -2,10 +2,11 @@ from fastapi import APIRouter
|
||||
|
||||
from src.controller.http.analytics import analytics_router
|
||||
from src.controller.http.auth import auth_router
|
||||
from src.controller.http.channels import channels_router
|
||||
from src.controller.http.creatives import creatives_router
|
||||
from src.controller.http.external_channels import external_channels_router
|
||||
from src.controller.http.placements import placements_router
|
||||
from src.controller.http.target_channels import target_channels_router
|
||||
from src.controller.http.projects import projects_router
|
||||
from src.controller.http.purchase_plans import purchase_plan_channels_router
|
||||
from src.controller.http.views import views_router
|
||||
from src.controller.http.workspaces import workspaces_router
|
||||
|
||||
@@ -14,8 +15,9 @@ api_router = APIRouter()
|
||||
# API v1 endpoints
|
||||
api_v1_router = APIRouter(prefix='/api/v1')
|
||||
api_v1_router.include_router(auth_router)
|
||||
api_v1_router.include_router(target_channels_router)
|
||||
api_v1_router.include_router(external_channels_router)
|
||||
api_v1_router.include_router(channels_router)
|
||||
api_v1_router.include_router(projects_router)
|
||||
api_v1_router.include_router(purchase_plan_channels_router)
|
||||
api_v1_router.include_router(creatives_router)
|
||||
api_v1_router.include_router(placements_router)
|
||||
api_v1_router.include_router(views_router)
|
||||
|
||||
@@ -15,12 +15,12 @@ analytics_router = APIRouter(prefix='/workspaces/{workspace_id}/analytics', tags
|
||||
async def get_placements_analytics(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
project_id: uuid.UUID | None = None,
|
||||
) -> dto.GetPlacementsAnalyticsOutput:
|
||||
input = dto.GetPlacementsAnalyticsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
return await deps.get_usecase().get_placements_analytics(input)
|
||||
|
||||
@@ -29,35 +29,35 @@ async def get_placements_analytics(
|
||||
async def get_creatives_analytics(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
project_id: uuid.UUID | None = None,
|
||||
) -> dto.GetCreativesAnalyticsOutput:
|
||||
input = dto.GetCreativesAnalyticsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
return await deps.get_usecase().get_creatives_analytics(input)
|
||||
|
||||
|
||||
@analytics_router.get('/external-channels')
|
||||
async def get_external_channels_analytics(
|
||||
@analytics_router.get('/channels')
|
||||
async def get_channel_analytics(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
) -> dto.GetExternalChannelsAnalyticsOutput:
|
||||
input = dto.GetExternalChannelsAnalyticsInput(
|
||||
project_id: uuid.UUID | None = None,
|
||||
) -> dto.GetChannelAnalyticsOutput:
|
||||
input = dto.GetChannelAnalyticsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
return await deps.get_usecase().get_external_channels_analytics(input)
|
||||
return await deps.get_usecase().get_channel_analytics(input)
|
||||
|
||||
|
||||
@analytics_router.get('/spending')
|
||||
async def get_spending_analytics(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
project_id: uuid.UUID | None = None,
|
||||
date_from: datetime.datetime | None = None,
|
||||
date_to: datetime.datetime | None = None,
|
||||
grouping: dto.DateGrouping = dto.DateGrouping.DAY,
|
||||
@@ -65,7 +65,7 @@ async def get_spending_analytics(
|
||||
input = dto.GetSpendingAnalyticsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
project_id=project_id,
|
||||
date_from=date_from,
|
||||
date_to=date_to,
|
||||
grouping=grouping,
|
||||
|
||||
18
src/controller/http/channels.py
Normal file
18
src/controller/http/channels.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends
|
||||
from fastapi.routing import APIRouter
|
||||
|
||||
from src import deps, dto
|
||||
from src.adapter.jwt import JWTPayload
|
||||
|
||||
channels_router = APIRouter(prefix='/channels', tags=['channels'])
|
||||
|
||||
|
||||
@channels_router.get('')
|
||||
async def get_channels(
|
||||
_: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
username: str | None = None,
|
||||
) -> dto.GetChannelsOutput:
|
||||
input = dto.GetChannelsInput(username=username)
|
||||
return await deps.get_usecase().get_channels(input=input)
|
||||
@@ -14,13 +14,13 @@ creatives_router = APIRouter(prefix='/workspaces/{workspace_id}/creatives', tags
|
||||
async def list_creatives(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
project_id: uuid.UUID | None = None,
|
||||
include_archived: bool = False,
|
||||
) -> dto.GetCreativesOutput:
|
||||
input = dto.GetCreativesInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
project_id=project_id,
|
||||
include_archived=include_archived,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import uuid
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends
|
||||
from fastapi.routing import APIRouter
|
||||
|
||||
from src import deps, dto
|
||||
from src.adapter.jwt import JWTPayload
|
||||
|
||||
external_channels_router = APIRouter(prefix='/workspaces/{workspace_id}/external_channels', tags=['external_channels'])
|
||||
|
||||
|
||||
@external_channels_router.get('/target/{target_channel_id}')
|
||||
async def get_external_channels(
|
||||
target_channel_id: uuid.UUID,
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.GetExternalChannelsOutput:
|
||||
"""Get all external channels for a specific target channel."""
|
||||
input = dto.GetExternalChannelsInput(
|
||||
target_channel_id=target_channel_id,
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
return await deps.get_usecase().get_external_channels(input=input)
|
||||
|
||||
|
||||
@external_channels_router.post('')
|
||||
async def create_external_channel(
|
||||
request: dto.CreateExternalChannelInput,
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.ExternalChannelOutput:
|
||||
"""Create a new external channel and link it to target channels."""
|
||||
return await deps.get_usecase().create_external_channel(
|
||||
input=request,
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
|
||||
@external_channels_router.patch('/{channel_id}')
|
||||
async def update_external_channel(
|
||||
channel_id: uuid.UUID,
|
||||
request: dto.UpdateExternalChannelInput,
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.ExternalChannelOutput:
|
||||
"""Update external channel fields (title, username, description, subscribers_count)."""
|
||||
return await deps.get_usecase().update_external_channel(
|
||||
channel_id=channel_id,
|
||||
input=request,
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
|
||||
@external_channels_router.patch('/{channel_id}/links')
|
||||
async def update_external_channel_links(
|
||||
channel_id: uuid.UUID,
|
||||
request: dto.UpdateExternalChannelLinksInput,
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.ExternalChannelOutput:
|
||||
"""
|
||||
Update target channel links for an existing external channel.
|
||||
|
||||
You can add new target channels, remove existing ones, or both in a single request.
|
||||
"""
|
||||
return await deps.get_usecase().update_external_channel_links(
|
||||
channel_id=channel_id,
|
||||
input=request,
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
|
||||
@external_channels_router.delete('/{channel_id}')
|
||||
async def delete_external_channel(
|
||||
channel_id: uuid.UUID,
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> None:
|
||||
"""Delete an external channel."""
|
||||
input = dto.DeleteExternalChannelInput(
|
||||
channel_id=channel_id,
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
await deps.get_usecase().delete_external_channel(input=input)
|
||||
@@ -14,16 +14,16 @@ placements_router = APIRouter(prefix='/workspaces/{workspace_id}/placements', ta
|
||||
async def list_placements(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
target_channel_id: uuid.UUID | None = None,
|
||||
external_channel_id: uuid.UUID | None = None,
|
||||
project_id: uuid.UUID | None = None,
|
||||
placement_channel_id: uuid.UUID | None = None,
|
||||
creative_id: uuid.UUID | None = None,
|
||||
include_archived: bool = False,
|
||||
) -> dto.GetPlacementsOutput:
|
||||
input = dto.GetPlacementsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
target_channel_id=target_channel_id,
|
||||
external_channel_id=external_channel_id,
|
||||
project_id=project_id,
|
||||
placement_channel_id=placement_channel_id,
|
||||
creative_id=creative_id,
|
||||
include_archived=include_archived,
|
||||
)
|
||||
|
||||
@@ -7,17 +7,17 @@ from fastapi.routing import APIRouter
|
||||
from src import deps, dto
|
||||
from src.adapter.jwt import JWTPayload
|
||||
|
||||
target_channels_router = APIRouter(prefix='/workspaces/{workspace_id}/target_channels', tags=['target_channels'])
|
||||
projects_router = APIRouter(prefix='/workspaces/{workspace_id}/projects', tags=['projects'])
|
||||
|
||||
|
||||
@target_channels_router.get('')
|
||||
async def get_user_target_chans(
|
||||
@projects_router.get('')
|
||||
async def get_workspace_projects(
|
||||
workspace_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.GetUserTargetChansOutput:
|
||||
input = dto.GetUserTargetChansInput(
|
||||
) -> dto.GetWorkspaceProjectsOutput:
|
||||
input = dto.GetWorkspaceProjectsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
|
||||
return await deps.get_usecase().get_user_target_chans(input=input)
|
||||
return await deps.get_usecase().get_workspace_projects(input=input)
|
||||
74
src/controller/http/purchase_plans.py
Normal file
74
src/controller/http/purchase_plans.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import uuid
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends
|
||||
from fastapi.routing import APIRouter
|
||||
|
||||
from src import deps, dto
|
||||
from src.adapter.jwt import JWTPayload
|
||||
|
||||
purchase_plan_channels_router = APIRouter(
|
||||
prefix='/workspaces/{workspace_id}/projects/{project_id}/purchase-plan/channels',
|
||||
tags=['purchase plan'],
|
||||
)
|
||||
|
||||
|
||||
@purchase_plan_channels_router.get('')
|
||||
async def get_purchase_plan_channels(
|
||||
workspace_id: uuid.UUID,
|
||||
project_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.GetPurchasePlanChannelsOutput:
|
||||
input = dto.GetPurchasePlanChannelsInput(
|
||||
user_id=current_user.user_id,
|
||||
workspace_id=workspace_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
return await deps.get_usecase().get_purchase_plan_channels(input=input)
|
||||
|
||||
|
||||
@purchase_plan_channels_router.post('')
|
||||
async def attach_channel_to_purchase_plan(
|
||||
request: dto.AttachChannelToPurchasePlanInput,
|
||||
workspace_id: uuid.UUID,
|
||||
project_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.PurchasePlanChannelOutput:
|
||||
return await deps.get_usecase().attach_channel_to_purchase_plan(
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
user_id=current_user.user_id,
|
||||
input=request,
|
||||
)
|
||||
|
||||
|
||||
@purchase_plan_channels_router.patch('/{channel_id}')
|
||||
async def update_purchase_plan_channel(
|
||||
channel_id: uuid.UUID,
|
||||
request: dto.UpdatePurchasePlanChannelInput,
|
||||
workspace_id: uuid.UUID,
|
||||
project_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> dto.PurchasePlanChannelOutput:
|
||||
return await deps.get_usecase().update_purchase_plan_channel(
|
||||
channel_id=channel_id,
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
user_id=current_user.user_id,
|
||||
input=request,
|
||||
)
|
||||
|
||||
|
||||
@purchase_plan_channels_router.delete('/{channel_id}')
|
||||
async def remove_purchase_plan_channel(
|
||||
channel_id: uuid.UUID,
|
||||
workspace_id: uuid.UUID,
|
||||
project_id: uuid.UUID,
|
||||
current_user: Annotated[JWTPayload, Depends(deps.get_current_user)],
|
||||
) -> None:
|
||||
await deps.get_usecase().remove_purchase_plan_channel(
|
||||
channel_id=channel_id,
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
user_id=current_user.user_id,
|
||||
)
|
||||
@@ -8,6 +8,6 @@ from . import ( # noqa: E402, F401
|
||||
chat_member_updated,
|
||||
creative_commands,
|
||||
my_chat_member,
|
||||
project_commands,
|
||||
start_with_login,
|
||||
target_channel_commands,
|
||||
)
|
||||
|
||||
@@ -29,12 +29,12 @@ async def on_bot_added_to_chat(event: ChatMemberUpdated) -> None:
|
||||
bot_removed = was_member and is_now_not_member
|
||||
|
||||
if bot_removed:
|
||||
disconnect_input = dto.DisconnectTargetChanByTgIdInput(
|
||||
disconnect_input = dto.DisconnectProjectByTgIdInput(
|
||||
telegram_id=event.chat.id,
|
||||
user_telegram_id=event.from_user.id,
|
||||
)
|
||||
try:
|
||||
await usecase.disconnect_target_chan_by_tg_id(input=disconnect_input)
|
||||
await usecase.disconnect_project_by_tg_id(input=disconnect_input)
|
||||
except HTTPException as e:
|
||||
log.error(e)
|
||||
|
||||
@@ -53,14 +53,14 @@ async def on_bot_added_to_chat(event: ChatMemberUpdated) -> None:
|
||||
)
|
||||
|
||||
if permissions_changed:
|
||||
permissions_input = dto.UpdateTargetChanPermissionsInput(
|
||||
permissions_input = dto.UpdateProjectPermissionsInput(
|
||||
telegram_id=event.chat.id,
|
||||
permissions=bot_permissions,
|
||||
chat_title=event.chat.title or f'Channel {event.chat.id}',
|
||||
user_telegram_id=event.from_user.id,
|
||||
)
|
||||
try:
|
||||
await usecase.update_target_chan_permissions(input=permissions_input)
|
||||
await usecase.update_project_permissions(input=permissions_input)
|
||||
except HTTPException as e:
|
||||
log.error(e)
|
||||
return
|
||||
@@ -71,7 +71,7 @@ async def on_bot_added_to_chat(event: ChatMemberUpdated) -> None:
|
||||
bot_added = was_not_member and is_now_member
|
||||
|
||||
if bot_added:
|
||||
connect_input = dto.ConnectTargetChanInput(
|
||||
connect_input = dto.ConnectProjectInput(
|
||||
telegram_id=event.chat.id,
|
||||
title=event.chat.title or f'Channel {event.chat.id}',
|
||||
username=event.chat.username,
|
||||
@@ -79,6 +79,6 @@ async def on_bot_added_to_chat(event: ChatMemberUpdated) -> None:
|
||||
bot_permissions=bot_permissions,
|
||||
)
|
||||
try:
|
||||
await usecase.tg_add_target_chan_1(input=connect_input)
|
||||
await usecase.tg_add_project_1(input=connect_input)
|
||||
except HTTPException as e:
|
||||
log.error(e)
|
||||
|
||||
@@ -9,14 +9,14 @@ from src.controller.telegram_callback import telegram_callback_router
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@telegram_callback_router.callback_query(F.data.startswith('tg_add_target_chan_2:'))
|
||||
async def callback_target_channel_workspace(callback: CallbackQuery) -> None:
|
||||
@telegram_callback_router.callback_query(F.data.startswith('tg_add_project_2:'))
|
||||
async def callback_project_workspace(callback: CallbackQuery) -> None:
|
||||
if not callback.from_user or not callback.message or not callback.data:
|
||||
log.error('Failed to get required data from callback query')
|
||||
return
|
||||
|
||||
usecase = deps.get_usecase()
|
||||
await usecase.tg_add_target_chan_2(
|
||||
await usecase.tg_add_project_2(
|
||||
telegram_id=callback.from_user.id,
|
||||
chat_id=callback.message.chat.id,
|
||||
callback_data=callback.data,
|
||||
Reference in New Issue
Block a user