Handle visits

This commit is contained in:
Sven Heidemann 2024-12-14 19:19:27 +01:00
parent e7a6a4b16b
commit dd5769823f
9 changed files with 112 additions and 1 deletions

View File

@ -1,9 +1,13 @@
from flask import redirect, jsonify
import json
from flask import redirect, jsonify, request
from api.route import Route
from core.logger import Logger
from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_dao import shortUrlDao
from data.schemas.public.short_url_visit import ShortUrlVisit
from data.schemas.public.short_url_visit_dao import shortUrlVisitDao
logger = Logger(__name__)
@ -26,4 +30,15 @@ async def handle_short_url(path: str):
if from_db is None:
return {"error": "Short URL not found"}, 404
try:
await shortUrlVisitDao.create(
ShortUrlVisit(
0,
from_db.id,
request.headers.get("User-Agent")
)
)
except Exception as e:
logger.error(f"Failed to update short url {from_db.short_url} with error", e)
return redirect(from_db.target_url)

View File

@ -9,6 +9,7 @@ type ShortUrl implements DbModel {
shortUrl: String
targetUrl: String
description: String
visits: Int
group: Group
deleted: Boolean

View File

@ -9,3 +9,4 @@ class ShortUrlQuery(DbModelQueryABC):
self.set_field("targetUrl", lambda x, *_: x.target_url)
self.set_field("description", lambda x, *_: x.description)
self.set_field("group", lambda x, *_: x.group)
self.set_field("visits", lambda x, *_: x.visit_count)

View File

@ -68,6 +68,12 @@ class ShortUrl(DbModelABC):
return await groupDao.get_by_id(self._group_id)
@async_property
async def visit_count(self) -> int:
from data.schemas.public.short_url_visit_dao import shortUrlVisitDao
return await shortUrlVisitDao.count_by_id(self.id)
def to_dto(self) -> dict:
return {
"id": self.id,

View File

@ -0,0 +1,37 @@
from datetime import datetime
from typing import Optional
from async_property import async_property
from core.database.abc.db_model_abc import DbModelABC
from core.typing import SerialId
from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_dao import shortUrlDao
class ShortUrlVisit(DbModelABC):
def __init__(
self,
id: SerialId,
short_url_id: SerialId,
client: Optional[str],
deleted: bool = False,
editor_id: Optional[SerialId] = None,
created: Optional[datetime] = None,
updated: Optional[datetime] = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._short_url_id = short_url_id
self._client = client
@property
def short_url_id(self) -> SerialId:
return self._short_url_id
@async_property
async def short_url(self) -> ShortUrl:
return await shortUrlDao.get_by_id(self._short_url_id)
@property
def client(self) -> Optional[str]:
return self._client

View File

@ -0,0 +1,25 @@
from core.logger import DBLogger
from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_visit import ShortUrlVisit
logger = DBLogger(__name__)
from core.database.abc.db_model_dao_abc import DbModelDaoABC
class ShortUrlVisitDao(DbModelDaoABC[ShortUrlVisit]):
def __init__(self):
DbModelDaoABC.__init__(self, __name__, ShortUrl, "public.short_url_visits")
self.attribute(ShortUrlVisit.short_url_id, int)
self.attribute(ShortUrlVisit.client, str)
async def count_by_id(self, fid: int) -> int:
result = await self._db.select_map(
f"SELECT COUNT(*) FROM {self._table_name} WHERE shortUrlId = {fid}"
)
if result is None or len(result) == 0:
return 0
return result[0]["count"]
shortUrlVisitDao = ShortUrlVisitDao()

View File

@ -0,0 +1,23 @@
CREATE TABLE IF NOT EXISTS public.short_url_visits
(
Id SERIAL PRIMARY KEY,
ShortUrlId INT NOT NULL REFERENCES public.short_urls (Id),
Client TEXT NOT NULL,
-- for history
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
EditorId INT NULL REFERENCES administration.users (Id),
CreatedUtc timestamptz NOT NULL DEFAULT NOW(),
UpdatedUtc timestamptz NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS public.short_url_visits_history
(
LIKE public.short_url_visits
);
CREATE TRIGGER short_url_visits_history_trigger
BEFORE INSERT OR UPDATE OR DELETE
ON public.short_url_visits
FOR EACH ROW
EXECUTE FUNCTION public.history_trigger_function();

View File

@ -6,6 +6,7 @@ export interface ShortUrl extends DbModel {
shortUrl: string;
targetUrl: string;
description: string;
visits: number;
group?: Group;
}

View File

@ -60,6 +60,7 @@ export class ShortUrlsDataService
shortUrl
targetUrl
description
visits
group {
id
name
@ -98,6 +99,7 @@ export class ShortUrlsDataService
shortUrl
targetUrl
description
visits
group {
id
name