mirror of
https://github.com/Murasame-Dev/McStatus-API.git
synced 2025-12-14 12:18:03 +00:00
Intial Init
This commit is contained in:
parent
c197ac5d5d
commit
3dbd5e8a8e
7 changed files with 294 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.pdm-python
|
||||
/__pycache__
|
||||
uv.lock
|
||||
.python-version
|
||||
47
BedrockServerStatus.py
Normal file
47
BedrockServerStatus.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 此模块用于查询基岩版版服务器状态,并将其数据赋值给类以供灵活调用单个值
|
||||
from mcstatus import BedrockServer
|
||||
|
||||
|
||||
class BedrockStatus:
|
||||
def __init__(self, gamemode, map_name, latency, motd, version, players, online_player, max_players):
|
||||
self.gamemode = gamemode
|
||||
self.map_name = map_name
|
||||
self.latency = latency
|
||||
self.motd = motd
|
||||
self.version = version
|
||||
self.players = players
|
||||
self.online_player = online_player
|
||||
self.max_players = max_players
|
||||
|
||||
def bedrock_status(ip):
|
||||
try:
|
||||
server = BedrockServer.lookup(ip)
|
||||
print(f'正在解析: {ip}')
|
||||
status = server.status()
|
||||
|
||||
# 将 status 属性拆分成多个变量
|
||||
gamemode = status.gamemode # 游戏模式
|
||||
map_name = status.map_name # 地图名
|
||||
latency = status.latency # 延迟
|
||||
motd = status.description # 标题
|
||||
version = status.version.name # 版本
|
||||
|
||||
# 关于玩家信息的获取
|
||||
players = status.players # 玩家总类
|
||||
online_player = players.online # 在线玩家数
|
||||
max_players = players.max # 最大玩家数
|
||||
|
||||
return BedrockStatus(
|
||||
gamemode,
|
||||
map_name,
|
||||
latency,
|
||||
motd,
|
||||
version,
|
||||
players,
|
||||
online_player,
|
||||
max_players
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return print(f"获取服务器状态时出错: {e}")
|
||||
66
FormatData.py
Normal file
66
FormatData.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 此模块用于格式化此项目的所有文本输出数据,包括那些鸡毛蒜皮的空值提示
|
||||
|
||||
# 格式化 Java 服务器状态的数据
|
||||
def format_java_data(ip, type, status):
|
||||
data = {
|
||||
'ip': ip,
|
||||
'type': type,
|
||||
'latency': status.latency,
|
||||
'motd': status.motd,
|
||||
'version': status.version,
|
||||
'enforces_secure_chat': status.enforces_secure_chat,
|
||||
'forge_data': status.forge_data,
|
||||
'players': {
|
||||
'online': status.online_player,
|
||||
'max': status.max_players,
|
||||
'sample': status.sample_players
|
||||
},
|
||||
'icon': status.icon
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
# 格式化基岩版服务器状态的数据
|
||||
def format_bedrock_data(ip, status):
|
||||
data = {
|
||||
'ip': ip,
|
||||
'gamemode': status.gamemode,
|
||||
'map_name': status.map_name,
|
||||
'latency': status.latency,
|
||||
'motd': status.motd,
|
||||
'version': status.version,
|
||||
'players': {
|
||||
'online': status.online_player,
|
||||
'max': status.max_players
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def format_index():
|
||||
message = {
|
||||
"message": "欢迎使用 Minecraft 服务器状态查询 API!",
|
||||
"usage": {
|
||||
"JavaStatus": "/java?ip=<IP> - (Required)",
|
||||
"BedrockStatus": "/bedrock?ip=<IP> - (Required)"
|
||||
}
|
||||
}
|
||||
|
||||
return message
|
||||
|
||||
def format_java_index():
|
||||
message = {
|
||||
"message": "缺少 IP 参数",
|
||||
"usage": "/java?ip=<IP> - (Required)"
|
||||
}
|
||||
|
||||
return message
|
||||
|
||||
def format_bedrock_index():
|
||||
message = {
|
||||
"message": "缺少 IP 参数",
|
||||
"usage": "/bedrock?ip=<IP> - (Required)"
|
||||
}
|
||||
|
||||
return message
|
||||
52
JavaServerStatus.py
Normal file
52
JavaServerStatus.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 此模块用于查询 Java 版服务器状态,并将其数据赋值给类以供灵活调用单个值
|
||||
from mcstatus import JavaServer
|
||||
|
||||
class JavaStatus:
|
||||
def __init__(self, enforces_secure_chat, forge_data, icon, latency, motd, version, players, online_player, max_players, sample_players):
|
||||
self.enforces_secure_chat = enforces_secure_chat
|
||||
self.forge_data = forge_data
|
||||
self.icon = icon
|
||||
self.latency = latency
|
||||
self.motd = motd
|
||||
self.version = version
|
||||
self.players = players
|
||||
self.online_player = online_player
|
||||
self.max_players = max_players
|
||||
self.sample_players = sample_players
|
||||
|
||||
def java_status(ip):
|
||||
try:
|
||||
print(f'正在解析: {ip}')
|
||||
server = JavaServer.lookup(ip)
|
||||
status = server.status()
|
||||
|
||||
# 将 status 属性拆分成多个变量
|
||||
enforces_secure_chat = status.enforces_secure_chat # 是否开启聊天签名
|
||||
forge_data = status.forge_data # FML版本
|
||||
icon = status.icon # 图标,输出为 base64
|
||||
latency = status.latency # 延迟
|
||||
motd = status.description # 标题
|
||||
version = status.version.name # 版本
|
||||
|
||||
# 关于玩家信息的获取
|
||||
players = status.players # 玩家总类
|
||||
online_player = players.online # 在线玩家数
|
||||
max_players = players.max # 最大玩家数
|
||||
sample_players = players.sample # 在线玩家的 ID,UUID
|
||||
|
||||
return JavaStatus(
|
||||
enforces_secure_chat,
|
||||
forge_data,
|
||||
icon,
|
||||
latency,
|
||||
motd,
|
||||
version,
|
||||
players,
|
||||
online_player,
|
||||
max_players,
|
||||
sample_players,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return print(f"获取服务器状态时出错: {e}")
|
||||
73
app.py
Normal file
73
app.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 重写 Flask-MCMOTD,早期版本用的是面向过程的方式进行写的,一个文件写了400多行,真是要爆了T.T
|
||||
|
||||
# API
|
||||
from flask import Flask, request, jsonify
|
||||
from flask_cors import CORS
|
||||
|
||||
# Java版查询模块
|
||||
from JavaServerStatus import java_status
|
||||
# 基岩版查询模块
|
||||
from BedrockServerStatus import bedrock_status
|
||||
# 此API优先解析 srv 记录
|
||||
from dnslookup import dns_lookup
|
||||
|
||||
# 格式化文本
|
||||
from FormatData import format_java_data, format_bedrock_data, format_index, format_java_index, format_bedrock_index
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.json.sort_keys = False
|
||||
app.json.ensure_ascii = False
|
||||
app.json.mimetype = 'application/json;charset=UTF-8'
|
||||
app.json.compact = False
|
||||
CORS(app)
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
message = format_index()
|
||||
return jsonify(message), 200
|
||||
|
||||
# Java 服务器状态查询
|
||||
@app.route('/java')
|
||||
def get_java_status():
|
||||
ip = request.args.get('ip')
|
||||
# 空值输出 API 用法
|
||||
if not ip:
|
||||
message = format_java_index()
|
||||
return jsonify(message), 400
|
||||
|
||||
try:
|
||||
ip, type = dns_lookup(ip)
|
||||
print(f"解析Java版IP: {ip}, 是否为 SRV: {type}")
|
||||
status = java_status(ip)
|
||||
|
||||
data = format_java_data(ip, type, status)
|
||||
|
||||
return jsonify(data), 200
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
# 基岩版服务器状态查询
|
||||
@app.route('/bedrock')
|
||||
def get_bedrock_status():
|
||||
ip = request.args.get('ip')
|
||||
# 空值输出 API 用法
|
||||
if not ip:
|
||||
message = format_bedrock_index()
|
||||
return jsonify(message), 400
|
||||
|
||||
try:
|
||||
print(f"解析基岩版IP: {ip}")
|
||||
status = bedrock_status(ip)
|
||||
|
||||
data = format_bedrock_data(ip, status)
|
||||
|
||||
return jsonify(data), 200
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, port=5000)
|
||||
41
dnslookup.py
Normal file
41
dnslookup.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 此模块用于解析 SRV 记录,返回值为 IP 和 解析类型(srv 或者 normal)
|
||||
import dns.resolver
|
||||
|
||||
def dns_lookup(ip):
|
||||
# 因为第一次解析是面向于 SRV 的,所以需要做是否带端口号的判断
|
||||
if ':' in ip:
|
||||
type = f'normal'
|
||||
return ip, type
|
||||
|
||||
# 自定义 DNS 解析器
|
||||
resolver = dns.resolver.Resolver()
|
||||
resolver.nameservers = ['223.5.5.5', '223.6.6.6'] # 添加备用DNS
|
||||
resolver.timeout = 5 # 单次查询超时时间
|
||||
resolver.lifetime = 10 # 总解析时间限制
|
||||
|
||||
try:
|
||||
print(f'正在解析 SRV 记录: _minecraft._tcp.{ip}')
|
||||
answers = resolver.resolve(f'_minecraft._tcp.{ip}', 'SRV')
|
||||
|
||||
# address 的源输出末端有沟槽的 ".",去掉它
|
||||
address = str(answers[0].target).rstrip('.')
|
||||
port = answers[0].port
|
||||
|
||||
# 拼接端口号,赋值 SRV
|
||||
ip = f'{address}:{port}'
|
||||
print(f'解析出 SRV 地址: {ip}')
|
||||
type = f'srv'
|
||||
return ip, type
|
||||
|
||||
except dns.resolver.NoAnswer:
|
||||
print(f'无法解析SRV记录: _minecraft._tcp.{ip} (DNS服务器无答应)')
|
||||
except dns.resolver.NXDOMAIN:
|
||||
print(f'域名不存在SRV记录: _minecraft._tcp.{ip}')
|
||||
except (dns.resolver.Timeout, dns.resolver.LifetimeTimeout):
|
||||
print(f'DNS解析超时: {ip}')
|
||||
except Exception as e:
|
||||
print(f'DNS解析出现未知错误: {e}')
|
||||
|
||||
type = f'normal'
|
||||
return ip, type
|
||||
11
pyproject.toml
Normal file
11
pyproject.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[project]
|
||||
name = "mcstatus-api"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"flask>=3.1.1",
|
||||
"flask-cors>=6.0.1",
|
||||
"mcstatus>=12.0.5",
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue