mcsmapi 0.1.1__py3-none-any.whl → 0.1.3__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 +52 -6
- mcsmapi/apis/daemon.py +70 -0
- mcsmapi/apis/file.py +318 -0
- mcsmapi/apis/image.py +102 -0
- mcsmapi/apis/instance.py +300 -0
- mcsmapi/apis/overview.py +17 -0
- mcsmapi/apis/user.py +82 -0
- mcsmapi/exceptions.py +5 -0
- mcsmapi/models/daemon.py +134 -0
- mcsmapi/models/file.py +108 -0
- mcsmapi/models/image.py +112 -0
- mcsmapi/models/instance.py +204 -0
- mcsmapi/models/overview.py +63 -0
- mcsmapi/models/user.py +76 -0
- mcsmapi/pool.py +14 -0
- mcsmapi/request.py +94 -0
- mcsmapi-0.1.3.dist-info/METADATA +83 -0
- mcsmapi-0.1.3.dist-info/RECORD +21 -0
- {mcsmapi-0.1.1.dist-info → mcsmapi-0.1.3.dist-info}/WHEEL +1 -1
- mcsmapi/common.py +0 -34
- mcsmapi/daemon.py +0 -86
- mcsmapi/file.py +0 -326
- mcsmapi/image.py +0 -104
- mcsmapi/instance.py +0 -424
- mcsmapi/overview.py +0 -35
- mcsmapi/users.py +0 -83
- mcsmapi-0.1.1.dist-info/METADATA +0 -88
- mcsmapi-0.1.1.dist-info/RECORD +0 -13
- {mcsmapi-0.1.1.dist-info → mcsmapi-0.1.3.dist-info}/LICENSE +0 -0
- {mcsmapi-0.1.1.dist-info → mcsmapi-0.1.3.dist-info}/top_level.txt +0 -0
mcsmapi/models/image.py
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
from pydantic import BaseModel
|
3
|
+
|
4
|
+
|
5
|
+
class DockerConfig(BaseModel):
|
6
|
+
containerName: str = ""
|
7
|
+
image: str = "mcsm-ubuntu:22.04"
|
8
|
+
memory: int = 1024 # in MB
|
9
|
+
ports: List[str] = ["25565:25565/tcp"]
|
10
|
+
extraVolumes: List[str] = []
|
11
|
+
maxSpace: Optional[int] = None
|
12
|
+
network: Optional[str] = None
|
13
|
+
io: Optional[str] = None
|
14
|
+
networkMode: str = "bridge"
|
15
|
+
networkAliases: List[str] = []
|
16
|
+
cpusetCpus: str = ""
|
17
|
+
cpuUsage: int = 100
|
18
|
+
workingDir: str = ""
|
19
|
+
env: List[str] = []
|
20
|
+
|
21
|
+
|
22
|
+
class DockerImageItem(BaseModel):
|
23
|
+
Id: str = ""
|
24
|
+
ParentId: str = ""
|
25
|
+
RepoTags: List[str] = []
|
26
|
+
RepoDigests: List[str] = []
|
27
|
+
Created: int = 0
|
28
|
+
Size: int = 0
|
29
|
+
VirtualSize: int = 0
|
30
|
+
SharedSize: int = 0
|
31
|
+
Labels: dict[str, str] = {}
|
32
|
+
Containers: int = 0
|
33
|
+
|
34
|
+
|
35
|
+
class DockerContainerItemPort(BaseModel):
|
36
|
+
PrivatePort: int = 0
|
37
|
+
PublicPort: Optional[int] = None
|
38
|
+
Type: str = ""
|
39
|
+
|
40
|
+
|
41
|
+
class DockerContainerItemNetworkSettingsNetwork(BaseModel):
|
42
|
+
NetworkID: str = ""
|
43
|
+
EndpointID: str = ""
|
44
|
+
Gateway: str = ""
|
45
|
+
IPAddress: str = ""
|
46
|
+
IPPrefixLen: int = 0
|
47
|
+
IPv6Gateway: str = ""
|
48
|
+
GlobalIPv6Address: str = ""
|
49
|
+
GlobalIPv6PrefixLen: int = 0
|
50
|
+
MacAddress: str = ""
|
51
|
+
|
52
|
+
|
53
|
+
class DockerContainerItemNetworkSettings(BaseModel):
|
54
|
+
Networks: dict[str, DockerContainerItemNetworkSettingsNetwork] = {}
|
55
|
+
|
56
|
+
|
57
|
+
class DockerContainerItemMount(BaseModel):
|
58
|
+
Name: str = ""
|
59
|
+
Source: str = ""
|
60
|
+
Destination: str = ""
|
61
|
+
Driver: str = ""
|
62
|
+
Mode: str = ""
|
63
|
+
RW: bool = False
|
64
|
+
Propagation: str = ""
|
65
|
+
|
66
|
+
|
67
|
+
class DockerContainerItemHostConfig(BaseModel):
|
68
|
+
NetworkMode: str = ""
|
69
|
+
|
70
|
+
|
71
|
+
class DockerContainerItem(BaseModel):
|
72
|
+
Id: str = ""
|
73
|
+
Names: List[str] = []
|
74
|
+
Image: str = ""
|
75
|
+
ImageID: str = ""
|
76
|
+
Command: str = ""
|
77
|
+
Created: int = 0
|
78
|
+
State: str = ""
|
79
|
+
Status: str = ""
|
80
|
+
Ports: List[DockerContainerItemPort] = []
|
81
|
+
Labels: dict[str, str] = {}
|
82
|
+
SizeRw: int = 0
|
83
|
+
SizeRootFs: int = 0
|
84
|
+
HostConfig: DockerContainerItemHostConfig = DockerContainerItemHostConfig()
|
85
|
+
NetworkSettings: DockerContainerItemNetworkSettings = (
|
86
|
+
DockerContainerItemNetworkSettings()
|
87
|
+
)
|
88
|
+
Mounts: List[DockerContainerItemMount] = []
|
89
|
+
|
90
|
+
|
91
|
+
class DockerNetworkItemIPAMConfig(BaseModel):
|
92
|
+
Subnet: str = ""
|
93
|
+
|
94
|
+
|
95
|
+
class DockerNetworkItemIPAM(BaseModel):
|
96
|
+
Driver: str = ""
|
97
|
+
Config: List[DockerNetworkItemIPAMConfig] = []
|
98
|
+
|
99
|
+
|
100
|
+
class DockerNetworkItem(BaseModel):
|
101
|
+
Name: str = ""
|
102
|
+
Id: str = ""
|
103
|
+
Created: str = ""
|
104
|
+
Scope: str = ""
|
105
|
+
Driver: str = ""
|
106
|
+
EnableIPv6: bool = False
|
107
|
+
Internal: bool = False
|
108
|
+
Attachable: bool = False
|
109
|
+
Ingress: bool = False
|
110
|
+
IPAM: DockerNetworkItemIPAM = DockerNetworkItemIPAM()
|
111
|
+
Options: dict[str, str]
|
112
|
+
Containers: Optional[dict[str, dict]] = {}
|
@@ -0,0 +1,204 @@
|
|
1
|
+
from typing import List, Dict
|
2
|
+
from pydantic import BaseModel
|
3
|
+
from .image import DockerConfig
|
4
|
+
|
5
|
+
|
6
|
+
class TerminalOption(BaseModel):
|
7
|
+
haveColor: bool = False
|
8
|
+
pty: bool = True
|
9
|
+
|
10
|
+
|
11
|
+
class EventTask(BaseModel):
|
12
|
+
autoStart: bool = False
|
13
|
+
autoRestart: bool = True
|
14
|
+
ignore: bool = False
|
15
|
+
|
16
|
+
|
17
|
+
class PingConfig(BaseModel):
|
18
|
+
ip: str = ""
|
19
|
+
port: int = 25565
|
20
|
+
type: int = 1
|
21
|
+
|
22
|
+
|
23
|
+
class InstanceConfig(BaseModel):
|
24
|
+
nickname: str = "New Name"
|
25
|
+
startCommand: str = "cmd.exe"
|
26
|
+
stopCommand: str = "^C"
|
27
|
+
cwd: str = ""
|
28
|
+
ie: str = "gbk" # 输入编码
|
29
|
+
oe: str = "gbk" # 输出编码
|
30
|
+
createDatetime: int = 0
|
31
|
+
lastDatetime: int = 0
|
32
|
+
type: str = "universal"
|
33
|
+
tag: List[str] = []
|
34
|
+
endTime: int = 0
|
35
|
+
fileCode: str = "gbk"
|
36
|
+
processType: str = "docker"
|
37
|
+
updateCommand: str = "shutdown -s"
|
38
|
+
actionCommandList: List[str] = []
|
39
|
+
crlf: int = 2
|
40
|
+
docker: "DockerConfig" = DockerConfig()
|
41
|
+
enableRcon: bool = True
|
42
|
+
rconPassword: str = ""
|
43
|
+
rconPort: int = 2557
|
44
|
+
rconIp: str = ""
|
45
|
+
terminalOption: TerminalOption = TerminalOption()
|
46
|
+
eventTask: EventTask = EventTask()
|
47
|
+
pingConfig: PingConfig = PingConfig()
|
48
|
+
|
49
|
+
|
50
|
+
class ProcessInfo(BaseModel):
|
51
|
+
cpu: int = 0
|
52
|
+
memory: int = 0
|
53
|
+
ppid: int = 0
|
54
|
+
pid: int = 0
|
55
|
+
ctime: int = 0
|
56
|
+
elapsed: int = 0
|
57
|
+
timestamp: int = 0
|
58
|
+
|
59
|
+
|
60
|
+
class InstanceInfo(BaseModel):
|
61
|
+
currentPlayers: int = -1
|
62
|
+
fileLock: int = 0
|
63
|
+
maxPlayers: int = -1
|
64
|
+
openFrpStatus: bool = False
|
65
|
+
playersChart: List[Dict] = []
|
66
|
+
version: str = ""
|
67
|
+
|
68
|
+
|
69
|
+
class InstanceDetail(BaseModel):
|
70
|
+
config: InstanceConfig = InstanceConfig()
|
71
|
+
info: InstanceInfo = InstanceInfo()
|
72
|
+
daemonId: str = ""
|
73
|
+
instanceUuid: str = ""
|
74
|
+
processInfo: ProcessInfo = ProcessInfo()
|
75
|
+
space: int = 0
|
76
|
+
started: int = 0 # 启动次数
|
77
|
+
status: int = 0 # -1 = 忙碌, 0 = 停止, 1 = 停止中, 2 = 启动中, 3 = 运行中
|
78
|
+
|
79
|
+
def start(self) -> str | bool:
|
80
|
+
"""
|
81
|
+
启动该实例。
|
82
|
+
|
83
|
+
**返回:**
|
84
|
+
- str|bool: str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
|
85
|
+
"""
|
86
|
+
from ..apis.instance import Instance
|
87
|
+
|
88
|
+
return Instance().start(self.daemonId, self.instanceUuid)
|
89
|
+
|
90
|
+
def stop(self) -> str | bool:
|
91
|
+
"""
|
92
|
+
停止该实例。
|
93
|
+
|
94
|
+
**返回:**
|
95
|
+
- str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
|
96
|
+
"""
|
97
|
+
from ..apis.instance import Instance
|
98
|
+
|
99
|
+
return Instance().stop(self.daemonId, self.instanceUuid)
|
100
|
+
|
101
|
+
def restart(self) -> str | bool:
|
102
|
+
"""
|
103
|
+
重启该实例。
|
104
|
+
|
105
|
+
**返回:**
|
106
|
+
- str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
|
107
|
+
"""
|
108
|
+
from ..apis.instance import Instance
|
109
|
+
|
110
|
+
return Instance().restart(self.daemonId, self.instanceUuid)
|
111
|
+
|
112
|
+
def kill(self) -> str | bool:
|
113
|
+
"""
|
114
|
+
强制关闭该实例。
|
115
|
+
|
116
|
+
**返回:**
|
117
|
+
- str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
|
118
|
+
"""
|
119
|
+
from ..apis.instance import Instance
|
120
|
+
|
121
|
+
return Instance().kill(self.daemonId, self.instanceUuid)
|
122
|
+
|
123
|
+
def delete(self, deleteFile=False) -> str:
|
124
|
+
"""
|
125
|
+
删除该实例。
|
126
|
+
|
127
|
+
**返回:**
|
128
|
+
- str: 被删除的实例的uuid。
|
129
|
+
"""
|
130
|
+
from ..apis.instance import Instance
|
131
|
+
|
132
|
+
return Instance().delete(self.daemonId, [self.instanceUuid], deleteFile)[0]
|
133
|
+
|
134
|
+
def update(self) -> bool:
|
135
|
+
"""
|
136
|
+
升级实例。
|
137
|
+
|
138
|
+
**返回:**
|
139
|
+
- bool: 返回操作结果,成功时返回True。
|
140
|
+
"""
|
141
|
+
from ..apis.instance import Instance
|
142
|
+
|
143
|
+
return Instance().update(self.daemonId, self.instanceUuid)
|
144
|
+
|
145
|
+
def updateConfig(self, config: dict) -> str | bool:
|
146
|
+
"""
|
147
|
+
更新该实例配置。
|
148
|
+
|
149
|
+
**参数:**
|
150
|
+
- config (dict): 新的实例配置,以字典形式提供,缺失内容由使用原实例配置填充。
|
151
|
+
|
152
|
+
**返回:**
|
153
|
+
- str|bool: 更新成功后返回更新的实例UUID,如果未找到该字段,则默认返回True。
|
154
|
+
"""
|
155
|
+
from ..apis.instance import Instance
|
156
|
+
|
157
|
+
updated_config = self.config.dict()
|
158
|
+
updated_config.update(config)
|
159
|
+
|
160
|
+
instance_config = InstanceConfig(**updated_config).dict()
|
161
|
+
|
162
|
+
return Instance().updateConfig(
|
163
|
+
self.daemonId, self.instanceUuid, instance_config
|
164
|
+
)
|
165
|
+
|
166
|
+
def reinstall(self, targetUrl: str, title: str = "", description: str = "") -> bool:
|
167
|
+
"""
|
168
|
+
重装实例。
|
169
|
+
|
170
|
+
**参数:**
|
171
|
+
- targetUrl (str): 重装文件的目标URL。
|
172
|
+
- title (str): 重装文件的标题。
|
173
|
+
- description (str, optional): 重装文件的描述,默认为空字符串。
|
174
|
+
|
175
|
+
**返回:**
|
176
|
+
- bool: 返回操作结果,成功时返回True
|
177
|
+
"""
|
178
|
+
from ..apis.instance import Instance
|
179
|
+
|
180
|
+
return Instance().reinstall(
|
181
|
+
self.daemonId, self.instanceUuid, targetUrl, title, description
|
182
|
+
)
|
183
|
+
|
184
|
+
|
185
|
+
class InstanceCreateResult(BaseModel):
|
186
|
+
instanceUuid: str = ""
|
187
|
+
config: InstanceConfig = InstanceConfig()
|
188
|
+
|
189
|
+
|
190
|
+
class InstanceSearchList(BaseModel):
|
191
|
+
pageSize: int = 0
|
192
|
+
maxPage: int = 0
|
193
|
+
data: List[InstanceDetail] = []
|
194
|
+
daemonId: str = ""
|
195
|
+
|
196
|
+
def __init__(self, **data: str):
|
197
|
+
super().__init__(**data)
|
198
|
+
for instance in self.data:
|
199
|
+
instance.daemonId = self.daemonId
|
200
|
+
|
201
|
+
|
202
|
+
class UserInstancesList(BaseModel):
|
203
|
+
instanceUuid: str = ""
|
204
|
+
daemonId: str = ""
|
@@ -0,0 +1,63 @@
|
|
1
|
+
from typing import Dict, List, Optional
|
2
|
+
from pydantic import BaseModel
|
3
|
+
from .daemon import DaemonModel
|
4
|
+
|
5
|
+
|
6
|
+
class SystemUser(BaseModel):
|
7
|
+
uid: int = 0
|
8
|
+
gid: int = 0
|
9
|
+
username: str = ""
|
10
|
+
homedir: str = ""
|
11
|
+
shell: Optional[str] = None
|
12
|
+
|
13
|
+
|
14
|
+
class SystemInfo(BaseModel):
|
15
|
+
user: SystemUser = SystemUser()
|
16
|
+
time: int = 0
|
17
|
+
totalmem: int = 0
|
18
|
+
freemem: int = 0
|
19
|
+
type: str = ""
|
20
|
+
version: str = ""
|
21
|
+
node: str = ""
|
22
|
+
hostname: str = ""
|
23
|
+
loadavg: List[float] = []
|
24
|
+
platform: str = ""
|
25
|
+
release: str = ""
|
26
|
+
uptime: float = 0
|
27
|
+
cpu: float = 0
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
class RecordInfo(BaseModel):
|
32
|
+
logined: int = 0
|
33
|
+
illegalAccess: int = 0
|
34
|
+
banips: int = 0
|
35
|
+
loginFailed: int = 0
|
36
|
+
|
37
|
+
|
38
|
+
class ChartInfo(BaseModel):
|
39
|
+
system: List[Dict[str, float]] = []
|
40
|
+
request: List[Dict[str, int]] = []
|
41
|
+
|
42
|
+
|
43
|
+
class ProcessInfo(BaseModel):
|
44
|
+
cpu: int = 0
|
45
|
+
memory: int = 0
|
46
|
+
cwd: str = ""
|
47
|
+
|
48
|
+
|
49
|
+
class RemoteCountInfo(BaseModel):
|
50
|
+
total: int = 0
|
51
|
+
available: int = 0
|
52
|
+
|
53
|
+
|
54
|
+
class OverviewModel(BaseModel):
|
55
|
+
version: str = ""
|
56
|
+
specifiedDaemonVersion: str = ""
|
57
|
+
system: SystemInfo = SystemInfo()
|
58
|
+
record: RecordInfo = RecordInfo()
|
59
|
+
process: ProcessInfo = ProcessInfo()
|
60
|
+
chart: ChartInfo = ChartInfo()
|
61
|
+
remoteCount: RemoteCountInfo = RemoteCountInfo()
|
62
|
+
remote: List["DaemonModel"] = []
|
63
|
+
|
mcsmapi/models/user.py
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
from typing import Any, List
|
2
|
+
from pydantic import BaseModel
|
3
|
+
from ..models.instance import InstanceDetail, UserInstancesList
|
4
|
+
|
5
|
+
|
6
|
+
class UserModel(BaseModel):
|
7
|
+
uuid: str = ""
|
8
|
+
userName: str = ""
|
9
|
+
passWord: str = ""
|
10
|
+
passWordType: int = 0
|
11
|
+
salt: str = ""
|
12
|
+
permission: int = 1 # 1=用户, 10=管理员, -1=被封禁的用户
|
13
|
+
registerTime: str = ""
|
14
|
+
loginTime: str = ""
|
15
|
+
apiKey: str = ""
|
16
|
+
isInit: bool = False
|
17
|
+
secret: str = ""
|
18
|
+
open2FA: bool = False
|
19
|
+
instances: List["UserInstancesList"] = []
|
20
|
+
|
21
|
+
def delete(self) -> bool:
|
22
|
+
"""
|
23
|
+
删除该用户。
|
24
|
+
|
25
|
+
**返回:**
|
26
|
+
- bool: 删除成功后返回True。
|
27
|
+
"""
|
28
|
+
from ..apis.user import User
|
29
|
+
|
30
|
+
return User().delete([self.uuid])
|
31
|
+
|
32
|
+
def update(self, config: dict[str, Any]) -> bool:
|
33
|
+
"""
|
34
|
+
更新该用户的信息。
|
35
|
+
|
36
|
+
参数:
|
37
|
+
- config (dict[str, Any]): 用户的新信息,以字典形式提供,缺失内容使用原用户信息填充。
|
38
|
+
|
39
|
+
返回:
|
40
|
+
- bool: 更新成功后返回True。
|
41
|
+
"""
|
42
|
+
from ..apis.user import User
|
43
|
+
|
44
|
+
updated_config = self.dict()
|
45
|
+
updated_config.update(config)
|
46
|
+
# 过滤用户信息中不需要的字段
|
47
|
+
user_config_dict = {
|
48
|
+
key: updated_config[key]
|
49
|
+
for key in UserConfig.__fields__.keys()
|
50
|
+
if key in updated_config
|
51
|
+
}
|
52
|
+
|
53
|
+
user_config = UserConfig(**user_config_dict).dict()
|
54
|
+
|
55
|
+
return User().update(self.uuid, user_config)
|
56
|
+
|
57
|
+
|
58
|
+
class SearchUserModel(BaseModel):
|
59
|
+
total: int = 0
|
60
|
+
page: int = 0
|
61
|
+
page_size: int = 0
|
62
|
+
max_page: int = 0
|
63
|
+
data: List[UserModel] = []
|
64
|
+
|
65
|
+
|
66
|
+
class UserConfig(BaseModel):
|
67
|
+
uuid: str
|
68
|
+
userName: str
|
69
|
+
loginTime: str
|
70
|
+
registerTime: str
|
71
|
+
instances: List[InstanceDetail]
|
72
|
+
permission: int # 1=用户, 10=管理员, -1=被封禁的用户
|
73
|
+
apiKey: str
|
74
|
+
isInit: bool
|
75
|
+
secret: str
|
76
|
+
open2FA: bool
|
mcsmapi/pool.py
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
|
4
|
+
class ApiPool(Enum):
|
5
|
+
def __str__(self):
|
6
|
+
return self.value
|
7
|
+
|
8
|
+
AUTH = "api/auth"
|
9
|
+
OVERVIEW = "api/overview"
|
10
|
+
INSTANCE = "api/instance"
|
11
|
+
PROTECTED_INSTANCE = "api/protected_instance"
|
12
|
+
SERVICE = "api/service"
|
13
|
+
FILE = "api/files"
|
14
|
+
IMAGE = "api/environment"
|
mcsmapi/request.py
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
from typing import Any
|
2
|
+
import requests
|
3
|
+
import urllib.parse
|
4
|
+
from .exceptions import MCSMError
|
5
|
+
|
6
|
+
|
7
|
+
class Request:
|
8
|
+
mcsm_url = ""
|
9
|
+
timeout = 5
|
10
|
+
session = requests.Session()
|
11
|
+
apikey = None
|
12
|
+
token = None
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
def set_mcsm_url(cls, url):
|
16
|
+
"""设置类级别的 mcsm_url"""
|
17
|
+
cls.mcsm_url = url
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def set_timeout(cls, timeout):
|
21
|
+
"""设置类级别的 timeout"""
|
22
|
+
cls.timeout = timeout
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
def set_apikey(cls, apikey):
|
26
|
+
"""设置类级别的 apikey"""
|
27
|
+
cls.apikey = apikey
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def set_token(cls, token):
|
31
|
+
"""设置类级别的 token"""
|
32
|
+
cls.token = token
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def __init__(cls, mcsm_url=None, timeout=None):
|
36
|
+
"""初始化时使用类变量,或者使用传入的参数覆盖默认值"""
|
37
|
+
cls.mcsm_url = mcsm_url or cls.mcsm_url
|
38
|
+
cls.timeout = timeout or cls.timeout
|
39
|
+
|
40
|
+
@classmethod
|
41
|
+
def send(cls, method: str, endpoint: Any, params=None, data=None) -> Any:
|
42
|
+
"""发送 HTTP 请求"""
|
43
|
+
if params is None:
|
44
|
+
params = {}
|
45
|
+
if data is None:
|
46
|
+
data = {}
|
47
|
+
if not isinstance(endpoint, str):
|
48
|
+
endpoint = str(endpoint)
|
49
|
+
|
50
|
+
url = urllib.parse.urljoin(cls.mcsm_url, endpoint)
|
51
|
+
if cls.apikey is not None:
|
52
|
+
params["apikey"] = cls.apikey
|
53
|
+
data["apikey"] = cls.apikey
|
54
|
+
if cls.token is not None:
|
55
|
+
params["token"] = cls.token
|
56
|
+
data["token"] = cls.token
|
57
|
+
|
58
|
+
response = cls.session.request(
|
59
|
+
method.upper(),
|
60
|
+
url,
|
61
|
+
params=params,
|
62
|
+
data=data,
|
63
|
+
timeout=cls.timeout,
|
64
|
+
)
|
65
|
+
try:
|
66
|
+
response.raise_for_status()
|
67
|
+
return response.json()["data"]
|
68
|
+
except requests.exceptions.HTTPError as e:
|
69
|
+
raise MCSMError(
|
70
|
+
response.status_code, response.json().get("data", response.text)
|
71
|
+
) from e
|
72
|
+
|
73
|
+
@classmethod
|
74
|
+
async def upload(cls, url: str, file: bytes) -> bool:
|
75
|
+
"""上传文件"""
|
76
|
+
|
77
|
+
response = cls.session.request(
|
78
|
+
"POST",
|
79
|
+
url,
|
80
|
+
headers={"Content-Type": "multipart/form-data"},
|
81
|
+
files={"file": file},
|
82
|
+
timeout=cls.timeout,
|
83
|
+
)
|
84
|
+
try:
|
85
|
+
response.raise_for_status()
|
86
|
+
return True
|
87
|
+
except requests.exceptions.HTTPError as e:
|
88
|
+
raise MCSMError(
|
89
|
+
response.status_code, response.json().get("data", response.text)
|
90
|
+
) from e
|
91
|
+
|
92
|
+
|
93
|
+
send = Request().send
|
94
|
+
upload = Request().upload
|
@@ -0,0 +1,83 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: mcsmapi
|
3
|
+
Version: 0.1.3
|
4
|
+
Summary: Shortcut the pypi package of MCSM./快捷操作MCSM的pypi包
|
5
|
+
Author-email: molanp <molanpp@outlook.com>
|
6
|
+
Project-URL: Source, https://github.com/molanp/mcsmapi
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: requests
|
12
|
+
Requires-Dist: pydantic
|
13
|
+
|
14
|
+
# MCSM API
|
15
|
+
|
16
|
+

|
17
|
+

|
18
|
+

|
19
|
+
|
20
|
+
English|[Chinese Simplified](README_zh-cn.md)
|
21
|
+
|
22
|
+
> [!important]
|
23
|
+
> We need your help, the documentation for this project has not been written yet, if you are willing, please submit pr to help us write the documentation.
|
24
|
+
|
25
|
+
## Introduction
|
26
|
+
|
27
|
+
`mcsmapi` is a PyPI package based on [MCSManager](https://github.com/MCSManager/MCSManager), designed to simplify interactions with the MCSM API.
|
28
|
+
|
29
|
+
With this library, you can more easily access and operate the various features provided by MCSM.
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
You can install `mcsmapi` using `pip`:
|
34
|
+
|
35
|
+
```bash
|
36
|
+
pip install mcsmapi
|
37
|
+
```
|
38
|
+
|
39
|
+
## Supported Features
|
40
|
+
|
41
|
+
- [x] Dashboard data ([Overview](doc/en/Overview.md))
|
42
|
+
- [x] User management ([User](doc/en/User.md))
|
43
|
+
- [x] Instance management (`Instance`)
|
44
|
+
- [x] Daemon management (`Daemon`)
|
45
|
+
- [x] File management (`File`)
|
46
|
+
- [x] Image management (`Image`)
|
47
|
+
|
48
|
+
## Supported MCSM Versions
|
49
|
+
|
50
|
+
| MCSM Version | Support Status |
|
51
|
+
| :---: | :---: |
|
52
|
+
| 10.x | ✅ |
|
53
|
+
|
54
|
+
### Quick Example
|
55
|
+
|
56
|
+
```python
|
57
|
+
from mcsmapi import MCSMAPI
|
58
|
+
|
59
|
+
# Initialize
|
60
|
+
mcsm = MCSMAPI("https://example.com")
|
61
|
+
|
62
|
+
# Log in with username and password (API permissions depend on the account permissions)
|
63
|
+
mcsm.login("username", "password")
|
64
|
+
|
65
|
+
# Log in with API key (API permissions depend on the API key permissions)
|
66
|
+
mcsm.login_with_apikey("apikey")
|
67
|
+
|
68
|
+
# Get dashboard data
|
69
|
+
overview = mcsm.overview()
|
70
|
+
|
71
|
+
# Get MCSM version
|
72
|
+
mcsm_version = mcsm.overview().version
|
73
|
+
```
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
If you encounter any issues or have suggestions for improvements, feel free to submit an [Issue](https://github.com/molanp/mcsmapi/issues) or create a [Pull Request](https://github.com/molanp/mcsmapi/pulls).
|
78
|
+
|
79
|
+
## License
|
80
|
+
|
81
|
+
`mcsmapi` is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
82
|
+
|
83
|
+
Please refer to the [LICENSE](LICENSE) file for more details.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
mcsmapi/__init__.py,sha256=MUAbGnG0qSVKcG9YTCkZru42x1UxcfzfJF9WJzDjU8Q,1451
|
2
|
+
mcsmapi/exceptions.py,sha256=mHsAHyoX9SiFDGBMEhesA_ao9hhZZ38EGTp97K7VDp8,184
|
3
|
+
mcsmapi/pool.py,sha256=CoOYbyECp4FoXkzwFN7WgtS3vgZtvWO8e93i18vhOEI,308
|
4
|
+
mcsmapi/request.py,sha256=5mCzKgrh4OPFKvBo22kIDpX_D1zqCza1nglYUeGWveg,2618
|
5
|
+
mcsmapi/apis/daemon.py,sha256=a0351ca2I68S2lFRg5wtV52FuLsaT-_dnqhuBXpE-tQ,1960
|
6
|
+
mcsmapi/apis/file.py,sha256=UKD295UK9755Y_fEANZCxPyS9uwpkJ6KcqnNlM2YHMY,10592
|
7
|
+
mcsmapi/apis/image.py,sha256=kGuO2U3D3OM8p1jo31U3ACKv-DD-60pkhn1LNiEhhM4,2890
|
8
|
+
mcsmapi/apis/instance.py,sha256=GTSMSfwaYElrSO3DO4IBbU8OJvd1A34DzgsL_xgU6I0,10968
|
9
|
+
mcsmapi/apis/overview.py,sha256=tBiZZEXVQukzMqw3EvAVbjkG6h2KO115ylpNRONSJ9s,607
|
10
|
+
mcsmapi/apis/user.py,sha256=Xza7jAmy8ORkeO2NS-nzKPkG5Immp4FUtskEN0Hd9Z4,2950
|
11
|
+
mcsmapi/models/daemon.py,sha256=u7leIa_91eVeia00rhD8HiYiaRKFCOiWFtqSI4WEC2g,3521
|
12
|
+
mcsmapi/models/file.py,sha256=qI_3e5C7cHUc0botBP7YWU90J-Uu2-JILzBTQ-PicRA,2760
|
13
|
+
mcsmapi/models/image.py,sha256=akx0b7aUnpl-9F2AHUbkinUP15hLHAnSdLlZZxM3bcI,2773
|
14
|
+
mcsmapi/models/instance.py,sha256=eDQng8BAVep_ufDYbLHc-sM5JIPn0-AeNqgkOh8wFEM,5595
|
15
|
+
mcsmapi/models/overview.py,sha256=kImr_Dy1Mkyf2jJ7bq5E5IAYGyEYzHZ7inrRNxV0u6k,1307
|
16
|
+
mcsmapi/models/user.py,sha256=CDJjiG9cY8gW4rYD8SDnxvMGnn1cdeUU801NucPfnrA,1940
|
17
|
+
mcsmapi-0.1.3.dist-info/LICENSE,sha256=kn0yZGn5uLIJtr2aAXy8pz_wJqal15ZGnynTU1fCnLQ,1063
|
18
|
+
mcsmapi-0.1.3.dist-info/METADATA,sha256=CgoVwe46VfW-2efVTqnpYXcKwic8DhaPOqGkO-o3rVI,2456
|
19
|
+
mcsmapi-0.1.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
20
|
+
mcsmapi-0.1.3.dist-info/top_level.txt,sha256=8MUYHd1Or4cbSCd93IaqLA72w0weEuKieopVwIfVlWo,8
|
21
|
+
mcsmapi-0.1.3.dist-info/RECORD,,
|