View Single Post
  #884  
Old 18.09.2019, 15:40
Demongornot Demongornot is offline
JD Beta
 
Join Date: Sep 2019
Location: Universe, Local group, Milky Way, Solar System, Earth, France
Posts: 50
Default

Quote:
Originally Posted by mgpai View Post
You can use myjd API methods:
Code:
my.jdownloader.org/developers/

Namespace: linkgrabberv2
Methods: getVariants, setVariant, addVariantCopy.
Sorry for the delay and thanks a lot for the answer, it took me a while but I made a script thanks to your informations.

Here is my script : Youtube Smart Subtitle Selector Script.
As it name suggest, it is made to have control over subtitles files.
All needed informations are in comment inside the script itself here :

Code:
/*
Youtube Smart Subtitle Selector Script by Demongornot for JDownloader 2.
This script allow you to set a list of subtitles and alternatives to download with variant filters.
If none of the alternatives have been found, it won't pick any, here is how it work :

First you'll need to enable JDownloader 2 Event Scripter,
if this isn't already done and then create this script, follow those steps :
Go to JDownloader 2 > Settings > Extension Modules > Event Scripter,
then on the top right check the Checkbox to enable Event Scripters if this is not already done.
Down left click the "Add" button if the list is empty though one should already be available,
but you'll only see a Checkbox, empty space, a drop down menu with "None" and a "edit" button.
Now (double) click on the left part of the empty script, if it is already named it might be an existing one.
Name it as you want "Youtube Smart Subtitle Selector Script by Demongornot" for example.
On the drop down menu right to the name part, click and select "A new link has been added", click "edit".
A windows appear, remove the text already in it and paste this entire code including "/*" at the beginning,
uncheck the "Synchronous execution of script" checkbox, this is really important !!!
Now down right click the "Save" button, the script windows is now closed,
check the Checkbox of this script to enable it, and it should now run automatically at every new links.

The work will be done when a new youtube video is added and a subtitles is added by the Youtue Plugin.


How to :
There is a variable called "deleteSubNotFound" by default at true, if set to "true",
if no subtitle in your list have been found, it will delete the one Jdownloader 2 & Youtube plugin took.
If set to "false", it will still be selected, this script have no control over which one is selected.
You also have a set of variables, the first one being called "ext" is the subtitle file extension,
if you need to you can change it, but this script being made for Youtube...
I don't think Youtube I don't think another format of subtitles will be taken in a close futur.
The other variables all starting by "lng" are in case the default Youtube subtitle code change.
I also doubt this will happen but this also lets anyone free to tweak if it was to happen anyway.
All those things shoudn't require any change, I also advise you to know what you are doing,
if you are going to change them, I won't take responsibility for miss use of my script.
Now the "SubLangList" array is where this is at, the process is actually really simple :

If you don't know how array work, simply consider it as a list.
It work that way : "var" "array_name" "[your list here]" ";".
Inside the "[]" brackets, you'll write your subtitle choices, inside brackets separated with a comma :
[[Subtitle choice 1],[Subtitle choice 2],[Subtitle choice 3]]; you can create as many as as you want.
By default JDownloader 2 will split them into lines, looking like this :
[[Subtitle choice 1],
[Subtitle choice 2],
[Subtitle choice 3]
];

Each "Subtitle choice" will be a possible subtitle file, so inside "Subtitle choice",
you'll write your chosen subtitle and its alternative if it is not found.
Making something like this :
[[GB English -> US English -> English],[French -> Canada French],[Brasil Portuguese -> Portugal Portuguese]]
As for how you write this, the language respect the IETF Language tag, you can find details here :
https://en.wikipedia.org/wiki/IETF_language_tag
As for which letters you'll need per country, here is a list :
https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements

You must use quote or double quote around each of them, and a coma, so the result will look like this :
[["en-GB", "en-US", "en"],['fr', 'fr-CA'],["pt-BR", 'pt-PT']];
The subtitle main language have to be lowercase and the country variant have to be uppercase.
There is no preference over quote or double quote, which is why I mixed them in this example, both work.
This example list will create up to 3 subtitle files if it find the 3 matching languages.
For the first file, it will look for UK English, if not found, US English, if not found, general English.
Of course if the last one isn't found, no file will be added.
The second list will look for French, if not found for Canadian French.
The last list will look for Brazilian Portuguese and if not found for Portuguese from Portugal.
Note that automatically generated and "special" version will be ignored in those cases.

You can also add special filters by using the caracter #, I'll use French ('fr') and as exemple.
A "#" before the language mean automatically generated language, I don't think it exist as country variant.
So '#fr' mean that only the automatically generated French will be looked for.
A "#" after the language mean special variant, with text in its name, like (English - Created by x).
So 'fr#' mean only a "special" variant of French will be looked for, like (English - With commentaries).
The language surrounded by two "#" mean "any variant of this language".
So '#fr#' will look for any subvariant (like 'fr-CA' or 'fr-CH'), but in priority the main one ('fr').
And finally, language with "-" and surrounded by "#" mean any subvariant but not the main language.
So '#fr-#' will look for any subvariant (like 'fr-CA' or 'fr-CH') but will ignore ('fr').
Note that for the "#any# and #any-#" code, automatically generated and special subtitles will be ignored.


In short :

//xx = Exact primary language, no variant, no autogeneration, no additional text in language name.
//xx-XX = xx language version of XX country variant, no autogeneration or additional text.
//xx# = only language with additional text in its name like (English - Created by x).
//#xx = only automatically generated subtitles of this language.
//#xx# = any version and country variant of xx language except autogenerated and additional text.
//#xx-# = any country variant of xx language except original, autogenerated and additional text.
*/

//___________________________________________________________________________________________________________

var deleteSubNotFound = true;
//'true' = delete JDownloader's chosen language if none is found, 'false' will keep it.

//In case the Youtube Subtitles format changed, here is some variables to fix it.
//Change it only if you know what you are doing, at your own risks.
var ext = '.srt'; //Write here the file extension name of the subtitle file.
var lngSep = '-'; //Write here the main and country language separator.
var lngIdf = 'lng='; //Write here the language value indicator.
var lngAGS = 'kind=asr'; //Write here the autogenerated subtitle value and type.
var lngNam = 'name='; //Write here the language display name value indicator.
var lngVID = '&'; //Write here the value indicator separator.
var lngTAS = '+'; //Write here the language display name string separator.

var subLangList = [
    ['en'], /*Will only take English*/
    ['xx'], /*Will be ignored*/
    ['en-CA'], /*Will only take Canadian English*/
    ['en-XX'], /*Will also be ignored*/
    ['#en'], /*Will only choose Auto Generated English*/
    ['en#'], /*Will only choose "special" subtitle in English*/
    ['#en#'], /*Will take any non special and non autogenerated English*/
    ['#en-#'], /*Will take any non special and non autogenerated English subvariant*/
    ['fr', 'fr-FR', 'fr-CA', '#fr'], /*Either French, France French, Canadian French or autogenerated*/
    ['fr' + lngSep + 'CA', '#fr'], /*You can also write it this way to always have the right separator*/
    ['fr-CH', '#fr-#'], /*Either Switzerland French or any non special, non autogenerated variant*/
    ['ja'], /*Japanese*/
    ['ko'], /*Korean*/
    ['ru'], /*Russian*/
    ['es-419', 'es'], /*Latin American Spanish or regular Spanish*/
    ['fr', '#fr#', 'en', '#en#'], /*You can also mix multiples languages*/
    ['xx', 'fr', 'en-US'] /*Incorrect first language still allow to choose other languages of the list*/
];
//Note that though there is multiples instance of the same language for demonstrations purposes,
//A specific subtitle can only be added once in the list, so you won't have two ['fr-FR'],
//But you still can have ['fr'] and ['fr-FR'] and/or ['en'] and ['en'] autogenerated and/or special.
//If you want to test, Ted Talk and Kurzgesagt Youtube channels often have many subtitles per video.

//___________________________________________________________________________________________________________


//Use the name of the added link to check if it is a subtitle file by checking it contain ".srt" at the end.
var download = link;
var linkName = download.getName();
if (download.getURL != null && download.name != null && linkName != null) {
    if (linkName.lastIndexOf(ext) == linkName.length - ext.length && linkName.indexOf(ext) >= 0) {

        //If it is a "srt" subtitle file, set some variables and get the list of the languages.
        var linkPackageUUID = null; //download.getPackage().getUUID();
        var parentUUID = null; //download.getUUID();
        //I didn't find any other way to get download UUID and download's package UUID than this loop...
        var myCrawledLink = getAllCrawledLinks();
        for (var i = myCrawledLink.length - 1; i >= 0; i--) {
            if (linkName == myCrawledLink[i].getName() && download.getURL() == myCrawledLink[i].getUrl()) {
                linkPackageUUID = myCrawledLink[i].getPackage().getUUID();
                parentUUID = myCrawledLink[i].getUUID();
                break;
            }
        }
        var subtitleList = callAPI("linkgrabberv2", "getVariants", parentUUID);
        var subtitleData = [];

        //Go through all the variants of the video and get informations about them.
        for (var counterA = 0; counterA < subtitleList.length; counterA++) {
            var subID = subtitleList[counterA].id;

            var mainLanguage = subID.substring(subID.indexOf(lngIdf) + lngIdf.length, subID.indexOf(lngVID, subID.indexOf(lngIdf) + lngIdf.length));

            var language = mainLanguage;

            var isMainLanguage = false;
            if (language.indexOf(lngSep) < 0) isMainLanguage = true;

            if (!isMainLanguage) mainLanguage = language.substring(0, language.indexOf(lngSep));

            var isLangAutoGenerated = false;
            if (subID.indexOf(lngAGS) > 0) isLangAutoGenerated = true;

            var isSpecial = false;
            if ((isMainLanguage && subID.indexOf(lngTAS, subID.indexOf(lngNam)) > 0) && !isLangAutoGenerated) isSpecial = true;

            //Put all gathered informations in an array so they are easily accessible without requiring long code.
            subtitleData.push([subID, mainLanguage, language, isMainLanguage, isLangAutoGenerated, isSpecial]);
        }
        var firstPass = true;

        //Go through all the user determined languages in its array and gather data.
        for (var counterB = 0; counterB < subLangList.length; counterB++) {
            for (var counterC = 0; counterC < subLangList[counterB].length; counterC++) {
                var userLanguage = subLangList[counterB][counterC];

                var isMainLanguage = true;
                if (userLanguage.indexOf(lngSep) > 0) isMainLanguage = false;

                var isAutoGenerated = false;
                if (userLanguage.lastIndexOf('#') == 0) isAutoGenerated = true;

                var isSpecial = false;
                if (userLanguage.indexOf('#') == userLanguage.length - 1) isSpecial = true;

                var isAnyVariant = false;
                if (userLanguage.indexOf('#') == 0 && userLanguage.lastIndexOf('#') ==
                    userLanguage.length - 1) isAnyVariant = true;

                var userMainLanguage = userLanguage.replace(/#/g, '');

                if (!isMainLanguage) {
                    userMainLanguage =
                        userLanguage.substring(0, userLanguage.indexOf(lngSep)).replace(/#/g, '');
                }
                var tmpLanguage = -1;

                /*Check through all the informations gathered from the subtitle list,
                and compare with previously gathered user subtitle(s) list/code.*/
                for (var counterD = 0; counterD < subtitleData.length; counterD++) {

                    //Check if this is the same main language (no point checking anything else if it's not).
                    if (subtitleData[counterD][1] == userMainLanguage) {
                        //Check if the two language (main or with country variant) match (meaning no filters).
                        if (subtitleData[counterD][2] == userLanguage && !subtitleData[counterD][4] && !subtitleData[counterD][5] && userLanguage.indexOf('#') < 0) {
                            //If match, check if it is needed to change the first or add a new subtitle.
                            if (firstPass) {
                                callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                firstPass = false;
                                break;
                            } else {
                                callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                break;
                            }

                            //If it don't match, it might be because there are filters, check without them.
                        } else if (subtitleData[counterD][2] == userLanguage.replace(/#/g, '') && !isAnyVariant && (isSpecial || isAutoGenerated) && (subtitleData[counterD][4] || subtitleData[counterD][5])) {
                            //Check if this is the autogenerated variant.
                            if (subtitleData[counterD][4] && isAutoGenerated) {
                                if (firstPass) {
                                    callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                    firstPass = false;
                                    break;
                                } else {
                                    callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                    break;
                                }
                                //Check if this is a special variant.
                            } else if (subtitleData[counterD][5] && isSpecial) {
                                if (firstPass) {
                                    callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                    firstPass = false;
                                    break;
                                } else {
                                    callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                    break;
                                }
                            }

                            //It might still be any variant user mode, check for matching language.
                        } else if (isAnyVariant && !isAutoGenerated && !isSpecial && !subtitleData[counterD][4] && !subtitleData[counterD][5]) {
                            if (isMainLanguage) {
                                //If it is ""main language"", in any language mode it already match since only equal main language reach here.
                                if (subtitleData[counterD][3]) {
                                    tmpLanguage = -1;
                                    if (firstPass) {
                                        callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                        firstPass = false;
                                        break;
                                    } else {
                                        callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                        break;
                                    }
                                    //If this isn't the main language, this is a variant, it will save its position for latter.
                                } else if (tmpLanguage == -1) {
                                    tmpLanguage = counterD;
                                }

                                //If it get to the end without finding the main language, it will add first found variant if one was found.
                                if (counterD >= subtitleData.length - 1 && tmpLanguage >= 0) {
                                    if (firstPass) {
                                        callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                        firstPass = false;
                                        break;
                                    } else {
                                        callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                        break;
                                    }
                                }

                                //Here it check for 'any except main'
                            } else {
                                if (!subtitleData[counterD][3]) {
                                    if (firstPass) {
                                        callAPI("linkgrabberv2", "setVariant", parentUUID, subtitleData[counterD][0]);
                                        firstPass = false;
                                        break;
                                    } else {
                                        callAPI("linkgrabberv2", "addVariantCopy", parentUUID, parentUUID, linkPackageUUID, subtitleData[counterD][0]);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

            }
            //If no desired subtitles have been found, delete the JDownloader's choosen one if user want to.
            if (counterB >= subLangList.length - 1 && firstPass && deleteSubNotFound) {
                getCrawledLinkByUUID(parentUUID).remove();
            }
        }
    }
}

The code should work properly (I didn't deeply test it) but if you see any problem or issues or encounter a bug, don't hesitate to report it !

Last edited by Demongornot; 23.09.2019 at 01:15. Reason: Fix little mistakes (again) and use the break; rather than counterC = x.length to exit loop and delete crawled link with UUID
Reply With Quote