dev #9

Merged
WorldTeacher merged 3 commits from dev into main 2025-05-05 07:06:56 +01:00
3 changed files with 74 additions and 17 deletions
Showing only changes of commit a7a167a3b2 - Show all commits

View File

@@ -5,6 +5,7 @@ from anilistapi.schemas.manga import Manga
from komconfig import KomConfig
from komcache import KomCache
from komgapi import komgapi as KOMGAPI
from typing import Any, Dict, List
app = Quart(__name__)
@@ -12,6 +13,9 @@ cache = KomCache()
cache.create_table(
"CREATE TABLE IF NOT EXISTS manga_requests (id INTEGER PRIMARY KEY, manga_id INTEGER, grabbed BOOLEAN DEFAULT 0)"
)
cache.create_table(
"CREATE TABLE IF NOT EXISTS manga_titles (id INTEGER PRIMARY KEY, anilist_id INTEGER DEFAULT 0, komga_title UNIQUE)"
)
settings = KomConfig()
@@ -20,13 +24,31 @@ komga = KOMGAPI(
username=settings.komga.user,
password=settings.komga.password,
)
komga_books = komga.bookList()
komga_series = komga.seriesList()
# store the entries in the database table manga_titles, komga_series is a list of strings of the series names
for series in komga_series:
# check if the series is already in the database
existing_series = cache.fetch_one(
query="SELECT komga_title FROM manga_titles WHERE komga_title = ?",
args=(series,),
)
if existing_series:
# series already exists, skip
continue
else:
cache.insert(
# insert into if not in database
query="INSERT OR IGNORE INTO manga_titles (komga_title) VALUES (?)",
args=(series,),
)
komga_series = [series.lower() for series in komga_series]
async def fetch_data(data):
# Update type annotations for fetch_data
async def fetch_data(data: Dict[str, Any]) -> List[Dict[str, Any]]:
async with httpx.AsyncClient() as client:
try:
variables = {"search": data["query"]}
variables: Dict[str, Any] = {"search": data["query"]}
if len(data["genres"]) > 0:
variables["genres"] = data["genres"]
if len(data["tags"]) > 0:
@@ -42,10 +64,13 @@ async def fetch_data(data):
response.raise_for_status()
data = response.json()
results = []
results: List[Dict[str, Any]] = []
for item in data.get("data", {}).get("Page", {}).get("media", []):
manga = Manga(**item)
in_komga = komga.getSeries(
manga.title.english if manga.title.english else manga.title.romaji
)
print(in_komga, manga.title.english)
results.append(
{
"id": manga.id,
@@ -63,6 +88,7 @@ async def fetch_data(data):
if manga.description
else "No description available",
"isAdult": manga.isAdult,
"in_komga": in_komga,
}
)
@@ -122,13 +148,13 @@ async def search():
@app.route("/", methods=["GET"])
async def index():
return await render_template("index.html")
return await render_template("index.html", komga_series=komga_series)
@app.route("/request", methods=["POST"])
async def log_request():
data = await request.get_json()
item = data.get("item")
item = data.get("title")
if item:
asynccache = KomCache()
manga_title = data.get("title")

View File

@@ -153,4 +153,13 @@ body.nsfw-disabled .image-container.nsfw:hover img {
.request {
/* Implement design here */
}
.card.komga {
border: 3px solid green;
box-sizing: border-box;
/* disable the request button for entries in Komga */
pointer-events: none;
opacity: 0.5;
}

View File

@@ -14,17 +14,17 @@
<input type="text" id="searchInput" placeholder="Search..." />
<div class="selectors">
<div class="autocomplete">
<input type="text" id="genreInput" placeholder="Select genres..." oninput="filterSuggestions('genre')"
onclick="showDropdown('genre')">
<button onclick="resetGenres()" , class="reset">Reset</button>
<input type="text" id="genreInput" placeholder="Select genres..." readonly
oninput="filterSuggestions('genre')" onclick="showDropdown('genre')">
<button onclick="resetGenres()" class="reset">Reset</button>
<div class="dropdown-content" id="genreDropdown">
<!-- Genre suggestions will be dynamically populated here -->
</div>
</div>
<div class="autocomplete">
<input type="text" id="tagInput" placeholder="Select tags..." oninput="filterSuggestions('tag')"
onclick="showDropdown('tag')">
<input type="text" id="tagInput" placeholder="Select tags..." readonly
oninput="filterSuggestions('tag')" onclick="showDropdown('tag')">
<button onclick="resetTags()" class="reset">Reset</button>
<div class="dropdown-content" id="tagDropdown">
<!-- Tag suggestions will be dynamically populated here -->
@@ -44,7 +44,8 @@
<div class="results">
{% for result in results %}
<div class="card">
<div class="card {% if result.in_komga %}komga{% endif %}">
<div class="image-container {{ 'nsfw' if result.isAdult else '' }}">
<img src="{{ result.image }}" alt="Cover">
@@ -56,7 +57,10 @@
<p>{{ result.title }}</p>
<div class="actions">
<button onclick="showInfo({{ result | tojson | safe }})" , class="info">Info</button>
<button onclick="sendRequest({{ result.id | tojson }})" , class="request">Request</button>
<!-- if entry has in_komga == true, do not show the request button, else show it -->
{% if not result.in_komga %}
<button onclick="sendRequest('{{ result.id }}')" class="request">Request</button>
{% endif %}
</div>
</div>
{% endfor %}
@@ -129,6 +133,8 @@
fetchOptions("/api/tags", "tag");
});
async function fetchOptions(url, dropdownId) {
try {
const res = await fetch(url);
@@ -151,10 +157,15 @@
const input = document.getElementById(inputId + 'Input');
const currentValues = input.value.split(',').map(v => v.trim()).filter(v => v);
// Add the selected value if it's not already in the list
if (!currentValues.includes(value)) {
currentValues.push(value);
input.value = currentValues.join(', ');
}
// Hide the dropdown after selection
const dropdown = document.getElementById(inputId + 'Dropdown');
dropdown.classList.remove('show');
}
function filterSuggestions(inputId) {
@@ -172,6 +183,13 @@
});
dropdown.classList.toggle('show', hasVisibleItems);
// Reset visibility of all items if input is cleared
if (!filter) {
Array.from(items).forEach(item => {
item.style.display = '';
});
}
}
function showDropdown(inputId) {
@@ -188,11 +206,15 @@
});
function resetGenres() {
document.getElementById('genreInput').value = '';
const input = document.getElementById('genreInput');
input.value = '';
filterSuggestions('genre'); // Reset dropdown to show all
}
function resetTags() {
document.getElementById('tagInput').value = '';
const input = document.getElementById('tagInput');
input.value = '';
filterSuggestions('tag'); // Reset dropdown to show all
}
function performSearch() {
@@ -222,7 +244,7 @@
data.forEach(result => {
const card = document.createElement('div');
card.className = 'card';
card.className = `card ${result.in_komga ? 'komga' : ''}`;
const imageContainer = document.createElement('div');
imageContainer.className = `image-container ${result.isAdult ? 'nsfw' : ''}`;