Handle visits
This commit is contained in:
parent
e7a6a4b16b
commit
dd5769823f
@ -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)
|
||||
|
@ -9,6 +9,7 @@ type ShortUrl implements DbModel {
|
||||
shortUrl: String
|
||||
targetUrl: String
|
||||
description: String
|
||||
visits: Int
|
||||
group: Group
|
||||
|
||||
deleted: Boolean
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
37
api/src/data/schemas/public/short_url_visit.py
Normal file
37
api/src/data/schemas/public/short_url_visit.py
Normal 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
|
25
api/src/data/schemas/public/short_url_visit_dao.py
Normal file
25
api/src/data/schemas/public/short_url_visit_dao.py
Normal 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()
|
23
api/src/data/scripts/2024-12-13-22-40-short-url-vistis.sql
Normal file
23
api/src/data/scripts/2024-12-13-22-40-short-url-vistis.sql
Normal 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();
|
||||
|
@ -6,6 +6,7 @@ export interface ShortUrl extends DbModel {
|
||||
shortUrl: string;
|
||||
targetUrl: string;
|
||||
description: string;
|
||||
visits: number;
|
||||
group?: Group;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user