mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Fix deploy data fetching (#1494)
Co-authored-by: Uriel <imurx@proton.me>
This commit is contained in:
1482
Cargo.lock
generated
1482
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
"@tauri-apps/api": "^2.0.2",
|
||||
"@tauri-apps/plugin-dialog": "^2.0.0",
|
||||
"@tauri-apps/plugin-fs": "^2.0.0",
|
||||
"@tauri-apps/plugin-http": "^2.5.0",
|
||||
"@tauri-apps/plugin-os": "^2.0.0",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
"@tauri-apps/plugin-store": "^2.0.0",
|
||||
|
||||
@@ -54,6 +54,7 @@ dirs-next = "2.0.0"
|
||||
discord-sdk = "0.3.6"
|
||||
tokio = { version = "1.37.0", features = ["time"] }
|
||||
itertools = "0.13.0"
|
||||
tauri-plugin-http = "2.5.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
win32job = "1"
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://github.com/SlimeVR/SlimeVR-Tracker-ESP/releases/download/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -254,6 +254,7 @@ fn setup_tauri(
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_store::Builder::default().build())
|
||||
.plugin(tauri_plugin_http::init())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
update_window_state,
|
||||
logging,
|
||||
|
||||
@@ -105,7 +105,7 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
|
||||
.title("SlimeVR")
|
||||
.tooltip("SlimeVR")
|
||||
.icon_as_template(true)
|
||||
.menu_on_left_click(false)
|
||||
.show_menu_on_left_click(false)
|
||||
.icon(if cfg!(target_os = "macos") {
|
||||
include_image!("icons/appleTrayIcon.png")
|
||||
} else {
|
||||
@@ -146,7 +146,7 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
|
||||
_ => {}
|
||||
})
|
||||
// We don't want this as we open the window on left click
|
||||
.menu_on_left_click(false)
|
||||
.show_menu_on_left_click(false)
|
||||
.build(app)?;
|
||||
|
||||
app.manage(TrayAvailable(true));
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { BoardType, DeviceDataT } from 'solarxr-protocol';
|
||||
import { fetch as tauriFetch } from '@tauri-apps/plugin-http';
|
||||
import { cacheWrap } from './cache';
|
||||
import semver from 'semver';
|
||||
import { hostname, locale, platform, version } from '@tauri-apps/plugin-os';
|
||||
|
||||
type DeployDataJson = Map<string, string>;
|
||||
type DeployData = Map<number, Date>;
|
||||
|
||||
export interface FirmwareRelease {
|
||||
name: string;
|
||||
version: string;
|
||||
@@ -26,49 +24,49 @@ const hash = (str: string) => {
|
||||
return (hash >>> 0) / 2 ** 32;
|
||||
};
|
||||
|
||||
const uniqueUserKey = `${await hostname()}-${await locale()}-${platform()}-${version()}`;
|
||||
|
||||
const firstAsset = (assets: any[], name: string) =>
|
||||
assets.find((asset: any) => asset.name === name && asset.browser_download_url);
|
||||
|
||||
const processDeployData = (sortedMap: [string, string][]) => {
|
||||
const deployData: DeployData = new Map();
|
||||
let minTime = 0;
|
||||
for (const [percent, date] of sortedMap) {
|
||||
const d = new Date(date);
|
||||
if (d.getTime() <= minTime) return null; // Dates in the wrong order / cancel
|
||||
minTime = d.getTime();
|
||||
deployData.set(parseFloat(percent), new Date(date));
|
||||
}
|
||||
return deployData;
|
||||
};
|
||||
|
||||
const checkUserCanUpdate = async (deployAssetUrl: string) => {
|
||||
if (!deployAssetUrl) return false;
|
||||
const deployDataJson: DeployData | null = await fetch(deployAssetUrl)
|
||||
.then((res) => res.json())
|
||||
.catch(() => null);
|
||||
if (!deployDataJson) return false;
|
||||
|
||||
const deployDataMap = new Map(
|
||||
Object.entries(deployDataJson)
|
||||
) as unknown as DeployDataJson;
|
||||
const sortedMap = [...deployDataMap].sort(
|
||||
([a], [b]) => parseFloat(b) - parseFloat(a)
|
||||
const checkUserCanUpdate = async (url: string, fwVersion: string) => {
|
||||
if (!url) return true;
|
||||
const deployDataJson = JSON.parse(
|
||||
(await cacheWrap(
|
||||
`firmware-${fwVersion}-deploy`,
|
||||
() =>
|
||||
tauriFetch(url)
|
||||
.then((res) => res.text())
|
||||
.catch(() => null),
|
||||
60 * 60 * 1000
|
||||
)) || 'null'
|
||||
);
|
||||
if (!deployDataJson) return true;
|
||||
|
||||
if (sortedMap.keys().find((key) => key > 1 || key <= 0)) return false; // values outside boundaries / cancel
|
||||
const deployData = (
|
||||
Object.entries(deployDataJson).map(([key, val]) => {
|
||||
return [parseFloat(key), new Date(val as string)];
|
||||
}) as [number, Date][]
|
||||
).sort(([a], [b]) => a - b);
|
||||
|
||||
const deployData = processDeployData(sortedMap);
|
||||
if (!deployData) return false;
|
||||
if (deployData.find(([key]) => key > 1 || key <= 0)) return false; // values outside boundaries / cancel
|
||||
|
||||
if (
|
||||
deployData.find(
|
||||
([, date], index) =>
|
||||
index > 0 && date.getTime() < deployData[index - 1][1].getTime()
|
||||
)
|
||||
)
|
||||
return false; // Dates in the wrong order / cancel
|
||||
|
||||
const todayUpdateRange = deployData.find(([, date], index) => {
|
||||
if (index === 0 && Date.now() < date.getTime()) return true;
|
||||
return Date.now() >= date.getTime();
|
||||
})?.[0];
|
||||
|
||||
const todayUpdateRange = deployData
|
||||
.entries()
|
||||
.find(([, date]) => Date.now() >= date.getTime())?.[0];
|
||||
if (!todayUpdateRange) return false;
|
||||
|
||||
const uniqueUserKey = `${await hostname()}-${await locale()}-${platform()}-${version()}`;
|
||||
// Make it so the hash change every version. Prevent the same user from getting the same delay
|
||||
return hash(`${uniqueUserKey}-${version}`) <= todayUpdateRange;
|
||||
return hash(`${uniqueUserKey}-${fwVersion}`) <= todayUpdateRange;
|
||||
};
|
||||
|
||||
export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | null> {
|
||||
@@ -87,7 +85,6 @@ export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | n
|
||||
const processedReleses = [];
|
||||
for (const release of releases) {
|
||||
const fwAsset = firstAsset(release.assets, 'BOARD_SLIMEVR-firmware.bin');
|
||||
const deployAsset = firstAsset(release.assets, 'deploy.json');
|
||||
if (!release.assets || !fwAsset /* || release.prerelease */) continue;
|
||||
|
||||
let version = release.tag_name;
|
||||
@@ -95,10 +92,11 @@ export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | n
|
||||
version = version.substring(1);
|
||||
}
|
||||
|
||||
const userCanUpdate = !deployAsset
|
||||
? true
|
||||
: await checkUserCanUpdate(deployAsset?.browser_download_url);
|
||||
|
||||
const deployAsset = firstAsset(release.assets, 'deploy.json');
|
||||
const userCanUpdate = await checkUserCanUpdate(
|
||||
deployAsset?.browser_download_url,
|
||||
version
|
||||
);
|
||||
processedReleses.push({
|
||||
name: release.name,
|
||||
version,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": ["dom", "dom.iterable", "ES2023"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -62,6 +62,9 @@ importers:
|
||||
'@tauri-apps/plugin-fs':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
'@tauri-apps/plugin-http':
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
'@tauri-apps/plugin-os':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@@ -485,6 +488,7 @@ packages:
|
||||
'@dword-design/functions@5.0.27':
|
||||
resolution: {integrity: sha512-16A97RKtn21xLWI7Y7VhFz4WCWui+TLit/J5/l77BDpWmPi2LzgjQzDbafDDw7OUeY6GEAi/M4jdbuQhsIbSEg==}
|
||||
engines: {node: '>=14'}
|
||||
deprecated: Use lodash and endent
|
||||
|
||||
'@esbuild/aix-ppc64@0.21.5':
|
||||
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
|
||||
@@ -1179,6 +1183,9 @@ packages:
|
||||
'@tauri-apps/api@2.0.2':
|
||||
resolution: {integrity: sha512-3wSwmG+1kr6WrgAFKK5ijkNFPp8TT3FLj3YHUb5EwMO+3FxX4uWlfSWkeeBy+Kc1RsKzugtYLuuya+98Flj+3w==}
|
||||
|
||||
'@tauri-apps/api@2.6.0':
|
||||
resolution: {integrity: sha512-hRNcdercfgpzgFrMXWwNDBN0B7vNzOzRepy6ZAmhxi5mDLVPNrTpo9MGg2tN/F7JRugj4d2aF7E1rtPXAHaetg==}
|
||||
|
||||
'@tauri-apps/cli-darwin-arm64@2.0.3':
|
||||
resolution: {integrity: sha512-jIsbxGWS+As1ZN7umo90nkql/ZAbrDK0GBT6UsgHSz5zSwwArICsZFFwE1pLZip5yoiV5mn3TGG2c1+v+0puzQ==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -1250,6 +1257,9 @@ packages:
|
||||
'@tauri-apps/plugin-fs@2.0.0':
|
||||
resolution: {integrity: sha512-BNEeQQ5aH8J5SwYuWgRszVyItsmquRuzK2QRkVj8Z0sCsLnSvJFYI3JHRzzr3ltZGq1nMPtblrlZzuKqVzRawA==}
|
||||
|
||||
'@tauri-apps/plugin-http@2.5.0':
|
||||
resolution: {integrity: sha512-l4M2DUIsOBIMrbj4dJZwrB4mJiB7OA/2Tj3gEbX2fjq5MOpETklJPKfDvzUTDwuq4lIKCKKykz8E8tpOgvi0EQ==}
|
||||
|
||||
'@tauri-apps/plugin-os@2.0.0':
|
||||
resolution: {integrity: sha512-M7hG/nNyQYTJxVG/UhTKhp9mpXriwWzrs9mqDreB8mIgqA3ek5nHLdwRZJWhkKjZrnDT4v9CpA9BhYeplTlAiA==}
|
||||
|
||||
@@ -5405,6 +5415,8 @@ snapshots:
|
||||
|
||||
'@tauri-apps/api@2.0.2': {}
|
||||
|
||||
'@tauri-apps/api@2.6.0': {}
|
||||
|
||||
'@tauri-apps/cli-darwin-arm64@2.0.3':
|
||||
optional: true
|
||||
|
||||
@@ -5456,6 +5468,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.0.2
|
||||
|
||||
'@tauri-apps/plugin-http@2.5.0':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.6.0
|
||||
|
||||
'@tauri-apps/plugin-os@2.0.0':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.0.2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "1.81"
|
||||
channel = "1.82"
|
||||
profile = "default"
|
||||
components = ["rustc", "cargo", "clippy", "rustfmt", "rust-analyzer", "rust-src"]
|
||||
|
||||
Reference in New Issue
Block a user