Skip to content

Commit

Permalink
feat: add API wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Makcal committed Mar 10, 2024
1 parent 940aa3e commit 4a9c375
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 1 deletion.
2 changes: 2 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
BOT_TOKEN="1234:abrakadabra"
API_URL="http://127.0.0.1:8000"
API_SECRET="secret"
139 changes: 138 additions & 1 deletion poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ python = "^3.11"
aiogram = "^3.4.1"
aiogram-dialog = "^2.1.0"
python-dotenv = "^1.0.1"
requests = "^2.31.0"

[tool.poetry.group.dev.dependencies]
pre-commit = "^3.6.2"
Expand Down
4 changes: 4 additions & 0 deletions src/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from src.api.methods import api_client


__all__ = ["api_client"]
113 changes: 113 additions & 0 deletions src/api/methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import os

import requests

from src.api.schemas.method_input_schemas import (
CreateTaskBody,
ModifyTaskBody,
)
from src.api.schemas.method_output_schemas import (
DailyInfoResponse,
IncomingInvitationInfo,
RoomInfoResponse,
TaskInfoResponse,
SentInvitationInfo,
Task,
)


class InNoHassleMusicRoomAPI:
url: str
secret: str

def _post(self, path: str, user_id: int = None, **data: any) -> any:
if user_id is not None:
data["user_id"] = user_id
r = requests.post(self.url + path, json=data, headers={"X-Token": self.secret})
if r.status_code != 200:
if r.status_code in (400, 422):
json = r.json()
if r.status_code == 400 and "code" in json:
raise RuntimeError(f"{json['code']}. {json['detail']}")
elif r.status_code == 422:
raise RuntimeError(json["detail"])
raise RuntimeError(r.text)
return r.json()

def __init__(self, url: str, secret: str) -> None:
self.url = url
self.secret = secret

def create_user(self, user_id: int) -> int:
return self._post("/bot/user/create", user_id)

def create_room(self, name: str, user_id: int) -> int:
return self._post("/bot/room/create", user_id, room={"name": name})

def invite_person(self, alias: str, user_id: int) -> int:
return self._post("/bot/invitation/create", user_id, addressee={"alias": alias})

def accept_invitation(self, id_: int, user_id: int) -> int:
return self._post("/bot/invitation/accept", user_id, invitation={"id": id_})

def create_order(self, users: list[int], user_id: int) -> int:
return self._post("/bot/order/create", user_id, order={"users": users})

def create_task(self, body: CreateTaskBody, user_id: int) -> int:
return self._post("/bot/task/create", user_id, task=body.model_dump())

def modify_task(self, body: ModifyTaskBody, user_id: int) -> bool:
return self._post("/bot/task/modify", user_id, task=body.model_dump())

def get_daily_info(self, user_id: int) -> DailyInfoResponse:
return DailyInfoResponse.model_validate(
self._post("/bot/room/daily_info", user_id)
)

def get_incoming_invitations(
self, alias: str, user_id: int
) -> list[IncomingInvitationInfo]:
return [
IncomingInvitationInfo.model_validate(obj)
for obj in self._post("/bot/invitation/inbox", user_id, alias=alias)[
"invitations"
]
]

def get_room_info(self, user_id: int) -> RoomInfoResponse:
return RoomInfoResponse.model_validate(self._post("/bot/room/info", user_id))

def leave_room(self, user_id: int) -> bool:
return self._post("/bot/room/leave", user_id)

def get_tasks(self, user_id: int) -> list[Task]:
return [
Task.model_validate(obj)
for obj in self._post("/bot/task/list", user_id)["tasks"]
]

def get_task_info(self, id_: int, user_id: int) -> TaskInfoResponse:
return TaskInfoResponse.model_validate(
self._post("/bot/task/info", user_id, task={"id": id_})
)

def get_sent_invitations(self, user_id: int) -> list[SentInvitationInfo]:
return [
SentInvitationInfo.model_validate(obj)
for obj in self._post("/bot/invitation/sent", user_id)["invitations"]
]

def delete_invitation(self, id_: int, user_id: int) -> bool:
return self._post("/bot/invitation/delete", user_id, invitation={"id": id_})

def reject_invitation(self, id_: int, user_id: int) -> bool:
return self._post("/bot/invitation/reject", user_id, invitation={"id": id_})

def get_order_info(self, id_: int, user_id: int) -> list[int]:
return self._post("/bot/order/info", user_id, order={"id": id_})["users"]


api_client = InNoHassleMusicRoomAPI(os.getenv("API_URL"), os.getenv("API_SECRET"))


__all__ = ["InNoHassleMusicRoomAPI", "api_client"]
Empty file added src/api/schemas/__init__.py
Empty file.
56 changes: 56 additions & 0 deletions src/api/schemas/method_input_schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from datetime import datetime

from pydantic import BaseModel, Field


class CreateUserBody(BaseModel):
user_id: int = Field(ge=0)


class CreateRoomBody(BaseModel):
name: str


class InvitePersonBody(BaseModel):
alias: str = Field(max_length=32)


class CreateOrderBody(BaseModel):
users: list[int]


class AcceptInvitationBody(BaseModel):
id: int


class CreateTaskBody(BaseModel):
name: str = Field(max_length=100)
description: str | None = Field("", max_length=1000)
start_date: datetime
period: int = Field(gt=0, description="period in days")
order_id: int | None = None


class ModifyTaskBody(BaseModel):
id: int
name: str | None = Field(None, max_length=100)
description: str | None = Field(None, max_length=1000)
start_date: datetime | None = None
period: int | None = Field(None, gt=0, description="period in days")
order_id: int | None = None


class TaskInfoBody(BaseModel):
id: int


class DeleteInvitationBody(BaseModel):
id: int


class RejectInvitationBody(BaseModel):
id: int


class OrderInfoBody(BaseModel):
id: int
63 changes: 63 additions & 0 deletions src/api/schemas/method_output_schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from datetime import datetime

from pydantic import BaseModel


class TaskDailyInfo(BaseModel):
id: int
name: str
today_user_id: int | None


class DailyInfoResponse(BaseModel):
tasks: list[TaskDailyInfo]


class IncomingInvitationInfo(BaseModel):
id: int
sender: int
room: int
room_name: str


class IncomingInvitationsResponse(BaseModel):
invitations: list[IncomingInvitationInfo]


class RoomInfoResponse(BaseModel):
name: str
users: list[int]


class Task(BaseModel):
id: int
name: str
inactive: bool


class TaskListResponse(BaseModel):
tasks: list[Task]


class TaskInfoResponse(BaseModel):
name: str
description: str | None
start_date: datetime
period: int
order_id: int | None
inactive: bool


class SentInvitationInfo(BaseModel):
id: int
addressee: str
room: int
room_name: str


class SentInvitationsResponse(BaseModel):
invitations: list[SentInvitationInfo]


class OrderInfoResponse(BaseModel):
users: list[int]

0 comments on commit 4a9c375

Please sign in to comment.