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 api.route import Route
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from data.schemas.public.short_url import ShortUrl
|
from data.schemas.public.short_url import ShortUrl
|
||||||
from data.schemas.public.short_url_dao import shortUrlDao
|
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__)
|
logger = Logger(__name__)
|
||||||
|
|
||||||
@ -26,4 +30,15 @@ async def handle_short_url(path: str):
|
|||||||
if from_db is None:
|
if from_db is None:
|
||||||
return {"error": "Short URL not found"}, 404
|
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)
|
return redirect(from_db.target_url)
|
||||||
|
@ -9,6 +9,7 @@ type ShortUrl implements DbModel {
|
|||||||
shortUrl: String
|
shortUrl: String
|
||||||
targetUrl: String
|
targetUrl: String
|
||||||
description: String
|
description: String
|
||||||
|
visits: Int
|
||||||
group: Group
|
group: Group
|
||||||
|
|
||||||
deleted: Boolean
|
deleted: Boolean
|
||||||
|
@ -9,3 +9,4 @@ class ShortUrlQuery(DbModelQueryABC):
|
|||||||
self.set_field("targetUrl", lambda x, *_: x.target_url)
|
self.set_field("targetUrl", lambda x, *_: x.target_url)
|
||||||
self.set_field("description", lambda x, *_: x.description)
|
self.set_field("description", lambda x, *_: x.description)
|
||||||
self.set_field("group", lambda x, *_: x.group)
|
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)
|
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:
|
def to_dto(self) -> dict:
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"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;
|
shortUrl: string;
|
||||||
targetUrl: string;
|
targetUrl: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
visits: number;
|
||||||
group?: Group;
|
group?: Group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ export class ShortUrlsDataService
|
|||||||
shortUrl
|
shortUrl
|
||||||
targetUrl
|
targetUrl
|
||||||
description
|
description
|
||||||
|
visits
|
||||||
group {
|
group {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@ -98,6 +99,7 @@ export class ShortUrlsDataService
|
|||||||
shortUrl
|
shortUrl
|
||||||
targetUrl
|
targetUrl
|
||||||
description
|
description
|
||||||
|
visits
|
||||||
group {
|
group {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
Loading…
Reference in New Issue
Block a user