-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
199 lines (177 loc) · 9.88 KB
/
Copy pathmain.py
File metadata and controls
199 lines (177 loc) · 9.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
from fastapi import FastAPI, Query, Path, HTTPException
from scraper.api import NyaaSiApi
from scraper.exceptions import NoSuchTorrentException
from scraper.models import (
SearchRequest, Sort, Ordering,
NyaaCategory, SukebeiCategory, Category
)
app = FastAPI(title="Nyaa-API", description="(Unofficial) Nyaa API built with Python", version="1.0.0")
nyaa_api = NyaaSiApi.get_nyaa()
sukebei_api = NyaaSiApi.get_sukebei()
# -------------------------------------------------------------
# Category Mapping
# -------------------------------------------------------------
def map_category(cat_str: str, sub_cat_str: str, is_sukebei: bool) -> Category:
if not cat_str:
return None
base = SukebeiCategory if is_sukebei else NyaaCategory
# Simple mapping for Sukebei
if is_sukebei:
mappings = {
"art": SukebeiCategory.ART,
"real": SukebeiCategory.REAL_LIFE,
"real_life": SukebeiCategory.REAL_LIFE
}
main = mappings.get(cat_str.lower())
if not main:
return None
if not sub_cat_str:
return main
sub_mappings = {
"anime": main.ANIME if hasattr(main, "ANIME") else None,
"doujinshi": main.DOUJINSHI if hasattr(main, "DOUJINSHI") else None,
"games": main.GAMES if hasattr(main, "GAMES") else None,
"manga": main.MANGA if hasattr(main, "MANGA") else None,
"pictures": main.PICTURES if hasattr(main, "PICTURES") else None,
"photobooks": main.PHOTOBOOKS if hasattr(main, "PHOTOBOOKS") else None,
"videos": main.VIDEOS if hasattr(main, "VIDEOS") else None
}
return sub_mappings.get(sub_cat_str.lower()) or main
else:
# Nyaa mappings
mappings = {
"anime": NyaaCategory.ANIME,
"audio": NyaaCategory.AUDIO,
"literature": NyaaCategory.LITERATURE,
"live_action": NyaaCategory.LIVE_ACTION,
"pictures": NyaaCategory.PICTURES,
"software": NyaaCategory.SOFTWARE
}
main = mappings.get(cat_str.lower())
if not main:
return None
if not sub_cat_str:
return main
# Common subcategories
s = sub_cat_str.lower()
if s == "raw": return main.RAW if hasattr(main, "RAW") else main
if s == "english": return main.ENGLISH if hasattr(main, "ENGLISH") else main
if s == "non-english": return main.NON_ENGLISH if hasattr(main, "NON_ENGLISH") else main
if s == "lossless": return main.LOSSLESS if hasattr(main, "LOSSLESS") else main
if s == "lossy": return main.LOSSY if hasattr(main, "LOSSY") else main
return main
# -------------------------------------------------------------
# Helpers to build request
# -------------------------------------------------------------
def build_request(q: str = None, user_name: str = None, category: str = None, sub_category: str = None,
sort: str = None, order: str = None, page: int = 1, is_sukebei: bool = False) -> SearchRequest:
req = SearchRequest()
if q:
req.set_term(q)
if user_name:
req.set_user(user_name)
if page:
req.set_page(page)
cat_obj = map_category(category, sub_category, is_sukebei)
if cat_obj:
req.set_category(cat_obj)
if sort:
sort_map = {
"comments": Sort.COMMENTS,
"size": Sort.SIZE,
"id": Sort.DATE,
"date": Sort.DATE,
"seeders": Sort.SEEDERS,
"leechers": Sort.LEECHERS,
"downloads": Sort.DOWNLOADS
}
if sort.lower() in sort_map:
req.set_sorted_by(sort_map[sort.lower()])
if order:
if order.lower() == "desc":
req.set_ordering(Ordering.DESCENDING)
elif order.lower() == "asc":
req.set_ordering(Ordering.ASCENDING)
return req
# -------------------------------------------------------------
# Endpoints
# -------------------------------------------------------------
@app.get("/", tags=["Home"], summary="Home", description="Home Route: Returns app details and health status.")
def home__get():
return {
"message": "Welcome to the (Unofficial) Nyaa API",
"version": "1.0.0",
"docs": "/docs",
"license": "GPL-3.0 License",
"github": "https://github.com/khw315/NyaaSi-API-Python"
}
@app.get("/nyaa", tags=["Search"], summary="Nyaa Category Search", operation_id="nyaa_category_search_nyaa_get")
def search_nyaa(
q: str = Query(None, description="The search query for torrents.", examples=["sword art online"]),
category: str = Query(None, description="Filter torrents by category (e.g., anime, audio, literature, pictures, software).", examples=["anime"]),
sub_category: str = Query(None, description="Filter torrents by subcategory (e.g., english, raw, non-english).", examples=["english"]),
sort: str = Query(None, description="Sort torrents by a particular attribute (comments, size, date, seeders, leechers, downloads).", examples=["seeders"]),
order: str = Query(None, description="Order in which torrents should be sorted (asc or desc).", examples=["desc"]),
page: int = Query(1, description="Page number for pagination.", ge=1, examples=[1])
):
"""Search nyaa.si and return results as JSON"""
req = build_request(q=q, category=category, sub_category=sub_category, sort=sort, order=order, page=page, is_sukebei=False)
results = nyaa_api.search(req)
return results.to_dict()
@app.get("/sukebei", tags=["Search"], summary="Sukebei Category Search", operation_id="sukebei_category_search_sukebei_get")
def search_sukebei(
q: str = Query(None, description="The search query for torrents.", examples=["MIDA-512"]),
category: str = Query(None, description="Filter torrents by category (e.g., art, real).", examples=["real"]),
sub_category: str = Query(None, description="Filter torrents by subcategory (e.g., anime, doujinshi, games, manga, pictures, photobooks, videos).", examples=["videos"]),
sort: str = Query(None, description="Sort torrents by a particular attribute (comments, size, date, seeders, leechers, downloads).", examples=["downloads"]),
order: str = Query(None, description="Order in which torrents should be sorted (asc or desc).", examples=["desc"]),
page: int = Query(1, description="Page number for pagination.", ge=1, examples=[1])
):
"""Search sukebei.nyaa.si and return results as JSON"""
req = build_request(q=q, category=category, sub_category=sub_category, sort=sort, order=order, page=page, is_sukebei=True)
results = sukebei_api.search(req)
return results.to_dict()
@app.get("/nyaa/id/{torrent_id}", tags=["ID Search"], summary="Nyaa Id Search", operation_id="nyaa_id_search_nyaa_id__torrent_id__get")
def get_nyaa_id(torrent_id: int = Path(..., title="Torrent Id", description="The unique numeric ID of the torrent on nyaa.si.", examples=[12345])):
"""Fetch full details (description, information, file list, comments) for a specific Nyaa torrent."""
try:
info = nyaa_api.get_torrent_info(torrent_id)
return info.to_dict()
except NoSuchTorrentException:
raise HTTPException(status_code=404, detail="Torrent not found")
@app.get("/sukebei/id/{torrent_id}", tags=["ID Search"], summary="Sukebei Id Search", operation_id="sukebei_id_search_sukebei_id__torrent_id__get")
def get_sukebei_id(torrent_id: int = Path(..., title="Torrent Id", description="The unique numeric ID of the torrent on sukebei.nyaa.si.", examples=[4505820])):
"""Fetch full details (description, information, file list, comments) for a specific Sukebei torrent."""
try:
info = sukebei_api.get_torrent_info(torrent_id)
return info.to_dict()
except NoSuchTorrentException:
raise HTTPException(status_code=404, detail="Torrent not found")
@app.get("/nyaa/user/{user_name}", tags=["User Search"], summary="Nyaa User Search", operation_id="nyaa_user_search_nyaa_user__user_name__get")
def search_nyaa_user(
user_name: str = Path(..., title="User Name", description="The Nyaa user name whose uploads you want to search.", examples=["HorribleSubs"]),
q: str = Query(None, description="The search query for torrents."),
category: str = Query(None, description="Filter torrents by category."),
sub_category: str = Query(None, description="Filter torrents by subcategory."),
sort: str = Query(None, description="Sort torrents by attribute."),
order: str = Query(None, description="Sorting order."),
page: int = Query(1, description="Page number.", ge=1)
):
"""Search for torrents uploaded by a specific user on nyaa.si."""
req = build_request(q=q, user_name=user_name, category=category, sub_category=sub_category, sort=sort, order=order, page=page, is_sukebei=False)
results = nyaa_api.search(req)
return results.to_dict()
@app.get("/sukebei/user/{user_name}", tags=["User Search"], summary="Sukebei User Search", operation_id="sukebei_user_search_sukebei_user__user_name__get")
def search_sukebei_user(
user_name: str = Path(..., title="User Name", description="The Sukebei user name whose uploads you want to search.", examples=["offkab"]),
q: str = Query(None, description="The search query for torrents."),
category: str = Query(None, description="Filter torrents by category."),
sub_category: str = Query(None, description="Filter torrents by subcategory."),
sort: str = Query(None, description="Sort torrents by attribute."),
order: str = Query(None, description="Sorting order."),
page: int = Query(1, description="Page number.", ge=1)
):
"""Search for torrents uploaded by a specific user on sukebei.nyaa.si."""
req = build_request(q=q, user_name=user_name, category=category, sub_category=sub_category, sort=sort, order=order, page=page, is_sukebei=True)
results = sukebei_api.search(req)
return results.to_dict()