Compare commits
6
Commits
No files matched your search
@@ -1,6 +1,4 @@
|
||||
def main():
|
||||
print("Hello from qrcode-from-onetab!")
|
||||
|
||||
import uvicorn
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
uvicorn.run("uhhhhup:app", host="0.0.0.0", port=2222, reload=True)
|
||||
@@ -0,0 +1,258 @@
|
||||
:root {
|
||||
--bg-color: #121212;
|
||||
--text-color: #e0e0e0;
|
||||
--primary-color: #bb86fc;
|
||||
--secondary-color: #03dac6;
|
||||
--error-color: #cf6679;
|
||||
--surface-color: #1e1e1e;
|
||||
--border-radius: 8px;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: 100dvh;
|
||||
box-sizing: border-box; /* Ensure padding is included in width/height */
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type="submit"],
|
||||
.btn {
|
||||
background-color: var(--surface-color);
|
||||
color: var(--primary-color);
|
||||
border: 1px solid var(--primary-color);
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--border-radius);
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
margin: 5px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
.btn:hover {
|
||||
background-color: var(--primary-color);
|
||||
color: var(--bg-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: var(--surface-color);
|
||||
color: var(--text-color);
|
||||
border: 1px solid #333;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
font-family: monospace;
|
||||
min-width: 20%;
|
||||
min-height: 20dvh;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
li {
|
||||
background-color: var(--surface-color);
|
||||
margin-bottom: 10px;
|
||||
padding: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
word-break: break-all;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
li a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
margin-top: 10px;
|
||||
background-color: white;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
/* Specifics for reader */
|
||||
#b {
|
||||
font-size: 1.5rem;
|
||||
padding: 20px 40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* Specifics for index */
|
||||
.hero {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: var(--surface-color);
|
||||
padding: 30px;
|
||||
border-radius: var(--border-radius);
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border: 1px solid #333;
|
||||
/* max-height: 90dvh; Prevent card from exceeding viewport height */
|
||||
overflow-y: auto; /* Scroll if content is too tall */
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
color: var(--secondary-color);
|
||||
margin-top: 0;
|
||||
/* margin-bottom: 10px; Reduced margin */
|
||||
/* font-size: 1.2rem; Slightly smaller title */
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin-bottom: 15px; /* Reduced margin */
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.card .actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
details {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin-top: 20px;
|
||||
background-color: var(--surface-color);
|
||||
border-radius: var(--border-radius);
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
summary {
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
color: var(--secondary-color);
|
||||
list-style: none; /* Hide default triangle */
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
summary::after {
|
||||
content: '+';
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
details[open] summary::after {
|
||||
content: '-';
|
||||
}
|
||||
|
||||
details[open] summary {
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.route-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.route-item {
|
||||
background-color: var(--surface-color);
|
||||
padding: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/* Queue Grid */
|
||||
.queue-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.queue-grid li {
|
||||
flex: 1 1 300px; /* Grow, shrink, basis */
|
||||
max-width: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.queue-grid li a {
|
||||
align-items: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Trail Page */
|
||||
.trail-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80dvh;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.trail-count {
|
||||
font-size: 5rem;
|
||||
font-weight: bold;
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.trail-hint {
|
||||
color: #666;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
+42
-16
@@ -3,23 +3,49 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Queue Reader</title>
|
||||
<title>Document</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', path='style.css') }}"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
{% from 'macros.html' import magic_link %} {% if current_link %}
|
||||
<p>{{ magic_link(current_link, current_link, "a") }}</p>
|
||||
<button id="b">skip/fw</button>
|
||||
<script>
|
||||
document.getElementById("b").addEventListener("click", async () => {
|
||||
await fetch("/r", { method: "GET", redirect: "manual" });
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% else %}
|
||||
<p>no</p>
|
||||
<button onclick="location.reload();">reload</button>
|
||||
{% endif %}
|
||||
<h1>Queue Manager</h1>
|
||||
|
||||
<div class="hero">
|
||||
<div class="card">
|
||||
<h2>Input (PC)</h2>
|
||||
<p>
|
||||
Paste your OneTab export or list of links here to add them
|
||||
to the queue.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<a href="/queuein" class="btn">Add Links</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Output (Mobile)</h2>
|
||||
<p>Open these on your phone to consume the queue.</p>
|
||||
<div class="actions">
|
||||
<a href="/q" class="btn">Reader (QR)</a>
|
||||
<a href="/t" class="btn">Trail (Focus)</a>
|
||||
<a href="/r" class="btn">Next Link</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details >
|
||||
<summary>System Routes</summary>
|
||||
<div class="route-list">
|
||||
{% macro this(route) %}
|
||||
<div class="route-item">
|
||||
<a href="{{ url_for(route.name) }}">{{ route.name }}</a>
|
||||
<span>{{ route.path }}</span>
|
||||
</div>
|
||||
{% endmacro %} {% for route in routes if "GET" in route.methods %}
|
||||
{{ this(route) }} {% endfor %}
|
||||
</div>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
||||
@@ -24,7 +24,7 @@
|
||||
})();
|
||||
</script>
|
||||
{% endmacro %} {% macro qrcode_queue(queue_items) %} {% if queue_items %}
|
||||
<ol>
|
||||
<ol class="queue-grid">
|
||||
{% for item in queue_items %}
|
||||
<li>
|
||||
<a href="{{ item }}" target="_blank" rel="noreferrer noopener">
|
||||
@@ -33,14 +33,6 @@
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<style>
|
||||
/* it works ig */
|
||||
& {
|
||||
li:has(.qrcode) {
|
||||
width: min-content;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</ol>
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/qrcode.js"></script>
|
||||
<script>
|
||||
@@ -50,6 +42,8 @@
|
||||
new QRCode(e, {
|
||||
text: a,
|
||||
correctLevel: QRCode.CorrectLevel.L,
|
||||
width: 256,
|
||||
height: 256,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+13
-14
@@ -4,11 +4,6 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Queue dump type shit</title>
|
||||
<style>
|
||||
li {
|
||||
width: min-content;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -34,9 +29,9 @@
|
||||
<script>
|
||||
/** @type {HTMLDivElement} */
|
||||
const bij = document.getElementById("gonk");
|
||||
let arrlen = 0;
|
||||
/** @type {HTMLInputElement} */
|
||||
const n = document.getElementById("n");
|
||||
|
||||
const changeHandler = async () => {
|
||||
const number = parseInt(n.value);
|
||||
if (isNaN(number)) {
|
||||
@@ -46,12 +41,11 @@
|
||||
const f = new URL("/api/queue", window.location.href);
|
||||
f.searchParams.append("n", number);
|
||||
console.log("fetching", f);
|
||||
const c = await fetch(f)
|
||||
return await fetch(f)
|
||||
.then((r) => r.json())
|
||||
.then((n) => {
|
||||
console.log(n);
|
||||
arrlen = n.length;
|
||||
if (n) {
|
||||
if (n.length > 0) {
|
||||
const ol = document.createElement("ol");
|
||||
for (const i of n) {
|
||||
const li = document.createElement("li");
|
||||
@@ -64,7 +58,7 @@
|
||||
ol.appendChild(li);
|
||||
}
|
||||
bij.textContent = `next ${
|
||||
n.length != 1
|
||||
n.length > 1
|
||||
? `${n.length} entries are`
|
||||
: "entry is"
|
||||
} SO gone`;
|
||||
@@ -72,26 +66,31 @@
|
||||
} else {
|
||||
bij.textContent = "wym empty";
|
||||
}
|
||||
return n.length;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
arrlen = 0;
|
||||
bij.textContent = `shit. cant fetch`;
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
n.addEventListener("change", changeHandler);
|
||||
|
||||
/** @type {HTMLFormElement} */
|
||||
const c = document.getElementById("c");
|
||||
c.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
await changeHandler();
|
||||
});
|
||||
|
||||
changeHandler();
|
||||
|
||||
const s = document.getElementById("s");
|
||||
s.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
console.log("ts runs");
|
||||
changeHandler();
|
||||
const arrlen = changeHandler();
|
||||
for (const _ of Array(arrlen)) {
|
||||
const w = window.open(
|
||||
"/r",
|
||||
@@ -103,11 +102,12 @@
|
||||
arrlen = 0;
|
||||
bij.textContent = "something idk";
|
||||
});
|
||||
|
||||
/** @type {HTMLButtonElement} */
|
||||
const all = document.getElementById("all");
|
||||
all.addEventListener(
|
||||
"click",
|
||||
async () =>
|
||||
async (e) =>
|
||||
await fetch("/api/queue/len")
|
||||
.then((d) => d.json())
|
||||
.then((len) => {
|
||||
@@ -120,7 +120,6 @@
|
||||
);
|
||||
console.log(w);
|
||||
}
|
||||
arrlen = 0;
|
||||
bij.textContent = "everything idk";
|
||||
})
|
||||
.catch((e) => console.error(e))
|
||||
|
||||
+20
-18
@@ -4,32 +4,34 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Queue Input</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', path='style.css') }}"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; width: 100%; max-width: 800px; margin-bottom: 20px;">
|
||||
<h1 style="margin: 0;">Add Links</h1>
|
||||
<a href="/" class="btn" style="margin: 0;">← Home</a>
|
||||
</div>
|
||||
<form method="POST" action="/queuein">
|
||||
<label for="lines">in:</label>
|
||||
<textarea
|
||||
id="l"
|
||||
rows="20"
|
||||
cols="100"
|
||||
style="min-width: 20%; min-height: 20dvh"
|
||||
name="lines"
|
||||
></textarea>
|
||||
<textarea id="lines" rows="20" cols="100" name="lines"></textarea>
|
||||
<input type="submit" value="ahh" />
|
||||
</form>
|
||||
<script>
|
||||
// lifted from google search ai
|
||||
/**@type {HTMLTextAreaElement} */
|
||||
(
|
||||
// lifted from google search ai
|
||||
document.getElementById("l")
|
||||
).addEventListener("keydown", function (e) {
|
||||
// Check for Ctrl+Enter (Windows/Linux) or Command+Enter (Mac)
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
||||
e.preventDefault(); // Prevent the default newline character
|
||||
// Submit the form associated with this textarea
|
||||
this.form.submit();
|
||||
(document.getElementById("lines")).addEventListener(
|
||||
"keydown",
|
||||
function (e) {
|
||||
// Check for Ctrl+Enter (Windows/Linux) or Command+Enter (Mac)
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
||||
e.preventDefault(); // Prevent the default newline character
|
||||
// Submit the form associated with this textarea
|
||||
this.form.submit();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
</script>
|
||||
{% from "macros.html" import qrcode_queue %} {% if queue_items %}
|
||||
<p>total: {{ queue_items|length }}</p>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Queue Reader</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', path='style.css') }}"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
{% from 'macros.html' import magic_link %} {% if current_link %}
|
||||
<div class="card">
|
||||
<h2>Current Link</h2>
|
||||
<p>{{ magic_link(current_link, current_link, "a") }}</p>
|
||||
|
||||
<div class="qrcode" id="current-qr"></div>
|
||||
|
||||
<div class="actions" style="margin-top: 20px">
|
||||
<button id="b" class="btn">Skip / Next</button>
|
||||
</div>
|
||||
<p style="margin-top: 10px; font-size: 0.8rem; color: #666">
|
||||
{{ queue_length }} items remaining
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/qrcode.js"></script>
|
||||
<script>
|
||||
// QR Code generation
|
||||
new QRCode(document.getElementById("current-qr"), {
|
||||
text: "{{ current_link }}",
|
||||
correctLevel: QRCode.CorrectLevel.L,
|
||||
width: 256,
|
||||
height: 256,
|
||||
});
|
||||
|
||||
// Skip button logic
|
||||
document.getElementById("b").addEventListener("click", async () => {
|
||||
await fetch("/r", { redirect: "manual" });
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% else %}
|
||||
<div class="card">
|
||||
<h2>Queue Empty</h2>
|
||||
<p>No links in the queue. Go add some!</p>
|
||||
<div class="actions">
|
||||
<a href="/" class="btn">Home</a>
|
||||
<a href="/queuein" class="btn">Add Links</a>
|
||||
<a href="javascript:location.reload()" class="btn">Reload</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Trail</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', path='style.css') }}"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
{% if queue_length > 0 %}
|
||||
<div class="trail-container">
|
||||
<div class="trail-count">{{ queue_length }}</div>
|
||||
<p>Items Left</p>
|
||||
|
||||
<p
|
||||
style="
|
||||
max-width: 80%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
>
|
||||
Next:
|
||||
<a
|
||||
href="{{ current_link }}"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>{{ current_link }}</a
|
||||
>
|
||||
</p>
|
||||
|
||||
<div class="trail-hint">Tap anywhere to open & next</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
if (window.opener) {
|
||||
// new tab = window open no "noopener". this probs does exist
|
||||
console.log(/** @type {Window} */ (window.opener)); // hi hello hi
|
||||
}
|
||||
window.addEventListener("load", () => {
|
||||
document.body.addEventListener("click", async (e) => {
|
||||
if (e.target.tagName === "A") return;
|
||||
|
||||
// do trix
|
||||
await fetch("/r", { redirect: "manual" });
|
||||
|
||||
// now this is the new updated
|
||||
const newTab = window.open(window.location.href, "_blank");
|
||||
|
||||
// yo this is good no security error
|
||||
window.location.replace("{{ current_link }}");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% else %}
|
||||
<div class="card">
|
||||
<h2>All Done!</h2>
|
||||
<p>The queue is empty.</p>
|
||||
<div class="actions">
|
||||
<a href="/" class="btn">Home</a>
|
||||
<a href="/queuein" class="btn">Add More</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +1,5 @@
|
||||
"why outdated"
|
||||
|
||||
from collections import deque
|
||||
|
||||
import flask
|
||||
@@ -13,11 +15,11 @@ a = flask.Flask(__name__)
|
||||
queue: deque[str] = deque()
|
||||
|
||||
|
||||
@a.route("/")
|
||||
@a.route("/q")
|
||||
def no():
|
||||
"if i click the link then it proceed. if i reload it doesnt."
|
||||
current_link = queue[0] if queue else None
|
||||
return flask.render_template("index.html", current_link=current_link)
|
||||
return flask.render_template("reader.html", current_link=current_link)
|
||||
|
||||
|
||||
@a.route("/r")
|
||||
@@ -26,7 +28,7 @@ def redir():
|
||||
if queue:
|
||||
q = queue.popleft()
|
||||
return flask.redirect(q)
|
||||
return flask.render_template("index.html", current_link=None)
|
||||
return flask.render_template("reader.html", current_link=None)
|
||||
|
||||
|
||||
@a.route("/queuein", methods=["GET", "POST"])
|
||||
|
||||
+32
-8
@@ -6,11 +6,13 @@ from itertools import islice
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, Form, Request
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
app = FastAPI()
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
queue: deque[str] = deque() # lifo ahh
|
||||
queue: deque[str] = deque() # fifo ahh
|
||||
|
||||
|
||||
def link_extract_from_onetab(line):
|
||||
@@ -20,10 +22,28 @@ def link_extract_from_onetab(line):
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def index(request: Request):
|
||||
"idgaf"
|
||||
return templates.TemplateResponse(request, "index.html", {"routes": app.routes})
|
||||
|
||||
|
||||
@app.get("/q", response_class=HTMLResponse)
|
||||
async def no(request: Request):
|
||||
current_link = queue[0] if queue else None
|
||||
return templates.TemplateResponse(
|
||||
request, "index.html", {"current_link": current_link}
|
||||
request,
|
||||
"reader.html",
|
||||
{"current_link": current_link, "queue_length": len(queue)},
|
||||
)
|
||||
|
||||
|
||||
@app.get("/t", response_class=HTMLResponse)
|
||||
async def trail(request: Request):
|
||||
current_link = queue[0] if queue else None
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"trail.html",
|
||||
{"current_link": current_link, "queue_length": len(queue)},
|
||||
)
|
||||
|
||||
|
||||
@@ -32,22 +52,26 @@ async def redir(request: Request):
|
||||
if queue:
|
||||
q = queue.popleft()
|
||||
return RedirectResponse(url=q)
|
||||
return templates.TemplateResponse(request, "index.html", {"current_link": None})
|
||||
return templates.TemplateResponse(
|
||||
request, "reader.html", {"current_link": None, "queue_length": len(queue)}
|
||||
)
|
||||
|
||||
|
||||
@app.get("/m", response_class=HTMLResponse)
|
||||
async def mlti(request: Request):
|
||||
"request first new style"
|
||||
"""request first new style.
|
||||
js still breaking (on mobile. they dont like mass popups) im so sad
|
||||
"""
|
||||
return templates.TemplateResponse(request, "multi.html")
|
||||
|
||||
|
||||
@app.get("/api/queue")
|
||||
async def queueview(n: int | None = None, s: int | None = None):
|
||||
async def queue_view(n: int | None = None, s: int | None = None):
|
||||
return list(islice(queue, s, n))
|
||||
|
||||
|
||||
@app.get("/api/queue/len")
|
||||
async def queuelen():
|
||||
async def queue_len():
|
||||
return len(queue)
|
||||
|
||||
|
||||
@@ -57,14 +81,14 @@ async def qrcodequeue(request: Request):
|
||||
|
||||
|
||||
@app.get("/queuein", response_class=HTMLResponse)
|
||||
async def cuh_get(request: Request):
|
||||
async def queue_in(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
request, "queue.html", {"queue_items": list(queue)}
|
||||
)
|
||||
|
||||
|
||||
@app.post("/queuein")
|
||||
async def cuh_post(lines: str = Form("")):
|
||||
async def send_queue(lines: str = Form("")):
|
||||
"""var name == form ele name (name="lines")"""
|
||||
queue.extend(
|
||||
link_extract_from_onetab(line) for line in lines.splitlines() if line.strip()
|
||||
|
||||
Reference in new issue
Block a user