@@ -25,6 +25,7 @@ def __init__(self):
2525 super ().__init__ ()
2626 try :
2727 self .conf = super ().load_config ()
28+ self .condition_2_and_3_cities = None # 天气查询,存储重复城市信息,Initially set to None
2829 if not self .conf :
2930 logger .warn ("[Apilot] inited but alapi_token not found in config" )
3031 self .alapi_token = None # Setting a default value for alapi_token
@@ -40,7 +41,7 @@ def on_handle_context(self, e_context: EventContext):
4041 ContextType .TEXT
4142 ]:
4243 return
43- content = e_context ["context" ].content
44+ content = e_context ["context" ].content . strip ()
4445 logger .debug ("[Apilot] on_handle_context. content: %s" % content )
4546
4647 if content == "早报" :
@@ -60,19 +61,29 @@ def on_handle_context(self, e_context: EventContext):
6061 # Extract the part after "快递"
6162 tracking_number = content [2 :].strip ()
6263
64+ tracking_number = tracking_number .replace (':' , ':' ) # 替换可能出现的中文符号
6365 # Check if alapi_token is available before calling the function
6466 if not self .alapi_token :
6567 self .handle_error ("alapi_token not configured" , "快递请求失败" )
6668 reply = self .create_reply (ReplyType .TEXT , "请先配置alapi的token" )
6769 else :
70+ # Check if the tracking_number starts with "SF" for Shunfeng (顺丰) Express
71+ if tracking_number .startswith ("SF" ):
72+ # Check if the user has included the last four digits of the phone number
73+ if ':' not in tracking_number :
74+ reply = self .create_reply (ReplyType .TEXT , "顺丰快递需要补充寄/收件人手机号后四位,格式:SF12345:0000" )
75+ e_context ["reply" ] = reply
76+ e_context .action = EventAction .BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
77+ return # End the function here
78+
6879 # Call query_express_info function with the extracted tracking_number and the alapi_token from config
6980 content = self .query_express_info (self .alapi_token , tracking_number )
7081 reply = self .create_reply (ReplyType .TEXT , content )
7182 e_context ["reply" ] = reply
7283 e_context .action = EventAction .BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
7384
74- match = re .match (r'^([\u4e00-\u9fa5]{2}座)$' , content )
75- if match :
85+ horoscope_match = re .match (r'^([\u4e00-\u9fa5]{2}座)$' , content )
86+ if horoscope_match :
7687 if content in ZODIAC_MAPPING :
7788 zodiac_english = ZODIAC_MAPPING [content ]
7889 content = self .get_horoscope (zodiac_english )
@@ -82,30 +93,49 @@ def on_handle_context(self, e_context: EventContext):
8293 e_context ["reply" ] = reply
8394 e_context .action = EventAction .BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
8495
85- if content == "微博热搜" :
86- content = self .get_weibo_hot_trends ()
96+ hot_trend_match = re .search (r'(.{1,6})热榜$' , content )
97+ if hot_trend_match :
98+ hot_trends_type = hot_trend_match .group (1 ).strip () # 提取匹配的组并去掉可能的空格
99+ content = self .get_hot_trends (hot_trends_type )
87100 reply = self .create_reply (ReplyType .TEXT , content )
88101 e_context ["reply" ] = reply
89102 e_context .action = EventAction .BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
90103
104+
91105 # 天气查询
92- weather_match = re .search (r'([\u4e00-\u9fa5]{1,6}) 的?天气$' , content )
106+ weather_match = re .search (r'([\u4e00-\u9fa5]{1,6}|\d{1,10})\s* 的?天气$' , content )
93107 if weather_match :
94- # 如果匹配成功,提取第一个捕获组(可能包含“的”的城市名)
95- city_with_optional_de = weather_match .group (1 )
96- # 移除可能存在的“的”
97- city = city_with_optional_de .replace ('的' , '' )
108+ # 如果匹配成功,提取第一个捕获组
109+ content = weather_match .group (1 )
98110 if not self .alapi_token :
99111 self .handle_error ("alapi_token not configured" , "天气请求失败" )
100112 reply = self .create_reply (ReplyType .TEXT , "请先配置alapi的token" )
101113 else :
102- content = self .get_weather (self .alapi_token , city )
114+ content = self .get_weather (self .alapi_token , content )
103115 reply = self .create_reply (ReplyType .TEXT , content )
104116 e_context ["reply" ] = reply
105117 e_context .action = EventAction .BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
106118
107- def get_help_text (self , ** kwargs ):
108- help_text = "\n 🐳发送“早报”、“摸鱼”、“微博热搜”、“星座名称”会有惊喜!\n 📦快递查询:<快递+快递单号>\n 🌦️天气查询:城市+天气"
119+ def get_help_text (self , verbose = False , ** kwargs ):
120+ short_help_text = " 发送特定指令以获取早报、查询天气、星座运势、快递信息等!"
121+
122+ if not verbose :
123+ return short_help_text
124+
125+ help_text = "📚 发送关键词获取特定信息!\n "
126+
127+ # 娱乐和信息类
128+ help_text += "\n 🎉 娱乐与资讯:\n "
129+ help_text += " 🌅 早报: 发送“早报”获取早报。\n "
130+ help_text += " 🐟 摸鱼: 发送“摸鱼”获取摸鱼人日历。\n "
131+ help_text += " 🔥 热榜: 发送“xx热榜”查看支持的热榜。\n "
132+
133+ # 查询类
134+ help_text += "\n 🔍 查询工具:\n "
135+ help_text += " 🌦️ 天气: 发送“城市+天气”查天气,如“北京天气”。\n "
136+ help_text += " 📦 快递: 发送“快递+单号”查询快递状态。如“快递112345655”\n "
137+ help_text += " 🌌 星座: 发送星座名称查看今日运势,如“白羊座”。\n "
138+
109139 return help_text
110140
111141
@@ -150,7 +180,6 @@ def get_moyu_calendar(self):
150180 except Exception as e :
151181 return self .handle_error (e , "获取摸鱼日历信息失败" )
152182
153-
154183 def get_horoscope (self , astro_sign : str , time_period : str = "today" ):
155184 url = BASE_URL_VVHAN + "horoscope"
156185 params = {
@@ -191,24 +220,33 @@ def get_horoscope(self, astro_sign: str, time_period: str = "today"):
191220 except Exception as e :
192221 return self .handle_error (e , "获取星座信息失败" )
193222
194-
195- def get_weibo_hot_trends (self ):
196- url = BASE_URL_VVHAN + "wbhot"
197- try :
198- data = self .make_request (url , "GET" )
199- if isinstance (data , dict ) and data ['success' ] == True :
200- output = []
201- topics = data ['data' ]
202- output .append (f'更新时间:{ data ["time" ]} \n ' )
203- for i , topic in enumerate (topics [:15 ], 1 ):
204- formatted_str = f"{ i } . { topic ['title' ]} ({ topic ['hot' ]} 浏览)\n URL: { topic ['url' ]} \n "
205- output .append (formatted_str )
206- return "\n " .join (output )
207- else :
208- return self .handle_error (data , "热榜获取失败" )
209- except Exception as e :
210- return self .handle_error (e , "获取热搜失败" )
211-
223+ def get_hot_trends (self , hot_trends_type ):
224+ # 查找映射字典以获取API参数
225+ hot_trends_type_en = hot_trend_types .get (hot_trends_type , None )
226+ if hot_trends_type_en is not None :
227+ url = BASE_URL_VVHAN + "hotlist?type=" + hot_trends_type_en
228+ try :
229+ data = self .make_request (url , "GET" )
230+ if isinstance (data , dict ) and data ['success' ] == True :
231+ output = []
232+ topics = data ['data' ]
233+ output .append (f'更新时间:{ data ["update_time" ]} \n ' )
234+ for i , topic in enumerate (topics [:15 ], 1 ):
235+ hot = topic .get ('hot' , '无热度参数, 0' )
236+ formatted_str = f"{ i } . { topic ['title' ]} ({ hot } 浏览)\n URL: { topic ['url' ]} \n "
237+ output .append (formatted_str )
238+ return "\n " .join (output )
239+ else :
240+ return self .handle_error (data , "热榜获取失败" )
241+ except Exception as e :
242+ return self .handle_error (e , "获取热榜失败" )
243+ else :
244+ supported_types = "/" .join (hot_trend_types .keys ())
245+ final_output = (
246+ f"👉 已支持的类型有:\n \n { supported_types } \n "
247+ f"\n 📝 请按照以下格式发送:\n 类型+热榜 例如:微博热榜"
248+ )
249+ return final_output
212250
213251 def query_express_info (self , alapi_token , tracking_number , com = "" , order = "asc" ):
214252 url = BASE_URL_ALAPI + "kd"
@@ -238,12 +276,28 @@ def query_express_info(self, alapi_token, tracking_number, com="", order="asc"):
238276 except Exception as e :
239277 return self .handle_error (e , "快递查询失败" )
240278
241- def get_weather (self , alapi_token , city : str ):
279+ def get_weather (self , alapi_token , city_or_id : str ):
242280 url = BASE_URL_ALAPI + 'tianqi'
243- params = {
244- 'city' : city ,
245- 'token' : f'{ alapi_token } ' # 请将你的token填在这里
246- }
281+ # 判断使用id还是city请求api
282+ if city_or_id .isnumeric (): # 判断是否为纯数字,也即是否为 city_id
283+ params = {
284+ 'city_id' : city_or_id ,
285+ 'token' : f'{ alapi_token } '
286+ }
287+ else :
288+ city_info = self .check_multiple_city_ids (city_or_id )
289+ if city_info :
290+ data = city_info ['data' ]
291+ formatted_city_info = "\n " .join (
292+ [f"{ idx + 1 } ) { entry ['province' ]} --{ entry ['leader' ]} , ID: { entry ['city_id' ]} "
293+ for idx , entry in enumerate (data )]
294+ )
295+ return f"查询 <{ city_or_id } > 具有多条数据:\n { formatted_city_info } \n 请使用id查询,发送“id天气”"
296+
297+ params = {
298+ 'city' : city_or_id ,
299+ 'token' : f'{ alapi_token } '
300+ }
247301 try :
248302 weather_data = self .make_request (url , "GET" , params = params )
249303 if isinstance (weather_data , dict ) and weather_data .get ('code' ) == 200 :
@@ -330,7 +384,6 @@ def create_reply(self, reply_type, content):
330384 reply .content = content
331385 return reply
332386
333-
334387 def handle_error (self , error , message ):
335388 logger .error (f"{ message } ,错误信息:{ error } " )
336389 return message
@@ -341,6 +394,25 @@ def is_valid_url(self, url):
341394 return all ([result .scheme , result .netloc ])
342395 except ValueError :
343396 return False
397+
398+ def load_city_conditions (self ):
399+ if self .condition_2_and_3_cities is None :
400+ try :
401+ json_file_path = os .path .join (os .path .dirname (__file__ ), 'duplicate-citys.json' )
402+ with open (json_file_path , 'r' , encoding = 'utf-8' ) as f :
403+ self .condition_2_and_3_cities = json .load (f )
404+ except Exception as e :
405+ return self .handle_error (e , "加载condition_2_and_3_cities.json失败" )
406+
407+
408+ def check_multiple_city_ids (self , city ):
409+ self .load_city_conditions ()
410+ city_info = self .condition_2_and_3_cities .get (city , None )
411+ if city_info :
412+ return city_info
413+ return None
414+
415+
344416ZODIAC_MAPPING = {
345417 '白羊座' : 'aries' ,
346418 '金牛座' : 'taurus' ,
@@ -355,3 +427,16 @@ def is_valid_url(self, url):
355427 '水瓶座' : 'aquarius' ,
356428 '双鱼座' : 'pisces'
357429 }
430+
431+ hot_trend_types = {
432+ "微博" : "wbHot" ,
433+ "虎扑" : "huPu" ,
434+ "知乎" : "zhihuHot" ,
435+ "哔哩哔哩" : "bili" ,
436+ "36氪" : "36Ke" ,
437+ "抖音" : "douyinHot" ,
438+ "少数派" : "ssPai" ,
439+ "IT最新" : "itNews" ,
440+ "IT科技" : "itInfo"
441+
442+ }
0 commit comments