Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions frontend/css/styles_global.css
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,4 @@ body {

.container-input button:active {
background-color: #6470ce;
}

.download-button:hover,
.stream-button:hover {
filter: brightness(95%);
}
40 changes: 34 additions & 6 deletions frontend/css/styles_mobile.css
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@
}

/* Result */

.container-result {
width: 100%;
height: 100vh;
Expand Down Expand Up @@ -219,24 +218,26 @@
border: none;
border-radius: 8px;
height: 100px;
width: 100%;
max-width: 449px;
min-width: 209px;
max-width: 500px;
transition: all 0.3s ease;
flex: auto;
display: flex;
flex-direction: column;
overflow: hidden;
flex-shrink: 0;
align-items: center;
justify-items: center;
}

.container-item-default {
height: 100px;
width: 100%;
flex-shrink: 0;
flex: auto;
display: flex;
flex-direction: row;
position: relative;
overflow: hidden;
align-items: center;
justify-content: center;
}

.container-image {
Expand Down Expand Up @@ -338,6 +339,33 @@
border: solid 1px #a2adff;
}

.download-all-button {
width: 100%;
font-size: 12px;
padding-bottom: 6px;
padding-top: 6px;
color: #7a88f7;
background-color: white;
border: solid 1px #a2adff;
border-radius: 4px;
}

.download-button:hover,
.stream-button:hover {
filter: brightness(95%);
}

.download-all-container.inactive {
display: none;
}

.download-all-warning {
font-size: 0.8em;
color: #bd2a2f;
margin-top: 8px;
display: block;
}

.stream-button {
width: 100%;
font-size: 10px;
Expand Down
215 changes: 196 additions & 19 deletions frontend/javascript/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Global
// Global variables
const box_result = document.getElementById('result');

const api = 'http://127.0.0.1:5000'; // Change This
// const api = 'https://teradl-api.dapuntaratya.com'; // Change This
Expand All @@ -24,6 +25,13 @@ submitButton.addEventListener('click', (event) => {
readInput(url);
});

// HTML template for the Download All container
const downloadAllContainerHTML = `
<div id="download-all-container" class="download-all-container inactive" style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<button id="download-all-button" type="button" class="download-all-button">Download All</button>
<span class="download-all-warning">Note: This downloads all files individually. Please allow multiple downloads in your browser if prompted.</span>
</div>`;

// Loading Spinner 1
function loading(element_id, active) {
const loadingBox = document.getElementById(element_id);
Expand Down Expand Up @@ -109,7 +117,7 @@ async function readInput(raw_url) {
stream_box.innerHTML = '';
stream_box.className = 'stream-video-section inactive'

document.getElementById('result').innerHTML = '';
clearResult(); // Clear previous results, including the old button container
loading('submit_button', true);
await fetchURL(url);
loading('submit_button', false);
Expand Down Expand Up @@ -137,30 +145,56 @@ async function fetchURL(url) {
'body' : JSON.stringify({'url':url, 'mode':mode})
};

const req = await fetch(get_file_url, data);
const response = await req.json();
try {
const req = await fetch(get_file_url, data);
const response = await req.json();

if (response.status == 'success') {
params = {uk:response.uk, shareid:response.shareid, timestamp:response.timestamp, sign:response.sign, js_token:response.js_token, cookie:response.cookie};
await sortFile(response.list);
}
if (response.status == 'success') {
// Clear previous results and add the button container structure first
clearResult();
box_result.innerHTML = downloadAllContainerHTML;
addDownloadAllEventListener(); // Re-attach listener after adding the button

// Now process and display the files
params = response;
await sortFile(response.list);

// Show the button container *if* files were actually added by sortFile
const fileItems = box_result.querySelectorAll('.container-item');
const downloadAllContainer = document.getElementById('download-all-container');
if (fileItems.length > 0 && downloadAllContainer) {
downloadAllContainer.classList.remove('inactive');
} else if (downloadAllContainer) {
downloadAllContainer.classList.add('inactive');
}
}

else {
loading('submit_button', false);
inputForm.value = '';
else {
errorFetch();
}
} catch (error) {
errorFetch();
}
}

// Error Fetch
function errorFetch() {
const box_result = document.getElementById('result');
clearResult();
box_result.innerHTML = `
<div class="container-failed">
<span>Fetch Failed</span>
<div class="error-message">
Fetch Failed
</div>`;
}

// Clear Result
function clearResult() {
box_result.innerHTML = '';

const streamSection = document.getElementById('stream-video');
streamSection.innerHTML = '';
streamSection.classList.add('inactive');
}

// Sort File Recursively
async function sortFile(list_file) {
list_file.forEach((item) => {
Expand All @@ -171,10 +205,12 @@ async function sortFile(list_file) {

// Show Item
async function printItem(item) {
const box_result = document.getElementById('result');
const new_element = document.createElement('div');
new_element.id = `file-${item.fs_id}`;
new_element.className = 'container-item';
if (item.link) {
new_element.dataset.dlink = item.link;
}
new_element.innerHTML = `
<div class="container-item-default">
<div id="image-${item.fs_id}" class="container-image"><img src="${item.image}" onclick="zoom(this)"></div>
Expand Down Expand Up @@ -247,7 +283,7 @@ async function initDownload(fs_id, dlink=null) {
new_element.setAttribute('value',value);
box_button.appendChild(new_element);

new_element.addEventListener('click', () => startDownload(new_element.value));
new_element.addEventListener('click', () => startDownload(new_element.value)); // Keep this for individual buttons
});
}

Expand All @@ -257,11 +293,18 @@ async function initDownload(fs_id, dlink=null) {
}

// Start Download
function startDownload(url) {
function startDownload(url, filename = '') { // Optional filename parameter
const anchor = document.createElement('a');
anchor.href = url;
anchor.target = '_blank';
// JANGAN gunakan anchor.download di sini!

// this case is for multiple download, so that the browser will not open many new tab (biar ga open new tab banyak)
// anchor.target = '_blank';

// can be used to set custom filename
anchor.download = filename || ''; // Use provided filename or empty string -> banh ini kyknya ga masalah? soalnya butuh buat download semua

// Append, click, remove is still necessary to trigger the download
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
Expand All @@ -287,7 +330,6 @@ async function initStream(fs_id, dlink=null) {

// Get URL Stream
async function getURLStream(fs_id, dlink=null) {

let param;

try {
Expand Down Expand Up @@ -318,6 +360,141 @@ async function getURLStream(fs_id, dlink=null) {
catch {return('');}
}

// Get and Start Download All)
async function getAndStartDownload(fs_id, dlink = null, linkPreference = 'url_2', filename = '') { // Added filename parameter
console.log(`Attempting to get link for fs_id: ${fs_id}`);
let param;
if (dlink && mode === 2) { // Mode 2 uses provided dlink
param = {'url': dlink, 'mode': mode};
} else if (mode === 1 || mode === 3) { // Mode 1 and 3 need params
if (!params || Object.keys(params).length === 0) {
console.error("Global params not set for mode 1 or 3.");
return;
}
param = {...params, 'fs_id': fs_id, 'mode': mode};
} else {
console.error(`Invalid mode (${mode}) or missing dlink for mode 2.`);
return;
}

const get_link_url = `${api}/generate_link`;
const headers = {'Content-Type': 'application/json'};
const data = {
'method': 'POST',
'mode': 'cors',
'headers': headers,
'body': JSON.stringify(param)
};

try {
const req = await fetch(get_link_url, data);
const response = await req.json();

if (response.status == 'success' && response.download_link) {
const links = response.download_link;
let urlToDownload = null;

if (linkPreference === 'url_2' && links.url_2) {
urlToDownload = links.url_2;
} else if (links.url_1) {
urlToDownload = links.url_1; // Fallback to url_1
} else if (links.url_2) {
urlToDownload = links.url_2; // Use url_2 if url_1 wasn't available but url_2 is
} else if (links.url_3) {
urlToDownload = links.url_3; // Fallback further if needed
}


if (urlToDownload) {
console.log(`Starting download for fs_id: ${fs_id} using URL: ${urlToDownload}`);
startDownload(urlToDownload, filename);
await sleep(0.5); // Delay 500ms
} else {
console.error(`No suitable download link found for fs_id: ${fs_id}`);
}
} else {
console.error(`Failed to get download link for fs_id: ${fs_id}. Status: ${response.status}, Message: ${response.message || 'No message'}`);
}
} catch (error) {
console.error(`Error fetching download link for fs_id: ${fs_id}:`, error);
}
}


// Initialization for Download All
async function initDownloadAll(linkPreference = 'url_2') {
const downloadAllButton = document.getElementById('download-all-button');
if (downloadAllButton) {
downloadAllButton.disabled = true;
downloadAllButton.innerText = 'Downloading...';
}

const fileItems = box_result.querySelectorAll('.container-item');
console.log(`Found ${fileItems.length} file items to download.`);

if (fileItems.length === 0) {
console.log("No files found to download.");
if (downloadAllButton) {
downloadAllButton.disabled = false;
downloadAllButton.innerText = 'Download All';
}
return;
}

// Check if params are needed and available for modes 1 or 3
if ((mode === 1 || mode === 3) && (!params || Object.keys(params).length === 0)) {
console.error("Cannot start 'Download All': Required parameters (uk, shareid, etc.) are missing.");
alert("Error: Could not retrieve necessary information to start downloads. Please try fetching the file list again.");
if (downloadAllButton) {
downloadAllButton.disabled = false;
downloadAllButton.innerText = 'Download All';
}
return;
}


for (const item of fileItems) {
const fs_id = item.id.replace('file-', '');
let dlink = null;

if (mode === 2) {
dlink = item.dataset.dlink;
if (!dlink) {
console.warn(`Could not find dlink for fs_id: ${fs_id} in mode 2. Skipping this file.`);
continue;
}
}

const titleSpan = item.querySelector('.title');
const filename = titleSpan ? titleSpan.innerText : '';

await getAndStartDownload(fs_id, dlink, linkPreference, filename);
}

console.log("Finished attempting to download all files.");
if (downloadAllButton) {
downloadAllButton.disabled = false;
downloadAllButton.innerText = 'Download All';
}
}

// Function to add the event listener
function addDownloadAllEventListener() {
const downloadAllButton = document.getElementById('download-all-button');
if (downloadAllButton) {
// Remove existing listener first to prevent duplicates if called multiple times
downloadAllButton.replaceWith(downloadAllButton.cloneNode(true));
// Get the new clone and add the listener
const newButton = document.getElementById('download-all-button');
if (newButton) {
newButton.addEventListener('click', () => {
initDownloadAll('url_2'); // Default url_2 yg pertama masih error banh
});
}
}
}


// Change status color
function changeStatus(mode) {
const status_box = document.getElementById('status-mode');
Expand Down
7 changes: 6 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@

<!-- Section Result -->
<div class="container-result">
<div id="result" class="box-result">
<div id="result">
<!-- Download All container stays here, starts inactive -->
<div id="download-all-container" class="download-all-container inactive">
<button id="download-all-button" type="button" class="download-button">Download All</button>
</div>
<!-- File items will be added AFTER the container -->
</div>
</div>

Expand Down