mirror of
https://codeberg.org/diginaut/digimarks.git
synced 2026-02-04 22:00:27 +01:00
Compare commits
4 Commits
2936a4815a
...
b4aff120c8
| Author | SHA1 | Date | |
|---|---|---|---|
| b4aff120c8 | |||
| 82e4202482 | |||
| 9b03d51276 | |||
| fe734d6dd8 |
@@ -10,7 +10,7 @@ authors = [
|
|||||||
]
|
]
|
||||||
description = 'Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags, automatic title fetching and REST API calls.'
|
description = 'Simple bookmarking service, using a SQLite database to store bookmarks, supporting tags, automatic title fetching and REST API calls.'
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.11"
|
||||||
keywords = ["bookmarks", "api"]
|
keywords = ["bookmarks", "api"]
|
||||||
license = { text = "Apache" }
|
license = { text = "Apache" }
|
||||||
classifiers = [
|
classifiers = [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Core application
|
# Core application
|
||||||
fastapi[all]
|
fastapi[all]
|
||||||
sqlmodel
|
sqlmodel
|
||||||
sqlalchemy
|
sqlalchemy[asyncio]
|
||||||
pydantic
|
pydantic
|
||||||
pydantic_settings
|
pydantic_settings
|
||||||
alembic
|
alembic
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import logging
|
|||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
from typing import Annotated
|
from typing import Annotated, AsyncGenerator, cast
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from fastapi import Depends, FastAPI, HTTPException, Query, Request
|
from fastapi import Depends, FastAPI, HTTPException, Query, Request
|
||||||
@@ -54,22 +54,32 @@ engine = create_async_engine(f'sqlite+aiosqlite:///{settings.database_file}', co
|
|||||||
|
|
||||||
async def get_session() -> AsyncSession:
|
async def get_session() -> AsyncSession:
|
||||||
"""SQLAlchemy session factory."""
|
"""SQLAlchemy session factory."""
|
||||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
async_session = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)
|
||||||
async with async_session() as session:
|
async with async_session() as session:
|
||||||
yield session
|
yield session
|
||||||
|
|
||||||
|
|
||||||
|
# Shorter way of getting the DB session in an endpoint
|
||||||
SessionDep = Annotated[AsyncSession, Depends(get_session)]
|
SessionDep = Annotated[AsyncSession, Depends(get_session)]
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(the_app: FastAPI):
|
async def lifespan(the_app: FastAPI) -> AsyncGenerator[None, None]:
|
||||||
"""Upon start, initialise an AsyncClient and assign it to an attribute named requests_client on the app object."""
|
"""Upon start, initialise an AsyncClient and assign it to an attribute named requests_client on the app object."""
|
||||||
the_app.requests_client = httpx.AsyncClient()
|
async with httpx.AsyncClient() as requests_client:
|
||||||
|
the_app.state.requests_client = requests_client
|
||||||
yield
|
yield
|
||||||
await the_app.requests_client.aclose()
|
await the_app.state.requests_client.aclose()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_requests_client(request: Request) -> httpx.AsyncClient:
|
||||||
|
"""Get the httpx client from the application object."""
|
||||||
|
return cast(httpx.AsyncClient, request.app.state.requests_client)
|
||||||
|
|
||||||
|
|
||||||
|
# Shorter way of getting the httpx client in an endpoint
|
||||||
|
RequestsDep = Annotated[AsyncSession, Depends(get_requests_client)]
|
||||||
|
|
||||||
app = FastAPI(lifespan=lifespan)
|
app = FastAPI(lifespan=lifespan)
|
||||||
app.mount('/static', StaticFiles(directory=settings.static_dir), name='static')
|
app.mount('/static', StaticFiles(directory=settings.static_dir), name='static')
|
||||||
app.mount('/content/favicons', StaticFiles(directory=settings.favicons_dir), name='favicons')
|
app.mount('/content/favicons', StaticFiles(directory=settings.favicons_dir), name='favicons')
|
||||||
@@ -275,12 +285,24 @@ async def bookmarks_changed_since(
|
|||||||
)
|
)
|
||||||
latest_created_bookmark = result.first()
|
latest_created_bookmark = result.first()
|
||||||
|
|
||||||
latest_modification = max(latest_modified_bookmark.modified_date, latest_created_bookmark.created_date)
|
# There needs to be at least one bookmark of course
|
||||||
|
if latest_created_bookmark:
|
||||||
|
latest_created_datetime = latest_created_bookmark.created_date
|
||||||
|
else:
|
||||||
|
latest_created_datetime = datetime.min
|
||||||
|
|
||||||
|
# We only have a modified datetime when at least one has been edited
|
||||||
|
if latest_modified_bookmark:
|
||||||
|
latest_modified_datetime = latest_modified_bookmark.modified_date
|
||||||
|
else:
|
||||||
|
latest_modified_datetime = datetime.min
|
||||||
|
|
||||||
|
latest_modification = max(latest_modified_datetime, latest_created_datetime)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'current_time': datetime.now(UTC),
|
'current_time': datetime.now(UTC),
|
||||||
'latest_change': latest_modified_bookmark.modified_date,
|
'latest_change': latest_modified_datetime,
|
||||||
'latest_created': latest_created_bookmark.created_date,
|
'latest_created': latest_created_datetime,
|
||||||
'latest_modification': latest_modification,
|
'latest_modification': latest_modification,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ document.addEventListener('alpine:init', () => {
|
|||||||
this.cache[this.userKey]['tags'] = await tagsResponse.json();
|
this.cache[this.userKey]['tags'] = await tagsResponse.json();
|
||||||
|
|
||||||
/* Filter bookmarks by (blacklisted) tags */
|
/* Filter bookmarks by (blacklisted) tags */
|
||||||
await this.filterBookmarksByTags();
|
this.filterBookmarksByTags();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user