Servers fixes

This commit is contained in:
Prospector
2025-06-03 16:15:57 -07:00
parent 3f77ab19ed
commit 4e8ebb5e5c
8 changed files with 66 additions and 29 deletions

View File

@@ -2,6 +2,7 @@
import { $fetch, FetchError } from "ofetch"; import { $fetch, FetchError } from "ofetch";
import type { ServerNotice } from "@modrinth/utils"; import type { ServerNotice } from "@modrinth/utils";
import type { FilesystemOp, FSQueuedOp, WSBackupState, WSBackupTask } from "~/types/servers.ts"; import type { FilesystemOp, FSQueuedOp, WSBackupState, WSBackupTask } from "~/types/servers.ts";
import { usePyroFetch } from "~/composables/pyroFetch.ts";
interface PyroFetchOptions { interface PyroFetchOptions {
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
@@ -1224,6 +1225,13 @@ const modules: any = {
suspend: suspendServer, suspend: suspendServer,
getMotd, getMotd,
setMotd, setMotd,
endIntro: async () => {
await usePyroFetch(`servers/${internalServerReference.value.serverId}/flows/intro`, {
method: "DELETE",
version: 1,
});
await internalServerReference.value.refresh(["general"]);
},
}, },
content: { content: {
get: async (serverId: string) => { get: async (serverId: string) => {
@@ -1454,6 +1462,8 @@ type GeneralFunctions = {
* @deprecated Use fs.downloadFile instead * @deprecated Use fs.downloadFile instead
*/ */
fetchConfigFile: (fileName: string) => Promise<any>; fetchConfigFile: (fileName: string) => Promise<any>;
endIntro: () => Promise<void>;
}; };
type ContentFunctions = { type ContentFunctions = {

View File

@@ -905,7 +905,7 @@ function pingRegions() {
} }
const PING_COUNT = 20; const PING_COUNT = 20;
const PING_INTERVAL = 400; const PING_INTERVAL = 200;
const MAX_PING_TIME = 1000; const MAX_PING_TIME = 1000;
function runPingTest(region, index = 1) { function runPingTest(region, index = 1) {

View File

@@ -862,11 +862,8 @@ const newLoaderVersion = ref<string | null>(null);
const newMCVersion = ref<string | null>(null); const newMCVersion = ref<string | null>(null);
const onReinstall = (potentialArgs: any) => { const onReinstall = (potentialArgs: any) => {
if (serverData.value?.flows?.intro) { if (serverData.value?.flows?.intro && server.general?.project) {
usePyroFetch(`servers/${server.serverId}/flows/intro`, { server.general?.endIntro();
method: "DELETE",
version: 1,
});
} }
if (!serverData.value) return; if (!serverData.value) return;
@@ -1188,6 +1185,10 @@ onMounted(() => {
connectWebSocket(); connectWebSocket();
} }
if (server.general?.flows?.intro && server.general?.project) {
server.general?.endIntro();
}
if (username.value && email.value && userId.value && createdAt.value) { if (username.value && email.value && userId.value && createdAt.value) {
const currentUser = auth.value?.user as any; const currentUser = auth.value?.user as any;
const matches = const matches =

View File

@@ -168,11 +168,19 @@ const fuse = computed(() => {
}); });
}); });
function introToTop(array: Server[]): Server[] {
return array.slice().sort((a, b) => {
return Number(b.flows?.intro) - Number(a.flows?.intro);
});
}
const filteredData = computed(() => { const filteredData = computed(() => {
if (!searchInput.value.trim()) { if (!searchInput.value.trim()) {
return serverList.value; return introToTop(serverList.value);
} }
return fuse.value ? fuse.value.search(searchInput.value).map((result) => result.item) : []; return fuse.value
? introToTop(fuse.value.search(searchInput.value).map((result) => result.item))
: [];
}); });
const previousServerList = ref<Server[]>([]); const previousServerList = ref<Server[]>([]);

View File

@@ -91,7 +91,7 @@ const {
const customServer = ref<boolean>(false) const customServer = ref<boolean>(false)
const acceptedEula = ref<boolean>(false) const acceptedEula = ref<boolean>(false)
const firstTimeThru = ref<boolean>(true) const skipPaymentMethods = ref<boolean>(true)
type Step = 'region' | 'payment' | 'review' type Step = 'region' | 'payment' | 'review'
@@ -117,9 +117,13 @@ const currentPing = computed(() => {
const currentStep = ref<Step>() const currentStep = ref<Step>()
const currentStepIndex = computed(() => (currentStep.value ? steps.indexOf(currentStep.value) : -1)) const currentStepIndex = computed(() => (currentStep.value ? steps.indexOf(currentStep.value) : -1))
const previousStep = computed(() => const previousStep = computed(() => {
currentStep.value ? steps[steps.indexOf(currentStep.value) - 1] : undefined, const step = currentStep.value ? steps[steps.indexOf(currentStep.value) - 1] : undefined
) if (step === 'payment' && skipPaymentMethods.value && primaryPaymentMethodId.value) {
return 'region'
}
return step
})
const nextStep = computed(() => const nextStep = computed(() =>
currentStep.value ? steps[steps.indexOf(currentStep.value) + 1] : undefined, currentStep.value ? steps[steps.indexOf(currentStep.value) + 1] : undefined,
) )
@@ -144,13 +148,12 @@ async function beforeProceed(step: string) {
case 'payment': case 'payment':
await initializeStripe() await initializeStripe()
if (primaryPaymentMethodId.value && firstTimeThru.value) { if (primaryPaymentMethodId.value && skipPaymentMethods.value) {
const paymentMethod = await props.paymentMethods.find( const paymentMethod = await props.paymentMethods.find(
(x) => x.id === primaryPaymentMethodId.value, (x) => x.id === primaryPaymentMethodId.value,
) )
await selectPaymentMethod(paymentMethod) await selectPaymentMethod(paymentMethod)
await setStep('review', true) await setStep('review', true)
firstTimeThru.value = false
return false return false
} }
return true return true
@@ -205,7 +208,7 @@ function begin(interval: ServerBillingInterval, plan?: ServerPlan) {
customServer.value = !selectedPlan.value customServer.value = !selectedPlan.value
selectedPaymentMethod.value = undefined selectedPaymentMethod.value = undefined
currentStep.value = steps[0] currentStep.value = steps[0]
firstTimeThru.value = true skipPaymentMethods.value = true
modal.value?.show() modal.value?.show()
} }
@@ -278,7 +281,12 @@ defineExpose({
:selected-payment-method="selectedPaymentMethod || inputtedPaymentMethod" :selected-payment-method="selectedPaymentMethod || inputtedPaymentMethod"
:tax="tax" :tax="tax"
:total="total" :total="total"
@change-payment-method="setStep('payment', true)" @change-payment-method="
() => {
skipPaymentMethods = false
setStep('payment', true)
}
"
@reload-payment-intent="reloadPaymentIntent" @reload-payment-intent="reloadPaymentIntent"
/> />
<div v-else>Something went wrong</div> <div v-else>Something went wrong</div>

View File

@@ -25,6 +25,16 @@ const checkingCustomStock = ref(false)
const selectedPlan = defineModel<ServerPlan>('plan') const selectedPlan = defineModel<ServerPlan>('plan')
const selectedRegion = defineModel<string>('region') const selectedRegion = defineModel<string>('region')
const regionOrder: string[] = [
// 'us-vin', 'eu-lim'
]
const sortedRegions = computed(() => {
return props.regions.slice().sort((a, b) => {
return regionOrder.indexOf(a.shortcode) - regionOrder.indexOf(b.shortcode)
})
})
const selectedRam = ref<number>(-1) const selectedRam = ref<number>(-1)
const ramOptions = computed(() => { const ramOptions = computed(() => {
@@ -55,7 +65,7 @@ function updateRamStock(regionToCheck: string, newRam: number) {
(product) => (product.metadata.ram ?? 0) / 1024 === newRam, (product) => (product.metadata.ram ?? 0) / 1024 === newRam,
) )
if (plan) { if (plan) {
const region = props.regions.find((region) => region.shortcode === regionToCheck) const region = sortedRegions.value.find((region) => region.shortcode === regionToCheck)
if (region) { if (region) {
props props
.fetchStock(region, { .fetchStock(region, {
@@ -113,7 +123,7 @@ const messages = defineMessages({
async function updateStock() { async function updateStock() {
currentStock.value = {} currentStock.value = {}
const capacityChecks = props.regions.map((region) => const capacityChecks = sortedRegions.value.map((region) =>
props.fetchStock( props.fetchStock(
region, region,
selectedPlan.value selectedPlan.value
@@ -133,7 +143,7 @@ async function updateStock() {
) )
const results = await Promise.all(capacityChecks) const results = await Promise.all(capacityChecks)
results.forEach((result, index) => { results.forEach((result, index) => {
currentStock.value[props.regions[index].shortcode] = result currentStock.value[sortedRegions.value[index].shortcode] = result
}) })
} }
@@ -146,10 +156,13 @@ onMounted(() => {
return acc.ping < cur.ping ? acc : cur return acc.ping < cur.ping ? acc : cur
})?.region })?.region
: undefined : undefined
selectedRegion.value = undefined
selectedRam.value = minRam.value selectedRam.value = minRam.value
checkingCustomStock.value = true checkingCustomStock.value = true
updateStock().then(() => { updateStock().then(() => {
const firstWithStock = props.regions.find((region) => currentStock.value[region.shortcode] > 0) const firstWithStock = sortedRegions.value.find(
(region) => currentStock.value[region.shortcode] > 0,
)
let stockedRegion = selectedRegion.value let stockedRegion = selectedRegion.value
if (!stockedRegion) { if (!stockedRegion) {
stockedRegion = stockedRegion =
@@ -176,7 +189,7 @@ onMounted(() => {
</h2> </h2>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<ServersRegionButton <ServersRegionButton
v-for="region in regions" v-for="region in sortedRegions"
:key="region.shortcode" :key="region.shortcode"
v-model="selectedRegion" v-model="selectedRegion"
:region="region" :region="region"

View File

@@ -81,10 +81,7 @@ function setRegion() {
class="shrink-0" class="shrink-0"
/> />
<SpinnerIcon v-else class="animate-spin" /> <SpinnerIcon v-else class="animate-spin" />
<span v-if="bestPing" :class="bestPing ? 'text-brand' : 'text-primary'"> <template v-if="ping"> {{ ping }}ms </template>
Lowest latency ({{ ping }}ms)
</span>
<template v-else-if="ping"> {{ ping }}ms </template>
<span v-else> Testing connection... </span> <span v-else> Testing connection... </span>
</template> </template>
</span> </span>

View File

@@ -343,13 +343,13 @@ export const getArrayOrString = (x: string[] | string): string[] => {
} }
export function getPingLevel(ping: number) { export function getPingLevel(ping: number) {
if (ping < 150) { if (ping < 120) {
return 5 return 5
} else if (ping < 300) { } else if (ping < 200) {
return 4 return 4
} else if (ping < 600) { } else if (ping < 300) {
return 3 return 3
} else if (ping < 1000) { } else if (ping < 400) {
return 2 return 2
} else { } else {
return 1 return 1