nonebot-plugin-railwaytools 2.2.4__tar.gz → 2.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/PKG-INFO +17 -10
  2. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/README.md +16 -9
  3. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/__init__.py +1 -1
  4. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/api.py +2 -2
  5. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/picture_function.py +32 -4
  6. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/route_info.py +28 -58
  7. nonebot_plugin_railwaytools-2.2.6/nonebot_plugin_railwaytools/station_info.py +140 -0
  8. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/train_info.py +17 -13
  9. nonebot_plugin_railwaytools-2.2.6/nonebot_plugin_railwaytools/utils.py +95 -0
  10. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/PKG-INFO +17 -10
  11. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/pyproject.toml +1 -1
  12. nonebot_plugin_railwaytools-2.2.4/nonebot_plugin_railwaytools/station_info.py +0 -142
  13. nonebot_plugin_railwaytools-2.2.4/nonebot_plugin_railwaytools/utils.py +0 -55
  14. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/LICENSE +0 -0
  15. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/emu_function.py +0 -0
  16. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/station_screen.py +0 -0
  17. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/SOURCES.txt +0 -0
  18. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/dependency_links.txt +0 -0
  19. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/requires.txt +0 -0
  20. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/top_level.txt +0 -0
  21. {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-railwaytools
3
- Version: 2.2.4
3
+ Version: 2.2.6
4
4
  Summary: 这是一个火车迷也许觉得很好用的铁路机器人工具箱
5
5
  Author-email: leaf2006 <leafdeveloper@qq.com>
6
6
  License-Expression: MIT
@@ -75,7 +75,7 @@ git clone https://github.com/leaf2006/nonebot-plugin-railwaytools.git
75
75
  | `/大屏` [车站名称] | 通过车站名称查看车站大屏(例如:`/大屏` 上海)|
76
76
  | `/线路` [线路名称] | 查询某条铁路基本信息(例如:`/线路` 宣杭铁路)|
77
77
  | `/车站` [车站名称] | 查询某车站基本信息(例如:`/车站` 上海)|
78
- | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` DF7C-5030)|
78
+ | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` HXD1D-1898)|
79
79
  | `/help` | 查看帮助信息 |
80
80
 
81
81
  #### 功能详细介绍
@@ -143,7 +143,7 @@ example:
143
143
  example:
144
144
  🤵:/查询 Z225
145
145
  🤖:
146
- 车次:Z225(北京丰台——合肥)
146
+ 车次:Z225(北京丰台——合肥)
147
147
  担当客运段:合肥客运段
148
148
  车型信息:25TAC380V
149
149
  配属:合肥车辆段
@@ -165,7 +165,7 @@ Z225次02月06日北京丰台方面正常开行
165
165
  example:
166
166
  🤵:/查询 Z225 -实时
167
167
  🤖:
168
- 车次:Z225(北京丰台——合肥)
168
+ 车次:Z225(北京丰台——合肥)
169
169
  担当客运段:合肥客运段
170
170
  车型信息:25TAC380V
171
171
  配属:合肥车辆段
@@ -254,7 +254,6 @@ example:
254
254
  🤖:
255
255
  【宣杭线】线路信息:
256
256
  线路类型:普速铁路
257
- 服务类型:客货两用
258
257
  单/复线:复线铁路
259
258
  设计时速:暂无数据
260
259
 
@@ -291,7 +290,6 @@ example:
291
290
  🤖:
292
291
  【上海】基础信息如下:
293
292
  电报码:SHH
294
- 拼音码:SHA
295
293
  所属路局:中国铁路上海局
296
294
  位置:上海市 静安区
297
295
  本站办理客运业务
@@ -312,12 +310,21 @@ example:
312
310
  数据来源:cnrail.geogv.org
313
311
  ```
314
312
 
315
- - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 DF7C-5030)
313
+ 由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
314
+
315
+ - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
316
316
  ```
317
317
  example:
318
- 🤵:/下关站 DF7C-5058
318
+ 🤵:/下关站 HXD1D-1898
319
319
  🤖:正在加载图片,时间可能略久...
320
- 🤖:[DF7C-5058的机车户口照]
320
+ 🤖:[HXD1D-1898的机车户口照]
321
+ 【HXD1D-1898】
322
+ 配属:上局沪段
323
+ 生产厂商:株洲
324
+ 拍摄日期:202403
325
+ 拍摄作者:吉亦铭
326
+
327
+ 数据来源:下关站-铁路摄影馆
321
328
  ```
322
329
 
323
330
  - 帮助:`/帮助` 或 `/help`
@@ -341,7 +348,7 @@ example:
341
348
 
342
349
  ⑥ 查询某车站基本信息:/车站 或 /cz (例如:/车站 上海)
343
350
 
344
- ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 DF7C-5030
351
+ ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 HXD1D-1898
345
352
 
346
353
  ⑧ 帮助:/帮助 或 /help
347
354
 
@@ -57,7 +57,7 @@ git clone https://github.com/leaf2006/nonebot-plugin-railwaytools.git
57
57
  | `/大屏` [车站名称] | 通过车站名称查看车站大屏(例如:`/大屏` 上海)|
58
58
  | `/线路` [线路名称] | 查询某条铁路基本信息(例如:`/线路` 宣杭铁路)|
59
59
  | `/车站` [车站名称] | 查询某车站基本信息(例如:`/车站` 上海)|
60
- | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` DF7C-5030)|
60
+ | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` HXD1D-1898)|
61
61
  | `/help` | 查看帮助信息 |
62
62
 
63
63
  #### 功能详细介绍
@@ -125,7 +125,7 @@ example:
125
125
  example:
126
126
  🤵:/查询 Z225
127
127
  🤖:
128
- 车次:Z225(北京丰台——合肥)
128
+ 车次:Z225(北京丰台——合肥)
129
129
  担当客运段:合肥客运段
130
130
  车型信息:25TAC380V
131
131
  配属:合肥车辆段
@@ -147,7 +147,7 @@ Z225次02月06日北京丰台方面正常开行
147
147
  example:
148
148
  🤵:/查询 Z225 -实时
149
149
  🤖:
150
- 车次:Z225(北京丰台——合肥)
150
+ 车次:Z225(北京丰台——合肥)
151
151
  担当客运段:合肥客运段
152
152
  车型信息:25TAC380V
153
153
  配属:合肥车辆段
@@ -236,7 +236,6 @@ example:
236
236
  🤖:
237
237
  【宣杭线】线路信息:
238
238
  线路类型:普速铁路
239
- 服务类型:客货两用
240
239
  单/复线:复线铁路
241
240
  设计时速:暂无数据
242
241
 
@@ -273,7 +272,6 @@ example:
273
272
  🤖:
274
273
  【上海】基础信息如下:
275
274
  电报码:SHH
276
- 拼音码:SHA
277
275
  所属路局:中国铁路上海局
278
276
  位置:上海市 静安区
279
277
  本站办理客运业务
@@ -294,12 +292,21 @@ example:
294
292
  数据来源:cnrail.geogv.org
295
293
  ```
296
294
 
297
- - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 DF7C-5030)
295
+ 由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
296
+
297
+ - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
298
298
  ```
299
299
  example:
300
- 🤵:/下关站 DF7C-5058
300
+ 🤵:/下关站 HXD1D-1898
301
301
  🤖:正在加载图片,时间可能略久...
302
- 🤖:[DF7C-5058的机车户口照]
302
+ 🤖:[HXD1D-1898的机车户口照]
303
+ 【HXD1D-1898】
304
+ 配属:上局沪段
305
+ 生产厂商:株洲
306
+ 拍摄日期:202403
307
+ 拍摄作者:吉亦铭
308
+
309
+ 数据来源:下关站-铁路摄影馆
303
310
  ```
304
311
 
305
312
  - 帮助:`/帮助` 或 `/help`
@@ -323,7 +330,7 @@ example:
323
330
 
324
331
  ⑥ 查询某车站基本信息:/车站 或 /cz (例如:/车站 上海)
325
332
 
326
- ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 DF7C-5030
333
+ ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 HXD1D-1898
327
334
 
328
335
  ⑧ 帮助:/帮助 或 /help
329
336
 
@@ -53,7 +53,7 @@ async def handle_information_helper():
53
53
  "④ 通过车站名称查看车站大屏:/大屏 或 /dp (例如:/大屏 上海)\n \n"
54
54
  "⑤ 查询某条铁路基本信息:/线路 或 /xl (例如:/线路 宣杭铁路) \n \n"
55
55
  "⑥ 查询某车站基本信息:/车站 或 /cz (例如:/车站 上海) \n \n"
56
- "⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 DF7C-5030) \n \n",
56
+ "⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 HXD1D-1898) \n \n",
57
57
  "⑧ 帮助:/帮助 或 /help \n \n",
58
58
  "更多功能正在开发中,尽情期待! \n",
59
59
  "------------------------------ \n \n",
@@ -5,9 +5,9 @@ class API:
5
5
  api_12306 = "https://mobile.12306.cn/wxxcx/wechat/main/travelServiceQrcodeTrainInfo"
6
6
  api_rail_re = "https://api.rail.re/"
7
7
  api_EMU_route_schedule = "https://rail.re/img/"
8
- api_xiaguanzhan = "http://www.xiaguanzhan.com/uploadfiles/"
8
+ api_xiaguanzhan = "http://www.xiaguanzhan.com/soso.asp"
9
9
  api_station_screen = "https://apis.uctb.cn/api/12306?"
10
- api_cnrail_geogv = "http://cnrail.geogv.org/api/v1/"
10
+ api_cnrail_geogv = "http://cnrail.geogv.org/api/"
11
11
 
12
12
  headers = { # 加个请求头,保险一点
13
13
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
@@ -6,7 +6,6 @@ from httpx import AsyncClient
6
6
  from nonebot import on_command # type: ignore
7
7
  from nonebot.adapters import Event
8
8
  from nonebot.adapters.onebot.v11 import Message, MessageSegment # type: ignore
9
- from nonebot.plugin import PluginMetadata # type: ignore
10
9
  from nonebot.params import CommandArg # type: ignore
11
10
  from nonebot.rule import to_me # type: ignore
12
11
  from .utils import utils
@@ -25,10 +24,39 @@ async def handle_xiaguanzhan_photo(event:Event, args: Message = CommandArg()): #
25
24
 
26
25
  if number := args.extract_plain_text():
27
26
  await xiaguanzhan_photo.send("正在加载图片,时间可能略久...")
28
- photo = API.api_xiaguanzhan + number + ".jpg"
29
- await xiaguanzhan_photo.finish(MessageSegment.image(photo))
27
+ async with httpx.AsyncClient(headers=API.headers, timeout=30.0) as client:
28
+ data = {
29
+ "keyword": number.lower() # Fix bug:小补丁
30
+ }
31
+ xiaguanzhan_resp = await client.post(API.api_xiaguanzhan, data=data)
32
+ xiaguanzhan_resp.encoding = "gb2312"
33
+ # 获取基本信息
34
+ first_match = utils.xiaguanzhan_first_match
35
+ title = first_match(r'<h1><span class="blue"><a href="ProView\.asp\?ProId=[^"]*" title="[^"]*" target="_blank">(.*?)</a></span></h1>', xiaguanzhan_resp.text)
36
+ if title == None:
37
+ await xiaguanzhan_photo.finish(f"暂无{number}的信息")
38
+ manufacturer = first_match(r'生产厂商:(.*?)<BR>', xiaguanzhan_resp.text)
39
+ shoot_date = first_match(r'拍摄日期:(.*?)<BR>', xiaguanzhan_resp.text)
40
+ shoot_author = first_match(r'拍摄作者:(.*?)</FONT>', xiaguanzhan_resp.text)
41
+ photo_url = first_match(r'下载地址:<a href="(.*?)" target="_blank">', xiaguanzhan_resp.text)
42
+
43
+ title_separate = title.split(' ')
44
+ locomotive_no = title_separate[1]
45
+ locomotive_allocation = title_separate[2]
46
+
47
+ xiaguanzhan_photo_output = Message ([
48
+ MessageSegment.image(photo_url),
49
+ f"【{locomotive_no}】\n",
50
+ f"配属:{locomotive_allocation}\n",
51
+ f"生产厂商:{manufacturer}\n",
52
+ f"拍摄日期:{shoot_date}\n",
53
+ f"拍摄作者:{shoot_author}\n\n",
54
+ "数据来源:下关站-铁路摄影馆",
55
+ ])
56
+ await xiaguanzhan_photo.finish(xiaguanzhan_photo_output)
57
+
30
58
  else:
31
- await xiaguanzhan_photo.finish("请输入正确的车号!,如:DF7C-5030")
59
+ await xiaguanzhan_photo.finish("请输入正确的车号!,如:HXD1D-1898")
32
60
 
33
61
  @EMU_route_schedule.handle() # 获取动车组交路表,还是来源于rail.re
34
62
  async def handle_EMU_route_schedule(event:Event, args: Message = CommandArg()):
@@ -43,102 +43,72 @@ async def handle_route_info(event:Event, args: Message = CommandArg()):
43
43
  if not res_search_data:
44
44
  await route_info.finish("未收录该线路或线路不存在,请重新输入!")
45
45
  else:
46
- for i in range(len(res_search_data)): # 搜索在所有搜索结果中属于“铁路”类别的条目
47
- if res_search_data[i][1] == "RAIL":
46
+ for search_results in res_search_data: # 搜索在所有搜索结果中属于“铁路”类别的条目
47
+ search_query = search_results['query']
48
+ search_name = search_results['name']
49
+ if "rail/" in search_query:
48
50
  if is_hsr == False:
49
- if "高速" not in res_search_data[i][2]:
51
+ if "高速" not in search_name:
50
52
  break
51
53
  else:
52
54
  break
53
-
54
- rail_id = res_search_data[i][0]
55
+ rail_id = search_query.replace("rail/","") # 去除query中的前缀rail/,这部分将不作为rail_id使用
55
56
 
56
- # print(rail_id)
57
- url_route_info = f"{API.api_cnrail_geogv}rail/{rail_id}?locale=zhcn"
57
+ url_route_info = f"{API.api_cnrail_geogv}feature/{rail_id}?locale=zhcn" # 已更新为新版调用方式
58
58
  route_info_res = await client.get(url_route_info)
59
59
  route_info_raw_data = json.loads(route_info_res.text)
60
60
  route_info_data = route_info_raw_data['data']
61
61
 
62
62
  route_info_name = route_info_data['name'] # 线路名称
63
63
 
64
- if route_info_data['lineNum'] == "2": # 线路形态
64
+ if route_info_data['lines'] == "2": # 线路形态
65
65
  route_info_linenum = "复线铁路"
66
- elif route_info_data['lineNum'] == "1":
66
+ elif route_info_data['lines'] == "1":
67
67
  route_info_linenum = "单线铁路"
68
68
  else:
69
- route_info_linenum = route_info_data['lineNum']
69
+ route_info_linenum = route_info_data['lines']
70
70
 
71
- if not route_info_data['designSpeed'] or route_info_data['designSpeed'].strip() == "null": # 设计时速
71
+ design_speed_raw = route_info_data.get("design_speed")
72
+ if not design_speed_raw or str(design_speed_raw).strip().lower() == "null":
72
73
  route_info_designSpeed = "暂无数据"
73
74
  else:
74
- route_info_designSpeed = route_info_data['designSpeed']
75
+ route_info_designSpeed = str(design_speed_raw)
75
76
 
76
- if route_info_data['railService'] == "F": # 服务类型
77
- route_info_railService = "货运"
78
- elif route_info_data['railService'] == "P":
79
- route_info_railService = "客运"
80
- elif route_info_data['railService'] == "PF":
81
- route_info_railService = "客货两用"
82
- elif route_info_data['railService'] == "P2F1":
83
- route_info_railService = "客运为主,兼顾货运"
84
- else:
85
- route_info_railService = route_info_data['railService']
86
-
87
- if route_info_data['railType'] == "CONV": # 线路类型
88
- route_info_railType = "普速铁路"
89
- elif route_info_data['railType'] == "RR":
90
- route_info_railType = "快速铁路"
91
- elif route_info_data['railType'] == "HSR":
92
- route_info_railType = "高速铁路"
93
- else:
94
- route_info_railType = route_info_data['railType']
77
+ route_info_railType = route_info_data['railtype'] # 新版模式
95
78
 
96
- if route_info_data['diagram'] == "null":
97
- route_info_diagram = "暂无沿途车站数据"
79
+ # 作者心还怪好的,新版调用方式的那个stations确实比原来的好
80
+ stations_list = route_info_data['stations']
81
+ if not stations_list or stations_list == "null":
82
+ route_info_stations = "暂无沿途车站数据"
98
83
  else:
99
- raw_diagram = route_info_data['diagram']['records']
100
- # route_info_diagram = raw_diagram[num][3][0][2]
101
- route_info_diagram = ""
102
- num = 0
103
- count = 1
104
- count_raw_diagram = len(raw_diagram) - 1
105
- while num < count_raw_diagram:
106
- if not raw_diagram[num][3] or raw_diagram[num][2] not in ['SST','MST']:
107
- num += 1
108
- continue
109
-
110
- station_name = raw_diagram[num][3][0][2]
111
- raw_kilometerage = str(raw_diagram[num][1])
112
- if raw_kilometerage.strip() == "":
84
+ route_info_stations = ""
85
+ for counts in range(len(stations_list)):
86
+ station_name = stations_list[counts]['name']
87
+ kilometerage_raw = stations_list[counts]['mileage']
88
+ if kilometerage_raw is None:
113
89
  kilometerage = ""
114
90
  else:
115
- kilometerage = f"{raw_kilometerage}Km"
116
- route_info_diagram += f"【{str(count)}】{station_name} {kilometerage} \n"
117
- count += 1
118
- num += 1
119
-
91
+ kilometerage = f"{kilometerage_raw}Km"
92
+ route_info_stations += f"【{str(counts+1)}】{station_name} {kilometerage} \n"
120
93
 
94
+ # 这里跟随原网站弃用“服务类型”
121
95
  route_info_result = Message([
122
- # "线路名称:",route_info_name,"\n",
123
96
  "【",route_info_name,"】线路信息:\n"
124
97
  "线路类型:",route_info_railType,"\n",
125
- "服务类型:",route_info_railService,"\n",
126
98
  "单/复线:",route_info_linenum,"\n",
127
99
  "设计时速:",route_info_designSpeed,"\n \n",
128
100
  "----------沿途车站----------\n",
129
- route_info_diagram,
101
+ route_info_stations,
130
102
  "------------------------------ \n \n",
131
103
  "*本表所列起点终点为该线路里程接算站,里程为营业用运价里程,与线路实际运行长度并不相同\n"
132
104
  "数据来源:cnrail.geogv.org",
133
-
134
105
  ])
135
106
 
136
107
  except (httpx.ReadTimeout,httpx.ConnectTimeout):
137
108
  route_info_result = "请求超时,请稍等一下再试"
138
109
  except Exception as error:
139
- route_info_result = "发生异常:" + str(error)
110
+ route_info_result = "发生异常:" + str(error) # TODO
140
111
 
141
-
142
112
  await route_info.finish(route_info_result)
143
113
 
144
114
  else:
@@ -0,0 +1,140 @@
1
+ # Copyright © Leaf developer 2023-2026
2
+ # 本文件负责实现“查询车站信息”功能
3
+
4
+ import httpx
5
+ import json
6
+ from nonebot import on_command
7
+ from nonebot.adapters import Event
8
+ from nonebot.adapters.onebot.v11 import Message, MessageSegment
9
+ from nonebot.plugin import PluginMetadata
10
+ from nonebot.params import CommandArg
11
+ from nonebot.rule import to_me
12
+ from .utils import utils
13
+ from .api import API
14
+
15
+ station_info = on_command("车站",aliases={"cz","车站信息","站"},priority=5,block=True)
16
+
17
+ @station_info.handle()
18
+ async def handle_station_info(event:Event, args: Message = CommandArg()):
19
+ raw_message = str(event.get_message()).strip()
20
+ command_part = utils.get_command_part(raw_message)
21
+ valid_commands = ['车站','cz','车站信息','站']
22
+ if command_part not in valid_commands:
23
+ return
24
+ if station_name_input := args.extract_plain_text():
25
+ is_metro_sta = False
26
+ if "地铁站" in station_name_input:
27
+ station_name_input = station_name_input.replace("地铁站","")
28
+ is_metro_sta = True
29
+ elif "站" in station_name_input: # 防止搜索出现问题
30
+ station_name_input = station_name_input.replace("站","")
31
+ elif "车站" in station_name_input:
32
+ station_name_input = station_name_input.replace("车站","")
33
+ else:
34
+ pass
35
+
36
+ try:
37
+ async with httpx.AsyncClient(headers=API.headers) as client:
38
+ res_search_data = await utils.cnrail_search(station_name_input)
39
+ if not res_search_data:
40
+ await station_info.finish("未收录该车站或车站不存在,请重新输入!")
41
+ else:
42
+ # 为了适应网站加入了地铁的新特性,将搜索与获取数据两步放在一起,便于对地铁车站与国铁车站重名现象的处理
43
+ sta_info_formatted_data = ""
44
+ for search_results in res_search_data:
45
+ search_query = search_results['query']
46
+ search_name = search_results['name']
47
+ if "geo/" in search_query and station_name_input == search_name:
48
+ sta_id = search_query.replace("geo/","")
49
+ url_sta_info = f"{API.api_cnrail_geogv}poi/{sta_id}?locale=zhcn"
50
+ sta_info_res = await client.get(url_sta_info)
51
+ sta_info_formatted_data = utils.decrypt_cnrail_data(sta_info_res.text)
52
+
53
+ if is_metro_sta == True:
54
+ if sta_info_formatted_data['featureType'] == "地铁站":
55
+ break
56
+ else:
57
+ if sta_info_formatted_data['featureType'] == "火车站":
58
+ break
59
+
60
+ sta_status_judge = sta_info_formatted_data['featureType'] # 上一步判断车站类型是为了筛选重名地铁站,防止误选,这里不是
61
+ if sta_status_judge == "地铁站":
62
+ is_metro_sta = True
63
+
64
+ sta_detail = sta_info_formatted_data['exd'][0]['data']
65
+ # 站名
66
+ if is_metro_sta == True:
67
+ sta_name = sta_info_formatted_data['name'] + "地铁站"
68
+ else:
69
+ sta_name = sta_info_formatted_data['name']
70
+
71
+ # 电报码
72
+ sta_telecode_raw = sta_detail.get("tele_code")
73
+ if not sta_telecode_raw or str(sta_telecode_raw).strip() == "null":
74
+ sta_telecode = ""
75
+ else:
76
+ sta_telecode = f"电报码:{sta_detail['tele_code']}\n"
77
+
78
+ sta_bureau = f"所属单位:{sta_detail['operators'][0]['name']}\n"
79
+ sta_location = f"位置:{sta_info_formatted_data['location']}\n"
80
+
81
+ serviceclass_judge = sta_detail.get('trainservice')
82
+ if is_metro_sta == True:
83
+ sta_serviceclass = "" # 地铁车站特殊处理
84
+ elif not serviceclass_judge and is_metro_sta == False:
85
+ sta_serviceclass = "本站不办理客运业务\n"
86
+ else:
87
+ sta_serviceclass = "本站办理客运业务\n"
88
+
89
+ hr_line = "------------------------------ \n"
90
+ # 沿途车站
91
+
92
+ if not sta_detail.get('connection'):
93
+ sta_route_info = f"{hr_line}暂无该车站线路数据\n"
94
+ else:
95
+ sta_route_data = sta_detail['connection']
96
+ sta_route_info = ""
97
+ for route in sta_route_data:
98
+ linename = route['linename']
99
+ next_data = route['next'][0]
100
+ if next_data.get('adj'): # 如果下一站不是null,则必然有dest_station;如果下一站是null,本站必然是终点站
101
+ next_sta = next_data['adj']['name']
102
+ next_dest_sta = f"({next_data['dest']['name']})方向"
103
+ else:
104
+ if next_data['dest']['status'] == "END":
105
+ next_sta = "起迄站"
106
+ next_dest_sta = ""
107
+
108
+ prev_data = route['prev'][0]
109
+ if prev_data.get('adj'):
110
+ prev_sta = prev_data['adj']['name']
111
+ prev_dest_sta = f"({prev_data['dest']['name']})方向"
112
+ else:
113
+ if prev_data['dest']['status'] == "END":
114
+ prev_sta = "起迄站"
115
+ prev_dest_sta = ""
116
+
117
+ sta_route_info += f"{hr_line}【{linename}】\n下站{next_dest_sta}:{next_sta}\n上站{prev_dest_sta}:{prev_sta}\n"
118
+ # TODO
119
+
120
+ sta_info_result = Message([
121
+ "【",sta_name,"】基础信息如下:\n",
122
+ sta_telecode,
123
+ sta_bureau,
124
+ sta_location,
125
+ sta_serviceclass,
126
+ sta_route_info,
127
+ "------------------------------\n \n",
128
+ "数据来源:cnrail.geogv.org",
129
+
130
+ ])
131
+ except (httpx.ReadTimeout,httpx.ConnectTimeout):
132
+ sta_info_result = "请求超时,请稍等一下再试"
133
+ except Exception as error:
134
+ sta_info_result = "发生异常:" + str(error)
135
+
136
+ await station_info.finish(sta_info_result)
137
+
138
+ else:
139
+ await station_info.finish("请输入线路名称")
140
+
@@ -4,7 +4,6 @@
4
4
  import json
5
5
  import datetime
6
6
  import httpx
7
- import traceback
8
7
  from nonebot import on_command,logger # type: ignore
9
8
  from nonebot.adapters import Event
10
9
  from nonebot.adapters.onebot.v11 import Message, MessageSegment # type: ignore
@@ -72,16 +71,15 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
72
71
 
73
72
  # 对返回数据进行分析
74
73
  stop_time = info_response_data['data']['trainDetail']['stopTime']
75
- # 此处控制台会输出warning,但是可以忽略,因为是12306的问题
76
74
 
77
- train_code = stop_time[0]['stationTrainCode'] # 车次
75
+ train_code_raw = stop_time[0]['stationTrainCode'] # 原始车次,根据始发站时的车次来判断
76
+ train_code_display = info_response_data['data']['trainDetail']['stationTrainCodeAll'] # 车次(全部)
78
77
  start_station_name = stop_time[0]['start_station_name'] # 始发站名
79
78
  end_station_name = stop_time[0]['end_station_name'] # 终到站名
80
79
 
81
80
  jiaolu_corporation_code = stop_time[0]["jiaolu_corporation_code"] # 担当客运段
82
81
  if info_data["trainCode"][0] == "D" or info_data["trainCode"][0] == "G" or info_data["trainCode"][0] == "C":
83
- # url_emu_code = API.api_rail_re + "train/" + info_data["trainCode"]
84
- url_emu_code = f"{API.api_rail_re}train/{train_code}"
82
+ url_emu_code = f"{API.api_rail_re}train/{train_code_raw}"
85
83
  res_info_EMU = await client.get(url_emu_code)
86
84
  info_EMU_code = json.loads(res_info_EMU.text)
87
85
  if res_info_EMU.status_code == 404 or not info_EMU_code:
@@ -99,9 +97,9 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
99
97
 
100
98
  if request_dates == toDay:
101
99
  current_date = datetime.date.today().strftime('%m月%d日') # Bug fixed:https://github.com/leaf2006/nonebot-plugin-railwaytools/issues/2
102
- train_schedule_info = f"{train_code}次{current_date}{start_station_name}方面正常开行"
100
+ train_schedule_info = f"{train_code_raw}次{current_date}{start_station_name}方面正常开行"
103
101
  else:
104
- train_schedule_info = f"{train_code}次{current_date}{start_station_name}方面不开行或已停运,请关注车站公告"
102
+ train_schedule_info = f"{train_code_raw}次{current_date}{start_station_name}方面不开行或已停运,请关注车站公告"
105
103
 
106
104
  stop_inf = []
107
105
  stop_dict = {}
@@ -114,6 +112,7 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
114
112
  stopover_time = stop['stopover_time'] + "分"
115
113
  ticketDelay = stop['ticketDelay']
116
114
  day_difference = stop['dayDifference']
115
+ train_code_now = stop['stationTrainCode'] # 当前车次
117
116
  stop_time_count = len(stop_time)
118
117
 
119
118
  if i == 0: # 判断始发/终到站,给不存在的到点/发点变成“--:--”
@@ -135,6 +134,7 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
135
134
  stop_dict.setdefault("发点",start_time)
136
135
  stop_dict.setdefault("停车时间",stopover_time)
137
136
  stop_dict.setdefault("day_difference",day_difference)
137
+ stop_dict.setdefault("当前车次",train_code_now)
138
138
  stop_inf.append(stop_dict)
139
139
  stop_dict = {}
140
140
 
@@ -172,10 +172,14 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
172
172
 
173
173
  station_result = ""
174
174
  count = 1 # 给时刻表标上序号
175
- # day_difference_buffer = 0
176
- # day_differences = [int(stop.get('day_difference', 0)) for stop in stop_inf]
175
+
176
+ train_code_compare = train_code_raw
177
177
  for i,stop in enumerate(stop_inf): # 想办法整出时刻表的结果,最后将结果添加到Message中去
178
- # day_difference_output = ""
178
+ if stop['当前车次'] != train_code_compare:
179
+ train_code_change_alarm = f"【列车自当前车站起车次号变更为{stop['当前车次']}】\n"
180
+ train_code_compare = stop['当前车次']
181
+ else:
182
+ train_code_change_alarm = ""
179
183
 
180
184
  if is_real_time_query == True:
181
185
  if request_dates != toDay:
@@ -191,12 +195,12 @@ async def handle_train_info(event:Event, args: Message = CommandArg()): # type:
191
195
  else:
192
196
  delay = ""
193
197
 
194
- station_result += str(count) + "." + stop['站点'] + ":" + stop['到点'] + "到," + stop['发点'] + "开,停车" + stop['停车时间'] + delay + "\n"
198
+ station_result += str(count) + "." + stop['站点'] + ":" + stop['到点'] + "到," + stop['发点'] + "开,停车" + stop['停车时间'] + delay + "\n" + train_code_change_alarm
195
199
  count += 1
196
200
 
197
201
  train_info_output = Message([ # 结果Message
198
- "车次:",train_code,
199
- "(",start_station_name , "——" , end_station_name , ") \n",
202
+ "车次:",train_code_display,
203
+ "(",start_station_name , "——" , end_station_name , " \n",
200
204
  "担当客运段:" , jiaolu_corporation_code , "\n",
201
205
  "车型信息:" , jiaolu_train_style , "\n",
202
206
  "配属:" , jiaolu_dept_train , "\n",
@@ -0,0 +1,95 @@
1
+ import re
2
+ import json
3
+ import httpx
4
+ import asyncio
5
+ import traceback
6
+
7
+ from .api import API
8
+
9
+ class utils:
10
+ """存放各类需要的def定义"""
11
+ def time_Formatter_1(time) -> str:
12
+ """格式化时间,1145 -> 11:45"""
13
+ return time[:2] + ":" + time[2:]
14
+
15
+ def time_Formatter_2(time) -> str:
16
+ """格式化时间,2025-12-17 14:50:00 -> 14:50"""
17
+ return time[11:16]
18
+ def EMU_code_formatter(str):
19
+ """格式化动车组车号 CRH2A2001 -> CRH2A-2001"""
20
+ return str[:-4] + "-" + str[-4:]
21
+
22
+ async def cnrail_search(input_text):
23
+ """cnrail的搜索模块,获取rail id必用"""
24
+ url_search = f"{API.api_cnrail_geogv}search?keyword={input_text}"
25
+ async with httpx.AsyncClient(headers=API.headers) as client:
26
+ res_search = await client.get(url_search)
27
+ res_search_data = json.loads(res_search.text) # Fixed:适配新版api调用方式
28
+ return res_search_data
29
+
30
+ def get_command_part(raw_message):
31
+ """
32
+ 获取命令部分
33
+ """
34
+ space_index = raw_message.find(' ') # 找到空格所在的位置(空格用于分隔指令与参数)
35
+ if space_index != -1:
36
+ command_part = raw_message[:space_index]
37
+ else:
38
+ command_part = raw_message
39
+
40
+ command_part = command_part.replace('/','')
41
+ return command_part
42
+
43
+ def short_tb(exc: Exception) -> str:
44
+ """
45
+ 用于精简TraceBack
46
+ """
47
+ te = traceback.TracebackException.from_exception(exc)
48
+ if te.stack:
49
+ last = te.stack[-1]
50
+ # 只保留最后一帧
51
+ frame = f'File "{last.filename}", line {last.lineno}, in {last.name}\n {last.line}'
52
+ else:
53
+ frame = "No traceback frame"
54
+ exc_only = "".join(te.format_exception_only()).strip()
55
+ return f"{frame}\n{exc_only}"
56
+
57
+ def decrypt_cnrail_data(encrypted_str: str) -> dict:
58
+ """
59
+ 解密 cnrail.geogv.org API 返回的混淆字符串
60
+ """
61
+
62
+ # 如果最外层包着多余的引号,先通过 json.loads 脱掉引号转为正常的内部字符串
63
+ if encrypted_str.startswith('"') and encrypted_str.endswith('"'):
64
+ try:
65
+ encrypted_str = json.loads(encrypted_str)
66
+ except json.JSONDecodeError:
67
+ pass
68
+
69
+ if not encrypted_str:
70
+ return "ERR"
71
+
72
+ key_length = ord(encrypted_str[0]) # 第一位字符的 ASCII 码值代表密钥的长度,如结果为\u0007则提取为7
73
+ key = encrypted_str[1:1+key_length] # 紧接着的key_length个字符是密钥
74
+ payload = encrypted_str[1+key_length:] # 剩下的都是加密过的密文
75
+
76
+ # 解密部分
77
+ decrypted_chars = []
78
+ for i, char in enumerate(payload):
79
+ key_char = key[i % len(key)]
80
+
81
+ # 密文字符 ASCII - 密钥字符 ASCII = 原文字符 ASCII
82
+ decrypted_char_code = ord(char) - ord(key_char)
83
+ decrypted_chars.append(chr(decrypted_char_code)) # 由ASCII解密为普通字符串
84
+
85
+ decrypted_str = "".join(decrypted_chars)
86
+
87
+ try:
88
+ return json.loads(decrypted_str)
89
+ except json.JSONDecodeError:
90
+ return "ERR"
91
+
92
+ def xiaguanzhan_first_match(pattern, text):
93
+ m = re.search(pattern, text, re.IGNORECASE)
94
+ return m.group(1).strip() if m else None
95
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-railwaytools
3
- Version: 2.2.4
3
+ Version: 2.2.6
4
4
  Summary: 这是一个火车迷也许觉得很好用的铁路机器人工具箱
5
5
  Author-email: leaf2006 <leafdeveloper@qq.com>
6
6
  License-Expression: MIT
@@ -75,7 +75,7 @@ git clone https://github.com/leaf2006/nonebot-plugin-railwaytools.git
75
75
  | `/大屏` [车站名称] | 通过车站名称查看车站大屏(例如:`/大屏` 上海)|
76
76
  | `/线路` [线路名称] | 查询某条铁路基本信息(例如:`/线路` 宣杭铁路)|
77
77
  | `/车站` [车站名称] | 查询某车站基本信息(例如:`/车站` 上海)|
78
- | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` DF7C-5030)|
78
+ | `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站` HXD1D-1898)|
79
79
  | `/help` | 查看帮助信息 |
80
80
 
81
81
  #### 功能详细介绍
@@ -143,7 +143,7 @@ example:
143
143
  example:
144
144
  🤵:/查询 Z225
145
145
  🤖:
146
- 车次:Z225(北京丰台——合肥)
146
+ 车次:Z225(北京丰台——合肥)
147
147
  担当客运段:合肥客运段
148
148
  车型信息:25TAC380V
149
149
  配属:合肥车辆段
@@ -165,7 +165,7 @@ Z225次02月06日北京丰台方面正常开行
165
165
  example:
166
166
  🤵:/查询 Z225 -实时
167
167
  🤖:
168
- 车次:Z225(北京丰台——合肥)
168
+ 车次:Z225(北京丰台——合肥)
169
169
  担当客运段:合肥客运段
170
170
  车型信息:25TAC380V
171
171
  配属:合肥车辆段
@@ -254,7 +254,6 @@ example:
254
254
  🤖:
255
255
  【宣杭线】线路信息:
256
256
  线路类型:普速铁路
257
- 服务类型:客货两用
258
257
  单/复线:复线铁路
259
258
  设计时速:暂无数据
260
259
 
@@ -291,7 +290,6 @@ example:
291
290
  🤖:
292
291
  【上海】基础信息如下:
293
292
  电报码:SHH
294
- 拼音码:SHA
295
293
  所属路局:中国铁路上海局
296
294
  位置:上海市 静安区
297
295
  本站办理客运业务
@@ -312,12 +310,21 @@ example:
312
310
  数据来源:cnrail.geogv.org
313
311
  ```
314
312
 
315
- - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 DF7C-5030)
313
+ 由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
314
+
315
+ - 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
316
316
  ```
317
317
  example:
318
- 🤵:/下关站 DF7C-5058
318
+ 🤵:/下关站 HXD1D-1898
319
319
  🤖:正在加载图片,时间可能略久...
320
- 🤖:[DF7C-5058的机车户口照]
320
+ 🤖:[HXD1D-1898的机车户口照]
321
+ 【HXD1D-1898】
322
+ 配属:上局沪段
323
+ 生产厂商:株洲
324
+ 拍摄日期:202403
325
+ 拍摄作者:吉亦铭
326
+
327
+ 数据来源:下关站-铁路摄影馆
321
328
  ```
322
329
 
323
330
  - 帮助:`/帮助` 或 `/help`
@@ -341,7 +348,7 @@ example:
341
348
 
342
349
  ⑥ 查询某车站基本信息:/车站 或 /cz (例如:/车站 上海)
343
350
 
344
- ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 DF7C-5030
351
+ ⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 HXD1D-1898
345
352
 
346
353
  ⑧ 帮助:/帮助 或 /help
347
354
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-railwaytools"
3
- version = "2.2.4"
3
+ version = "2.2.6"
4
4
  description = "这是一个火车迷也许觉得很好用的铁路机器人工具箱"
5
5
  authors = [
6
6
  { name = "leaf2006", email = "leafdeveloper@qq.com" }
@@ -1,142 +0,0 @@
1
- # Copyright © Leaf developer 2023-2026
2
- # 本文件负责实现“查询车站信息”功能
3
-
4
- import httpx
5
- import json
6
- from nonebot import on_command
7
- from nonebot.adapters import Event
8
- from nonebot.adapters.onebot.v11 import Message, MessageSegment
9
- from nonebot.plugin import PluginMetadata
10
- from nonebot.params import CommandArg
11
- from nonebot.rule import to_me
12
- from .utils import utils
13
- from .api import API
14
-
15
- station_info = on_command("车站",aliases={"cz","车站信息","站"},priority=5,block=True)
16
-
17
- @station_info.handle()
18
- async def handle_station_info(event:Event, args: Message = CommandArg()):
19
- raw_message = str(event.get_message()).strip()
20
- command_part = utils.get_command_part(raw_message)
21
- valid_commands = ['车站','cz','车站信息','站']
22
- if command_part not in valid_commands:
23
- return
24
- if station_name_input := args.extract_plain_text():
25
- if "站" in station_name_input: # 防止搜索出现问题
26
- station_name_input = station_name_input.replace("站","")
27
- elif "车站" in station_name_input:
28
- station_name_input = station_name_input("车站","")
29
- else:
30
- pass
31
-
32
- try:
33
- async with httpx.AsyncClient(headers=API.headers) as client:
34
- res_search_data = await utils.cnrail_search(station_name_input)
35
- if not res_search_data:
36
- await station_info.finish("未收录该车站或车站不存在,请重新输入!")
37
- else:
38
- for i in range(len(res_search_data)): # 搜索所有搜索结果中属于“车站”类别的 条目
39
- if res_search_data[i][2] == station_name_input and res_search_data[i][1] == "STATION":
40
- continue_search = False
41
- break
42
- else:
43
- continue_search = True
44
-
45
- if continue_search == True:
46
- for i in range(len(res_search_data)):
47
- if res_search_data[i][1] == "STATION":
48
- break
49
- else:
50
- pass
51
-
52
- rail_id = res_search_data[i][0]
53
-
54
- url_sta_basic_info = f"{API.api_cnrail_geogv}station/{rail_id}?locale=zhcn&query-override=&requestGeom=true" # 车站基本信息
55
- url_sta_route_info = f"{API.api_cnrail_geogv}station-link/{rail_id}?locale=zhcn&query-override=" # 车站所属线路
56
-
57
- sta_basic_info_res = await client.get(url_sta_basic_info)
58
- sta_basic_info_data = json.loads(sta_basic_info_res.text) # 返回数据直接可以使用,没有套了个"data":{}的壳
59
-
60
- sta_route_info_res = await client.get(url_sta_route_info)
61
- sta_route_info_rawdata = json.loads(sta_route_info_res.text)
62
-
63
- sta_telecode_rawdata = sta_basic_info_data['teleCode'] # 电报码
64
- sta_pinyincode_rawdata = sta_basic_info_data['pinyinCode'] # 拼音码
65
- sta_location_rawdata = sta_basic_info_data['location'] # 所在地点
66
- sta_serviceclass_rawdata = sta_basic_info_data['serviceClass'] # 服务类型
67
-
68
- sta_name = sta_basic_info_data['localName'] # 车站名称
69
- sta_bureau = "所属路局:" + sta_basic_info_data['bureau'].get("name") + "\n" # 所属单位
70
-
71
- if not sta_telecode_rawdata or sta_telecode_rawdata.strip() == "null":
72
- sta_telecode = ""
73
- else:
74
- sta_telecode = f"电报码:{sta_telecode_rawdata}\n"
75
-
76
- if not sta_pinyincode_rawdata or sta_pinyincode_rawdata.strip() == "null":
77
- sta_pinyincode = ""
78
- else:
79
- sta_pinyincode = f"拼音码:{sta_pinyincode_rawdata}\n"
80
-
81
- if not sta_location_rawdata or sta_location_rawdata.strip() == "null":
82
- sta_location = ""
83
- else:
84
- sta_location = f"位置:{sta_location_rawdata}\n"
85
-
86
- if sta_serviceclass_rawdata == "":
87
- sta_serviceclass = "本站不办理客运业务\n"
88
- else:
89
- sta_serviceclass = "本站办理客运业务\n"
90
-
91
- hr_line = "------------------------------ \n"
92
- if sta_route_info_rawdata['success'] == False:
93
- sta_route_info_result = f"{hr_line}暂无该车站线路数据\n"
94
- else:
95
- sta_route_info_data = sta_route_info_rawdata['data']
96
- sta_route_info_result = ""
97
- for i in range(len(sta_route_info_data)):
98
- railname = sta_route_info_data[i]['railName']
99
-
100
- next_station_raw = sta_route_info_data[i]['next'][0][2]
101
- terminal_station_raw = sta_route_info_data[i]['next'][0][8]
102
- if next_station_raw == "*" and terminal_station_raw == "*":
103
- next_station = "起迄站"
104
- terminal_station = ""
105
- else:
106
- next_station = next_station_raw
107
- terminal_station = f"({terminal_station_raw})方向"
108
-
109
- prev_station_raw = sta_route_info_data[i]['prev'][0][2]
110
- starting_station_raw = sta_route_info_data[i]['prev'][0][8]
111
- if prev_station_raw == "*" and starting_station_raw == "*":
112
- prev_station = "起迄站"
113
- starting_station = ""
114
- else:
115
- prev_station = prev_station_raw
116
- starting_station = f"({starting_station_raw})方向"
117
-
118
- sta_route_info_result += f"{hr_line}【{railname}】\n 下站{terminal_station}:{next_station}\n 上站{starting_station}:{prev_station}\n"
119
-
120
-
121
- sta_info_result = Message([
122
- "【",sta_name,"】基础信息如下:\n",
123
- sta_telecode,
124
- sta_pinyincode,
125
- sta_bureau,
126
- sta_location,
127
- sta_serviceclass,
128
- sta_route_info_result,
129
- "------------------------------\n \n",
130
- "数据来源:cnrail.geogv.org",
131
-
132
- ])
133
- except (httpx.ReadTimeout,httpx.ConnectTimeout):
134
- sta_info_result = "请求超时,请稍等一下再试"
135
- except Exception as error:
136
- sta_info_result = "发生异常:" + str(error)
137
-
138
- await station_info.finish(sta_info_result)
139
-
140
- else:
141
- await station_info.finish("请输入线路名称")
142
-
@@ -1,55 +0,0 @@
1
- import json
2
- import httpx
3
- import asyncio
4
- import traceback
5
-
6
- from .api import API
7
-
8
- class utils:
9
- """存放各类需要的def定义"""
10
- def time_Formatter_1(time) -> str:
11
- """格式化时间,1145 -> 11:45"""
12
- return time[:2] + ":" + time[2:]
13
-
14
- def time_Formatter_2(time) -> str:
15
- """格式化时间,2025-12-17 14:50:00 -> 14:50"""
16
- return time[11:16]
17
- def EMU_code_formatter(str):
18
- """格式化动车组车号 CRH2A2001 -> CRH2A-2001"""
19
- return str[:-4] + "-" + str[-4:]
20
-
21
- async def cnrail_search(input_text):
22
- """cnrail的搜索模块,获取rail id必用"""
23
- url_search = f"{API.api_cnrail_geogv}match_feature/{input_text}?locale=zhcn&query-override"
24
- async with httpx.AsyncClient(headers=API.headers) as client:
25
- res_search = await client.get(url_search)
26
- res_search_raw_data = json.loads(res_search.text)
27
- res_search_data = res_search_raw_data['data']
28
- return res_search_data
29
-
30
- def get_command_part(raw_message):
31
- """
32
- 获取命令部分
33
- """
34
- space_index = raw_message.find(' ') # 找到空格所在的位置(空格用于分隔指令与参数)
35
- if space_index != -1:
36
- command_part = raw_message[:space_index]
37
- else:
38
- command_part = raw_message
39
-
40
- command_part = command_part.replace('/','')
41
- return command_part
42
-
43
- def short_tb(exc: Exception) -> str:
44
- """
45
- 用于精简TraceBack
46
- """
47
- te = traceback.TracebackException.from_exception(exc)
48
- if te.stack:
49
- last = te.stack[-1]
50
- # 只保留最后一帧
51
- frame = f'File "{last.filename}", line {last.lineno}, in {last.name}\n {last.line}'
52
- else:
53
- frame = "No traceback frame"
54
- exc_only = "".join(te.format_exception_only()).strip()
55
- return f"{frame}\n{exc_only}"