mcsmapi 0.1.8b1__py3-none-any.whl → 0.1.8b2__py3-none-any.whl

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.
mcsmapi/__init__.py CHANGED
@@ -11,14 +11,14 @@ from mcsmapi.request import Request
11
11
 
12
12
  class MCSMAPI:
13
13
 
14
- def __init__(self, url: str, timeout: int = 5) -> None:
14
+ def __init__(self, url: str, timeout: int = 5):
15
15
  split_url = urllib.parse.urlsplit(url)
16
16
  Request.set_mcsm_url(
17
17
  urllib.parse.urljoin(f"{split_url.scheme}://{split_url.netloc}", "")
18
18
  )
19
19
  Request.set_timeout(timeout)
20
20
 
21
- def login(self, username: str, password: str) -> "MCSMAPI":
21
+ def login(self, username: str, password: str):
22
22
  Request.set_token(
23
23
  Request.send(
24
24
  "POST",
@@ -34,20 +34,20 @@ class MCSMAPI:
34
34
  self.authentication = "apikey"
35
35
  return self
36
36
 
37
- def overview(self) -> Overview:
37
+ def overview(self):
38
38
  return Overview()
39
39
 
40
- def instance(self) -> Instance:
40
+ def instance(self):
41
41
  return Instance()
42
42
 
43
- def user(self) -> User:
43
+ def user(self) :
44
44
  return User()
45
45
 
46
- def daemon(self) -> Daemon:
46
+ def daemon(self):
47
47
  return Daemon()
48
48
 
49
- def file(self) -> File:
49
+ def file(self):
50
50
  return File()
51
51
 
52
- def image(self) -> Image:
52
+ def image(self):
53
53
  return Image()
mcsmapi/apis/daemon.py CHANGED
@@ -1,12 +1,18 @@
1
1
  from typing import Any
2
2
  from mcsmapi.pool import ApiPool
3
3
  from mcsmapi.request import send
4
- from mcsmapi.models.daemon import DaemonConfig, DaemonModel
4
+ from mcsmapi.models.daemon import (
5
+ DaemonConfig,
6
+ DaemonInfo,
7
+ DaemonSystemInfo,
8
+ DaemonStatus,
9
+ DaemonUpdateConfig,
10
+ )
5
11
 
6
12
 
7
13
  class Daemon:
8
14
  @staticmethod
9
- def show() -> list[DaemonConfig]:
15
+ def config() -> list[DaemonStatus]:
10
16
  """
11
17
  获取全部节点配置信息
12
18
 
@@ -16,10 +22,23 @@ class Daemon:
16
22
  "GET",
17
23
  f"{ApiPool.SERVICE}/remote_services_list",
18
24
  )
19
- return [DaemonConfig(**daemon) for daemon in daemons]
25
+ return [DaemonStatus(**daemon) for daemon in daemons]
20
26
 
21
27
  @staticmethod
22
- def system() -> list[DaemonModel]:
28
+ def info() -> list[DaemonInfo]:
29
+ """
30
+ 获取全部节点信息
31
+
32
+ :returns: 节点信息列表
33
+ """
34
+ daemons = send(
35
+ "GET",
36
+ f"{ApiPool.SERVICE}/remote_services",
37
+ )
38
+ return [DaemonInfo(**daemon) for daemon in daemons]
39
+
40
+ @staticmethod
41
+ def system() -> list[DaemonSystemInfo]:
23
42
  """
24
43
  获取全部节点的系统信息
25
44
 
@@ -29,7 +48,7 @@ class Daemon:
29
48
  "GET",
30
49
  f"{ApiPool.SERVICE}/remote_services_system",
31
50
  )
32
- return [DaemonModel(**daemon) for daemon in daemons]
51
+ return [DaemonSystemInfo(**daemon) for daemon in daemons]
33
52
 
34
53
  @staticmethod
35
54
  def add(config: dict[str, Any]) -> str:
@@ -53,7 +72,7 @@ class Daemon:
53
72
 
54
73
  :params daemonId: 节点的UUID
55
74
 
56
- :returns: 删除成功后返回True
75
+ :returns: 操作成功后返回True
57
76
  """
58
77
  return send(
59
78
  "DELETE", f"{ApiPool.SERVICE}/remote_service", params={"uuid": daemonId}
@@ -66,7 +85,7 @@ class Daemon:
66
85
 
67
86
  :params daemonId: 节点的UUID
68
87
 
69
- :returns: 连接成功后返回True
88
+ :returns: 操作成功后返回True
70
89
  """
71
90
  return send(
72
91
  "GET", f"{ApiPool.SERVICE}/link_remote_service", params={"uuid": daemonId}
@@ -77,16 +96,14 @@ class Daemon:
77
96
  """
78
97
  更新一个节点的配置
79
98
 
80
- **不建议直接使用此函数,建议调用overview()后在remote属性内使用节点对象的updateConfig方法按需更新**
81
-
82
99
  :params daemonId: 节点的UUID
83
- :params config: 节点的配置信息,以字典形式提供,缺失内容由DaemonConfig模型补全
100
+ :params config: 节点的配置信息,以字典形式提供,缺失内容由DaemonUpdateConfig模型补全
84
101
 
85
- :returns: 更新成功后返回True
102
+ :returns: 操作成功后返回True
86
103
  """
87
104
  return send(
88
105
  "PUT",
89
106
  f"{ApiPool.SERVICE}/remote_service",
90
107
  params={"uuid": daemonId},
91
- data=DaemonConfig(**config).model_dump(),
108
+ data=DaemonUpdateConfig(**config).model_dump(),
92
109
  )
mcsmapi/apis/file.py CHANGED
@@ -70,7 +70,7 @@ class File:
70
70
  :params target: 目标文件的路径
71
71
  :params text: 新的文件内容
72
72
 
73
- :returns: 更新成功后返回True
73
+ :returns: 操作成功后返回True
74
74
  """
75
75
  return send(
76
76
  "PUT",
@@ -111,7 +111,7 @@ class File:
111
111
  :params file: 要上传的文件内容
112
112
  :params upload_dir: 文件上传到的目标路径
113
113
 
114
- :returns: 上传成功后返回True
114
+ :returns: 操作成功后返回True
115
115
  """
116
116
  result = send(
117
117
  "POST",
@@ -134,7 +134,7 @@ class File:
134
134
  :params uuid: 实例的UUID
135
135
  :params copy_map: 复制映射,格式为 {源路径: 目标路径}
136
136
 
137
- :returns: 复制成功后返回True
137
+ :returns: 操作成功后返回True
138
138
  """
139
139
  targets = [[source, target] for source, target in copy_map.items()]
140
140
  return send(
@@ -154,7 +154,7 @@ class File:
154
154
  :params source: 源文件或文件夹的路径
155
155
  :params target: 目标文件或文件夹的路径
156
156
 
157
- :return: 移动成功后返回True
157
+ :returns: 操作成功后返回True
158
158
  """
159
159
  return File.copy(daemonId, uuid, {source: target})
160
160
 
@@ -167,7 +167,7 @@ class File:
167
167
  :params uuid: 实例的UUID
168
168
  :params copy_map: 移动映射,格式为 {源路径: 目标路径}
169
169
 
170
- :returns: 移动成功后返回True
170
+ :returns: 操作成功后返回True
171
171
  """
172
172
  targets = [[source, target] for source, target in copy_map.items()]
173
173
  return send(
@@ -187,7 +187,7 @@ class File:
187
187
  :params source: 源文件或文件夹的路径
188
188
  :params target: 目标文件或文件夹的路径
189
189
 
190
- :returns: 移动成功后返回True
190
+ :returns: 操作成功后返回True
191
191
  """
192
192
  return File.move(daemonId, uuid, {source: target})
193
193
 
@@ -201,7 +201,7 @@ class File:
201
201
  :params source: 源文件或文件夹的路径
202
202
  :params new_name: 源文件或文件夹的新名字
203
203
 
204
- :returns: 重命名成功后返回True
204
+ :returns: 操作成功后返回True
205
205
  """
206
206
  directory = os.path.dirname(source)
207
207
  target = os.path.join(directory, new_name)
@@ -217,8 +217,7 @@ class File:
217
217
  :params source: 要压缩到的目标文件的路径
218
218
  :params targets: 需要压缩的文件路径
219
219
 
220
- **返回:**
221
- - bool: 压缩成功后返回True
220
+ :returns: 操作成功后返回True
222
221
  """
223
222
  return send(
224
223
  "POST",
@@ -244,7 +243,7 @@ class File:
244
243
  :params targets: 解压到的目标路径
245
244
  :params code: 压缩文件的编码方式
246
245
 
247
- :returns: 解压成功后返回True
246
+ :returns: 操作成功后返回True
248
247
  """
249
248
  return send(
250
249
  "POST",
@@ -262,7 +261,7 @@ class File:
262
261
  :params uuid: 实例的UUID
263
262
  :params targets: 要删除的文件或文件夹的路径
264
263
 
265
- :returns: 删除成功后返回True
264
+ :returns: 操作成功后返回True
266
265
  """
267
266
  return send(
268
267
  "DELETE",
@@ -280,7 +279,7 @@ class File:
280
279
  :params uuid: 实例的UUID
281
280
  :params target: 目标文件的路径,包含文件名
282
281
 
283
- :returns: 创建成功后返回True
282
+ :returns: 操作成功后返回True
284
283
  """
285
284
  return send(
286
285
  "POST",
@@ -298,7 +297,7 @@ class File:
298
297
  :params uuid: 实例的UUID
299
298
  :params target: 目标文件夹的路径
300
299
 
301
- :returns: 创建成功后返回True
300
+ :returns: 操作成功后返回True
302
301
  """
303
302
  return send(
304
303
  "POST",
mcsmapi/apis/image.py CHANGED
@@ -70,7 +70,7 @@ class Image:
70
70
  :params name: 镜像名称
71
71
  :params tag: 镜像版本
72
72
 
73
- :returns: 新增镜像成功后返回True
73
+ :returns: 操作成功后返回True
74
74
  """
75
75
  return send(
76
76
  "POST",
mcsmapi/apis/instance.py CHANGED
@@ -63,7 +63,7 @@ class Instance:
63
63
  ApiPool.INSTANCE,
64
64
  params={"uuid": uuid, "daemonId": daemonId},
65
65
  )
66
- return InstanceDetail(**result)
66
+ return InstanceDetail(**result, daemonId=daemonId)
67
67
 
68
68
  @staticmethod
69
69
  def create(daemonId: str, config: dict[str, Any]) -> InstanceCreateResult:
@@ -94,7 +94,7 @@ class Instance:
94
94
  :params uuid: 实例的UUID
95
95
  :params config: 新的实例配置,以字典形式提供,缺失内容由InstanceConfig模型补全
96
96
 
97
- :returns: 更新成功后返回更新的实例UUID
97
+ :returns: 被更新配置的实例UUID
98
98
  """
99
99
  result = send(
100
100
  "PUT",
@@ -109,7 +109,7 @@ class Instance:
109
109
  """
110
110
  删除实例
111
111
 
112
- :params daemonId: 节点的标识符
112
+ :params daemonId: 节点的UUID
113
113
  :params uuids: 要删除的实例UUID列表
114
114
  :params deleteFile: 是否删除关联的文件
115
115
 
@@ -130,7 +130,7 @@ class Instance:
130
130
  :params daemonId: 节点的UUID
131
131
  :params uuid: 实例的UUID
132
132
 
133
- :returns: 返回被操作的实例的UUID
133
+ :returns: 被启动的实例的UUID
134
134
  """
135
135
  result = send(
136
136
  "GET",
@@ -147,7 +147,7 @@ class Instance:
147
147
  :params daemonId: 节点的UUID
148
148
  :params uuid: 实例的UUID
149
149
 
150
- :returns: 返回被操作的实例的UUID
150
+ :returns: 被关闭的实例的UUID
151
151
  """
152
152
  result = send(
153
153
  "GET",
@@ -164,7 +164,7 @@ class Instance:
164
164
  :params daemonId: 节点的UUID
165
165
  :params uuid: 实例的UUID
166
166
 
167
- :returns: 返回被操作的实例的UUID
167
+ :returns: 被重启的实例的UUID
168
168
  """
169
169
  result = send(
170
170
  "GET",
@@ -181,7 +181,7 @@ class Instance:
181
181
  :params daemonId: 节点的UUID
182
182
  :params uuid: 实例的UUID
183
183
 
184
- :returns: 返回被操作的实例的UUID
184
+ :returns: 被强制关闭的实例的UUID
185
185
  """
186
186
  result = send(
187
187
  "GET",
@@ -230,7 +230,7 @@ class Instance:
230
230
  :params uuid: 实例的UUID
231
231
  :params command: 要发送的命令
232
232
 
233
- :params: 返回被操作的实例的UUID
233
+ :returns: 被操作的实例的UUID
234
234
  """
235
235
  result = send(
236
236
  "GET",
mcsmapi/models/common.py CHANGED
@@ -21,7 +21,7 @@ class ProcessInfo(BaseModel):
21
21
  """工作路径"""
22
22
 
23
23
 
24
- class InstanceInfo(BaseModel):
24
+ class InstanceStat(BaseModel):
25
25
  """实例统计信息"""
26
26
 
27
27
  running: int
mcsmapi/models/daemon.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from typing import Any
2
2
  from pydantic import BaseModel
3
- from mcsmapi.models.instance import InstanceCreateResult
4
- from mcsmapi.models.common import ProcessInfo, InstanceInfo, CpuMemChart
3
+ from mcsmapi.models.instance import InstanceCreateResult, InstanceDetail
4
+ from mcsmapi.models.common import ProcessInfo, InstanceStat, CpuMemChart
5
5
 
6
6
 
7
- class DaemonSystemInfo(BaseModel):
7
+ class SystemInfo(BaseModel):
8
8
  """节点系统信息"""
9
9
 
10
10
  type: str
@@ -35,37 +35,50 @@ class DaemonSystemInfo(BaseModel):
35
35
  """未知"""
36
36
 
37
37
 
38
- class DaemonModel(BaseModel):
39
- """节点详细信息"""
38
+ class DaemonSetting(BaseModel):
39
+ """节点系统配置信息"""
40
+
41
+ language: str
42
+ """节点语言"""
43
+ uploadSpeedRate: int
44
+ """上传速度限制(0为不限制, 限制为(n * 64)KB/s)"""
45
+ downloadSpeedRate: int
46
+ """下载速度限制(0为不限制, 限制为(n * 64)KB/s)"""
47
+ portRangeStart: int
48
+ """端口范围起始值"""
49
+ portRangeEnd: int
50
+ """端口范围结束值"""
51
+ portAssignInterval: int
52
+ """未知"""
53
+ port: int
54
+ """节点监听端口"""
55
+
56
+
57
+ class DaemonSystemInfo(BaseModel):
58
+ """节点系统信息"""
40
59
 
41
- version: str
60
+ version: str | None = None
42
61
  """远程节点版本"""
43
- process: ProcessInfo
62
+ process: ProcessInfo | None = None
44
63
  """远程节点的基本信息"""
45
- instance: InstanceInfo
64
+ instance: InstanceStat | None = None
46
65
  """远程节点实例基本信息"""
47
- system: DaemonSystemInfo
66
+ system: SystemInfo | None = None
48
67
  """远程节点系统信息"""
49
- cpuMemChart: list[CpuMemChart]
68
+ cpuMemChart: list[CpuMemChart] | None = None
50
69
  """cpu和内存使用趋势"""
70
+ config: DaemonSetting
71
+
72
+
73
+ class DaemonOperation(BaseModel):
51
74
  uuid: str
52
- """远程节点的uuid"""
53
- ip: str
54
- """远程节点的ip"""
55
- port: int
56
- """远程节点的端口"""
57
- prefix: str
58
- """远程节点的路径前缀"""
59
- available: bool
60
- """远程节点的可用状态"""
61
- remarks: str
62
- """远程节点的名称"""
75
+ """节点UUID"""
63
76
 
64
77
  def delete(self):
65
78
  """
66
79
  删除该节点
67
80
 
68
- :returns: 删除成功后返回True
81
+ :returns: 操作成功后返回True
69
82
  """
70
83
  from mcsmapi.apis.daemon import Daemon
71
84
 
@@ -75,7 +88,7 @@ class DaemonModel(BaseModel):
75
88
  """
76
89
  尝试连接该节点
77
90
 
78
- :returns: 连接成功后返回True
91
+ :returns: 操作成功后返回True
79
92
  """
80
93
  from mcsmapi.apis.daemon import Daemon
81
94
 
@@ -87,20 +100,14 @@ class DaemonModel(BaseModel):
87
100
 
88
101
  :params config: 节点的配置信息,以字典形式提供,缺失内容使用原节点配置填充
89
102
 
90
- :returns: 更新成功后返回True
103
+ :returns: 操作成功后返回True
91
104
  """
92
105
  from mcsmapi.apis.daemon import Daemon
93
106
 
94
107
  updated_config = self.model_dump()
95
108
  updated_config.update(config)
96
- # 过滤节点配置中不需要的字段
97
- daemon_config_dict = {
98
- key: updated_config[key]
99
- for key in DaemonConfig.model_fields.keys()
100
- if key in updated_config
101
- }
102
109
 
103
- daemon_config = DaemonConfig(**daemon_config_dict).model_dump()
110
+ daemon_config = DaemonUpdateConfig(**updated_config).model_dump()
104
111
 
105
112
  return Daemon.update(self.uuid, daemon_config)
106
113
 
@@ -140,7 +147,31 @@ class DaemonConfig(BaseModel):
140
147
  """远程节点的端口"""
141
148
  prefix: str = ""
142
149
  """远程节点的路径前缀"""
143
- remarks: str = "New Daemon"
150
+ remarks: str = "Unnamed Node"
144
151
  """远程节点的备注"""
145
- available: bool = True
146
- """远程节点的可用状态"""
152
+ apiKey: str = ""
153
+ """远程节点的apiKey"""
154
+
155
+
156
+ class DaemonStatus(DaemonOperation):
157
+ """节点状态信息"""
158
+ ip: str = "localhost"
159
+ """远程节点的ip"""
160
+ port: int = 24444
161
+ """远程节点的端口"""
162
+ prefix: str = ""
163
+ """远程节点的路径前缀"""
164
+ remarks: str = "Unnamed Node"
165
+ """远程节点的备注"""
166
+ available: bool
167
+ """节点可用状态"""
168
+
169
+
170
+ class DaemonInfo(DaemonStatus):
171
+ """节点信息"""
172
+ instances: list[InstanceDetail]
173
+
174
+
175
+ class DaemonUpdateConfig(DaemonConfig):
176
+ """节点更新配置信息"""
177
+ setting: DaemonSetting
mcsmapi/models/file.py CHANGED
@@ -1,10 +1,12 @@
1
1
  from enum import IntEnum
2
- from typing import Literal
3
- from pydantic import BaseModel
2
+ from typing import Any, Literal
3
+ from pydantic import BaseModel, field_validator
4
4
  import os
5
5
 
6
6
 
7
7
  class FileType(IntEnum):
8
+ """文件类型"""
9
+
8
10
  FOLDER = 0
9
11
  FILE = 1
10
12
 
@@ -13,7 +15,7 @@ class FileItem(BaseModel):
13
15
  """文件信息"""
14
16
 
15
17
  name: str
16
- """文件名称"""
18
+ """文件或文件夹名称"""
17
19
  size: int
18
20
  """文件大小(单位: byte)"""
19
21
  time: str
@@ -37,7 +39,7 @@ class FileItem(BaseModel):
37
39
 
38
40
  :params new_name: 源文件或文件夹的新名字
39
41
 
40
- :returns: 重命名成功后返回True
42
+ :returns: 操作成功后返回True
41
43
  """
42
44
  from mcsmapi.apis.file import File
43
45
 
@@ -49,7 +51,7 @@ class FileItem(BaseModel):
49
51
  """
50
52
  删除该文件或文件夹
51
53
 
52
- :returns: 重命名成功后返回True
54
+ :returns: 操作成功后返回True
53
55
  """
54
56
  from mcsmapi.apis.file import File
55
57
 
@@ -57,13 +59,13 @@ class FileItem(BaseModel):
57
59
  self.daemonId, self.uuid, [os.path.join(self.target, self.name)]
58
60
  )
59
61
 
60
- def copy(self, target: str):
62
+ def copy2(self, target: str):
61
63
  """
62
64
  复制该文件或文件夹到目标路径
63
65
 
64
66
  :param target: 目标路径
65
67
 
66
- :returns: 复制成功后返回True
68
+ :returns: 操作成功后返回True
67
69
  """
68
70
  from mcsmapi.apis.file import File
69
71
 
@@ -77,7 +79,7 @@ class FileItem(BaseModel):
77
79
 
78
80
  :params target: 目标文件或文件夹的路径
79
81
 
80
- :returns: 移动成功后返回True
82
+ :returns: 操作成功后返回True
81
83
  """
82
84
  from mcsmapi.apis.file import File
83
85
 
@@ -99,13 +101,11 @@ class FileItem(BaseModel):
99
101
 
100
102
  def zip(self, targets: list[str]):
101
103
  """
102
- 压缩多个文件或文件夹到指定位置
104
+ 压缩该文件或文件夹到指定位置
103
105
 
104
- **参数:**
105
- - targets (list): 要压缩到的目标文件的路径
106
+ :params targets: 要压缩到的目标文件的路径
106
107
 
107
- **返回:**
108
- - bool: 压缩成功后返回True
108
+ :returns: 操作成功后返回True
109
109
  """
110
110
  from mcsmapi.apis.file import File
111
111
 
@@ -113,19 +113,14 @@ class FileItem(BaseModel):
113
113
  self.daemonId, self.uuid, os.path.join(self.target, self.name), targets
114
114
  )
115
115
 
116
- def unzip(
117
- self, target: str, code: Literal["utf-8", "gbk", "big5"] = "utf-8"
118
- ) -> bool:
116
+ def unzip(self, target: str, code: Literal["utf-8", "gbk", "big5"] = "utf-8"):
119
117
  """
120
118
  解压缩该 zip 文件到目标位置
121
119
 
122
- **参数:**
123
- - target (str): 解压到的目标路径
124
- - code (str, optional): 压缩文件的编码方式,默认为"utf-8"
125
- 可选值: utf-8, gbk, big5
120
+ :params target: 解压到的目标路径
121
+ :params code: 压缩文件的编码方式
126
122
 
127
- **返回:**
128
- - bool: 解压成功后返回True
123
+ :returns: 操作成功后返回True
129
124
  """
130
125
  from mcsmapi.apis.file import File
131
126
 
@@ -133,13 +128,13 @@ class FileItem(BaseModel):
133
128
  self.daemonId, self.uuid, os.path.join(self.target, self.name), target, code
134
129
  )
135
130
 
136
- def update(self, text: str) -> bool:
131
+ def update(self, text: str):
137
132
  """
138
133
  更新该文件内容
139
- **参数:**
140
- - text (str): 文件内容
141
- **返回:**
142
- - bool: 更新成功后返回True
134
+
135
+ :params text: 文件内容
136
+
137
+ :returns: 操作成功后返回True
143
138
  """
144
139
  from mcsmapi.apis.file import File
145
140
 
@@ -147,11 +142,11 @@ class FileItem(BaseModel):
147
142
  self.daemonId, self.uuid, os.path.join(self.target, self.name), text
148
143
  )
149
144
 
150
- def download(self) -> str:
145
+ def download(self):
151
146
  """
152
147
  下载该文件
153
- **返回:**
154
- - str: 文件下载的URL
148
+
149
+ :returns: 文件下载的URL
155
150
  """
156
151
  from mcsmapi.apis.file import File
157
152
 
@@ -180,23 +175,30 @@ class FileList(BaseModel):
180
175
  target: str
181
176
  """文件(名称或目录)路径"""
182
177
 
183
- def __init__(self, **data: str):
184
- super().__init__(**data)
185
- for item in self.items:
186
- item.daemonId = self.daemonId
187
- item.uuid = self.uuid
188
- item.target = self.target
178
+ @field_validator("items", mode="before")
179
+ @classmethod
180
+ def fill_info(cls, v: Any, info) -> Any:
181
+ """在验证 items 字段前填充基本信息"""
182
+ if isinstance(info.data, dict):
183
+ daemon_id = info.data.get("daemonId", "")
184
+ uuid = info.data.get("uuid", "")
185
+ target = info.data.get("target", "")
186
+ if isinstance(v, list):
187
+ for item in v:
188
+ if isinstance(item, dict):
189
+ item["daemonId"] = daemon_id
190
+ item["uuid"] = uuid
191
+ item["target"] = target
192
+ return v
189
193
 
190
194
  async def upload(self, file: bytes, upload_dir: str) -> bool:
191
195
  """
192
196
  上传文件到实例
193
197
 
194
- **参数:**
195
- - file (bytes): 要上传的文件内容
196
- - upload_dir (str): 上传文件的目标目录(包含文件名)
198
+ :params file: 要上传的文件内容
199
+ :params upload_dir: 文件上传到的目标路径
197
200
 
198
- **返回:**
199
- - bool: 操作成功返回True
201
+ :returns: 操作成功返回True
200
202
  """
201
203
  from mcsmapi.apis.file import File
202
204
 
@@ -206,11 +208,9 @@ class FileList(BaseModel):
206
208
  """
207
209
  创建文件
208
210
 
209
- **参数:**
210
- - target (str): 目标文件的路径,包含文件名
211
+ :params target: 目标文件的路径,包含文件名
211
212
 
212
- **返回:**
213
- - bool: 创建成功后返回True
213
+ :returns: 操作成功后返回True
214
214
  """
215
215
  from mcsmapi.apis.file import File
216
216
 
@@ -220,11 +220,9 @@ class FileList(BaseModel):
220
220
  """
221
221
  创建文件夹
222
222
 
223
- **参数:**
224
- - target (str): 目标文件夹的路径
223
+ :params target: 目标文件夹的路径
225
224
 
226
- **返回:**
227
- - bool: 创建成功后返回True
225
+ :returns: 操作成功后返回True
228
226
  """
229
227
  from mcsmapi.apis.file import File
230
228
 
@@ -1,6 +1,6 @@
1
1
  from enum import IntEnum
2
2
  from typing import Any, TypedDict
3
- from pydantic import BaseModel
3
+ from pydantic import BaseModel, field_validator
4
4
  from mcsmapi.models.image import DockerConfig
5
5
 
6
6
 
@@ -121,55 +121,15 @@ class InstanceConfig(BaseModel):
121
121
  """运行该实例的系统用户,为空则使用启动面板的系统用户"""
122
122
 
123
123
 
124
- class InstanceProcessInfo(BaseModel):
125
- """进程信息"""
126
-
127
- cpu: int
128
- """CPU 使用率 (单位: %)"""
129
- memory: int
130
- """进程占用内存 (单位: KB)"""
131
- ppid: int
132
- """父进程 ID"""
133
- pid: int
134
- """进程 ID"""
135
- ctime: int
136
- """进程创建时间 (Unix 时间戳)"""
137
- elapsed: int
138
- """进程运行时长 (单位: 秒)"""
139
- timestamp: int
140
- """时间戳"""
141
-
142
-
143
- class InstanceInfo(BaseModel):
144
- """实例运行状态信息(这些选项在新版中已不再支持设置,但仍在API中返回)"""
145
-
146
- currentPlayers: int
147
- """当前玩家数量"""
148
- fileLock: int = 0
149
- """文件锁状态 (0: 无锁)"""
150
- maxPlayers: int = -1
151
- """最大允许玩家数 (-1 表示未知)"""
152
- openFrpStatus: bool = False
153
- """是否启用 FRP 远程服务"""
154
- playersChart: list[dict] = []
155
- """玩家数量变化图表数据"""
156
- version: str = ""
157
- """服务器版本"""
158
-
159
-
160
124
  class InstanceDetail(BaseModel):
161
125
  """实例详细信息"""
162
126
 
163
127
  config: InstanceConfig
164
128
  """实例的配置信息"""
165
- info: InstanceInfo
166
- """实例的运行状态信息"""
167
129
  daemonId: str
168
130
  """所属的节点UUID"""
169
131
  instanceUuid: str
170
132
  """实例UUID"""
171
- processInfo: InstanceProcessInfo
172
- """实例的进程信息"""
173
133
  started: int
174
134
  """实例的启动次数"""
175
135
  status: Status
@@ -179,7 +139,7 @@ class InstanceDetail(BaseModel):
179
139
  """
180
140
  启动该实例
181
141
 
182
- :returns: 返回被操作的实例的UUID
142
+ :returns: 被启动的实例的UUID
183
143
  """
184
144
  from mcsmapi.apis.instance import Instance
185
145
 
@@ -189,7 +149,7 @@ class InstanceDetail(BaseModel):
189
149
  """
190
150
  停止该实例
191
151
 
192
- :returns: 返回被操作的实例的UUID
152
+ :returns: 被停止的实例的UUID
193
153
  """
194
154
  from mcsmapi.apis.instance import Instance
195
155
 
@@ -199,7 +159,7 @@ class InstanceDetail(BaseModel):
199
159
  """
200
160
  重启该实例
201
161
 
202
- :returns: 返回被操作的实例的UUID
162
+ :returns: 被重启的实例的UUID
203
163
  """
204
164
  from mcsmapi.apis.instance import Instance
205
165
 
@@ -209,16 +169,18 @@ class InstanceDetail(BaseModel):
209
169
  """
210
170
  强制关闭该实例
211
171
 
212
- :returns: 返回被操作的实例的UUID
172
+ :returns: 被强制关闭的实例的UUID
213
173
  """
214
174
  from mcsmapi.apis.instance import Instance
215
175
 
216
176
  return Instance.kill(self.daemonId, self.instanceUuid)
217
177
 
218
- def delete(self, deleteFile=False):
178
+ def delete(self, deleteFile: bool = False):
219
179
  """
220
180
  删除该实例
221
181
 
182
+ :params deleteFile: 是否删除关联的文件
183
+
222
184
  :returns: 被删除的实例的uuid
223
185
  """
224
186
  from mcsmapi.apis.instance import Instance
@@ -268,6 +230,30 @@ class InstanceDetail(BaseModel):
268
230
  self.daemonId, self.instanceUuid, targetUrl, title, description
269
231
  )
270
232
 
233
+ def command(self, command: str) -> str:
234
+ """
235
+ 发送命令给实例
236
+
237
+ :params command: 要发送的命令
238
+
239
+ :returns: 被操作的实例的UUID
240
+ """
241
+ from mcsmapi.apis.instance import Instance
242
+
243
+ return Instance.command(self.daemonId, self.instanceUuid, command)
244
+
245
+ def get_output(self, size: int | None = None) -> str:
246
+ """
247
+ 获取实例的输出
248
+
249
+ :params size: 要获取的输出大小
250
+
251
+ :returns: 输出结果
252
+ """
253
+ from mcsmapi.apis.instance import Instance
254
+
255
+ return Instance.get_output(self.daemonId, self.instanceUuid, size)
256
+
271
257
  def files(
272
258
  self, target: str = "", page: int = 0, page_size: int = 100, file_name: str = ""
273
259
  ):
@@ -291,9 +277,9 @@ class InstanceDetail(BaseModel):
291
277
  class InstanceCreateResult(BaseModel):
292
278
  """实例创建结果"""
293
279
 
294
- instanceUuid: str = ""
280
+ instanceUuid: str
295
281
  """实例UUID"""
296
- config: InstanceConfig = InstanceConfig()
282
+ config: InstanceConfig
297
283
  """实例的配置信息"""
298
284
 
299
285
 
@@ -309,11 +295,17 @@ class InstanceSearchList(BaseModel):
309
295
  daemonId: str = ""
310
296
  """所属的节点UUID"""
311
297
 
312
- def __init__(self, **data: str):
313
- """实例化对象,并在每个实例中填充 daemonId"""
314
- super().__init__(**data)
315
- for instance in self.data:
316
- instance.daemonId = self.daemonId
298
+ @field_validator("data", mode="before")
299
+ @classmethod
300
+ def fill_daemon_id(cls, v: Any, info) -> Any:
301
+ """在验证 data 字段前填充 daemonId"""
302
+ if isinstance(info.data, dict):
303
+ daemon_id = info.data.get("daemonId", "")
304
+ if isinstance(v, list):
305
+ for instance in v:
306
+ if isinstance(instance, dict):
307
+ instance["daemonId"] = daemon_id
308
+ return v
317
309
 
318
310
 
319
311
  class UserInstancesList(BaseModel):
@@ -2,7 +2,7 @@ from enum import Enum
2
2
  from typing import Literal
3
3
  from pydantic import BaseModel
4
4
  from mcsmapi.models.common import CpuMemChart, ProcessInfo
5
- from mcsmapi.models.daemon import DaemonModel
5
+ from mcsmapi.models.daemon import DaemonSystemInfo
6
6
 
7
7
 
8
8
  class SystemUser(BaseModel):
@@ -110,7 +110,7 @@ class OverviewModel(BaseModel):
110
110
  """系统与请求统计图表数据"""
111
111
  remoteCount: RemoteCountInfo
112
112
  """远程节点统计信息"""
113
- remote: list[DaemonModel]
113
+ remote: list[DaemonSystemInfo]
114
114
  """远程节点详细信息"""
115
115
 
116
116
 
mcsmapi/models/user.py CHANGED
@@ -57,7 +57,7 @@ class UserModel(BaseModel):
57
57
  """
58
58
  删除该用户
59
59
 
60
- :returns: 删除成功后返回True
60
+ :returns: 操作成功后返回True
61
61
  """
62
62
  from mcsmapi.apis.user import User
63
63
 
@@ -69,20 +69,13 @@ class UserModel(BaseModel):
69
69
 
70
70
  :params config: 用户的新信息,以字典形式提供,缺失内容使用原用户信息填充
71
71
 
72
- :returns: 更新成功后返回True
72
+ :returns: 操作成功后返回True
73
73
  """
74
74
  from mcsmapi.apis.user import User
75
75
 
76
76
  updated_config = self.model_dump()
77
77
  updated_config.update(config)
78
- # 过滤用户信息中不需要的字段
79
- user_config_dict = {
80
- key: updated_config[key]
81
- for key in UserConfig.model_fields.keys()
82
- if key in updated_config
83
- }
84
-
85
- user_config = UserConfig(**user_config_dict).model_dump()
78
+ user_config = UserConfig(**updated_config).model_dump()
86
79
 
87
80
  return User().update(self.uuid, user_config)
88
81
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcsmapi
3
- Version: 0.1.8b1
3
+ Version: 0.1.8b2
4
4
  Summary: Shortcut the pypi package of MCSM./快捷操作MCSM的pypi包
5
5
  Author-email: molanp <molanpp@outlook.com>
6
6
  License-Expression: MIT
@@ -32,7 +32,7 @@ The documentation is not yet complete, if you need it, please visit [deepwiki-mc
32
32
 
33
33
  You can also find:
34
34
 
35
- 📄 Work-in-progress docs: [docs](docs)
35
+ 📄 Work-in-progress docs: [docs](https://mcsmapi.awkchan.top/en/)
36
36
 
37
37
  💡 Example: [example](example)
38
38
 
@@ -50,7 +50,7 @@ You can install `mcsmapi` using `pip`:
50
50
  pip install mcsmapi
51
51
  ```
52
52
 
53
- If you need the latest build files (untested), please visit
53
+ If you need the latest build files, please visit
54
54
  [Actions](https://github.com/molanp/mcsmapi/actions/workflows/auto-build.yml)
55
55
 
56
56
  ## Supported Features
@@ -0,0 +1,24 @@
1
+ mcsmapi/__init__.py,sha256=e5rSZDGOeaq-Wky85uQokqDBMt-v7Ktp6GTH0PVRUkc,1339
2
+ mcsmapi/exceptions.py,sha256=mHsAHyoX9SiFDGBMEhesA_ao9hhZZ38EGTp97K7VDp8,184
3
+ mcsmapi/pool.py,sha256=Xa1DvBdfn5zTZ-eB50BFbYxhKX8j-4vfus9QOGO_FQE,348
4
+ mcsmapi/request.py,sha256=G6O4Q3oXidmauyraUgoMTkms5XFlY-iHPhZ3s0k9TmM,2743
5
+ mcsmapi/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ mcsmapi/apis/daemon.py,sha256=fdoZIuS-8Hm9YS3YeCDmxJwOFGp4KaqnHlwQum2JBRU,2827
7
+ mcsmapi/apis/file.py,sha256=pCjZUl5W6F8Y0WBhRf0dsefnNqX8pKpXGehCwYM-8N0,9610
8
+ mcsmapi/apis/image.py,sha256=JcRESUz9j6kozWT7XAr-PoVIyoDvl55OSdjYB33yFpw,2650
9
+ mcsmapi/apis/instance.py,sha256=Ttu7Ww5C7FOdUNrl5VBWjWhr_lMuRnjvbqHgg1BjntE,8297
10
+ mcsmapi/apis/overview.py,sha256=7wRAdhFzbtLq6Oknj4_ncO5fETZuZCGtliErA0NNju0,514
11
+ mcsmapi/apis/user.py,sha256=KXd8OPjyQBprPTlJD-wLGE-BtaOsM_0WF1yqRlGgTfg,2414
12
+ mcsmapi/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ mcsmapi/models/common.py,sha256=SoJt0fFab9hCzWI8ubQDPyep9YCXmny4bCy9utFNW9o,531
14
+ mcsmapi/models/daemon.py,sha256=nBxks9FOHxxIKr3oNE-FPjXQ6VJn0pPZ48UDI8Z3Ru0,4791
15
+ mcsmapi/models/file.py,sha256=w7KVUauGGp6w1BVm9QlR6kM0hBZJ12wLVkqRvNS-HJ8,6031
16
+ mcsmapi/models/image.py,sha256=mpyS7KTVoOwH2opB-fQC2GD3An_bXcERLmLPDBuoYUA,5643
17
+ mcsmapi/models/instance.py,sha256=YBaMAZfG1PvZAXy9FLog-vptnC9_umTNRSV1-g1xO4U,8219
18
+ mcsmapi/models/overview.py,sha256=2mytJbI6mivNqytIjd8ddkgL4wJcADa2HrTVeqlrkFI,5294
19
+ mcsmapi/models/user.py,sha256=Vbjx8H1_o0ovB8PdLK2eHNIfadK5vR4wLeXOkMmH_HU,3098
20
+ mcsmapi-0.1.8b2.dist-info/licenses/LICENSE,sha256=bMKDPsvaybvY-4TTlSZtCXPPtxb7KPpDVqXgDA8Ogo0,1068
21
+ mcsmapi-0.1.8b2.dist-info/METADATA,sha256=WYRN8v3Sb4-b4Ekg6FWl4k-Uo0f77GBugSs2mhnjthY,3048
22
+ mcsmapi-0.1.8b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ mcsmapi-0.1.8b2.dist-info/top_level.txt,sha256=8MUYHd1Or4cbSCd93IaqLA72w0weEuKieopVwIfVlWo,8
24
+ mcsmapi-0.1.8b2.dist-info/RECORD,,
@@ -1,24 +0,0 @@
1
- mcsmapi/__init__.py,sha256=TxBjQPMtwR_Eh0N7nZAoKinONAgnDsSbt47-cLvbeLk,1418
2
- mcsmapi/exceptions.py,sha256=mHsAHyoX9SiFDGBMEhesA_ao9hhZZ38EGTp97K7VDp8,184
3
- mcsmapi/pool.py,sha256=Xa1DvBdfn5zTZ-eB50BFbYxhKX8j-4vfus9QOGO_FQE,348
4
- mcsmapi/request.py,sha256=G6O4Q3oXidmauyraUgoMTkms5XFlY-iHPhZ3s0k9TmM,2743
5
- mcsmapi/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- mcsmapi/apis/daemon.py,sha256=0ng7Twv04gs4y09AYFIH2o5YPoxGV3c3TwsUkqxpgTI,2555
7
- mcsmapi/apis/file.py,sha256=1SYNw-6Qaiq5knS0Pu1_7-y82WtcB6EOHPGakYvvqjQ,9630
8
- mcsmapi/apis/image.py,sha256=ajTiZXSj0o5aMEDcPe6JkFI5JJcYZhQXszmNqnbSJxA,2656
9
- mcsmapi/apis/instance.py,sha256=h2y3gTLINvDZq7vOzBhQ3X02f3mmg5ZlPunMDkTahgo,8318
10
- mcsmapi/apis/overview.py,sha256=7wRAdhFzbtLq6Oknj4_ncO5fETZuZCGtliErA0NNju0,514
11
- mcsmapi/apis/user.py,sha256=KXd8OPjyQBprPTlJD-wLGE-BtaOsM_0WF1yqRlGgTfg,2414
12
- mcsmapi/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- mcsmapi/models/common.py,sha256=HNvYJnbxrtkJ7-H2zCXSuB-J-YXBXCcfyK0TzQprsKI,531
14
- mcsmapi/models/daemon.py,sha256=It7kPyxogqY6oBdyXYNi4EmyqlGwizu7j-N37snko8k,4093
15
- mcsmapi/models/file.py,sha256=vk9rQp3Yw_aK7F8ghi5eiBYuwcjK1m-2IQ0YbUWoj3A,5933
16
- mcsmapi/models/image.py,sha256=mpyS7KTVoOwH2opB-fQC2GD3An_bXcERLmLPDBuoYUA,5643
17
- mcsmapi/models/instance.py,sha256=FTFLkwi3r9OUQnusIQ1JI1f7dX4QIbH1Q5BxfUWIqxM,8362
18
- mcsmapi/models/overview.py,sha256=Q_MG04iCkQ7KdBZnji3xA9XzwM3JZ6fZe3NWap8lMdU,5284
19
- mcsmapi/models/user.py,sha256=f2fZS1EQFwqOJM7fKu91dcvHHAdRjhAhwY8XfwXhRvk,3318
20
- mcsmapi-0.1.8b1.dist-info/licenses/LICENSE,sha256=bMKDPsvaybvY-4TTlSZtCXPPtxb7KPpDVqXgDA8Ogo0,1068
21
- mcsmapi-0.1.8b1.dist-info/METADATA,sha256=FyYvDSMJwqwYImKbLTXSSNx4f7mI_LFb9EqxOITuWVs,3032
22
- mcsmapi-0.1.8b1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
- mcsmapi-0.1.8b1.dist-info/top_level.txt,sha256=8MUYHd1Or4cbSCd93IaqLA72w0weEuKieopVwIfVlWo,8
24
- mcsmapi-0.1.8b1.dist-info/RECORD,,