Skip to content

Commit f5fff35

Browse files
authored
Add files via upload
1 parent 1219854 commit f5fff35

13 files changed

Lines changed: 1668 additions & 14 deletions

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# MPRanime
2-
A small program interact with AnimePahe and Kwik in python
32
MPR anime downloader uses animepahe to download anime
43
it has simple GUI and it is very user friendly
54
to build the exe file use

anime_info.py

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import requests
2+
import tempfile
3+
import os
4+
import re
5+
6+
def format_date(date):
7+
if not date or not date.get('year'):
8+
return "?"
9+
year = date.get('year')
10+
month = str(date.get('month', '??')).zfill(2) if date.get('month') else "??"
11+
day = str(date.get('day', '??')).zfill(2) if date.get('day') else "??"
12+
return f"{year}-{month}-{day}"
13+
14+
def format_status(status):
15+
status_map = {
16+
'FINISHED': 'Finished',
17+
'RELEASING': 'Ongoing',
18+
'NOT_YET_RELEASED': 'Not Yet Released',
19+
'CANCELLED': 'Cancelled',
20+
'HIATUS': 'Hiatus'
21+
}
22+
return status_map.get(status, status)
23+
24+
def format_type(type_):
25+
type_map = {
26+
'TV': 'TV Series',
27+
'TV_SHORT': 'TV Short',
28+
'MOVIE': 'Movie',
29+
'SPECIAL': 'Special',
30+
'OVA': 'OVA',
31+
'ONA': 'ONA',
32+
'MUSIC': 'Music'
33+
}
34+
return type_map.get(type_, type_)
35+
36+
def format_source(source):
37+
source_map = {
38+
'ORIGINAL': 'Original',
39+
'MANGA': 'Manga',
40+
'LIGHT_NOVEL': 'Light Novel',
41+
'VISUAL_NOVEL': 'Visual Novel',
42+
'VIDEO_GAME': 'Video Game',
43+
'NOVEL': 'Novel',
44+
'DOUJINSHI': 'Doujinshi',
45+
'ANIME': 'Anime'
46+
}
47+
return source_map.get(source, source)
48+
49+
def format_season(season):
50+
season_map = {
51+
'WINTER': 'Winter',
52+
'SPRING': 'Spring',
53+
'SUMMER': 'Summer',
54+
'FALL': 'Fall'
55+
}
56+
return season_map.get(season, season)
57+
58+
def clean_description(description):
59+
if not description:
60+
return "No description available"
61+
desc = re.sub(r'<[^>]*>', '', description)
62+
return desc[:700] + ("..." if len(desc) > 700 else "")
63+
64+
def fetch_anime_info(anime_name, send_message_func):
65+
# send_message_func(msg, attachment_path=None)
66+
query = '''
67+
query ($search: String) {
68+
Media(search: $search, type: ANIME) {
69+
title { romaji english native }
70+
description(asHtml: false)
71+
coverImage { extraLarge large color }
72+
bannerImage
73+
episodes
74+
duration
75+
status
76+
averageScore
77+
meanScore
78+
popularity
79+
favourites
80+
genres
81+
studios(isMain: true) { nodes { name } }
82+
startDate { year month day }
83+
endDate { year month day }
84+
season
85+
seasonYear
86+
format
87+
source
88+
countryOfOrigin
89+
hashtag
90+
trailer { id site thumbnail }
91+
nextAiringEpisode { airingAt timeUntilAiring episode }
92+
relations { edges { relationType node { title { romaji english } siteUrl } } }
93+
recommendations { nodes { mediaRecommendation { title { romaji } siteUrl } } }
94+
siteUrl
95+
}
96+
}
97+
'''
98+
variables = {"search": anime_name}
99+
send_message_func("🔍 Searching anime info...")
100+
try:
101+
response = requests.post('https://graphql.anilist.co', json={"query": query, "variables": variables})
102+
response.raise_for_status()
103+
anime = response.json()['data']['Media']
104+
if not anime:
105+
send_message_func(f"❌ No results found for \"{anime_name}\". Please check the name and try again.")
106+
return
107+
description = clean_description(anime.get('description'))
108+
relations = anime.get('relations', {}).get('edges', [])
109+
relations_text = ""
110+
if relations:
111+
relations_text = '\n'.join([
112+
f"{edge.get('relationType')}: {edge.get('node', {}).get('title', {}).get('romaji')}" for edge in relations[:3]
113+
])
114+
recommendations = anime.get('recommendations', {}).get('nodes', [])
115+
recommendations_text = ""
116+
if recommendations:
117+
recommendations_text = '\n'.join([
118+
f"- {node.get('mediaRecommendation', {}).get('title', {}).get('romaji')}" for node in recommendations[:3]
119+
])
120+
next_ep = anime.get('nextAiringEpisode')
121+
next_episode_text = ""
122+
if next_ep:
123+
time_until = next_ep.get('timeUntilAiring', 0)
124+
days = time_until // (24 * 60 * 60)
125+
hours = (time_until % (24 * 60 * 60)) // (60 * 60)
126+
next_episode_text = f"\n⏳ Next Episode: #{next_ep.get('episode')} in {days}d {hours}h"
127+
studio = anime.get('studios', {}).get('nodes', [{}])[0].get('name', 'Unknown')
128+
title = anime['title']
129+
info_msg = f"🎌 𝗧𝗶𝘁𝗹𝗲: {title.get('romaji') or title.get('english')}\n"
130+
if title.get('english'):
131+
info_msg += f"🏴 𝗘𝗻𝗴𝗹𝗶𝘀𝗵: {title['english']}\n"
132+
if title.get('native'):
133+
info_msg += f"🗾 𝗡𝗮𝘁𝗶𝘃𝗲: {title['native']}\n\n"
134+
info_msg += f"📌 𝗦𝘁𝗮𝘁𝘂𝘀: {format_status(anime.get('status'))}\n"
135+
info_msg += f"📺 𝗘𝗽𝗶𝘀𝗼𝗱𝗲𝘀: {anime.get('episodes', 'Unknown')} ({anime.get('duration', '?')} min/ep)\n"
136+
info_msg += f"⭐ 𝗥𝗮𝘁𝗶𝗻𝗴: {anime.get('averageScore', '?')}/100 ({anime.get('meanScore', '?')} mean)\n"
137+
info_msg += f"❤️ 𝗙𝗮𝘃𝗼𝗿𝗶𝘁𝗲𝘀: {anime.get('favourites', 0):,}\n"
138+
info_msg += f"🔥 𝗣𝗼𝗽𝘂𝗹𝗮𝗿𝗶𝘁𝘆: #{anime.get('popularity', '?')}\n\n"
139+
info_msg += f"🎬 𝗙𝗼𝗿𝗺𝗮𝘁: {format_type(anime.get('format'))}\n"
140+
info_msg += f"🎥 𝗦𝗼𝘂𝗿𝗰𝗲: {format_source(anime.get('source'))}\n"
141+
info_msg += f"🏢 𝗦𝘁𝘂𝗱𝗶𝗼: {studio}\n"
142+
info_msg += f"🌐 𝗖𝗼𝘂𝗻𝘁𝗿𝘆: {anime.get('countryOfOrigin', 'Japan')}\n\n"
143+
info_msg += f"🗓️ 𝗔𝗶𝗿𝗲𝗱: {format_date(anime.get('startDate'))} to {format_date(anime.get('endDate'))}\n"
144+
if anime.get('season'):
145+
info_msg += f"🍂 𝗦𝗲𝗮𝘀𝗼𝗻: {format_season(anime['season'])} {anime.get('seasonYear', '')}\n"
146+
info_msg += next_episode_text
147+
info_msg += f"\n🏷️ 𝗚𝗲𝗻𝗿𝗲𝘀: {', '.join(anime.get('genres', []))}\n\n"
148+
# info_msg += f"📝 𝗗𝗲𝘀𝗰𝗿𝗶𝗽𝘁𝗶𝗼𝗻:\n{description}\n\n" # Description turned off as requested
149+
if relations_text:
150+
info_msg += f"🔗 𝗥𝗲𝗹𝗮𝘁𝗶𝗼𝗻𝘀:\n{relations_text}\n\n"
151+
if recommendations_text:
152+
info_msg += f"💡 𝗥𝗲𝗰𝗼𝗺𝗺𝗲𝗻𝗱𝗲𝗱:\n{recommendations_text}\n\n"
153+
info_msg += f"🔗 𝗠𝗼𝗿𝗲 𝗜𝗻𝗳𝗼: {anime.get('siteUrl')}"
154+
trailer = anime.get('trailer')
155+
if trailer and trailer.get('id'):
156+
info_msg += f"\n🎬 𝗧𝗿𝗮𝗶𝗹𝗲𝗿: https://youtube.com/watch?v={trailer['id']}"
157+
image_url = anime.get('coverImage', {}).get('extraLarge') or anime.get('coverImage', {}).get('large')
158+
if image_url:
159+
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as img_file:
160+
img_resp = requests.get(image_url)
161+
img_file.write(img_resp.content)
162+
img_path = img_file.name
163+
# Telegram caption limit is 1024 chars
164+
if len(info_msg) > 1024:
165+
short_caption = title.get('romaji') or title.get('english') or 'Anime Info'
166+
send_message_func(short_caption, attachment_path=img_path)
167+
# Send the rest as a text message
168+
send_message_func(info_msg)
169+
else:
170+
send_message_func(info_msg, attachment_path=img_path)
171+
os.unlink(img_path)
172+
else:
173+
send_message_func(info_msg)
174+
except Exception as e:
175+
send_message_func("❌ Error fetching anime info. Please try again later.")
176+
print(f"❌ Anime Error: {str(e)}")
177+
178+
def fetch_manga_info(manga_name, send_message_func):
179+
query = '''
180+
query ($search: String) {
181+
Media(search: $search, type: MANGA) {
182+
title { romaji english native }
183+
description(asHtml: false)
184+
coverImage { extraLarge large color }
185+
chapters
186+
volumes
187+
status
188+
averageScore
189+
meanScore
190+
popularity
191+
favourites
192+
genres
193+
startDate { year month day }
194+
endDate { year month day }
195+
siteUrl
196+
}
197+
}
198+
'''
199+
variables = {"search": manga_name}
200+
send_message_func("🔍 Searching manga info...")
201+
try:
202+
response = requests.post('https://graphql.anilist.co', json={"query": query, "variables": variables})
203+
response.raise_for_status()
204+
manga = response.json()['data']['Media']
205+
if not manga:
206+
send_message_func(f"❌ No results found for \"{manga_name}\". Please check the name and try again.")
207+
return
208+
title = manga['title']
209+
info_msg = f"📖 𝗧𝗶𝘁𝗹𝗲: {title.get('romaji') or title.get('english')}\n"
210+
if title.get('english'):
211+
info_msg += f"🏴 𝗘𝗻𝗴𝗹𝗶𝘀𝗵: {title['english']}\n"
212+
if title.get('native'):
213+
info_msg += f"🗾 𝗡𝗮𝘁𝗶𝘃𝗲: {title['native']}\n\n"
214+
info_msg += f"📌 𝗦𝘁𝗮𝘁𝘂𝘀: {format_status(manga.get('status'))}\n"
215+
info_msg += f"📚 𝗖𝗵𝗮𝗽𝘁𝗲𝗿𝘀: {manga.get('chapters', 'Unknown')}\n"
216+
info_msg += f"📖 𝗩𝗼𝗹𝘂𝗺𝗲𝘀: {manga.get('volumes', 'Unknown')}\n"
217+
info_msg += f"⭐ 𝗥𝗮𝘁𝗶𝗻𝗴: {manga.get('averageScore', '?')}/100 ({manga.get('meanScore', '?')} mean)\n"
218+
info_msg += f"❤️ 𝗙𝗮𝘃𝗼𝗿𝗶𝘁𝗲𝘀: {manga.get('favourites', 0):,}\n"
219+
info_msg += f"🔥 𝗣𝗼𝗽𝘂𝗹𝗮𝗿𝗶𝘁𝘆: #{manga.get('popularity', '?')}\n\n"
220+
info_msg += f"🗓️ 𝗔𝗶𝗿𝗲𝗱: {format_date(manga.get('startDate'))} to {format_date(manga.get('endDate'))}\n"
221+
info_msg += f"🏷️ 𝗚𝗲𝗻𝗿𝗲𝘀: {', '.join(manga.get('genres', []))}\n\n"
222+
# info_msg += f"📝 𝗗𝗲𝘀𝗰𝗿𝗶𝗽𝘁𝗶𝗼𝗻:\n{clean_description(manga.get('description'))}\n\n" # Description turned off as requested
223+
info_msg += f"🔗 𝗠𝗼𝗿𝗲 𝗜𝗻𝗳𝗼: {manga.get('siteUrl')}"
224+
image_url = manga.get('coverImage', {}).get('extraLarge') or manga.get('coverImage', {}).get('large')
225+
if image_url:
226+
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as img_file:
227+
img_resp = requests.get(image_url)
228+
img_file.write(img_resp.content)
229+
img_path = img_file.name
230+
# Telegram caption limit is 1024 chars
231+
if len(info_msg) > 1024:
232+
short_caption = title.get('romaji') or title.get('english') or 'Manga Info'
233+
send_message_func(short_caption, attachment_path=img_path)
234+
send_message_func(info_msg)
235+
else:
236+
send_message_func(info_msg, attachment_path=img_path)
237+
os.unlink(img_path)
238+
else:
239+
send_message_func(info_msg)
240+
except Exception as e:
241+
send_message_func("❌ Error fetching manga info. Please try again later.")
242+
print(f"❌ Manga Error: {str(e)}")
243+
244+
# Example usage:
245+
# def send_message(msg, attachment_path=None):
246+
# print(msg)
247+
# if attachment_path:
248+
# print(f"[Image at {attachment_path}]")
249+
# fetch_anime_info("Naruto", send_message)

0 commit comments

Comments
 (0)