feat: add availability check

This commit is contained in:
2025-06-29 14:59:04 +02:00
parent 31196f6c5d
commit ac0461f815
2 changed files with 83 additions and 37 deletions

View File

@@ -35,12 +35,13 @@ komga = KOMGAPI(
username=settings.komga.user,
password=settings.komga.password,
)
cat = Nyaa()
# komga_series = komga.seriesList()
@limit(limit=1, every=2)
async def fetch_data(
inputdata: Dict[str, Any], check_downloads: bool = False
inputdata: Dict[str, Any], check_downloads: int = 0
) -> List[Dict[str, Any]]:
log.error(f"fetch_data called with data: {inputdata}")
async with httpx.AsyncClient() as client:
@@ -92,36 +93,41 @@ async def fetch_data(
args={"id": manga.id},
)
komga_request = bool(requested)
results.append(
{
"id": manga.id,
"title": manga.title.english
if manga.title.english
else manga.title.romaji,
"image": manga.coverImage.get("large")
if manga.coverImage
else "https://demofree.sirv.com/nope-not-here.jpg",
"status": manga.status,
"type": manga.format,
"genres": manga.genres or [],
"tags": [tag.name for tag in (manga.tags or [])],
"description": manga.description.replace("<br>", "\n")
if manga.description
else "No description available",
"isAdult": manga.isAdult,
"in_komga": in_komga,
"requested": komga_request,
"siteUrl": manga.siteUrl,
}
)
if check_downloads:
for result in results:
downloads = Nyaa().search(result.get("title"), 3, 1)
else:
downloads = []
result["download"] = len(downloads) if downloads else 0
result_data: dict[str, Any] = {
"id": manga.id,
"title": manga.title.english
if manga.title.english
else manga.title.romaji,
"image": manga.coverImage.get("large")
if manga.coverImage
else "https://demofree.sirv.com/nope-not-here.jpg",
"status": manga.status,
"type": manga.format,
"genres": manga.genres or [],
"tags": [tag.name for tag in (manga.tags or [])],
"description": manga.description.replace("<br>", "\n")
if manga.description
else "No description available",
"isAdult": manga.isAdult,
"in_komga": in_komga,
"requested": komga_request,
"siteUrl": manga.siteUrl,
}
results.append(result_data)
# async check for available downloads
log.debug(f"Fetched {len(results)} results for query: {inputdata['query']}")
if check_downloads == 1:
for manga in results:
log.debug(f"Checking downloads for manga: {manga['title']}")
search_query = manga["title"]
search_results = cat.search(search_query, 3, 1)
manga["downloads"] = (
len(search_results) if isinstance(search_results, list) else 0
)
log.debug(f"Downloads for {manga['title']}: {manga['downloads']}")
log.error(f"Results: {results}")
return results
except ValueError as ve:
@@ -247,7 +253,10 @@ async def get_tags():
async def search():
data = await request.get_json()
print(data)
results = await fetch_data(data)
# in data replace bool value for check_downloads with 1 or 0
if "check_downloads" in data:
data["check_downloads"] = 1 if data["check_downloads"] is True else 0
results = await fetch_data(data, check_downloads=data.get("check_downloads", 0))
if not results:
return jsonify({"error": "No results found"}), 404
return jsonify(results)
@@ -358,9 +367,23 @@ async def delete_request():
return jsonify({"status": "failed"}), 400
if __name__ == "__main__":
log.info("Starting Komga Manga Grabber API")
# use hypercorn to run the app
import uvicorn
import sys
uvicorn.run(app, host="0.0.0.0", port=5001)
# run in test mode
log.info("Starting Komga Manga Grabber API")
if len(sys.argv) > 1:
if sys.argv[1] == "test":
log.info("Running in test mode")
# run in test mode
app.run(debug=True, host="0.0.0.0", port=5001)
elif sys.argv[1] == "prod":
log.info("Running in production mode")
# run in production mode
log.info("Starting Komga Manga Grabber API")
# use hypercorn to run the app
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5001)
# run in test mode
else:
log.info("No arguments provided, running in default mode")
app.run(debug=True, host="0.0.0.0", port=5000)

View File

@@ -52,6 +52,10 @@
<input type="checkbox" id="toggleNovels" checked />
Show Novels
</label>
<label style="margin-left: 1em;">
<input type="checkbox" id="checkAvailability" />
Check Availability
</label>
</div>
@@ -271,13 +275,14 @@
const selectedGenres = document.getElementById("genreInput").value.split(',').map(v => v.trim()).filter(v => v);
const selectedTags = document.getElementById("tagInput").value.split(',').map(v => v.trim()).filter(v => v);
const selectedType = document.getElementById("typeSelect").value;
const checkDownloads = document.getElementById("checkAvailability").checked; // Get the checkbox value
const query = {
query: searchTerm,
genres: selectedGenres,
tags: selectedTags,
type: selectedType // Include the selected type in the query
type: selectedType,
check_downloads: checkDownloads // Pass the checkbox value
};
const loadingElement = document.getElementById("loading");
@@ -324,6 +329,24 @@
imageContainer.appendChild(badge);
}
// Add download badge if applicable
if (result.downloads && document.getElementById("checkAvailability").checked) {
const downloadBadge = document.createElement('div');
downloadBadge.className = 'download-badge';
downloadBadge.textContent = `${result.downloads} Downloads`;
downloadBadge.style.position = 'absolute';
downloadBadge.style.top = '8px';
downloadBadge.style.right = '8px';
downloadBadge.style.backgroundColor = 'rgba(0, 0, 255, 0.8)';
downloadBadge.style.color = 'white';
downloadBadge.style.padding = '4px 8px';
downloadBadge.style.fontSize = '12px';
downloadBadge.style.fontWeight = 'bold';
downloadBadge.style.borderRadius = '4px';
downloadBadge.style.zIndex = '1';
imageContainer.appendChild(downloadBadge);
}
const title = document.createElement('p');
title.textContent = result.title || 'Untitled';