Compare commits
3 Commits
0cd3a6c4ae
...
076449b9f9
Author | SHA1 | Date | |
---|---|---|---|
076449b9f9 | |||
00f9926016 | |||
cdadd234d5 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2591,7 +2591,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sr_download"
|
name = "sr_download"
|
||||||
version = "1.1.1"
|
version = "1.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
102
pages.md
Normal file
102
pages.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# sr-download 提供的网络 api
|
||||||
|
|
||||||
|
## 设置
|
||||||
|
|
||||||
|
要想设置这部分内容
|
||||||
|
|
||||||
|
请编辑 `config.toml` 文件
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# 这个部分
|
||||||
|
[serve]
|
||||||
|
# 服务的地址和端口
|
||||||
|
host_with_port = "0.0.0.0:10002"
|
||||||
|
# 数据库最大连接数
|
||||||
|
db_max_connect = 10
|
||||||
|
# 是否启用 serve 模式
|
||||||
|
enable = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## 页面
|
||||||
|
|
||||||
|
`/dashboard`
|
||||||
|
|
||||||
|
展示当前信息
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### GET `/last/data`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": {
|
||||||
|
"save_id": 1322273,
|
||||||
|
"save_type": "save",
|
||||||
|
"len": 2955,
|
||||||
|
"blake_hash": "1e327361ae30604f7828f3e1a0987098a61a16df0ce830352237e60c9db434fe"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET `/last/save`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": {
|
||||||
|
"save_id": 1322273,
|
||||||
|
"len": 2955,
|
||||||
|
"blake_hash": "1e327361ae30604f7828f3e1a0987098a61a16df0ce830352237e60c9db434fe"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET `/last/ship`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": {
|
||||||
|
"save_id": 1322271,
|
||||||
|
"len": 13721,
|
||||||
|
"blake_hash": "79c97ca4fe9fa982209e58d1e11df6ebf22cf2e96a2fc8cc48f9316982e6d7d5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET `/info/:id`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": {
|
||||||
|
"save_id": 1322271,
|
||||||
|
"save_type": "ship",
|
||||||
|
"len": 13721,
|
||||||
|
"blake_hash": "79c97ca4fe9fa982209e58d1e11df6ebf22cf2e96a2fc8cc48f9316982e6d7d5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET `/download/:id`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": {
|
||||||
|
"info": {
|
||||||
|
"save_id": 1322271,
|
||||||
|
"save_type": "ship",
|
||||||
|
"len": 13721,
|
||||||
|
"blake_hash": "79c97ca4fe9fa982209e58d1e11df6ebf22cf2e96a2fc8cc48f9316982e6d7d5"
|
||||||
|
},
|
||||||
|
"raw_data": "<Ship version=\"1\" liftedOff ..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
34
readme.md
34
readme.md
@ -10,39 +10,7 @@ Rewritten in Rust !
|
|||||||
|
|
||||||
现在支持提供 api 了
|
现在支持提供 api 了
|
||||||
|
|
||||||
- `GET /last_data` 获取最新的数据信息
|
具体 API 请参考 [这个页面](./pages.md)
|
||||||
- 返回范例:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"save_id": 1322269,
|
|
||||||
"save_type": "save",
|
|
||||||
"len": 3404,
|
|
||||||
"blake_hash": "0b4758dbda98fea0ab6ad58fd589ccc7bb14c29ab8b22e6e49b670db8fec8da9"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `GET /last_save` 获取最新的存档信息
|
|
||||||
- 返回范例:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"save_id": 1322269,
|
|
||||||
"len": 3404,
|
|
||||||
"blake_hash": "0b4758dbda98fea0ab6ad58fd589ccc7bb14c29ab8b22e6e49b670db8fec8da9"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `GET /last_ship` 获取最新的船只信息
|
|
||||||
- 返回范例:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"save_id": 1322267,
|
|
||||||
"len": 38967,
|
|
||||||
"blake_hash": "9474267203155e5cf31e0e7e34ec014773f8f89c78d262f5bd57b6e27fdc25b2"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## V1
|
## V1
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "sr_download"
|
name = "sr_download"
|
||||||
version = "1.1.1"
|
version = "1.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "sr_download"
|
default-run = "sr_download"
|
||||||
|
|
||||||
|
208
sr_download/src/info.html
Normal file
208
sr_download/src/info.html
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cn">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
|
||||||
|
<title>sr-download 信息页面</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #F5F5F5FF;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
width: 80%;
|
||||||
|
padding: 40px;
|
||||||
|
border: 2px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box:nth-child(1) {
|
||||||
|
background-color: #FFE0B2;
|
||||||
|
/* 淡橙色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.box:nth-child(2) {
|
||||||
|
background-color: #C8E6C9;
|
||||||
|
/* 淡绿色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.box2 {
|
||||||
|
width: 90%;
|
||||||
|
padding: 20px;
|
||||||
|
border: 2px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box2:nth-child(1) {
|
||||||
|
background-color: #BBDEFB;
|
||||||
|
/* 淡蓝色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 40px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monospace {
|
||||||
|
font-family: monospace;
|
||||||
|
/* 启用等宽字体 */
|
||||||
|
border: 1px solid #000;
|
||||||
|
/* 添加边框 */
|
||||||
|
padding: 2px;
|
||||||
|
/* 添加内边距 */
|
||||||
|
background-color: #343942ba;
|
||||||
|
/* 浅灰色背景 */
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
height: 40px;
|
||||||
|
/* 设置行间距 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-section {
|
||||||
|
flex-basis: 50%;
|
||||||
|
/* 占满宽度 */
|
||||||
|
padding: 20px;
|
||||||
|
border: 2px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
background-color: #FFCDD2;
|
||||||
|
/* 淡蓝色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-section input {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-section button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 18px;
|
||||||
|
background-color: #b3ffe8;
|
||||||
|
/* 淡蓝色 */
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-section button:hover {
|
||||||
|
background-color: #90CAF9;
|
||||||
|
/* 深蓝色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-display {
|
||||||
|
flex-basis: 100%;
|
||||||
|
/* 占满宽度 */
|
||||||
|
padding: 20px;
|
||||||
|
border: 2px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
background-color: #E1BEE7;
|
||||||
|
/* 淡紫色 */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="box2">
|
||||||
|
<div class="title">最新数据</div>
|
||||||
|
<div>最大 id: |MAX_ID|</div>
|
||||||
|
<div>类型: |MAX_SAVE_TYPE|</div>
|
||||||
|
<div>长度: |MAX_LEN|</div>
|
||||||
|
<div>blake hash: <span class="monospace">|MAX_HASH|</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="box">
|
||||||
|
<div class="title">最新飞船</div>
|
||||||
|
<div>最大飞船 id: |MAX_SHIP_ID|</div>
|
||||||
|
<div>长度: |MAX_SHIP_LEN|</div>
|
||||||
|
<div>blake hash: <span class="monospace">|MAX_SHIP_HASH|</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="title">最新存档</div>
|
||||||
|
<div>最大存档 id: |MAX_SAVE_ID|</div>
|
||||||
|
<div>长度: |MAX_SAVE_LEN|</div>
|
||||||
|
<div>blake hash: <span class="monospace">|MAX_SAVE_HASH|</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="input-section">
|
||||||
|
<input type="number" id="dataId" placeholder="输入ID">
|
||||||
|
<button onclick="fetchData()">获取数据</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="result-display">
|
||||||
|
<div class="title">请求结果</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function fetchData() {
|
||||||
|
// 获取输入框中的 ID
|
||||||
|
const dataId = document.getElementById('dataId').value;
|
||||||
|
if (!dataId) {
|
||||||
|
alert('请输入 ID');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dataId < 76858) {
|
||||||
|
alert('ID 不能小于 76858 (这个是目前最小的 ID)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 发送请求
|
||||||
|
fetch(`/info/${dataId}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
// 获取结果显示区域
|
||||||
|
const resultDisplay = document.querySelector('.result-display');
|
||||||
|
// 清空结果显示区域
|
||||||
|
resultDisplay.innerHTML = '';
|
||||||
|
// 创建结果显示区域的元素
|
||||||
|
const resultTitle = document.createElement('div');
|
||||||
|
resultTitle.classList.add('title');
|
||||||
|
resultTitle.innerText = '请求结果';
|
||||||
|
resultDisplay.appendChild(resultTitle);
|
||||||
|
// 先判断数据拿没拿到
|
||||||
|
if (data["code"] != 200) {
|
||||||
|
// 没拿到
|
||||||
|
const resultContent = document.createElement('div');
|
||||||
|
resultContent.innerText = data["msg"];
|
||||||
|
resultDisplay.appendChild(resultContent);
|
||||||
|
} else {
|
||||||
|
// 拿到了
|
||||||
|
// 创建结果显示区域的元素
|
||||||
|
const resultContent = document.createElement('div');
|
||||||
|
const inner_data = data["data"];
|
||||||
|
// 添加数据
|
||||||
|
resultContent.innerHTML = `<div>id: ${inner_data["save_id"]}</div>
|
||||||
|
<div>类型: ${inner_data["save_type"]}</div>
|
||||||
|
<div>长度: ${inner_data["len"]}</div>
|
||||||
|
<div>blake hash: <span class="monospace">${inner_data["blake_hash"]}</span></div>`;
|
||||||
|
resultDisplay.appendChild(resultContent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -1,10 +1,60 @@
|
|||||||
use axum::{extract::State, routing::get, Json, Router};
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::{Html, IntoResponse},
|
||||||
|
routing::get,
|
||||||
|
Json, Router,
|
||||||
|
};
|
||||||
use sea_orm::{ActiveEnum, DatabaseConnection};
|
use sea_orm::{ActiveEnum, DatabaseConnection};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::db_part;
|
use crate::db_part;
|
||||||
use migration::SaveId;
|
use migration::SaveId;
|
||||||
|
|
||||||
|
pub mod traits;
|
||||||
|
|
||||||
|
use traits::FromDb;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct WebResponse<T> {
|
||||||
|
pub code: u32,
|
||||||
|
pub msg: String,
|
||||||
|
pub data: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WebResponse<T> {
|
||||||
|
pub fn new(data: Option<T>) -> Self {
|
||||||
|
match data {
|
||||||
|
Some(data) => Self::new_normal(data),
|
||||||
|
None => Self::new_missing("internal error?".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_normal(data: T) -> Self {
|
||||||
|
Self {
|
||||||
|
code: StatusCode::OK.as_u16() as u32,
|
||||||
|
msg: "ok".to_string(),
|
||||||
|
data: Some(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_missing(msg: String) -> Self {
|
||||||
|
Self {
|
||||||
|
code: StatusCode::NOT_FOUND.as_u16() as u32,
|
||||||
|
msg,
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_error(status: StatusCode, msg: String) -> Self {
|
||||||
|
Self {
|
||||||
|
code: status.as_u16() as u32,
|
||||||
|
msg,
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 最后一个数据的信息
|
/// 最后一个数据的信息
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LastData {
|
pub struct LastData {
|
||||||
@ -15,8 +65,7 @@ pub struct LastData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LastData {
|
impl LastData {
|
||||||
pub async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
pub async fn from_db_by_id(db: &DatabaseConnection, id: SaveId) -> Option<Self> {
|
||||||
let id = db_part::find_max_id(db).await;
|
|
||||||
let data = db_part::get_raw_data(id, db).await?;
|
let data = db_part::get_raw_data(id, db).await?;
|
||||||
Some(Self {
|
Some(Self {
|
||||||
save_id: data.save_id,
|
save_id: data.save_id,
|
||||||
@ -35,17 +84,6 @@ pub struct LastSave {
|
|||||||
pub blake_hash: String,
|
pub blake_hash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LastSave {
|
|
||||||
pub async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
|
||||||
let data = db_part::find_max_save(db).await?;
|
|
||||||
Some(Self {
|
|
||||||
save_id: data.save_id,
|
|
||||||
len: data.len,
|
|
||||||
blake_hash: data.blake_hash,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 最后一个飞船的信息
|
/// 最后一个飞船的信息
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LastShip {
|
pub struct LastShip {
|
||||||
@ -54,27 +92,135 @@ pub struct LastShip {
|
|||||||
pub blake_hash: String,
|
pub blake_hash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LastShip {
|
/// 实际信息
|
||||||
pub async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
#[derive(Serialize, Deserialize)]
|
||||||
let data = db_part::find_max_ship(db).await?;
|
pub struct RawData {
|
||||||
|
pub info: LastData,
|
||||||
|
pub raw_data: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawData {
|
||||||
|
pub async fn from_db_by_id(db: &DatabaseConnection, id: SaveId) -> Option<Self> {
|
||||||
|
let data = db_part::get_raw_data(id, db).await?;
|
||||||
Some(Self {
|
Some(Self {
|
||||||
|
info: LastData {
|
||||||
save_id: data.save_id,
|
save_id: data.save_id,
|
||||||
|
save_type: data.save_type.to_value().to_string(),
|
||||||
len: data.len,
|
len: data.len,
|
||||||
blake_hash: data.blake_hash,
|
blake_hash: data.blake_hash,
|
||||||
|
},
|
||||||
|
raw_data: data.text?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_last_data(State(db): State<DatabaseConnection>) -> Json<Option<LastData>> {
|
async fn get_last_data(State(db): State<DatabaseConnection>) -> Json<WebResponse<LastData>> {
|
||||||
Json(LastData::from_db(&db).await)
|
Json(WebResponse::new(LastData::from_db(&db).await))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_last_save(State(db): State<DatabaseConnection>) -> Json<Option<LastSave>> {
|
async fn get_last_save(State(db): State<DatabaseConnection>) -> Json<WebResponse<LastSave>> {
|
||||||
Json(LastSave::from_db(&db).await)
|
Json(WebResponse::new(LastSave::from_db(&db).await))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_last_ship(State(db): State<DatabaseConnection>) -> Json<Option<LastShip>> {
|
async fn get_last_ship(State(db): State<DatabaseConnection>) -> Json<WebResponse<LastShip>> {
|
||||||
Json(LastShip::from_db(&db).await)
|
Json(WebResponse::new(LastShip::from_db(&db).await))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_data_info_by_id(
|
||||||
|
State(db): State<DatabaseConnection>,
|
||||||
|
Path(raw_id): Path<String>,
|
||||||
|
) -> Json<WebResponse<LastData>> {
|
||||||
|
match raw_id.parse::<SaveId>() {
|
||||||
|
Ok(id) => match LastData::from_db_by_id(&db, id).await {
|
||||||
|
Some(data) => Json(WebResponse::new_normal(data)),
|
||||||
|
None => Json(WebResponse::new_missing("data not found".to_string())),
|
||||||
|
},
|
||||||
|
Err(e) => Json(WebResponse::new_error(
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
format!("id parse error: {:?}", e),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_data_by_id(
|
||||||
|
State(db): State<DatabaseConnection>,
|
||||||
|
Path(raw_id): Path<String>,
|
||||||
|
) -> Json<WebResponse<RawData>> {
|
||||||
|
match raw_id.parse::<SaveId>() {
|
||||||
|
Ok(id) => match RawData::from_db_by_id(&db, id).await {
|
||||||
|
Some(data) => Json(WebResponse::new_normal(data)),
|
||||||
|
None => Json(WebResponse::new_missing("data not found".to_string())),
|
||||||
|
},
|
||||||
|
Err(e) => Json(WebResponse::new_error(
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
format!("id parse error: {:?}", e),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn jump_to_info(Path(path): Path<String>) -> impl IntoResponse {
|
||||||
|
// html jump
|
||||||
|
(
|
||||||
|
StatusCode::MOVED_PERMANENTLY,
|
||||||
|
Html(format!(
|
||||||
|
"<h1>Jumping from {} to /dashboard</h1><script>location.href='/dashboard'</script>",
|
||||||
|
path
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 下面这段话是用于喂给 GitHub Copilot 让他帮我生成一个好用的 info 页面的 prompt
|
||||||
|
/// 页面背景 F5F5F5FF
|
||||||
|
/// 页面标题为 "sr-download 信息页面"
|
||||||
|
/// 页面内容为三个白色框, 横向排列
|
||||||
|
/// 里面分别是最大 id, 最大飞船 id, 最大存档 id 的信息展示
|
||||||
|
/// 框内文字居中,字体大小 24px, 字体为浏览器默认给的
|
||||||
|
/// 最大 id 部分的文字为 "最大 id: |MAX_ID|\n存档类型: |MAX_SAVE_TYPE|\n长度: |MAX_LEN|\nblake hash: |MAX_HASH|"
|
||||||
|
/// 最大飞船 id 部分展示相关信息, 存档 id 部分同理, 用 相关 |xxx| 作为占位符
|
||||||
|
/// 同时展示 长度, blake hash
|
||||||
|
/// 两个部分分别会展示三行字
|
||||||
|
/// 三个框之间的间距为 20px, 宽度为 80%, 高度为 100%
|
||||||
|
/// 框上面分别是 "最新数据" "最新飞船" "最新存档" 的标题
|
||||||
|
const INFO_PAGE: &str = include_str!("info.html");
|
||||||
|
|
||||||
|
async fn dashboard_page(State(db): State<DatabaseConnection>) -> Html<String> {
|
||||||
|
let max_id = db_part::find_max_id(&db).await;
|
||||||
|
let max_id_data = db_part::get_raw_data(max_id, &db).await.unwrap();
|
||||||
|
let max_ship = db_part::find_max_ship(&db).await;
|
||||||
|
let max_save = db_part::find_max_save(&db).await;
|
||||||
|
|
||||||
|
let mut page_content = INFO_PAGE
|
||||||
|
.replace("|MAX_ID|", &max_id_data.save_id.to_string())
|
||||||
|
.replace(
|
||||||
|
"|MAX_SAVE_TYPE|",
|
||||||
|
&max_id_data.save_type.to_value().to_string(),
|
||||||
|
)
|
||||||
|
.replace("|MAX_LEN|", &max_id_data.len.to_string())
|
||||||
|
.replace("|MAX_HASH|", &max_id_data.blake_hash);
|
||||||
|
if let Some(max_ship) = max_ship {
|
||||||
|
page_content = page_content
|
||||||
|
.replace("|MAX_SHIP_ID|", &max_ship.save_id.to_string())
|
||||||
|
.replace("|MAX_SHIP_LEN|", &max_ship.len.to_string())
|
||||||
|
.replace("|MAX_SHIP_HASH|", &max_ship.blake_hash);
|
||||||
|
} else {
|
||||||
|
page_content = page_content
|
||||||
|
.replace("|MAX_SHIP_ID|", "not found")
|
||||||
|
.replace("|MAX_SHIP_LEN|", "not found")
|
||||||
|
.replace("|MAX_SHIP_HASH|", "not found");
|
||||||
|
}
|
||||||
|
if let Some(max_save) = max_save {
|
||||||
|
page_content = page_content
|
||||||
|
.replace("|MAX_SAVE_ID|", &max_save.save_id.to_string())
|
||||||
|
.replace("|MAX_SAVE_LEN|", &max_save.len.to_string())
|
||||||
|
.replace("|MAX_SAVE_HASH|", &max_save.blake_hash);
|
||||||
|
} else {
|
||||||
|
page_content = page_content
|
||||||
|
.replace("|MAX_SAVE_ID|", "not found")
|
||||||
|
.replace("|MAX_SAVE_LEN|", "not found")
|
||||||
|
.replace("|MAX_SAVE_HASH|", "not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
Html(page_content)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn web_main() -> anyhow::Result<()> {
|
pub async fn web_main() -> anyhow::Result<()> {
|
||||||
@ -83,12 +229,23 @@ pub async fn web_main() -> anyhow::Result<()> {
|
|||||||
let listener = tokio::net::TcpListener::bind(conf.serve.host_with_port.clone()).await?;
|
let listener = tokio::net::TcpListener::bind(conf.serve.host_with_port.clone()).await?;
|
||||||
let db = db_part::connect_server(&conf).await?;
|
let db = db_part::connect_server(&conf).await?;
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
// get /last_data
|
// 获取最后一个数据
|
||||||
.route("/last_data", get(get_last_data))
|
.route("/last/data", get(get_last_data).post(get_last_data))
|
||||||
// get /last_save
|
// 获取最后一个存档
|
||||||
.route("/last_save", get(get_last_save))
|
.route("/last/save", get(get_last_save).post(get_last_save))
|
||||||
// get /last_ship
|
// 获取最后一个飞船
|
||||||
.route("/last_ship", get(get_last_ship))
|
.route("/last/ship", get(get_last_ship).post(get_last_ship))
|
||||||
|
// 获取指定 id 的数据(也有可能返回 not found)
|
||||||
|
.route(
|
||||||
|
"/info/:id",
|
||||||
|
get(get_data_info_by_id).post(get_data_info_by_id),
|
||||||
|
)
|
||||||
|
// 获取下载指定 id 的数据
|
||||||
|
.route("/download/:id", get(get_data_by_id).post(get_data_by_id))
|
||||||
|
// info 页面
|
||||||
|
.route("/dashboard", get(dashboard_page).post(dashboard_page))
|
||||||
|
// 其他所有路径, 直接跳转到 info 页面
|
||||||
|
.route("/*path", get(jump_to_info).post(jump_to_info))
|
||||||
// db
|
// db
|
||||||
.with_state(db);
|
.with_state(db);
|
||||||
|
|
||||||
|
45
sr_download/src/serve/traits.rs
Normal file
45
sr_download/src/serve/traits.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use sea_orm::{ActiveEnum, DatabaseConnection};
|
||||||
|
|
||||||
|
use super::{LastData, LastSave, LastShip};
|
||||||
|
use crate::db_part;
|
||||||
|
|
||||||
|
pub trait FromDb {
|
||||||
|
async fn from_db(db: &DatabaseConnection) -> Option<Self>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromDb for LastData {
|
||||||
|
async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
||||||
|
let id = db_part::find_max_id(db).await;
|
||||||
|
let data = db_part::get_raw_data(id, db).await?;
|
||||||
|
Some(Self {
|
||||||
|
save_id: data.save_id,
|
||||||
|
save_type: data.save_type.to_value().to_string(),
|
||||||
|
len: data.len,
|
||||||
|
blake_hash: data.blake_hash,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromDb for LastSave {
|
||||||
|
async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
||||||
|
let data = db_part::find_max_save(db).await?;
|
||||||
|
Some(Self {
|
||||||
|
save_id: data.save_id,
|
||||||
|
len: data.len,
|
||||||
|
blake_hash: data.blake_hash,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromDb for LastShip {
|
||||||
|
async fn from_db(db: &DatabaseConnection) -> Option<Self> {
|
||||||
|
let data = db_part::find_max_ship(db).await?;
|
||||||
|
Some(Self {
|
||||||
|
save_id: data.save_id,
|
||||||
|
len: data.len,
|
||||||
|
blake_hash: data.blake_hash,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user