init
This commit is contained in:
commit
81ddc973d9
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
venv
|
||||
__pycache__
|
68
README.md
Normal file
68
README.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
# JetbrainsLSAvaliableChecker
|
||||
|
||||
Check a Jetbrains License Server is avaliable or not.
|
||||
|
||||
## Quick Start
|
||||
|
||||
- Install Python
|
||||
|
||||
- ```bash
|
||||
$ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
- ```bash
|
||||
$ uvicorn app.main:app --reload
|
||||
```
|
||||
|
||||
## API Usage
|
||||
|
||||
- Path: `/api/fetch`
|
||||
|
||||
- Methods: `GET` or `POST`
|
||||
|
||||
- params:
|
||||
|
||||
- `server`: The server url of the license server
|
||||
|
||||
- Return:
|
||||
|
||||
- ```json
|
||||
{
|
||||
"available": bool,
|
||||
"message": str,
|
||||
"data": {
|
||||
"release_ticket_data": {
|
||||
"action": str,
|
||||
"confirmation_stamp": str,
|
||||
"lease_signature": str,
|
||||
"response_code": str,
|
||||
"salt": str,
|
||||
"server_lease": str,
|
||||
"server_uid": str,
|
||||
"validation_deadline_period": str,
|
||||
"validation_period": str
|
||||
},
|
||||
"obtain_ticket_data": {
|
||||
"action": str,
|
||||
"confirmation_stamp": str,
|
||||
"lease_signature": str,
|
||||
"message": str,
|
||||
"prolongation_period": str,
|
||||
"response_code": str,
|
||||
"salt": str,
|
||||
"server_lease": str,
|
||||
"server_uid": str,
|
||||
"validation_deadline_period": str,
|
||||
"validation_period": str
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This program and its related documentation are provided for general informational purposes only. While we strive to ensure the accuracy and completeness of the information, we make no representations or warranties of any kind, express or implied, regarding the accuracy, reliability, or completeness of the content. You use this program at your own risk.
|
||||
|
||||
We shall not be liable for any direct, indirect, incidental, special, or consequential damages arising from the use or inability to use this program, including but not limited to loss of data or profits, even if we have been advised of the possibility of such damages.
|
||||
|
||||
The use of this program may be subject to certain legal and regulatory requirements, and users are responsible for understanding and complying with applicable laws and regulations. We reserve the right to modify this disclaimer at any time without notice.
|
0
app/__init__.py
Normal file
0
app/__init__.py
Normal file
94
app/main.py
Normal file
94
app/main.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
from fastapi import FastAPI, Form, Request
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import httpx
|
||||
import uuid
|
||||
import string
|
||||
import random
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
templates = Jinja2Templates(directory="app/templates")
|
||||
|
||||
ascii_list = list(string.ascii_letters + string.digits)
|
||||
DESKTOP_NAME = "DESKTOP-" + "".join(random.sample(ascii_list, 7)).upper()
|
||||
MACHINE_ID = uuid.uuid4()
|
||||
USERNAME = "".join(random.sample(ascii_list, 7)).upper()
|
||||
VERSION = 2024100
|
||||
BUILD_NUMBER = "2024.1.4+Build+CL-241.18034.45"
|
||||
|
||||
# 配置静态文件
|
||||
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
||||
|
||||
# 获取并解析 XML 响应
|
||||
def get_xml_data(server: str, ticket_path: str):
|
||||
client = httpx.Client(verify=False)
|
||||
try:
|
||||
response = client.get(server + ticket_path, timeout=3) # 设置超时为10秒
|
||||
response.raise_for_status() # 检查响应状态
|
||||
root = ET.fromstring(response.text)
|
||||
|
||||
return {
|
||||
"action": root.find("action").text,
|
||||
"confirmation_stamp": root.find("confirmationStamp").text,
|
||||
"lease_signature": root.find("leaseSignature").text,
|
||||
"response_code": root.find("responseCode").text,
|
||||
"salt": root.find("salt").text,
|
||||
"server_lease": root.find("serverLease").text,
|
||||
"server_uid": root.find("serverUid").text,
|
||||
"validation_deadline_period": root.find("validationDeadlinePeriod").text,
|
||||
"validation_period": root.find("validationPeriod").text,
|
||||
"message": root.find("message").text
|
||||
}
|
||||
except httpx.ReadTimeout:
|
||||
return {"error": "Timeout: Please try again later."}
|
||||
except Exception as e:
|
||||
return {"error": f"An unexpected error occurred: {str(e)}. It seems that this server is not avaliable or you can try again later."}
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def index(request: Request):
|
||||
return templates.TemplateResponse("index.html", {"request": request})
|
||||
|
||||
@app.post("/fetch", response_class=HTMLResponse)
|
||||
async def fetch_data(request: Request, server: str = Form(...)):
|
||||
RELEASE_TICKET_PATH = f"/rpc/releaseTicket.action?buildNumber={BUILD_NUMBER}&clientVersion=16&hostName={DESKTOP_NAME}&machineId={MACHINE_ID}&productCode=cfc7082d-ae43-4978-a2a2-46feb1679405&productFamilyId=cfc7082d-ae43-4978-a2a2-46feb1679405&salt=1726973268812&secure=false&ticketId=rsoaehfbbg&userName={USERNAME}"
|
||||
OBTAIN_TICKET_PATH = f"/rpc/obtainTicket.action?buildDate=20240409&{BUILD_NUMBER}&clientVersion=16&hostName={DESKTOP_NAME}&machineId={MACHINE_ID}&productCode=cfc7082d-ae43-4978-a2a2-46feb1679405&productFamilyId=cfc7082d-ae43-4978-a2a2-46feb1679405&salt=1726973269845&secure=false&userName={USERNAME}&version={VERSION}&versionNumber={VERSION}"
|
||||
|
||||
release_ticket_data = get_xml_data(server, RELEASE_TICKET_PATH)
|
||||
obtain_ticket_data = get_xml_data(server, OBTAIN_TICKET_PATH)
|
||||
|
||||
return templates.TemplateResponse("index.html", {
|
||||
"request": request,
|
||||
"release_data": release_ticket_data,
|
||||
"obtain_data": obtain_ticket_data,
|
||||
"server": server
|
||||
})
|
||||
|
||||
@app.get("/api/fetch")
|
||||
@app.post("/api/fetch")
|
||||
async def api_fetch(server: str = Form(...)):
|
||||
return await handle_fetch(server)
|
||||
|
||||
async def handle_fetch(server: str):
|
||||
RELEASE_TICKET_PATH = f"/rpc/releaseTicket.action?buildNumber={BUILD_NUMBER}&clientVersion=16&hostName={DESKTOP_NAME}&machineId={MACHINE_ID}&productCode=cfc7082d-ae43-4978-a2a2-46feb1679405&productFamilyId=cfc7082d-ae43-4978-a2a2-46feb1679405&salt=1726973268812&secure=false&ticketId=rsoaehfbbg&userName={USERNAME}"
|
||||
OBTAIN_TICKET_PATH = f"/rpc/obtainTicket.action?buildDate=20240409&{BUILD_NUMBER}&clientVersion=16&hostName={DESKTOP_NAME}&machineId={MACHINE_ID}&productCode=cfc7082d-ae43-4978-a2a2-46feb1679405&productFamilyId=cfc7082d-ae43-4978-a2a2-46feb1679405&salt=1726973269845&secure=false&userName={USERNAME}&version={VERSION}&versionNumber={VERSION}"
|
||||
|
||||
release_ticket_data = get_xml_data(server, RELEASE_TICKET_PATH)
|
||||
obtain_ticket_data = get_xml_data(server, OBTAIN_TICKET_PATH)
|
||||
|
||||
available = False
|
||||
if obtain_ticket_data.get("response_code") == "OK":
|
||||
available = True
|
||||
elif obtain_ticket_data.get("response_code") == "Error":
|
||||
available = False
|
||||
|
||||
return JSONResponse(content={
|
||||
"available": available,
|
||||
"message": obtain_ticket_data.get("message", ""),
|
||||
"data": {
|
||||
"release_ticket_data": release_ticket_data,
|
||||
"obtain_ticket_data": obtain_ticket_data,
|
||||
}
|
||||
})
|
7
app/static/scripts.js
Normal file
7
app/static/scripts.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
document.getElementById('server-form').addEventListener('submit', function(e) {
|
||||
const serverInput = document.getElementById('server').value;
|
||||
if (!serverInput.startsWith('https://') && !serverInput.startsWith('http://')) {
|
||||
e.preventDefault();
|
||||
alert('Please enter a valid server URL starting with https:// or http://');
|
||||
}
|
||||
});
|
69
app/static/styles.css
Normal file
69
app/static/styles.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #007bff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 15px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
#results {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 1200px;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
word-wrap: break-word; /* 允许单词换行 */
|
||||
max-width: 300px; /* 设置最大宽度 */
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
67
app/templates/index.html
Normal file
67
app/templates/index.html
Normal file
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>License Server Information</title>
|
||||
<link rel="stylesheet" href="/static/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>JetBrains License Server Info Fetcher</h1>
|
||||
|
||||
<form id="server-form" method="post" action="/fetch">
|
||||
<label for="server">Enter Server URL:</label>
|
||||
<input type="text" id="server" name="server" placeholder="https://your-server.com" required>
|
||||
<button type="submit">Fetch Data</button>
|
||||
</form>
|
||||
<br>
|
||||
<div align="center">
|
||||
{% if obtain_data.response_code == "" %}
|
||||
<h3> Please input your server to check. </h3>
|
||||
{% elif obtain_data.error %}
|
||||
<h3 style="color: red;">{{ obtain_data.error }}</h3> <!-- 显示错误信息 -->
|
||||
{% elif obtain_data.response_code == "OK" %}
|
||||
<h3> This server is available. </h3>
|
||||
{% else %}
|
||||
<h3> This server is not available: {{ obtain_data.message }} </h3>
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div id="results" align="center">
|
||||
{% if release_data and obtain_data %}
|
||||
<h2>Release Ticket Data</h2>
|
||||
<table>
|
||||
<tr><th>Field</th><th>Value</th></tr>
|
||||
<tr><td>Action</td><td>{{ release_data.action }}</td></tr>
|
||||
<tr><td>Confirmation Stamp</td><td>{{ release_data.confirmation_stamp }}</td></tr>
|
||||
<tr><td>Lease Signature</td><td>{{ release_data.lease_signature }}</td></tr>
|
||||
<tr><td>Response Code</td><td>{{ release_data.response_code }}</td></tr>
|
||||
<tr><td>Salt</td><td>{{ release_data.salt }}</td></tr>
|
||||
<tr><td>Server Lease</td><td>{{ release_data.server_lease }}</td></tr>
|
||||
<tr><td>Server UID</td><td>{{ release_data.server_uid }}</td></tr>
|
||||
<tr><td>Validation Deadline Period</td><td>{{ release_data.validation_deadline_period }}</td></tr>
|
||||
<tr><td>Validation Period</td><td>{{ release_data.validation_period }}</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Obtain Ticket Data</h2>
|
||||
<table>
|
||||
<tr><th>Field</th><th>Value</th></tr>
|
||||
<tr><td>Action</td><td>{{ obtain_data.action }}</td></tr>
|
||||
<tr><td>Confirmation Stamp</td><td>{{ obtain_data.confirmation_stamp }}</td></tr>
|
||||
<tr><td>Lease Signature</td><td>{{ obtain_data.lease_signature }}</td></tr>
|
||||
<tr><td>Message</td><td>{{ obtain_data.message }}</td></tr>
|
||||
<tr><td>Prolongation Period</td><td>{{ obtain_data.prolongation_period }}</td></tr>
|
||||
<tr><td>Response Code</td><td>{{ obtain_data.response_code }}</td></tr>
|
||||
<tr><td>Salt</td><td>{{ obtain_data.salt }}</td></tr>
|
||||
<tr><td>Server Lease</td><td>{{ obtain_data.server_lease }}</td></tr>
|
||||
<tr><td>Server UID</td><td>{{ obtain_data.server_uid }}</td></tr>
|
||||
<tr><td>Validation Deadline Period</td><td>{{ obtain_data.validation_deadline_period }}</td></tr>
|
||||
<tr><td>Validation Period</td><td>{{ obtain_data.validation_period }}</td></tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script src="/static/scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
5
requirements.txt
Normal file
5
requirements.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
fastapi
|
||||
uvicorn
|
||||
httpx
|
||||
jinja2
|
||||
python-multipart
|
Loading…
Reference in New Issue
Block a user