aboutsummaryrefslogtreecommitdiffstats
path: root/backend/models
diff options
context:
space:
mode:
authorGravatar Joe Banks <[email protected]>2020-12-21 19:39:56 +0000
committerGravatar GitHub <[email protected]>2020-12-21 19:39:56 +0000
commit59a605290795c0563311993fb16d992972104025 (patch)
treed1b392efe12ccaa053e3f6253f12a471d94da253 /backend/models
parentRemove validator import (diff)
parentMerge pull request #39 from python-discord/discord-webhook (diff)
Merge branch 'main' into big-int-fix
Diffstat (limited to 'backend/models')
-rw-r--r--backend/models/form.py76
1 files changed, 75 insertions, 1 deletions
diff --git a/backend/models/form.py b/backend/models/form.py
index 9d8ffaa..d5e2ff5 100644
--- a/backend/models/form.py
+++ b/backend/models/form.py
@@ -1,13 +1,34 @@
import typing as t
+import httpx
from pydantic import BaseModel, Field, validator
+from pydantic.error_wrappers import ErrorWrapper, ValidationError
-from backend.constants import FormFeatures
+from backend.constants import FormFeatures, Meta, WebHook
from .question import Question
PUBLIC_FIELDS = ["id", "features", "questions", "name", "description"]
+class _WebHook(BaseModel):
+ """Schema model of discord webhooks."""
+ url: str
+ message: t.Optional[str]
+
+ @validator("url")
+ def validate_url(cls, url: str) -> str:
+ """Validates URL parameter."""
+ if "discord.com/api/webhooks/" not in url:
+ raise ValueError("URL must be a discord webhook.")
+
+ return url
+
+
+class _FormMeta(BaseModel):
+ """Schema model for form meta data."""
+ webhook: _WebHook = None
+
+
class Form(BaseModel):
"""Schema model for form."""
@@ -16,6 +37,7 @@ class Form(BaseModel):
questions: list[Question]
name: str
description: str
+ meta: _FormMeta = _FormMeta()
class Config:
allow_population_by_field_name = True
@@ -56,3 +78,55 @@ class Form(BaseModel):
class FormList(BaseModel):
__root__: t.List[Form]
+
+
+async def validate_hook_url(url: str) -> t.Optional[ValidationError]:
+ """Validator for discord webhook urls."""
+ async def validate() -> t.Optional[str]:
+ if not isinstance(url, str):
+ raise ValueError("Webhook URL must be a string.")
+
+ if "discord.com/api/webhooks/" not in url:
+ raise ValueError("URL must be a discord webhook.")
+
+ try:
+ async with httpx.AsyncClient() as client:
+ response = await client.get(url)
+ response.raise_for_status()
+
+ except httpx.RequestError as error:
+ # Catch exceptions in request format
+ raise ValueError(
+ f"Encountered error while trying to connect to url: `{error}`"
+ )
+
+ except httpx.HTTPStatusError as error:
+ # Catch exceptions in response
+ status = error.response.status_code
+
+ if status == 401:
+ raise ValueError(
+ "Could not authenticate with target. Please check the webhook url."
+ )
+ elif status == 404:
+ raise ValueError(
+ "Target could not find webhook url. Please check the webhook url."
+ )
+ else:
+ raise ValueError(
+ f"Unknown error ({status}) while connecting to target: {error}"
+ )
+
+ return url
+
+ # Validate, and return errors, if any
+ try:
+ await validate()
+ except Exception as e:
+ loc = (
+ Meta.__name__.lower(),
+ WebHook.__name__.lower(),
+ WebHook.URL.value
+ )
+
+ return ValidationError([ErrorWrapper(e, loc=loc)], _WebHook)