add ability for user to override skin and cape without sysop intervention
This commit is contained in:
241
index.js
241
index.js
@@ -6,6 +6,10 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const request = require('sync-request');
|
||||
const fetch = require('node-fetch');
|
||||
var session = require('express-session');
|
||||
const fileUpload = require('express-fileupload');
|
||||
var sizeOf = require('image-size');
|
||||
|
||||
function downloadFileSync(url) {
|
||||
return require('child_process')
|
||||
@@ -371,6 +375,23 @@ function get_cape(uname) {
|
||||
}
|
||||
}
|
||||
|
||||
// oauth_to_uuid
|
||||
// Purpose: Uses mc-oauth.net to translate an OAuth code into a UUID.
|
||||
// Returns: Nothing - this is a callback based function.
|
||||
|
||||
function oAuthToUUID(token, cb) {
|
||||
return fetch('https://mc-oauth.net/api/api?token', {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"token": token
|
||||
}
|
||||
}).then(response => {
|
||||
return response.json();
|
||||
}).then(json => {
|
||||
cb(json);
|
||||
});
|
||||
}
|
||||
|
||||
// rm_dir
|
||||
// Purpose: removes all files in a directory.
|
||||
// Returns: nothing.
|
||||
@@ -417,16 +438,232 @@ rm_dir(Cape_CacheLocation);
|
||||
console.log('[CACHE] Cape cache wipe completed.')
|
||||
|
||||
// Initialise express.
|
||||
const express = require('express')
|
||||
const express = require('express');
|
||||
const { O_TRUNC } = require('constants');
|
||||
const { resourceUsage } = require('process');
|
||||
const app = express()
|
||||
const port = 80
|
||||
const port = process.env.NODE_PORT || 6481
|
||||
|
||||
// Initialise session cookie middleware.
|
||||
app.set('trust proxy', 1) // trust first proxy
|
||||
app.use(session({
|
||||
secret: process.env.COOKIE_SECRET,
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
cookie: { secure: false, maxAge: 7200000 }
|
||||
}))
|
||||
|
||||
// Initialise static folders.
|
||||
app.use(express.static('static'))
|
||||
app.use('/MinecraftResources', express.static('resources'))
|
||||
|
||||
// Initialise middleware.
|
||||
app.use(express.urlencoded());
|
||||
|
||||
app.use(fileUpload());
|
||||
|
||||
// Initialise routers.
|
||||
|
||||
// POST /authenticate
|
||||
// Parameters:
|
||||
// code: OAuth code from MC-OAuth.
|
||||
// Returns:
|
||||
// 301 redirect to appropriate page.
|
||||
|
||||
app.post('/authenticate', (req,res) => {
|
||||
oAuthToUUID(req.body.code, (response) => {
|
||||
if (response.status !== "fail") {
|
||||
// add to session
|
||||
req.session.username = response.username
|
||||
req.session.uuid = response.uuid
|
||||
|
||||
// redirect
|
||||
res.redirect('/skin_landing')
|
||||
} else {
|
||||
// throw back to auth page.
|
||||
res.redirect('/auth.html')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// GET /end_session
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// redirect to home page with user session expired.
|
||||
|
||||
app.get('/end_session', (req,res) => {
|
||||
req.session.regenerate(function(err) {
|
||||
// will have a new session here
|
||||
res.redirect('/')
|
||||
})
|
||||
})
|
||||
|
||||
// GET /skin_landing
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// landing page
|
||||
|
||||
app.get('/skin_landing', (req,res) => {
|
||||
if (req.session.username !== undefined) {
|
||||
let temp = fs.readFileSync(path.join(__dirname, 'templates', 'landing.html')).toString();
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
res.send(temp)
|
||||
} else {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
|
||||
// GET /skin_change
|
||||
// No parameters
|
||||
// Returns:
|
||||
// skin changing page
|
||||
|
||||
app.get('/skin_change', (req,res) => {
|
||||
if (req.session.username !== undefined) {
|
||||
let temp = fs.readFileSync(path.join(__dirname, 'templates', 'skin_change.html')).toString();
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
res.send(temp)
|
||||
} else {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
|
||||
// POST /upload_skin
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// success or fail page
|
||||
|
||||
app.post('/upload_skin', (req,res) => {
|
||||
if (req.session.username == undefined) {
|
||||
// Don't even look at it.
|
||||
return res.redirect('/')
|
||||
}
|
||||
|
||||
if (!req.files || Object.keys(req.files).length === 0) {
|
||||
return res.redirect('/skin_change');
|
||||
}
|
||||
|
||||
if (req.files.upload.mimetype != "image/png") {
|
||||
return res.redirect('/skin_change');
|
||||
}
|
||||
|
||||
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
|
||||
let sampleFile = req.files.upload;
|
||||
|
||||
// Use the mv() method to place the file somewhere on your server
|
||||
sampleFile.mv(path.join(Skin_OverrideLocation, req.session.username + '.png'), function(err) {
|
||||
if (err) {
|
||||
return res.redirect('/failure');
|
||||
}
|
||||
|
||||
var dimensions = sizeOf(path.join(Skin_OverrideLocation, req.session.username + '.png'));
|
||||
|
||||
if (dimensions.width == "64" && dimensions.height == "32") {
|
||||
// classic steve skin
|
||||
res.redirect('/success');
|
||||
} else if (dimensions.width == "64" && dimensions.height == "64") {
|
||||
// non-classic skins (alex or something)
|
||||
res.redirect('/success')
|
||||
} else {
|
||||
// user must be trying to test us.
|
||||
fs.unlinkSync(path.join(Skin_OverrideLocation, req.session.username + '.png'))
|
||||
res.sendFile(path.join(__dirname, 'templates', 'size_too_big.html'))
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
// GET /cape_change
|
||||
// No parameters
|
||||
// Returns:
|
||||
// cape changing page
|
||||
|
||||
app.get('/cape_change', (req,res) => {
|
||||
if (req.session.username !== undefined) {
|
||||
let temp = fs.readFileSync(path.join(__dirname, 'templates', 'cape_change.html')).toString();
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
res.send(temp)
|
||||
} else {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
|
||||
// POST /upload_cape
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// success or fail page
|
||||
|
||||
app.post('/upload_cape', (req,res) => {
|
||||
if (req.session.username == undefined) {
|
||||
// Don't even look at it.
|
||||
return res.redirect('/')
|
||||
}
|
||||
|
||||
if (!req.files || Object.keys(req.files).length === 0) {
|
||||
return res.redirect('/cape_change');
|
||||
}
|
||||
|
||||
if (req.files.upload.mimetype != "image/png") {
|
||||
return res.redirect('/cape_change');
|
||||
}
|
||||
|
||||
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
|
||||
let sampleFile = req.files.upload;
|
||||
|
||||
// Use the mv() method to place the file somewhere on your server
|
||||
sampleFile.mv(path.join(Cape_OverrideLocation, req.session.username + '.png'), function(err) {
|
||||
if (err) {
|
||||
return res.redirect('/failure');
|
||||
}
|
||||
|
||||
var dimensions = sizeOf(path.join(Cape_OverrideLocation, req.session.username + '.png'));
|
||||
|
||||
if (dimensions.width == "64" && dimensions.height == "32") {
|
||||
// cape, GOOD
|
||||
res.redirect('/success');
|
||||
} else {
|
||||
// user must be trying to test us.
|
||||
fs.unlinkSync(path.join(Cape_OverrideLocation, req.session.username + '.png'))
|
||||
res.sendFile(path.join(__dirname, 'templates', 'size_too_big.html'))
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// GET /success
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// success page
|
||||
|
||||
app.get('/success', (req,res) => {
|
||||
if (req.session.username !== undefined) {
|
||||
let temp = fs.readFileSync(path.join(__dirname, 'templates', 'success.html')).toString();
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
res.send(temp)
|
||||
} else {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
|
||||
// GET /failure
|
||||
// No parameters.
|
||||
// Returns:
|
||||
// failure page
|
||||
|
||||
app.get('/failure', (req,res) => {
|
||||
if (req.session.username !== undefined) {
|
||||
let temp = fs.readFileSync(path.join(__dirname, 'templates', 'failure.html')).toString();
|
||||
temp = temp.replace('%%USERNAME%%', req.session.username)
|
||||
res.send(temp)
|
||||
} else {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
|
||||
// GET /MinecraftSkins/:username
|
||||
// Paramters:
|
||||
// username: username of character to get skin for
|
||||
|
||||
95
package-lock.json
generated
95
package-lock.json
generated
@@ -76,6 +76,14 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"busboy": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz",
|
||||
"integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==",
|
||||
"requires": {
|
||||
"dicer": "0.3.0"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
@@ -156,6 +164,14 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"dicer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz",
|
||||
"integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==",
|
||||
"requires": {
|
||||
"streamsearch": "0.1.2"
|
||||
}
|
||||
},
|
||||
"download-file-sync": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/download-file-sync/-/download-file-sync-1.0.4.tgz",
|
||||
@@ -218,6 +234,41 @@
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"express-fileupload": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.2.0.tgz",
|
||||
"integrity": "sha512-oe4WpKcSppXnl5peornawWUa6tKmIc1/kJxMNRGJR1A0v4zyLL6VsFR6wZ8P2a4Iq3aGx8xae3Vlr+MOMQhFPw==",
|
||||
"requires": {
|
||||
"busboy": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"express-session": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
|
||||
"integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
|
||||
"requires": {
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~2.0.0",
|
||||
"on-headers": "~1.0.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"safe-buffer": "5.2.0",
|
||||
"uid-safe": "~2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
@@ -296,6 +347,14 @@
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"image-size": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.9.3.tgz",
|
||||
"integrity": "sha512-5SakFa79uhUVSjKeQE30GVzzLJ0QNzB53+I+/VD1vIesD6GP6uatWIlgU0uisFNLt1u0d6kBydp7yfk+lLJhLQ==",
|
||||
"requires": {
|
||||
"queue": "6.0.1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
@@ -354,6 +413,11 @@
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
@@ -362,6 +426,11 @@
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
|
||||
},
|
||||
"parse-cache-control": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
|
||||
@@ -404,6 +473,19 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"queue": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.1.tgz",
|
||||
"integrity": "sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg==",
|
||||
"requires": {
|
||||
"inherits": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@@ -492,6 +574,11 @@
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"streamsearch": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
|
||||
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
@@ -562,6 +649,14 @@
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||
},
|
||||
"uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||
"requires": {
|
||||
"random-bytes": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
"dependencies": {
|
||||
"download-file-sync": "^1.0.4",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.0",
|
||||
"express-session": "^1.17.1",
|
||||
"image-size": "^0.9.3",
|
||||
"node-fetch": "^2.6.1",
|
||||
"sync-request": "^6.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
40
static/auth.html
Normal file
40
static/auth.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>To authenticate, join this server (works with MC 1.7.x to latest):</h3>
|
||||
<h2>srv.mc-oauth.net</h2>
|
||||
<h3>It will give you a six digit code, enter that in the input box below.</h3>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>Authenticate</h3>
|
||||
|
||||
<form action="/authenticate" method="POST">
|
||||
<input name="code" placeholder="Code (e.g. 007007)">
|
||||
<br />
|
||||
<br />
|
||||
<button type="submit">Submit Code</button>
|
||||
<h4>Codes generated by MC-OAuth expire within 5 minutes of their creation!</h4>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,2 +1,43 @@
|
||||
<h1>Theta Skin Server</h1>
|
||||
<p>Your website goes here!</p>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>This page lets you change your skin on our skins server.</h3>
|
||||
|
||||
<h3>Click the button below to start the authentication procedure.</h3>
|
||||
<button onmouseup="window.location.href = '/auth.html';">Authenticate</button>
|
||||
<h3>Currently, changing your skin is only available to people with premium Minecraft accounts.</h3>
|
||||
<h4>This is subject to change.</h4>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>What is a "Premium" Minecraft account?</h3>
|
||||
|
||||
<h4>A premium Minecraft account is an account that you have PAID for e.g. bought from Mojang/Microsoft.</h4>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>Other Links</h3>
|
||||
|
||||
<h4><a href="/skin-previewer.html">Skin Previewer</a></h4>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
2
static/skin-previewer.html
Normal file
2
static/skin-previewer.html
Normal file
@@ -0,0 +1,2 @@
|
||||
<h1>Theta Skin Server</h1>
|
||||
<p>Your website goes here!</p>
|
||||
76
static/style-dark.css
Normal file
76
static/style-dark.css
Normal file
@@ -0,0 +1,76 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-image: url("/tile.png");
|
||||
background-repeat: repeat;
|
||||
}
|
||||
|
||||
.body-dark {
|
||||
background-image: url("/tile_dark.png");
|
||||
background-repeat: repeat;
|
||||
}
|
||||
|
||||
.alert-frame {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
text-align:center;
|
||||
background-color: #800080;
|
||||
color: white;
|
||||
margin: 20px;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.invis {
|
||||
display: none;
|
||||
}
|
||||
.title-frame {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align:center;
|
||||
background-color: #3a3a3a;
|
||||
color: white;
|
||||
margin: 50px;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.main-frame {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
text-align:center;
|
||||
background-color: #4a4a4a;
|
||||
color: white;
|
||||
margin: 50px;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.server-frame {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
text-align:center;
|
||||
background-color: #606060;
|
||||
color: white;
|
||||
margin: 50px;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.hidden-frame {
|
||||
text-align:center;
|
||||
color: white;
|
||||
margin: 50px;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
BIN
static/tile_dark.png
Normal file
BIN
static/tile_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
40
templates/cape_change.html
Normal file
40
templates/cape_change.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>Cape Change</h3>
|
||||
<h2>Please upload the cape you wish to put on your character:</h2>
|
||||
<form action="/upload_cape" method="POST" enctype="multipart/form-data">
|
||||
<input type="file" name="upload" accept="image/png" />
|
||||
<br />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
<h3>Maximum file size is 16KB (16384 bytes). Skin must be a PNG file.</h3>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
35
templates/failure.html
Normal file
35
templates/failure.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h2>An error occured.</h2>
|
||||
<h3>The server encountered an error trying to handle your request.</h3>
|
||||
<button onmousedown="window.location.href='/skin_landing';">Try Again</button>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
49
templates/landing.html
Normal file
49
templates/landing.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>Hello, %%USERNAME%%.</h3>
|
||||
<h2>What do you wish to change?</h2>
|
||||
<button onmouseup="window.location.href='/skin_change';">Skin</button>
|
||||
<button onmouseup="window.location.href='/cape_change';">Cape</button>
|
||||
<br />
|
||||
<br />
|
||||
<button onmouseup="window.location.href='/end_session';">Logout</button>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>These are your current skin and cape textures:</h3>
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<th><h3>Skin</h3><a href="/MinecraftSkins/%%USERNAME%%.png"><img src="MinecraftSkins/%%USERNAME%%.png" /></a></th>
|
||||
<th><h3>Cape</h3><a href="/MinecraftCloaks/%%USERNAME%%.png"><img src="/MinecraftCloaks/%%USERNAME%%.png" /></a></th>
|
||||
</tr>
|
||||
</table>
|
||||
<h4>Keep in mind these are the skins we either have cached from Mojang for you or the skin you set using our service.</h4>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
37
templates/size_too_big.html
Normal file
37
templates/size_too_big.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h2>Image size too big!</h2>
|
||||
<h3>Skins must be either 64x32 or 64x64 pixels.</h3>
|
||||
<h3>Capes can only be 64x32 pixels.</h3>
|
||||
<button onmousedown="window.location.href='/skin_landing';">Try Again</button>
|
||||
<h4>The file you have uploaded was removed from the server.</h4>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
40
templates/skin_change.html
Normal file
40
templates/skin_change.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h3>Skin Change</h3>
|
||||
<h2>Please upload the skin you wish to put on your character:</h2>
|
||||
<form action="/upload_skin" method="POST" enctype="multipart/form-data">
|
||||
<input type="file" name="upload" accept="image/png" />
|
||||
<br />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
<h3>Maximum file size is 16KB (16384 bytes). Skin must be a PNG file.</h3>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
35
templates/success.html
Normal file
35
templates/success.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Action MC Skins</title>
|
||||
<link rel="stylesheet" type="text/css" href="/style-dark.css">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
button {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
<body class="body-dark">
|
||||
<div class="title-frame center">
|
||||
<h1>ActionMC Skins</h1>
|
||||
</div>
|
||||
|
||||
<div class="main-frame center">
|
||||
<h2>Skin Successfully Changed!</h2>
|
||||
<h3>You will now see your new skin in-game.</h3>
|
||||
<button onmousedown="window.location.href='/skin_landing';">Go Back</button>
|
||||
<h4></h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="hidden-frame center">
|
||||
<p>Powered by Theta, a custom skin server solution by Virtue.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user