11import sys ,os
22import concurrent .futures
3+ import urllib .parse
4+
35parent_folder_path = os .path .abspath (os .path .dirname (__file__ ))
46sys .path .append (parent_folder_path )
57sys .path .append (os .path .join (parent_folder_path , 'lib' ))
68
79from flowlauncher import FlowLauncher
810import webbrowser
911import requests
10- requests .packages .urllib3 .util .connection .HAS_IPV6 = False
11- requests .packages .urllib3 .disable_warnings ()
12+
13+ s = requests .Session ()
14+ _ICON_PATH = os .path .join (parent_folder_path , "assets" , "app.png" )
1215
1316class AutoRenderSearch (FlowLauncher ):
1417
1518 def format_time (self , time_hundredths ):
1619 if time_hundredths is None :
1720 return "Unknown Time"
18- total_seconds = time_hundredths / 100
19- minutes , seconds = divmod (total_seconds ,60 )
20- formatted_seconds = f"{ int (seconds )} "
21- fractional_part = f"{ round ((total_seconds % 1 ) * 100 ):02} "
22- formatted_time = f"{ formatted_seconds } .{ fractional_part } "
23- if minutes >= 1 :
24- formatted_time = f"{ int (minutes )} :{ formatted_time } "
25- return formatted_time
21+
22+ try :
23+ hundredths_total = int (time_hundredths )
24+ except (TypeError , ValueError ):
25+ return "Unknown Time"
26+
27+ minutes , remainder = divmod (hundredths_total , 6000 )
28+ seconds , hundredths = divmod (remainder , 100 )
29+
30+ if minutes :
31+ return f"{ minutes } :{ seconds :02} .{ hundredths :02} "
32+
33+ return f"{ seconds } .{ hundredths :02} "
2634
2735 def fetch_result (self , query , result ):
28- video = result [ 'share_id' ]
36+ share_id = result . get ( 'share_id' )
2937 user = result .get ('user' , 'Unknown User' )
3038 time_hundredths = result .get ('time' , 0 )
3139 comment = result .get ('comment' , '' )
3240 original_rank = result .get ('orig_rank' )
33- map_id = result .get ('map' )
34- autorender_url = f'https://autorender.p2sr.org/videos/{ video } '
35- default_thumbnail_path = r"assets\app.png"
41+ map_id = result .get ('map' , 'Unknown Map' )
42+ default_thumbnail_path = _ICON_PATH
3643 formatted_time = self .format_time (time_hundredths )
37- subtitle = f"User: { user } | Rank: { original_rank } | Comment: { comment } "
44+ rank_text = original_rank if original_rank is not None else 'Unknown Rank'
45+ comment_text = comment if comment else 'No comment'
46+ subtitle = f"User: { user } | Rank: { rank_text } | Comment: { comment_text } "
3847
39- return {
48+ item = {
4049 "Title" : f"{ map_id } - { formatted_time } " ,
4150 "SubTitle" : subtitle ,
4251 "IcoPath" : default_thumbnail_path ,
43- "JsonRPCAction" : {
52+ }
53+
54+ if share_id :
55+ autorender_url = f'https://autorender.p2sr.org/videos/{ share_id } '
56+ item ["JsonRPCAction" ] = {
4457 "method" : "open_url" ,
4558 "parameters" : [autorender_url ]
4659 }
47- }
60+
61+ return item
4862
4963 def query (self , query ):
64+ sanitized_query = query .strip ()
65+ if not sanitized_query :
66+ return [
67+ {
68+ "Title" : "Enter a search term" ,
69+ "SubTitle" : "Type a map or runner name to search autorender" ,
70+ "IcoPath" : _ICON_PATH ,
71+ }
72+ ]
73+
5074 try :
51- search_string = query . replace ( ' ' , '+' )
75+ search_string = urllib . parse . quote_plus ( sanitized_query )
5276 url = f'https://autorender.p2sr.org/api/v1/search?q={ search_string } '
53- r = s .get (url , verify = False )
54-
55- results = r .json ()['results' ]
77+ response = s .get (url , timeout = 5 )
78+ response .raise_for_status ()
79+
80+ payload = response .json ()
81+ results = payload .get ('results' , [])
5682 if results :
5783 with concurrent .futures .ThreadPoolExecutor () as executor :
58- result_list = list (executor .map (lambda result : self .fetch_result (query , result ), results ))
59-
60- return result_list
61- else :
62- return [
63- {
64- "Title" : "No results found" ,
65- "SubTitle" : "Try a different search term" ,
66- "IcoPath" : "assets/app.png" ,
67- }
68- ]
69- except Exception as e :
70- print (f"Error in query: { e } " )
71- return []
84+ items = [item for item in executor .map (lambda result : self .fetch_result (query , result ), results ) if item ]
85+ if items :
86+ return items
87+
88+ return [
89+ {
90+ "Title" : "No results found" ,
91+ "SubTitle" : "Try a different search term" ,
92+ "IcoPath" : _ICON_PATH ,
93+ }
94+ ]
95+ except requests .exceptions .RequestException as exc :
96+ print (f"Network error in query: { exc } " )
97+ return [
98+ {
99+ "Title" : "Network error" ,
100+ "SubTitle" : "Check your connection and try again" ,
101+ "IcoPath" : _ICON_PATH ,
102+ }
103+ ]
104+ except ValueError as exc :
105+ print (f"Error parsing response: { exc } " )
106+ return [
107+ {
108+ "Title" : "Unexpected response" ,
109+ "SubTitle" : "The autorender API returned data in an unexpected format" ,
110+ "IcoPath" : _ICON_PATH ,
111+ }
112+ ]
72113
73114 def open_url (self , url ):
74115 if url :
75116 webbrowser .open (url )
76117
77118if __name__ == "__main__" :
78- s = requests .Session ()
79- AutoRenderSearch ()
119+ AutoRenderSearch ()
0 commit comments