Skip to content

Commit

Permalink
v2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukiiy committed Aug 21, 2024
1 parent 92c017f commit 202f443
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 71 deletions.
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
# MCSkinGrabber
# [Skin Grabber](https://lukiiy.github.io/mcskingrabber/)

## Test this repo [here](https://lukiiy.github.io/mcskingrabber/)

A simple minecraft (java edition) skin grabber with JS (and cape) using Electroid's Mojang API.
**The API can be found [here](https://github.com/Electroid/mojang-api)!**

Also sorry for the bad code, I was in a hurry while coding it for my website.
A simple Minecraft: Java Edition skin (& cape) grabber using the [Crafthead API](https://crafthead.net/).
106 changes: 62 additions & 44 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,82 @@
const capeImg = document.getElementById('cape');
const skinImg = document.getElementById('skin');
var button = document.querySelector('#btn');
const button = document.getElementById('btn');
const usernameInput = document.getElementById('username');
const dataBox = document.getElementById('data');

async function getSkin(username) {
if (button.disabled) return;
btnState(false);
function isValidUsernameOrUUID(input) {
const usernameRegex = /^\w{3,16}$/;
const UUIDRegex = /^[0-9a-f]{32}$/i;
const dashedUUIDRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
return usernameRegex.test(input) || UUIDRegex.test(input) || dashedUUIDRegex.test(input);
}

if (username === "" || username == null) {
alert("Please, insert a username!");
btnState(true);
return;
function buttonState(state) {
button.textContent = state ? 'Get Skin' : 'Loading...';
button.disabled = !state;
}

async function fetchProfile(identifier) {
const response = await fetch(`https://crafthead.net/profile/${identifier}`);
if (!response.ok) throw new Error("Error while getting player data.");

const data = await response.json();

if (data.error === "User does not exist") {
alert("User does not exist. Please check the username or UUID and try again.");
throw new Error("User does not exist.");
}
if (!(/^\w{3,16}$/).test(username)) {
alert("Please, insert a valid username!");
btnState(true);

return data;
}

async function execute(identifier) {
if (button.disabled) return;
if (!isValidUsernameOrUUID(identifier)) {
alert("Please, insert a valid username or UUID!");
return;
}

buttonState(false);
skinImg.style.display = 'none';
capeImg.style.display = 'none';
skinImg.src = "";
capeImg.src = "";
skinImg.src = '';
capeImg.src = '';

try {
const response = await fetch(`https://api.ashcon.app/mojang/v2/user/${username}`);
if (!response.ok) throw new Error("Error while getting the player's data.");
const profile = await fetchProfile(identifier);
const textureProperty = profile.properties.find(p => p.name === 'textures');
if (!textureProperty) throw new Error("Error while getting skin data.");

const decodedTextures = JSON.parse(atob(textureProperty.value));

const skinUrl = decodedTextures.textures.SKIN?.url;
const capeUrl = decodedTextures.textures.CAPE?.url;

const data = await response.json();
if (!data.textures) throw new Error("Error while getting player data.");
if (skinUrl) {
skinImg.src = skinUrl;
skinImg.style.display = 'block';
} else {
throw new Error("Skin not found.");
}

skinImg.src = `data:image/png;base64,${data.textures.skin.data}`;
skinImg.style.display = 'block';
if (data.textures.cape.data != null) {
capeImg.src = `data:image/png;base64,${data.textures.cape.data}`;
if (capeUrl) {
capeImg.src = capeUrl;
capeImg.style.display = 'block';
}
} catch (error) {console.error(error.message);}
btnState(true);
}

function btnState(state) {
if (state === false) {
button.textContent = 'Loading...';
button.disabled = true;
return;
} catch (e) {
console.error(e.message);
} finally {
buttonState(true);
}
button.disabled = false;
button.textContent = 'Get Skin';
};

function dl(type) {
var a = document.createElement("a");
if (type === "Skin") a.href = skinImg.src;
if (type === "Cape") a.href = capeImg.src;
a.download = `${type}.png`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}

document.addEventListener("keydown", function(e) {
if (e.key === "Enter") getSkin(document.getElementById('username').value.trim());
});
setTimeout(() => {
document.addEventListener("keydown", function(e) {
if (e.key === "Enter") {
e.preventDefault();
execute(usernameInput.value.trim());
};
});
}, 300);
15 changes: 8 additions & 7 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script defer src="app.js"></script>
<meta name="description" content="Minecraft Skin Grabber">
<meta name="author" content="Lukiiy">
<title>Minecraft Skin Grabber</title>
<script defer src="app.js"></script>
</head>
<body>
<body class="flex">
<h1>Skin Grabber</h1>
<div>
<label for="username">Player:</label>
<input type="text" id="username" name="player">
<input type="text" id="username" name="player" placeholder="jeb_">
<button id="btn" onclick="execute(usernameInput.value.trim())">Get Skin</button>
</div>
<button onclick="getSkin(document.getElementById('username').value.trim());" id="btn">Get Skin</button>
<section id="data">
<img id="skin" onclick="dl('Skin')" alt="Skin"></img>
<img id="cape" onclick="dl('Cape')" alt="Cape"></img>
<section id="data" class="flex">
<img id="skin" alt="Skin"></img>
<img id="cape" alt="Cape"></img>
</section>
<p><a href="https://github.com/Lukiiy/mcskingrabber">Source Code</a></p>
</body>
</html>
21 changes: 8 additions & 13 deletions style.css
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
html {color-scheme: light dark;}
body {
font-family: system-ui;
font-family: monospace;
image-rendering: pixelated;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
#data {

.flex {
display: flex;
flex-direction: column;
gap: 5px;
}

#skin, #cape {
display: none;
animation: dl 2s linear infinite;
background-color: rgba(0, 0, 0, 0.393);
border: 2px solid #000;
background-color: rgba(0, 0, 0, 0.4);
object-fit: contain;
cursor: pointer;
}

#skin {width: 200px;}
#cape {height: 100px;}
@keyframes dl {
0%, 100% {border: 2px solid #fff;}
50% {border: 2px solid #ccc;}
}
#cape {height: 100px;}

0 comments on commit 202f443

Please sign in to comment.