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, username=settings.komga.user,
password=settings.komga.password, password=settings.komga.password,
) )
cat = Nyaa()
# komga_series = komga.seriesList() # komga_series = komga.seriesList()
@limit(limit=1, every=2) @limit(limit=1, every=2)
async def fetch_data( async def fetch_data(
inputdata: Dict[str, Any], check_downloads: bool = False inputdata: Dict[str, Any], check_downloads: int = 0
) -> List[Dict[str, Any]]: ) -> List[Dict[str, Any]]:
log.error(f"fetch_data called with data: {inputdata}") log.error(f"fetch_data called with data: {inputdata}")
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
@@ -92,36 +93,41 @@ async def fetch_data(
args={"id": manga.id}, args={"id": manga.id},
) )
komga_request = bool(requested) komga_request = bool(requested)
results.append(
{ result_data: dict[str, Any] = {
"id": manga.id, "id": manga.id,
"title": manga.title.english "title": manga.title.english
if manga.title.english if manga.title.english
else manga.title.romaji, else manga.title.romaji,
"image": manga.coverImage.get("large") "image": manga.coverImage.get("large")
if manga.coverImage if manga.coverImage
else "https://demofree.sirv.com/nope-not-here.jpg", else "https://demofree.sirv.com/nope-not-here.jpg",
"status": manga.status, "status": manga.status,
"type": manga.format, "type": manga.format,
"genres": manga.genres or [], "genres": manga.genres or [],
"tags": [tag.name for tag in (manga.tags or [])], "tags": [tag.name for tag in (manga.tags or [])],
"description": manga.description.replace("<br>", "\n") "description": manga.description.replace("<br>", "\n")
if manga.description if manga.description
else "No description available", else "No description available",
"isAdult": manga.isAdult, "isAdult": manga.isAdult,
"in_komga": in_komga, "in_komga": in_komga,
"requested": komga_request, "requested": komga_request,
"siteUrl": manga.siteUrl, "siteUrl": manga.siteUrl,
} }
)
if check_downloads: results.append(result_data)
for result in results: # async check for available downloads
downloads = Nyaa().search(result.get("title"), 3, 1)
else:
downloads = []
result["download"] = len(downloads) if downloads else 0
log.debug(f"Fetched {len(results)} results for query: {inputdata['query']}") 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}") log.error(f"Results: {results}")
return results return results
except ValueError as ve: except ValueError as ve:
@@ -247,7 +253,10 @@ async def get_tags():
async def search(): async def search():
data = await request.get_json() data = await request.get_json()
print(data) 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: if not results:
return jsonify({"error": "No results found"}), 404 return jsonify({"error": "No results found"}), 404
return jsonify(results) return jsonify(results)
@@ -358,9 +367,23 @@ async def delete_request():
return jsonify({"status": "failed"}), 400 return jsonify({"status": "failed"}), 400
if __name__ == "__main__": if __name__ == "__main__":
log.info("Starting Komga Manga Grabber API") import sys
# use hypercorn to run the app
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5001) log.info("Starting Komga Manga Grabber API")
# run in test mode 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 /> <input type="checkbox" id="toggleNovels" checked />
Show Novels Show Novels
</label> </label>
<label style="margin-left: 1em;">
<input type="checkbox" id="checkAvailability" />
Check Availability
</label>
</div> </div>
@@ -271,13 +275,14 @@
const selectedGenres = document.getElementById("genreInput").value.split(',').map(v => v.trim()).filter(v => v); 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 selectedTags = document.getElementById("tagInput").value.split(',').map(v => v.trim()).filter(v => v);
const selectedType = document.getElementById("typeSelect").value; const selectedType = document.getElementById("typeSelect").value;
const checkDownloads = document.getElementById("checkAvailability").checked; // Get the checkbox value
const query = { const query = {
query: searchTerm, query: searchTerm,
genres: selectedGenres, genres: selectedGenres,
tags: selectedTags, 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"); const loadingElement = document.getElementById("loading");
@@ -324,6 +329,24 @@
imageContainer.appendChild(badge); 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'); const title = document.createElement('p');
title.textContent = result.title || 'Untitled'; title.textContent = result.title || 'Untitled';