add admin tools
This commit is contained in:
@ -6,6 +6,7 @@ import { team } from './team.ts';
|
|||||||
import { settings } from './settings.ts';
|
import { settings } from './settings.ts';
|
||||||
import { feedback } from './feedback.ts';
|
import { feedback } from './feedback.ts';
|
||||||
import { report } from './report.ts';
|
import { report } from './report.ts';
|
||||||
|
import { tools } from './tools.ts';
|
||||||
|
|
||||||
export const server = {
|
export const server = {
|
||||||
admin,
|
admin,
|
||||||
@ -15,5 +16,6 @@ export const server = {
|
|||||||
user,
|
user,
|
||||||
report,
|
report,
|
||||||
feedback,
|
feedback,
|
||||||
settings
|
settings,
|
||||||
|
tools
|
||||||
};
|
};
|
||||||
|
57
src/actions/tools.ts
Normal file
57
src/actions/tools.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { ActionError, defineAction } from 'astro:actions';
|
||||||
|
import { Session } from '@util/session.ts';
|
||||||
|
import { Permissions } from '@util/permissions.ts';
|
||||||
|
import { z } from 'astro:schema';
|
||||||
|
import { getBedrockUuid, getJavaUuid } from '@util/minecraft.ts';
|
||||||
|
|
||||||
|
export const tools = {
|
||||||
|
uuidFromUsername: defineAction({
|
||||||
|
input: z.object({
|
||||||
|
edition: z.enum(['java', 'bedrock']),
|
||||||
|
username: z.string()
|
||||||
|
}),
|
||||||
|
handler: async (input, context) => {
|
||||||
|
Session.actionSessionFromCookies(context.cookies, Permissions.Tools);
|
||||||
|
|
||||||
|
let uuid = null;
|
||||||
|
switch (input.edition) {
|
||||||
|
case 'java':
|
||||||
|
try {
|
||||||
|
uuid = await getJavaUuid(input.username);
|
||||||
|
} catch (_) {
|
||||||
|
throw new ActionError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: `Der Username ${input.username} existiert nicht`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (uuid == null) {
|
||||||
|
throw new ActionError({
|
||||||
|
code: 'BAD_REQUEST',
|
||||||
|
message: `Während der Anfrage zur Mojang API ist ein Fehler aufgetreten`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'bedrock':
|
||||||
|
try {
|
||||||
|
uuid = await getBedrockUuid(input.username);
|
||||||
|
} catch (_) {
|
||||||
|
throw new ActionError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: `Der Username ${input.username} existiert nicht`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (uuid == null) {
|
||||||
|
throw new ActionError({
|
||||||
|
code: 'BAD_REQUEST',
|
||||||
|
message: `Während der Anfrage zum Username Resolver ist ein Fehler aufgetreten`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: uuid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
29
src/app/admin/tools/AccountUuidFinder.svelte
Normal file
29
src/app/admin/tools/AccountUuidFinder.svelte
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Input from '@components/input/Input.svelte';
|
||||||
|
import Select from '@components/input/Select.svelte';
|
||||||
|
import { uuidFromUsername } from '@app/admin/tools/tools.ts';
|
||||||
|
|
||||||
|
// states
|
||||||
|
let edition = $state<'java' | 'bedrock'>('java');
|
||||||
|
let username = $state('');
|
||||||
|
let uuid = $state<null | string>(null);
|
||||||
|
|
||||||
|
// callbacks
|
||||||
|
async function onSubmit() {
|
||||||
|
uuid = await uuidFromUsername(edition, username);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<fieldset class="fieldset border border-base-200 rounded-box px-4">
|
||||||
|
<legend class="fieldset-legend">Account UUID finder</legend>
|
||||||
|
<div>
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<Input bind:value={username} />
|
||||||
|
<Select bind:value={edition} values={{ java: 'Java', bedrock: 'Bedrock' }} />
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<button class="btn w-4/6" class:disabled={!username} onclick={onSubmit}>UUID finden</button>
|
||||||
|
</div>
|
||||||
|
<Input bind:value={uuid} readonly />
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
7
src/app/admin/tools/Tools.svelte
Normal file
7
src/app/admin/tools/Tools.svelte
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import AccountUuidFinder from '@app/admin/tools/AccountUuidFinder.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex justify-center mt-2">
|
||||||
|
<AccountUuidFinder />
|
||||||
|
</div>
|
12
src/app/admin/tools/tools.ts
Normal file
12
src/app/admin/tools/tools.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { actions } from 'astro:actions';
|
||||||
|
import { actionErrorPopup } from '@util/action.ts';
|
||||||
|
|
||||||
|
export async function uuidFromUsername(edition: 'java' | 'bedrock', username: string) {
|
||||||
|
const { data, error } = await actions.tools.uuidFromUsername({ edition: edition, username: username });
|
||||||
|
if (error) {
|
||||||
|
actionErrorPopup(error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.uuid;
|
||||||
|
}
|
@ -72,6 +72,12 @@ const adminTabs = [
|
|||||||
name: 'Einstellungen',
|
name: 'Einstellungen',
|
||||||
icon: 'heroicons:adjustments-horizontal',
|
icon: 'heroicons:adjustments-horizontal',
|
||||||
enabled: session?.permissions.settings
|
enabled: session?.permissions.settings
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: 'admin/tools',
|
||||||
|
name: 'Tools',
|
||||||
|
icon: 'heroicons:wrench-screwdriver',
|
||||||
|
enabled: session?.permissions.tools
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
---
|
---
|
||||||
|
14
src/pages/admin/tools/index.astro
Normal file
14
src/pages/admin/tools/index.astro
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
import { Session } from '@util/session';
|
||||||
|
import { Permissions } from '@util/permissions';
|
||||||
|
import { BASE_PATH } from 'astro:env/server';
|
||||||
|
import AdminLayout from '@layouts/admin/AdminLayout.astro';
|
||||||
|
import Tools from '@app/admin/tools/Tools.svelte';
|
||||||
|
|
||||||
|
const session = Session.sessionFromCookies(Astro.cookies, Permissions.Tools);
|
||||||
|
if (!session) return Astro.redirect(`${BASE_PATH}/admin`);
|
||||||
|
---
|
||||||
|
|
||||||
|
<AdminLayout title="Reports">
|
||||||
|
<Tools client:load />
|
||||||
|
</AdminLayout>
|
@ -12,3 +12,46 @@ export async function getJavaUuid(username: string) {
|
|||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `${id.substring(0, 8)}-${id.substring(8, 12)}-${id.substring(12, 16)}-${id.substring(16, 20)}-${id.substring(20)}`;
|
return `${id.substring(0, 8)}-${id.substring(8, 12)}-${id.substring(12, 16)}-${id.substring(16, 20)}-${id.substring(20)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/carlop3333/XUIDGrabber/blob/main/grabber.js
|
||||||
|
export async function getBedrockUuid(username: string): Promise<string> {
|
||||||
|
const initialPageResponse = await fetch('https://cxkes.me/xbox/xuid');
|
||||||
|
const initialPageContent = await initialPageResponse.text();
|
||||||
|
const token = /name="_token"\svalue="(?<token>\w+)"/.exec(initialPageContent)?.groups?.token;
|
||||||
|
|
||||||
|
const cookies = initialPageResponse.headers.get('set-cookie')?.split(' ');
|
||||||
|
if (token === undefined || cookies === undefined || cookies.length < 11) return null;
|
||||||
|
|
||||||
|
const requestBody = new URLSearchParams();
|
||||||
|
requestBody.set('_token', token);
|
||||||
|
requestBody.set('gamertag', username);
|
||||||
|
|
||||||
|
const resultPageResponse = await fetch('https://cxkes.me/xbox/xuid', {
|
||||||
|
method: 'post',
|
||||||
|
body: requestBody,
|
||||||
|
// prettier-ignore
|
||||||
|
headers: {
|
||||||
|
'Host': 'www.cxkes.me',
|
||||||
|
'Accept-Encoding': 'gzip, deflate,br',
|
||||||
|
'Content-Length': Buffer.byteLength(requestBody.toString()).toString(),
|
||||||
|
'Origin': 'https://www.cxkes.me',
|
||||||
|
'DNT': '1',
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Referer': 'https://www.cxkes.me/xbox/xuid',
|
||||||
|
'Cookie': `${cookies[0]} ${cookies[10].slice(0, cookies[10].length - 1)}`,
|
||||||
|
'Upgrade-Insecure-Requests': '1',
|
||||||
|
'Sec-Fectch-Dest': 'document',
|
||||||
|
'Sec-Fetch-Mode': 'navigate',
|
||||||
|
'Sec-Fetch-Site': 'same-origin',
|
||||||
|
'Sec-Fetch-User': '?1',
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
|
||||||
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||||
|
'Accept-Language': 'en-US,es;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const resultPageContent = await resultPageResponse.text();
|
||||||
|
let xuid: string | undefined;
|
||||||
|
if ((xuid = /id="xuidHex">(?<xuid>\w+)</.exec(resultPageContent)?.groups?.xuid) === undefined) throw new Error();
|
||||||
|
return `00000000-0000-0000-${xuid.substring(0, 4)}-${xuid.substring(4)}`;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user