Feat: Adding SFTP Client & Automatic Connections via button!
This commit is contained in:
@ -144,6 +144,7 @@
|
|||||||
<div class="flex space-x-4">
|
<div class="flex space-x-4">
|
||||||
<button id="refresh" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded">Refresh</button>
|
<button id="refresh" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded">Refresh</button>
|
||||||
<button id="backupBtn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded">Backup</button>
|
<button id="backupBtn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded">Backup</button>
|
||||||
|
<button id="sftpBtn" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded">SFTP</button>
|
||||||
<div id="authControls">
|
<div id="authControls">
|
||||||
<input id="apiKey" type="text" placeholder="Enter API Key" class="bg-gray-700 px-4 py-2 rounded text-white">
|
<input id="apiKey" type="text" placeholder="Enter API Key" class="bg-gray-700 px-4 py-2 rounded text-white">
|
||||||
</div>
|
</div>
|
||||||
@ -211,6 +212,12 @@
|
|||||||
<pre id="consoleOutput" class="bg-gray-900 p-4 rounded mt-4 h-48 overflow-y-auto"></pre>
|
<pre id="consoleOutput" class="bg-gray-900 p-4 rounded mt-4 h-48 overflow-y-auto"></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6" id="sftpBrowserSection" style="display: none;">
|
||||||
|
<h2 class="text-xl font-semibold mb-4">SFTP Browser</h2>
|
||||||
|
<!-- Iframe height set explicitly to 650px to ensure visibility and prevent shrinking -->
|
||||||
|
<iframe id="sftpIframe" class="w-full rounded" style="height: 650px; min-height: 650px;" sandbox="allow-same-origin allow-scripts"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||||
<h2 class="text-xl font-semibold mb-4">Mod Management</h2>
|
<h2 class="text-xl font-semibold mb-4">Mod Management</h2>
|
||||||
<form id="modSearchForm" onsubmit="event.preventDefault(); searchMods(1);">
|
<form id="modSearchForm" onsubmit="event.preventDefault(); searchMods(1);">
|
||||||
@ -277,7 +284,7 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -13,6 +13,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let modListCurrentPage = 1;
|
let modListCurrentPage = 1;
|
||||||
let modListSearchQuery = '';
|
let modListSearchQuery = '';
|
||||||
let allProperties = {};
|
let allProperties = {};
|
||||||
|
let sftpCredentials = null;
|
||||||
|
let isSftpOnline = false;
|
||||||
const filteredSettings = [
|
const filteredSettings = [
|
||||||
'bug-report-link',
|
'bug-report-link',
|
||||||
'query.port',
|
'query.port',
|
||||||
@ -92,7 +94,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
effectModal: document.getElementById('effectModal'),
|
effectModal: document.getElementById('effectModal'),
|
||||||
effectPlayerName: document.getElementById('effectPlayerName'),
|
effectPlayerName: document.getElementById('effectPlayerName'),
|
||||||
effectSelect: document.getElementById('effectSelect'),
|
effectSelect: document.getElementById('effectSelect'),
|
||||||
effectForm: document.getElementById('effectForm')
|
effectForm: document.getElementById('effectForm'),
|
||||||
|
sftpBtn: document.getElementById('sftpBtn'),
|
||||||
|
sftpBrowserSection: document.getElementById('sftpBrowserSection'),
|
||||||
|
sftpIframe: document.getElementById('sftpIframe')
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadouts = {
|
const loadouts = {
|
||||||
@ -358,7 +363,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
'my-link-cache',
|
'my-link-cache',
|
||||||
'my-geyser-cache',
|
'my-geyser-cache',
|
||||||
'my-sftp-cache',
|
'my-sftp-cache',
|
||||||
'backup'
|
'backup',
|
||||||
|
'sftp-status'
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
responseTimeout = setTimeout(() => {
|
responseTimeout = setTimeout(() => {
|
||||||
@ -438,6 +444,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
updateGeyserStatusUI(message);
|
updateGeyserStatusUI(message);
|
||||||
} else if (message.type === 'sftp-status') {
|
} else if (message.type === 'sftp-status') {
|
||||||
updateSftpStatusUI(message);
|
updateSftpStatusUI(message);
|
||||||
|
} else if (message.type === 'my-sftp-cache') {
|
||||||
|
updateSftpCacheUI(message);
|
||||||
} else if (message.type === 'update-mods') {
|
} else if (message.type === 'update-mods') {
|
||||||
updateModsUI(message);
|
updateModsUI(message);
|
||||||
} else if (message.type === 'backup') {
|
} else if (message.type === 'backup') {
|
||||||
@ -485,6 +493,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const editPropertiesBtn = elements.editPropertiesBtn;
|
const editPropertiesBtn = elements.editPropertiesBtn;
|
||||||
const updateModsBtn = elements.updateModsBtn;
|
const updateModsBtn = elements.updateModsBtn;
|
||||||
const backupBtn = elements.backupBtn;
|
const backupBtn = elements.backupBtn;
|
||||||
|
const sftpBtn = elements.sftpBtn;
|
||||||
const startBtn = document.getElementById('startBtn');
|
const startBtn = document.getElementById('startBtn');
|
||||||
const stopBtn = elements.stopBtn;
|
const stopBtn = elements.stopBtn;
|
||||||
const restartBtn = elements.restartBtn;
|
const restartBtn = elements.restartBtn;
|
||||||
@ -514,6 +523,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (backupBtn) {
|
if (backupBtn) {
|
||||||
backupBtn.classList.add('hidden');
|
backupBtn.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
if (sftpBtn) {
|
||||||
|
sftpBtn.classList.add('hidden');
|
||||||
|
}
|
||||||
if (stopBtn) {
|
if (stopBtn) {
|
||||||
stopBtn.disabled = true;
|
stopBtn.disabled = true;
|
||||||
stopBtn.classList.add('disabled-btn');
|
stopBtn.classList.add('disabled-btn');
|
||||||
@ -539,6 +551,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (backupBtn) {
|
if (backupBtn) {
|
||||||
backupBtn.classList.remove('hidden');
|
backupBtn.classList.remove('hidden');
|
||||||
}
|
}
|
||||||
|
if (sftpBtn) {
|
||||||
|
sftpBtn.classList.remove('hidden');
|
||||||
|
}
|
||||||
if (stopBtn) {
|
if (stopBtn) {
|
||||||
stopBtn.disabled = false;
|
stopBtn.disabled = false;
|
||||||
stopBtn.classList.remove('disabled-btn');
|
stopBtn.classList.remove('disabled-btn');
|
||||||
@ -598,6 +613,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
function updateSftpStatusUI(message) {
|
function updateSftpStatusUI(message) {
|
||||||
if (message.data?.isOnline !== undefined && elements.sftpStatus) {
|
if (message.data?.isOnline !== undefined && elements.sftpStatus) {
|
||||||
const statusIcon = message.data.isOnline ? '✅' : '❌';
|
const statusIcon = message.data.isOnline ? '✅' : '❌';
|
||||||
|
isSftpOnline = message.data.isOnline;
|
||||||
if (state.sftpStatus !== statusIcon) {
|
if (state.sftpStatus !== statusIcon) {
|
||||||
elements.sftpStatus.textContent = statusIcon;
|
elements.sftpStatus.textContent = statusIcon;
|
||||||
state.sftpStatus = statusIcon;
|
state.sftpStatus = statusIcon;
|
||||||
@ -605,6 +621,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSftpCacheUI(message) {
|
||||||
|
if (message.data?.hostname && message.data?.port && message.data?.user && message.data?.password) {
|
||||||
|
sftpCredentials = {
|
||||||
|
hostname: message.data.hostname,
|
||||||
|
port: message.data.port,
|
||||||
|
user: message.data.user,
|
||||||
|
password: message.data.password
|
||||||
|
};
|
||||||
|
const sftpLinkText = `${message.data.hostname}:${message.data.port} (Auth: User: ${message.data.user} | Pass: ${message.data.password})`;
|
||||||
|
if (state.sftpLink !== sftpLinkText && elements.sftpLink) {
|
||||||
|
elements.sftpLink.textContent = sftpLinkText;
|
||||||
|
state.sftpLink = sftpLinkText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateModsUI(message) {
|
function updateModsUI(message) {
|
||||||
if (message.error) {
|
if (message.error) {
|
||||||
elements.updateModsOutput.textContent = `Error: ${message.error}`;
|
elements.updateModsOutput.textContent = `Error: ${message.error}`;
|
||||||
@ -912,14 +944,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.type === 'my-sftp-cache' && message.data?.hostname && message.data?.port && message.data?.user && message.data?.password) {
|
|
||||||
const sftpLinkText = `${message.data.hostname}:${message.data.port} (Auth: User: ${message.data.user} | Pass: ${message.data.password})`;
|
|
||||||
if (state.sftpLink !== sftpLinkText && elements.sftpLink) {
|
|
||||||
elements.sftpLink.textContent = sftpLinkText;
|
|
||||||
state.sftpLink = sftpLinkText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.type === 'my-link' && message.data?.hostname && message.data?.port) {
|
if (message.type === 'my-link' && message.data?.hostname && message.data?.port) {
|
||||||
const myLinkText = `${message.data.hostname}:${message.data.port}`;
|
const myLinkText = `${message.data.hostname}:${message.data.port}`;
|
||||||
if (state.myLink !== myLinkText && elements.myLink) {
|
if (state.myLink !== myLinkText && elements.myLink) {
|
||||||
@ -1537,6 +1561,47 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function connectSftp() {
|
||||||
|
if (!isSftpOnline) {
|
||||||
|
showNotification('SFTP is offline. Please try again later.', 'error', 'sftp-offline');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sftpCredentials) {
|
||||||
|
showNotification('SFTP credentials not available.', 'error', 'sftp-credentials');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const key = `action-sftp-connect`;
|
||||||
|
const notification = showNotification('Connecting to SFTP...', 'loading', key);
|
||||||
|
const response = await fetch('https://sftp.my-mc.link/auto-connection', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
host: sftpCredentials.hostname.replace('sftp://', ''),
|
||||||
|
port: sftpCredentials.port,
|
||||||
|
username: sftpCredentials.user,
|
||||||
|
password: sftpCredentials.password,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.success && result.connectionUrl) {
|
||||||
|
elements.sftpIframe.src = result.connectionUrl;
|
||||||
|
elements.sftpBrowserSection.style.display = 'block';
|
||||||
|
updateNotification(notification, 'SFTP connected successfully', 'success', key);
|
||||||
|
} else {
|
||||||
|
updateNotification(notification, 'Failed to establish SFTP connection.', 'error', key);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('SFTP connection error:', error);
|
||||||
|
showNotification(`Failed to connect to SFTP: ${error.message}`, 'error', 'sftp-connect-error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elements.loginBtn.addEventListener('click', () => {
|
elements.loginBtn.addEventListener('click', () => {
|
||||||
apiKey = elements.loginApiKey.value.trim();
|
apiKey = elements.loginApiKey.value.trim();
|
||||||
if (apiKey) {
|
if (apiKey) {
|
||||||
@ -1584,6 +1649,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
elements.sftpBtn.addEventListener('click', connectSftp);
|
||||||
|
|
||||||
document.getElementById('refresh').addEventListener('click', async () => {
|
document.getElementById('refresh').addEventListener('click', async () => {
|
||||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
const key = `action-refresh`;
|
const key = `action-refresh`;
|
Reference in New Issue
Block a user