GP SoftwareTwitter
Opus FAQsManualCommandsObjects

EBook Columns

This Script AddIn provides five new columns to display Ebook metadata in DOpus. Currently only epub, mobi and azw3 are supported and you must have the ebook-meta.exe program which is installed by default with Calibre.


Warning: This script runs slowly, it's got a lot to do for each file. You can prevent the column from continuing to process the remaining files by clicking the spinning circle in the location field and selecting "abort".
abort

The script expects that you have installed Calibre into the default location: C:\Program Files (x86)\Calibre2 . If not, there's a configuration option where you can change this.

The script uses the ebook-meta.exe file to extract the metadata for the ebook files and outputs it to a temporary file in "..\AppData\Local\Temp". This file is automatically deleted once the metadata has been read.

Note:

Series data is handled horribly by ebook formats. Epub3 allows for the series information to be embedded into the ebook file but other filetypes don't seem to. Because of this the ebook-meta.exe program will not read or write series information for those files. Calibre cheats and adds metadata to a separate file for each ebook and the ebook-meta.exe program ignores this data as far as I can tell (Happy to learn otherwise if anyone knows more).

Because of this, the series column will only display data for .epub files.

History:

  • 1.0 (6/4/20)
    • Initial Release.
  • 1.2 (14/4/20)
    • Added Tags column.
    • Merged Series and Series Index into one column.
    • Fixed "Title sort" data overwriting the "Title" column.
  • 1.4 (24/4/20)
    • Now using multicol columns correctly so the data for each file is only read/extracted once.
    • Added: Calibre path is now a configuration item.
  • 1.4.1 (1/5/20)
    • Fixed bug which occurred when the script was used in the Advanced Rename dialog.

Installation:

  1. Download: Ebook Columns 1.4.1.js.txt (8.0 KB)
  2. Drag the .js.txt file to Preferences / Toolbars / Scripts.

Script Config:

A couple of settings are available in the normal Script Addin configuration editor:

  • directories - Enter a string to be used for directories (can be blank).
  • non_ebook_files - Enter a string to be used for non ebook files (can be blank).
  • series_show_index - Include the series index in the series column.
  • calibre_path - The path to your Calibre installation.

Usage:

To use the column (once the script is installed) simply choose your config options and then turn on any or all of the following columns:

Script / Ebook Columns / Ebook Author
Script / Ebook Columns / Ebook Title
Script / Ebook Columns / Ebook Series
Script / Ebook Columns / Ebook Series #
Script / Ebook Columns / Ebook Tags

Script:

// EBook Columns
// (c) 2020 Steve Banham

var pathCalibre;
var arrLines = [];
var busyAbort = false;

scriptName = "Ebook Columns";
scriptVersion = "1.4.1";
scriptDate = "1/5/2020";
scriptCopyright = "(c) 2020 Steve Banham";
scriptMinVersion = "12.20";
scriptDesc = "Display author, title, series and tags of ebooks in DOpus columns.";

function OnInit(initData) {

    initData.name = scriptName;
    initData.version = scriptVersion;
    initData.copyright = scriptCopyright;
    initData.desc = scriptDesc;
    initData.default_enable = true;
    initData.min_version = scriptMinVersion;
	initData.url = "https://resource.dopus.com/t/ebook-columns/35114";

    initData.config_desc = DOpus.Create.Map();
    initData.config_groups = DOpus.Create.Map();
    var configName = "";

	configName = "directories";
	initData.Config[configName] = "<dir>";
	initData.config_desc(configName) = "String to show for any directory (Can be blank).";
	
	configName = "non_ebook_files";
	initData.Config[configName] = "---";
    initData.config_desc(configName) = "String to show for non ebook files (Can be blank).";
    
    configName = "series_show_index";
    initData.Config[configName] = true;
    initData.config_desc(configName) = "Include the series index in the series column.";

    configName = "calibre_path";
	initData.Config[configName] = "C:\\Program Files (x86)\\Calibre2";
	initData.config_desc(configName) = "The path to your Calibre installation.";

    var col = initData.AddColumn();

    col.name = "EbookAuthor";
    col.method = "onEbookCol";
    col.label = "Ebook Author";
	col.header = "Ebook Author";
    col.autogroup = true; 
    col.autorefresh = true;
    col.justify = "left";
    col.multicol = true;

    var col = initData.AddColumn();

    col.name = "EbookTitle";
    col.method = "onEbookCol";
    col.label = "Ebook Title";
	col.header = "Ebook Title";
    col.autogroup = true; 
    col.autorefresh = true;
    col.justify = "left";
    col.multicol = true;

    var col = initData.AddColumn();

    col.name = "EbookSeries";
    col.method = "onEbookCol";
    col.label = "Ebook Series";
	col.header = "Ebook Series";
    col.autogroup = true; 
    col.autorefresh = true;
    col.justify = "left";
    col.multicol = true;
    
    var col = initData.AddColumn();

    col.name = "EbookSeriesNum";
    col.method = "onEbookCol";
    col.label = "Ebook Series #";
	col.header = "Ebook Series #";
    col.autogroup = true; 
    col.autorefresh = true;
    col.justify = "center";
    col.multicol = true;

    var col = initData.AddColumn();

    col.name = "EbookTags";
    col.method = "onEbookCol";
    col.label = "Ebook Tags";
	col.header = "Ebook Tags";
    col.autogroup = true; 
    col.autorefresh = true;
    col.justify = "left";
    col.multicol = true;
}

function onEbookCol(scriptColData) {

    if (busyAbort) return;

    if (scriptColData.tab != 0) {
        var busy = DOpus.create.BusyIndicator();
        busy.abort = true;
        busy.Init(scriptColData.tab.lister, "Extracting metadata...", true);
    }

    pathCalibre = Script.Config["calibre_path"];

	if (pathCalibre.substr(-1) == "\\") {
		pathCalibre = pathCalibre.substr(0, pathCalibre.length - 1);
	}

    if (scriptColData.item.is_dir) {
        scriptColData.columns("EbookAuthor").value = Script.Config["directories"];
        scriptColData.columns("EbookTitle").value = Script.Config["directories"];
        scriptColData.columns("EbookSeries").value = Script.Config["directories"];
        scriptColData.columns("EbookSeriesNum").value = Script.Config["directories"];
        scriptColData.columns("EbookTags").value = Script.Config["directories"];
        return;
    }

    if (scriptColData.item.ext == ".epub" || scriptColData.item.ext == ".azw3" || scriptColData.item.ext == ".mobi"){

        ReadMetadata(scriptColData);

        for (i=0; i < arrLines.length; i ++) {
            
            if (arrLines[i].search("Author") > -1) {
                var strAuthor = arrLines[i].substring(22);
	            var hasSortField = strAuthor.search("\\[");
		        if (hasSortField > -1) {
			        strAuthor = strAuthor.substring(0,hasSortField);
                }
                strAuthor = strAuthor.replace(/^\s+|\s+$/gm,'');
            }

            if (arrLines[i].search("Title") > -1) {
                if (arrLines[i].search("Title sort") == -1) {
                    var strTitle = arrLines[i].substring(22);
                    strTitle = strTitle.replace(/^\s+|\s+$/gm,'');
                }
            }

            if (arrLines[i].search("Series") > -1) {
                
                var strSeries = "-";
                strSeries = arrLines[i].substring(22);

                var hasSeriesNum = strSeries.search("#");
                if (hasSeriesNum > -1) {
                    var strSeriesNum = "-";
                    strSeriesNum = strSeries.slice(hasSeriesNum);
                    strSeries = strSeries.substring(0,hasSeriesNum);
				    strSeriesNum = strSeriesNum.replace("#","");
                }   
                else {
                    strSeriesNum = " ";
                }

                if (Script.Config["series_show_index"] == true) {
                    strSeries = strSeries + " #" + strSeriesNum;
                }
            }

            if (arrLines[i].search("Tags") > -1) {
                var strTags = arrLines[i].substring(22);
			    strTags = strTags.replace(/^\s+|\s+$/gm,'');
            }
        }

        if (strAuthor == undefined) strAuthor = " ";
        scriptColData.columns("EbookAuthor").value = strAuthor;
        if (strTitle == undefined) strTitle = " ";
        scriptColData.columns("EbookTitle").value = strTitle;
        if (strSeries == undefined) strSeries = " ";
        scriptColData.columns("EbookSeries").value = strSeries;
        if (strSeriesNum == undefined) strSeriesNum = " ";
        scriptColData.columns("EbookSeriesNum").value = strSeriesNum;
        if (strTags == undefined) strTags = " ";
        scriptColData.columns("EbookTags").value = strTags;
    }
    else {
        scriptColData.columns("EbookAuthor").value = Script.Config["non_ebook_files"];
        scriptColData.columns("EbookTitle").value = Script.Config["non_ebook_files"];
        scriptColData.columns("EbookSeries").value = Script.Config["non_ebook_files"];
        scriptColData.columns("EbookSeriesNum").value = Script.Config["non_ebook_files"];
        scriptColData.columns("EbookTags").value = Script.Config["non_ebook_files"];
    }

    if (scriptColData.tab != 0) {
        busy.Destroy();
        if (busy.abort) {
            busyAbort = true;
            return;
        }
    }
}


function ReadMetadata(scriptColData){

    var cmd = DOpus.Create.command;

	cmd.SetType("msdos");
	cmd.SetModifier("runmode","hide");

	var fso = new ActiveXObject("Scripting.FilesystemObject");

	var tmpFolder = fso.GetSpecialFolder(2);
    var tmpName = fso.GetTempName();
    var tmpFile = tmpFolder + "\\" + tmpName;

	cmd.RunCommand("\"" + pathCalibre + "\\ebook-meta.exe\" " + "\"" + scriptColData.item.realpath + "\"" + " > " + tmpFile);
	
	var tmpDataFile = fso.OpenTextFile(tmpFile, 1, 0);
	
	if (!tmpDataFile.AtEndOfStream) {
		var content = tmpDataFile.ReadAll();
		arrLines = content.split(/\r\n|\n/);
	}

    tmpDataFile.Close();

    cmd.RunCommand("DELETE NORECYCLE QUIET \"" + tmpFile + "\"");

    return;
}

function OnScriptConfigChange() {
	
	Script.RefreshColumn("EbookAuthor");
	Script.RefreshColumn("EbookTitle");
    Script.RefreshColumn("EbookSeries");
    Script.RefreshColumn("EbookSeriesNum")
	Script.RefreshColumn("EbookTags");
}

function OnAboutScript(aboutData){
    dlg = DOpus.Dlg;
    dlg.window = aboutData.window;
    dlg.title = scriptName + " " + scriptVersion;
    dlg.message = scriptName + " v" + scriptVersion + "\t\t\t\t" + scriptDate + "\n\n" + scriptDesc + "\n\n" + scriptCopyright;
    dlg.buttons = "Close";
    dlg.icon = "info";
    dlg.show;
}
3 Likes