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.
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/PKG-INFO +17 -10
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/README.md +16 -9
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/__init__.py +1 -1
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/api.py +2 -2
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/picture_function.py +32 -4
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/route_info.py +28 -58
- nonebot_plugin_railwaytools-2.2.6/nonebot_plugin_railwaytools/station_info.py +140 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/train_info.py +17 -13
- nonebot_plugin_railwaytools-2.2.6/nonebot_plugin_railwaytools/utils.py +95 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/PKG-INFO +17 -10
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/pyproject.toml +1 -1
- nonebot_plugin_railwaytools-2.2.4/nonebot_plugin_railwaytools/station_info.py +0 -142
- nonebot_plugin_railwaytools-2.2.4/nonebot_plugin_railwaytools/utils.py +0 -55
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/LICENSE +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/emu_function.py +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools/station_screen.py +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/SOURCES.txt +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/dependency_links.txt +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/requires.txt +0 -0
- {nonebot_plugin_railwaytools-2.2.4 → nonebot_plugin_railwaytools-2.2.6}/nonebot_plugin_railwaytools.egg-info/top_level.txt +0 -0
- {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.
|
|
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
|
-
| `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站`
|
|
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
|
-
|
|
313
|
+
由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
|
|
314
|
+
|
|
315
|
+
- 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
|
|
316
316
|
```
|
|
317
317
|
example:
|
|
318
|
-
🤵:/下关站
|
|
318
|
+
🤵:/下关站 HXD1D-1898
|
|
319
319
|
🤖:正在加载图片,时间可能略久...
|
|
320
|
-
🤖:[
|
|
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 (例如:/下关站
|
|
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
|
-
| `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站`
|
|
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
|
-
|
|
295
|
+
由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
|
|
296
|
+
|
|
297
|
+
- 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
|
|
298
298
|
```
|
|
299
299
|
example:
|
|
300
|
-
🤵:/下关站
|
|
300
|
+
🤵:/下关站 HXD1D-1898
|
|
301
301
|
🤖:正在加载图片,时间可能略久...
|
|
302
|
-
🤖:[
|
|
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 (例如:/下关站
|
|
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 (例如:/下关站
|
|
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/
|
|
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/
|
|
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
|
-
|
|
29
|
-
|
|
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("请输入正确的车号!,如:
|
|
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
|
|
47
|
-
|
|
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
|
|
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
|
-
#
|
|
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['
|
|
64
|
+
if route_info_data['lines'] == "2": # 线路形态
|
|
65
65
|
route_info_linenum = "复线铁路"
|
|
66
|
-
elif route_info_data['
|
|
66
|
+
elif route_info_data['lines'] == "1":
|
|
67
67
|
route_info_linenum = "单线铁路"
|
|
68
68
|
else:
|
|
69
|
-
route_info_linenum = route_info_data['
|
|
69
|
+
route_info_linenum = route_info_data['lines']
|
|
70
70
|
|
|
71
|
-
|
|
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 =
|
|
75
|
+
route_info_designSpeed = str(design_speed_raw)
|
|
75
76
|
|
|
76
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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"{
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"{
|
|
100
|
+
train_schedule_info = f"{train_code_raw}次{current_date}{start_station_name}方面正常开行"
|
|
103
101
|
else:
|
|
104
|
-
train_schedule_info = f"{
|
|
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
|
-
|
|
176
|
-
|
|
175
|
+
|
|
176
|
+
train_code_compare = train_code_raw
|
|
177
177
|
for i,stop in enumerate(stop_inf): # 想办法整出时刻表的结果,最后将结果添加到Message中去
|
|
178
|
-
|
|
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
|
-
"车次:",
|
|
199
|
-
"(",start_station_name , "——" , end_station_name , "
|
|
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.
|
|
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
|
-
| `/下关站` [机车车号] | 通过车号查询下关站机车户口照(例如:`/下关站`
|
|
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
|
-
|
|
313
|
+
由于cnrail的更新,现在还支持查询地铁车站。建议在查询地铁站时,在地铁站名后加“地铁站”二字,方便搜索
|
|
314
|
+
|
|
315
|
+
- 通过车号查询下关站收录的机车户口照:`/下关站` [机车车号] 或 `/xgz` [机车车号] (例如:/下关站 HXD1D-1898)
|
|
316
316
|
```
|
|
317
317
|
example:
|
|
318
|
-
🤵:/下关站
|
|
318
|
+
🤵:/下关站 HXD1D-1898
|
|
319
319
|
🤖:正在加载图片,时间可能略久...
|
|
320
|
-
🤖:[
|
|
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 (例如:/下关站
|
|
351
|
+
⑦ 通过车号查询下关站机车户口照:/下关站 或 /xgz (例如:/下关站 HXD1D-1898)
|
|
345
352
|
|
|
346
353
|
⑧ 帮助:/帮助 或 /help
|
|
347
354
|
|
|
@@ -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}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|