#1
|
|||
|
|||
[Event Scripter] Scripts and requests
EDIT2 by pspzockerscene
As of 2024-11-26, we got a separate subforum for EventScripter related questions. EDIT by pspzockerscene: If you were sent to this thread but you do not know what the EventScripter is, please read THIS support article first. Convert AAC/M4A/OGG/OPUS files to MP3. Code:
// Convert aac/m4a/ogg/opus files to mp3. // Trigger required: "A Download Stopped". // Requires ffmpeg/ffprobe. Uses JD ffmpeg/ffprobe settings if available. // Overwrites destination file (mp3) if it already exists. if (link.isFinished()) { var fileName = link.name.replace(/(.+)(\..+$)/, "$1"); var fileType = link.name.replace(/(.+)(\..+$)/, "$2"); var sourceFile = link.getDownloadPath(); var audioFile = /\.(aac|m4a|ogg|opus)$/.test(sourceFile); if (audioFile) { var downloadFolder = package.getDownloadFolder(); var destFile = downloadFolder + "/" + fileName + ".mp3"; var ffmpeg = callAPI("config", "get", "org.jdownloader.controlling.ffmpeg.FFmpegSetup", null, "binarypath"); var ffprobe = callAPI("config", "get", "org.jdownloader.controlling.ffmpeg.FFmpegSetup", null, "binarypathprobe"); var data = JSON.parse(callSync(ffprobe, "-v", "quiet", "-print_format", "json", "-show_streams", "-show_format", sourceFile)); var streamsBitrate = data.streams[0].bit_rate ? data.streams[0].bit_rate : 0; var formatBitrate = data.format.bit_rate ? data.format.bit_rate : 0; var bitrate = Math.max(streamsBitrate, formatBitrate) / 1000; var deleteSourceFile = false; // Set this to true to delete source file after conversion. if (bitrate > 0) { callSync(ffmpeg, "-y", "-i", sourceFile, "-b:a", bitrate + "k", destFile); if (deleteSourceFile && getPath(destFile).exists()) deleteFile(sourceFile, false); } } } Alternate version (2021.11.04) Code:
/* Convert audio files to mp3 format Trigger : A download stopped */ if (link.finished) { var input = link.downloadPath; var output = input.replace(/(aac|m4a|ogg|opus)$/, "mp3"); if (input != output) { try { var ffmpeg = callAPI("config", "get", "org.jdownloader.controlling.ffmpeg.FFmpegSetup", null, "binarypath"); var bitrate = callSync(ffmpeg, "-i", input).match(/bitrate: (\d+) kb/)[1]; callAsync(function(error) { !error && getPath(input).delete(); }, ffmpeg, "-y", "-i", input, "-b:a", bitrate + "k", output); } catch (e) {}; } } Last edited by pspzockerscene; 26.11.2024 at 11:35. Reason: Added info about new EventScripter subforum |
#2
|
|||
|
|||
Save youtube links and basic information to a html page
Code:
// Save youtube links and basic information to a html page. // Trigger required: "A Download Stopped" // Get link property String.prototype.prop = function() { return link.getProperty(this); }; // Convert duration to hh:mm:ss.ms format Date.prototype.duration = function() { var ms = parseInt((this % 1000) / 100); var ss = parseInt((this / 1000) % 60); var mm = parseInt((this / (1000 * 60)) % 60); var hh = parseInt((this / (1000 * 60 * 60)) % 24); hh = (hh < 10) ? "0" + hh : hh; mm = (mm < 10) ? "0" + mm : mm; ss = (ss < 10) ? "0" + ss : ss; return hh + ":" + mm + ":" + ss + "." + ms; }; // Get media bitrate Number.prototype.toKbps = function() { return ((this / mediaDuration) * 8).toFixed(2); }; // youtube media check var youtubeMedia = link.getHost() == "youtube.com" && (/\.(m4a|aac|ogg|mp3|mp4|webm)$/).test(link.getName()); // Get Data if (youtubeMedia) { var output = []; var variant = JSON.parse("YT_VARIANT".prop()); var variantData = JSON.parse(variant.data); var youtube = "<a href=\"" + "http"+ "s://youtube.com/"; var saveFile = link.getDownloadPath() + ".info.html"; var fileSize = link.getBytesTotal(); var demux = (/DEMUX/).test(variant.id); var audioSize = !demux ? "DASH_AUDIO_SIZE".prop() : fileSize; var videoSize = "DASH_VIDEO_SIZE".prop(); var mediaDuration = "YT_DURATION".prop(); var data = { Video: youtube + "watch?v=" + "YT_ID".prop() + "\">" + "YT_TITLE".prop() + "</a>", Playlist: "YT_PLAYLIST_ID".prop() && "YT_PLAYLIST_TITLE".prop() ? youtube + "playlist?list=" + "YT_PLAYLIST_ID".prop() + "\">" + "YT_PLAYLIST_TITLE".prop() + "</a>" : null, User: youtube + "user/" + "YT_USER_NAME".prop() + "\">" + "YT_USER_NAME".prop() + "</a>", Channel: youtube + "channel/" + "YT_CHANNEL_ID".prop() + "\">" + "YT_CHANNEL".prop() + "</a>" + "\r\n", Published: new Date("YT_DATE".prop()).toDateString(), Size: (fileSize / 1048576).toFixed(2) + " MiB", Duration: new Date(mediaDuration).duration(), Width: variantData.width, Height: variantData.height, FPS: variantData.fps, Audio_Bitrate: audioSize.toKbps() + " kbps", Video_Bitrate: !demux && fileSize > audioSize ? videoSize.toKbps() + " kbps" : null, Overall_Bitrate: !demux && fileSize > audioSize ? fileSize.toKbps() + " kbps" : null, Variant_ID: variant.id, }; // Generate output[] for (i in data) { if (data[i] && data[i] != -1) { output.push(i.replace(/_/g, " ") + " : " + data[i]); } } // Format output[] and save to html file try { deleteFile(saveFile, false); // Delete info file if it already exists on the disk. writeFile(saveFile, "<pre>" + output.join("<br>") + "</pre>", false); } catch (err) { log(err + ""); } } Last edited by Jiaz; 15.07.2019 at 14:33. |
#3
|
|||
|
|||
Extraction Scheduler
Code:
// Schedule Extraction // Trigger Required: Interval // Disable Auto Extract in Archive Extractor // Forum Topic: https://board.jdownloader.org/showthread.php?t=70655 var t = [21, 30]; //Set Starting Time [hours,minutes] e.g. [21,30] is 9:30 PM if ((new Date().setHours(t[0], t[1], 0, 0) % new Date() < interval)) { var links = getAllDownloadLinks(); for (i = 0; i < links.length; i++) { var link = links[i]; var autoExtract = link.getArchive().getInfo().autoExtract; if (link.isFinished() && link.getArchive() && link.getExtractionStatus() == null && autoExtract != "FALSE") { callAPI("extraction", "startExtractionNow", [link.getUUID()], []); } } } Rewritten: Code:
github.com/mgpai/resources/blob/master/jdownloader/eventscripter/scripts/Taobaibai.js Last edited by mgpai; 22.02.2018 at 18:00. Reason: Added link to rewritten script |
#4
|
|||
|
|||
Update JD when idle.
Code:
// Restart and Update JD when idle // Trigger Required: "Interval" var newInterval = 600000; if (interval == newInterval) { if (isDownloadControllerIdle()) { if (isUpdateAvailable() && !isExtracting() && !isCrawling()) { restartAndUpdate(); } else { if (!isAutoUpdateCheckEnabled()) { runUpdateCheck(); } } } } else { interval = newInterval; } //Functions function isUpdateAvailable() { return callAPI("update", "isUpdateAvailable"); } function isExtracting() { return callAPI("extraction", "getQueue").length > 0; } function isCrawling() { return callAPI("linkcrawler", "isCrawling"); } function restartAndUpdate() { callAPI("update", "restartAndUpdate"); } function isAutoUpdateCheckEnabled() { return callAPI("config", "get", "org.jdownloader.updatev2.UpdateSettings", null, "autoupdatecheckenabled"); } function runUpdateCheck() { callAPI("update", "runUpdateCheck"); } Updated version of the script can be found in Post# 881 of this thread. Last edited by mgpai; 15.09.2019 at 10:52. Reason: Link to new version of the script. |
#5
|
|||
|
|||
md5sum
Generate md5 hash file in download folder
Code:
// Generate md5 hash file in download folder // Trigger: "A Download Stopped" // Latest updates: **External links are only visible to Support Staff**// Credits: mgpai if (link.isFinished()) { var filename = link.getName() var file = link.getDownloadPath() var folder = link.package.getDownloadFolder() var hashfile = folder + "/" + filename + "\.md5" if (getPath(hashfile).exists()) getPath(hashfile).delete() var MD5text = getChecksum("md5", file).toLowerCase() + "\t" + filename + "\n" writeFile(hashfile, MD5text, true) } Last edited by DoctorD90; 10.09.2016 at 13:29. |
#6
|
|||
|
|||
Split packages and create sub-folders
Adding custom command to context menu
Code:
// Split Packages and create sub-folder based on package length // Trigger : Linkgrabber Contextmenu Button Pressed // Forum Topic: https://board.jdownloader.org/showthread.php?t=70979 if (name == "Split Packages") { var package = lgSelection.getContextPackage(); var links = package.getDownloadLinks(); var newSize = 100; // Specify max number of links per package var UUIDS = []; var count = 1; if (links.length > newSize) { for (i = 0; i < links.length; i++) { var link = links[i]; UUIDS.push(link.getUUID()); } while (UUIDS.length) { var oldFolder = package.getDownloadFolder(); var packageName = package.getName(); var splitUUIDS = UUIDS.splice(0, newSize); var newFolder = oldFolder + "/" + pad(count); setNewFolder(); count++; } } } // Add sub folder function setNewFolder() { callAPI("linkgrabberv2", "movetoNewPackage", splitUUIDS, [], packageName, newFolder); } // Pad number with leading zeros function pad(num) { var a = num + ""; var b = (links.length / newSize).toFixed(0); while (a.length < b.length) a = "0" + a; return a; } |
#7
|
|||
|
|||
Simple history of downloaded links in text format.
Code:
// Simple history // Trigger Required : A Download Stopped if (link.isFinished()) { var a /*date*/ = new Date().toString().substring(4, 16); var b /*history folder*/ = JD_HOME + "/auto/history/"; var c /*history file Name */ = a + ".txt"; var d /*download url*/ = link.getContentURL(); var e /*download file name*/ = link.getName(); if (!getPath(b).exists()) getPath(b).mkdirs(); writeFile(b + c, [d, e].join(",") + "\r\n", true); } |
#8
|
|||
|
|||
Hide/Unhide Infobar Window
Adding custom command to Tray menu
Code:
// Hide/Unhide Infobar Window // Trigger: Traymenu Button Pressed // Can also use other 'button pressed' triggers if you want to specify/use 'keyboard shortcut' // Requirements: Install and enable infobar extension // Forum Topic: https://board.jdownloader.org/showthread.php?t=70617 if (name = "Infobar") { var infobar = "org.jdownloader.extensions.infobar.InfoBarConfig"; var storage = "cfg/org.jdownloader.extensions.infobar.InfoBarExtension"; var windowVisible = callAPI("config", "get", infobar, storage, "windowvisible"); if (windowVisible) { callAPI("config", "set", infobar, storage, "windowvisible", false); } else { callAPI("config", "set", infobar, storage, "windowvisible", true); } } Last edited by mgpai; 18.10.2016 at 11:56. Reason: Modified scrtipt to Hide/Unhide Infobar Window instead of Enable/Disable Infobar Extension |
#9
|
|||
|
|||
EDIT by psp: Thank you mgpai - I've removed my request- post above this one to keep the thread clean!
Code:
// Add single URL at user defined interval // Trigger required: "Interval" var setInterval = 60; // in minutes var link = "http://jdownloader.org/download/index"; // Specify URL to be added if (interval == setInterval * 60 * 1000) { callAPI("linkgrabberv2", "addLinks", { "deepDecrypt": true, "links": link }); } else { interval = setInterval * 60 * 1000; } Code:
// Add multiple URLs at user defined interval // Trigger required: "Interval" var setInterval = 60; // in minutes var feeds = JD_HOME + "/feeds/links.txt"; // Full path to text file containing the urls if (interval == setInterval * 60 * 1000) { callAPI("linkgrabberv2", "addLinks", { "deepDecrypt": true, "links": readFile(feeds) }); } else { interval = setInterval * 60 * 1000; } Last edited by pspzockerscene; 11.11.2016 at 03:36. |
#10
|
|||
|
|||
Quote:
Falls im Beitrag ergrenzt kann dieser Post gelöscht werden :-) @Administratoren: Wäre es nicht schlecht für kommende Scripts ein extra Foren-bereich einzurichten und für jeden Script ein Thema zu erstellen. Dann noch ein Verweis via URL im JD in der Script-Erweiterung auf den Foren bereich... Scheint künftig übersichtlicher und Interessanter oder? Klasse wärs, wenn genannte Scripte bei "Beispielen im JD auftauchen würden und ggf. die außenstehenden Infos im Script dokumentiert werden sodass sie funktionstüchtig laufen. Beispielsweise wie [...] Default folder: "< [...] Oder eben der Hinweis via URL. Last edited by Spongshga; 11.11.2016 at 01:09. |
#11
|
|||
|
|||
Quote:
Code:
var b /*history folder*/ = "c:/myFolder/history/"; Note: Path should always include "/" at the end. |
#12
|
|||
|
|||
Hello mgpai,
i have crawljob white description inside. Is it possible to write this in txt file and do in downloadfolder? I have no idea how to implement this. regards https://board.jdownloader.org/showthread.php?t=71524 |
#13
|
|||
|
|||
If the description is available in JD, for example in the 'comment' field, it is possible to save it in a text file in the download folder. If you want to write the script yourself I can help you with that, or you can post an example here I will take a look at it.
|
#14
|
|||
|
|||
Yes, i have in comment field, but this no work
Edit: please use private messages for examples Last edited by Jiaz; 14.11.2016 at 13:20. Reason: removed example links. |
#15
|
||||
|
||||
You cannot use multiple comment lines!
__________________
JD-Dev & Server-Admin |
#16
|
|||
|
|||
sorry, failed to set new value
I become the message:
sorry, failed to set new value what is here wrong? |
#17
|
||||
|
||||
Can you please provide screenshots/example what you want to set?
__________________
JD-Dev & Server-Admin |
#18
|
|||
|
|||
Replace 128kbit audio with 192kbit audio in 1080p youtube videos
Code:
// Replace 128kbit audio with 192kbit audio in 1080p youtube videos // Trigger Required: "Package Finished" // Forum Topic: https://board.jdownloader.org/showthread.php?t=69971 var links = package.getDownloadLinks(); if (links.length == 2) { var video = false; var audio = false; for (i = 0; i < links.length; i++) { var link = links[i]; if (link.getHost() == "youtube.com") { var file = link.getDownloadPath(); var variant = JSON.parse(link.getProperty("YT_VARIANT")).id; if ((/DEMUX.+192KBIT/i).test(variant)) { audio = file; var audioURL = link.getContainerURL(); } if ((/1080P.+128KBIT/i).test(variant)) { video = file; var videoURL = link.getContainerURL(); var out = (/128/).test(file) ? file.replace(/128/, "192") : file.replace(/(.+)(\..+)/, "$1 (192kbit Audio)$2"); } } } if (video && audio && videoURL == audioURL) { var ffmpeg = callAPI("config", "get", "org.jdownloader.controlling.ffmpeg.FFmpegSetup", null, "binarypath"); callSync(ffmpeg, "-i", video, "-i", audio, "-c", "copy", "-map", "0:v:0", "-map", "1:a:0", out); } } Last edited by mgpai; 17.11.2016 at 18:21. Reason: Added fallback method for 'output' file name |
#19
|
|||
|
|||
Export download URLs (Linkgrabber List)
Code:
// Export download URLs // Trigger : "Linkgrabber Contextmenu Button Pressed" if (name == "Export URLs") { var exportFolder = JD_HOME + "/auto/export/"; // <- Folder for exporting the text files var now = new Date().toString().substring(4, 24).replace(/:/g, "."); // <- Timestamp used in file name var exportFile = now + " - LG Selection.txt"; // <- Filename for exporting the URLs var links = lgSelection.getLinks(); var urls = []; for (i = 0; i < links.length; i++) { var link = links[i]; var fileName = link.getName(); var downloadURL = link.getContentURL(); urls.push(downloadURL + "," + fileName); } if (!getPath(exportFolder).exists()) getPath(exportFolder).mkdirs(); writeFile(exportFolder + exportFile, urls.join("\r\n"), true); } Export Download URLs (Download List)
Code:
// Export download URLs // Trigger : "DownloadList Contextmenu Button Pressed" if (name == "Export URLs") { var exportFolder = JD_HOME + "/auto/export/"; // <- Folder for exporting the text files var now = new Date().toString().substring(4, 24).replace(/:/g, "."); // <- Timestamp used in file name var exportFile = now + " - DL Selection.txt"; // <- Filename for exporting the URLs var links = dlSelection.getDownloadLinks(); var urls = []; for (i = 0; i < links.length; i++) { var link = links[i]; var fileName = link.getName(); var downloadURL = link.getContentURL(); urls.push(downloadURL + "," + fileName); } if (!getPath(exportFolder).exists()) getPath(exportFolder).mkdirs(); writeFile(exportFolder + exportFile, urls.join("\r\n"), true); } |
#20
|
|||
|
|||
Do you take requests?
I need a script that will stop downloads if my download speed drops below say 100kb\s for x amount of minutes and then restart after that time has passed. |
#21
|
||||
|
||||
@Tyler: either wait for response here or write him a pm
__________________
JD-Dev & Server-Admin |
#22
|
|||
|
|||
Don't know if this should be posted since it's so simple, but I wanted a way of getting notifications on my phone via pushover when a package had finished. It was quite easy and using the code
Code:
postPage("**External links are only visible to Support Staff**, "token=appToken&user=userKey&message=" + package.getName() + " finished."); Works like a charm but if this thread is meant for more elaborate scripts, feel free to move or delete this post. Since I didn't find any other hints or tutorials for using pushover for jdownloader-notifications, I thought I'd just leave it here. |
#23
|
||||
|
||||
@Wicküler: your script is perfectly fine and I'm sure it will be useful for others as well
__________________
JD-Dev & Server-Admin |
#24
|
|||
|
|||
Quote:
Code:
// Auto stop/restart downloads if the current average speed is below limit. // Trigger Required: "Interval" var minSpeed = 128; // (KiB/s) <- minimum average download Speed. var minDuration = 1; // (minutes) <- minimum download duration per link. var waitTime = 1; // (minutes) <- wait time before restart. if (running() && getAverageSpeed() < minSpeed * 1024) { stopDownloads(); sleep(waitTime * 60 * 1000); startDownloads(); } // Check if all downloads have been running for atleast the minimum duration. function running() { var links = getRunningDownloadLinks(); if (links.length > 0) { for (i = 0; i < links.length; i++) { var link = links[i]; if (link.getDownloadDuration() < minDuration * 60 * 1000) { return false; } } return true; } else { return false; } } |
#25
|
|||
|
|||
thank you mgpai, that works perfectly.
|
#26
|
|||
|
|||
is there any documentation i can look at for the event scripter?
|
#27
|
||||
|
||||
@Tyler
check the editor, it has doco on each method which is available. raztoki
__________________
raztoki @ jDownloader reporter/developer http://svn.jdownloader.org/users/170 Don't fight the system, use it to your advantage. :] |
#28
|
|||
|
|||
Hi mgpai, can you help me with a script to move completed downloads to a new folder? This way I can pick them up with filebot to get subtitles and place them in their proper folder.
BTW, I know packagizer can do this for compressed files but I want a solution for compressed and uncompressed files. Thanks in advance! Last edited by mrstimpy; 23.01.2017 at 07:28. Reason: Explained packagizer is not good enough |
#29
|
|||
|
|||
Code:
// Move finished non-archive files, to user defined folder // Trigger required: "A Download Stopped" var destFolder = "c:/myFolder/movedFiles"; // <- Set destination folder. if (link.isFinished() && !link.getArchive()) { getPath(link.getDownloadPath()).moveTo(destFolder); } |
#30
|
|||
|
|||
Quote:
is it possible to also reconnect and not just stop and restart? while testing, i realized that if i activate the speed limit in jdownloader and the speed is below the limit in your script, than it also activates the script. could you maybe add an "suspend the script code" if "speed limit" in jdownloader is active? and is there a way to make buttons for the toolbar, that actives/deactivates an specific script from the event scripter list? i tried the "activate/deactivate Event Scripter Button", but it doesn't seem to work. even if i deactivate the Event Scripter the activated scripts still run. and i have to deactivate them in the Event Scripter List in the settings tab. i think to get the "activate/deactivate Event Scripter Button" to work it needs a restart and thats not practical. thank you for your work/help :) Last edited by jdorg; 04.02.2017 at 12:51. |
#31
|
|||
|
|||
Code:
// Request reconnect if the current average speed is below limit. // Trigger Required: "Interval" var minSpeed = 128; // (KiB/s) <- minimum average download Speed. var minDuration = 1; // (minutes) <- minimum download duration per link. if (running() && !limitEnabled() && getAverageSpeed() < minSpeed * 1024) { requestReconnect(); } // Check if all downloads are resumeable and have been running for atleast the minimum duration. function running() { var links = getRunningDownloadLinks(); if (links.length > 0) { for (i = 0; i < links.length; i++) { var link = links[i]; if (!link.isResumeable() || link.getDownloadDuration() < minDuration * 60 * 1000) { return false; } } return true; } return false; } // Check if Speed limit or pause is currently enabled function limitEnabled() { if (callAPI("config", "get", "org.jdownloader.settings.GeneralSettings", null, "downloadspeedlimitenabled") || isDownloadControllerPaused()) { return true; } return false; } Quote:
You are welcome Last edited by mgpai; 06.02.2017 at 14:13. Reason: Added check for non-resumeable downloads before reconnect |
#32
|
|||
|
|||
thank you for the script, but i forgot to ask if its possible to check if one or more (active/downloading) files in the download list are NOT resumable.
when there are some of them, than suspend the script and/or give a warning alert/popup that there are NOT resumable links in the list. EDIT: i just had a case that my download limit on mega filehoster was reached and the download speed was 0/nothing but there was no reconnect. what could be the reason? Last edited by jdorg; 05.02.2017 at 13:40. |
#33
|
|||
|
|||
Quote:
In this case, I think the script will not be triggered at all. Instead, a reconnect (if enabled) would be performed by JD automatically. Jiaz should be able to provide more information in this regard. |
#34
|
|||
|
|||
thank you for the modification with non-resumables.
for the mega filehoster limit with no reconnect, the built-in auto reconnect of jdownloader was not activated. i thought your script would reconnect, but i will try it with the built-in auto reconnect and see if it reconnects. EDIT: built-in auto reconnect works after i have reached the download limit. but it waits until all active downloads end and get decrypted. (even with active setting to be allowed to interrupt resumable downloads for reconnect) the problem is, that most of the time the last active downloads fall down to extreme low speed and it takes hours to end the downloads. so i lose a lot of time in that jdownloader could have downloaded with max speed and it just needed one reconnect. Last edited by jdorg; 07.02.2017 at 16:22. |
#35
|
|||
|
|||
After activating 'Auto reconnect' in JD, have you disabled the script?
If there are no active downloads, and new downloads do not start due to download limit being reached, JD should perform a reconnect automatically. On the other hand, if the downloads are running and speed drops below the specified limit, the script should request a reconnect, irrespective of whether the download limit has reached or not. |
#36
|
|||
|
|||
sorry for late reply.
i tested with built-in auto reconnect only. now i tested with both activated: built-in + your script and it works. when i get limit reached "error" and download speed falls below the limit i set in your script, then it reconnects. thank you for your help and script. |
#37
|
|||
|
|||
Check for new update logs at user defined intervals and open them in notepad.
Code:
// View Update Log // Trigger Required: "Interval" // OS: Windows var int = 10; // (minutes) <- Interval between checks. if (interval == int * 60 * 1000) { var logFiles = getPath(JD_HOME + "/logs/updatehistory").getChildren(); for (i = 0; i < logFiles.length; i++) { var logFile = logFiles[i]; var age = new Date() - getPath(logFile).getModifiedDate(); if (!/self/.test(logFile) && age < int * 60 * 1000) callAsync(function() {}, "notepad.exe", logFile); } } else { interval = int * 60 * 1000; } |
#38
|
||||
|
||||
Any chance to get UUID or packagename with only "archive" (method/class) and trigger "Archive extraction finished" ?
__________________
Join 9kw.eu Captcha Service now and let your JD continue downloads while you sleep. |
#39
|
|||
|
|||
Quote:
Code:
var packageName = archive.getDownloadLinks()[0].getPackage().getName(); |
#40
|
||||
|
||||
this of course will only work in case there are download links
__________________
JD-Dev & Server-Admin |
Thread Tools | |
Display Modes | |
|
|