This commit is contained in:
lda committed 2025-12-29 15:03:03 +07:00
1 parent 58d3e58759
commit c09e018bc5
4 files changed
+50 -44

No files matched your search

+41 -6
View File
@@ -4,11 +4,12 @@ import string
from collections import deque
from itertools import islice
from random import choice
from typing import Iterator, Optional, cast
from typing import AsyncIterator, Iterator, Optional, TypedDict, cast
from urllib.parse import urlsplit, urlunsplit
import fastapi
import urlextract
from fastapi import FastAPI, Form, HTTPException, Request
from fastapi import Body, FastAPI, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
@@ -131,8 +132,12 @@ async def manage_view(request: Request):
)
class _queueCount(TypedDict):
count: int
@app.post("/api/queue/dedup")
async def api_queue_dedup():
async def api_queue_dedup() -> _queueCount:
"""Deduplicate the queue."""
global queue
# Preserve order while removing duplicates
@@ -147,7 +152,7 @@ async def api_queue_dedup():
@app.post("/api/queue/sort")
async def api_queue_sort(reverse: bool = False):
async def api_queue_sort(reverse: bool = False) -> _queueCount:
"""Sort the queue."""
global queue
queue = deque(sorted(queue, reverse=reverse))
@@ -156,15 +161,39 @@ async def api_queue_sort(reverse: bool = False):
# --- Routes: Queue (API) ---
@app.get("/api/queue")
async def api_queue_list(n: int | None = None, s: int | None = None):
async def api_queue_list(n: int | None = None, s: int | None = None) -> list[str]:
return list(islice(queue, s, n))
@app.get("/api/queue/len")
async def api_queue_len():
async def api_queue_len() -> int:
return len(queue)
@app.post("/api/queue")
async def api_queue_push(uhh: list[str] = Body(default_factory=list)) -> _queueCount:
queue.extend(map(link_extract_from_onetab, uhh))
return {"count": len(queue)}
@app.delete("/api/queue")
async def api_queue_pop(n: int = 1) -> list[str]:
def c() -> Iterator[str]:
for _ in range(n):
if not queue:
break
yield queue.popleft()
return list(c())
@app.get("/api/queue/first")
async def api_queue_first() -> str:
if not queue:
raise HTTPException(fastapi.status.HTTP_404_NOT_FOUND)
return queue[0]
@app.post("/api/queue/clear")
async def api_queue_clear():
queue.clear()
@@ -248,6 +277,12 @@ async def api_extract_jumblang(request: ExtractRequest):
return list(extract_urls_from_jumblang(request.text))
@app.post("/api/extract/plaintext")
async def api_extract_plaintext(text: str = Body(..., media_type="text/plain")):
"""Extract URLs from messy text using urlextract."""
return list(extract_urls_from_jumblang(text))
def encode_safe(link: str) -> str:
return base64.urlsafe_b64encode(link.encode()).rstrip(b"=").decode()
+3 -3
View File
@@ -149,10 +149,10 @@ body_class %}layout-wide{% endblock %}{% block content %}
if (mode === "jumblang") {
try {
const response = await fetch("/api/extract/jumblang", {
const response = await fetch("/api/extract/plaintext", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: content }),
headers: { "Content-Type": "text/plain" },
body: content,
});
if (!response.ok) throw new Error("Extraction failed");
links = await response.json();
+6 -4
View File
@@ -64,12 +64,15 @@ import qrcode_queue %}
}
function filterQueue() {
/** @type {HTMLInputElement} */
const input = document.getElementById("search-input");
const filter = input.value.toLowerCase();
/** @type {NodeListOf<HTMLLIElement>} */
const listItems = document.querySelectorAll(".queue-grid li");
let visibleCount = 0;
listItems.forEach((li) => {
/** @type {HTMLAnchorElement} */
const link = li.querySelector("a");
const text = link.textContent || link.innerText;
if (text.toLowerCase().indexOf(filter) > -1) {
@@ -79,10 +82,9 @@ import qrcode_queue %}
li.style.display = "none";
}
});
document.getElementById(
"count-display"
).textContent = `Showing: ${visibleCount} / ${listItems.length}`;
/** @type {HTMLParagraphElement} */
const countDisplay = document.getElementById("count-display");
countDisplay.textContent = `Showing: ${visibleCount} / ${listItems.length}`;
}
</script>
{% endblock %}
-31
View File
@@ -45,37 +45,6 @@
});
// Trigger the message event to run the swap on the next tick
newTab.postMessage("");
// background. This block is racing with the slow internet.
if (newTab.document.body) {
newTab.document.body.style.backgroundColor =
getComputedStyle(document.body).backgroundColor;
document
.querySelectorAll("body > *:not(script)")
.forEach((f) =>
newTab.document.body.appendChild(
f.cloneNode(true)
)
);
// maybe just replace the whole document with this one and then use API to check length
// i aint doing that
const st = new newTab.CSSStyleSheet();
[
...document.styleSheets,
...document.adoptedStyleSheets,
].forEach((i) =>
Array.from(i.cssRules).forEach((ii) =>
st.insertRule(
ii.cssText,
st.cssRules.length
)
)
);
newTab.document.adoptedStyleSheets.push(st);
newTab.document.close();
}
}
});
});