Rewrite using fastapi
This commit is contained in:
+101
@@ -0,0 +1,101 @@
|
||||
from math import ceil
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from typing import Any
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from recoll import recoll
|
||||
|
||||
from fastapi import BackgroundTasks
|
||||
|
||||
# from .config import settings
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
DOC_FOLDER = "/mnt/docs"
|
||||
|
||||
STRIP_CHARS = len(DOC_FOLDER) + len("file:///")
|
||||
|
||||
|
||||
class Recoll(object):
|
||||
def __init__(self):
|
||||
self._indexing = False
|
||||
|
||||
def reindex(self):
|
||||
if self._indexing:
|
||||
raise RuntimeError("Reindex already underway")
|
||||
self._indexing = True
|
||||
subprocess.call(["recollindex"])
|
||||
self._indexing = False
|
||||
|
||||
|
||||
repo = Recoll()
|
||||
|
||||
app = FastAPI()
|
||||
app.mount("/static", StaticFiles(directory="app/static"))
|
||||
app.mount("/docs", StaticFiles(directory=DOC_FOLDER))
|
||||
app.mount(
|
||||
"/icons",
|
||||
StaticFiles(directory="/usr/share/icons/breeze/mimetypes/32", follow_symlink=True),
|
||||
)
|
||||
|
||||
templates = Jinja2Templates(directory="app/templates")
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def home(request: Request):
|
||||
ctx = {"request": request}
|
||||
return templates.TemplateResponse("home.html", context=ctx)
|
||||
|
||||
|
||||
@app.get("/search")
|
||||
def search_results(request: Request, q: str, count: int = 20, page: int = 1):
|
||||
ctx: dict[str, Any] = {"request": request}
|
||||
ctx["search"] = search(q, count, page)
|
||||
return templates.TemplateResponse("search_results.html", context=ctx)
|
||||
|
||||
|
||||
@app.get("/api/reindex")
|
||||
async def get_reindex(tasks: BackgroundTasks) -> dict[str, str]:
|
||||
tasks.add_task(repo.reindex)
|
||||
return {"message": "Recoll index started"}
|
||||
|
||||
|
||||
@app.get("/api/search")
|
||||
def get_search(q: str, count: int = 20, page: int = 1) -> dict[str, str]:
|
||||
return search(q, count, page)
|
||||
|
||||
|
||||
def search(q: str, count: int, page: int):
|
||||
db = recoll.connect()
|
||||
query = db.query()
|
||||
nres = query.execute(q)
|
||||
result = {
|
||||
"query": q,
|
||||
"count": count,
|
||||
"page": page,
|
||||
"pages": ceil(nres / count),
|
||||
"total": nres,
|
||||
"xquery": query.getxquery(),
|
||||
"results": [],
|
||||
}
|
||||
if page > result["pages"] or page < 1:
|
||||
return result
|
||||
|
||||
query.scroll((page - 1) * count)
|
||||
docs = query.fetchmany(count)
|
||||
for doc in docs:
|
||||
d = dict(doc)
|
||||
d["snippets"] = query.getsnippets(doc, ctxwords=20)
|
||||
d["fpath"] = d["url"][STRIP_CHARS:]
|
||||
result["results"].append(d)
|
||||
return result
|
||||
|
||||
|
||||
@app.get("/api/info")
|
||||
def get_info():
|
||||
db = recoll.connect()
|
||||
return dir(db)
|
||||
@@ -0,0 +1,12 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
from os.path import abspath
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = "Squirrel"
|
||||
items_per_user: int = 50
|
||||
archive: str = "./archive"
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
settings.archive = abspath(settings.archive)
|
||||
@@ -0,0 +1,9 @@
|
||||
import uvicorn
|
||||
|
||||
|
||||
def daemon(reload=False):
|
||||
uvicorn.run("squirrel.api:app", host="0.0.0.0", port=8000, reload=reload)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
daemon(True)
|
||||
Reference in New Issue
Block a user