Greasy Fork is available in English.

btsync 1.4.111 批量添加 Key

在添加Key左边增加一个按钮,功能为批量添加Key

// ==UserScript==
// @name         btsync 1.4.111 批量添加 Key
// @namespace    https://userscript.snomiao.com/
// @version      0.4.1
// @description  在添加Key左边增加一个按钮,功能为批量添加Key
// @author       snomiao@gmail.com
// @match        http://localhost:8888/gui/
// @match        http://127.0.0.1:8888/gui/
// @grant        none
// ==/UserScript==

function 睡(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
function 转WIN路径为WSL路径(path) {
    return path.replace(
        /^([A-Z]):(.*)/,
        (a, disk, path) =>
            `/mnt/${ 
            disk.toLowerCase() 
            }/${ 
            path
                .split("\\")
                .filter((e) => e)
                .join("/")}`
    );
}
var { app } = window;
async function 尝试到(ms, fn) {
    let ret;
    const t = +new Date();
    while (!(ret = await fn()))
        if (+new Date() > t + ms) throw "TimeOut";
        else await 睡(1);
    return ret;
}
async function 等元素(ms, sel, el = document) {
    return await 尝试到(ms, () => el.querySelector(sel));
}
async function 等元素消失(ms, sel, el = document) {
    return await 尝试到(ms, () => !el.querySelector(sel));
}
// function 绑定Click到元素(f, 元素) {
//     return (元素.addEventListener("click", f), 元素);
// }
function 新元素(innerHTML, attributes = {}) {
    return Object.assign(
        Object.assign(document.createElement("div"), { innerHTML }).children[0],
        attributes
    );
}
function 解析行(line) {
    var m = line.trim().match(/^(\S*?(\b[A|B][0-9A-Z]{32}\b))$/);
    m = m || line.trim().match(/^(\S*?)\s+#?(\b[A|B][0-9A-Z]{32}\b)$/);
    return (m && { path: 转WIN路径为WSL路径(m[1]), key: m[2] }) || null;
}
async function 异步循环(fn, array) {
    for (let index = 0; index < array.length; index++) {
        await fn(array[index], index, array);
    }
}
async function 批量添加行(text) {
    var lines = text.split(/\r?\n/).filter((e) => e);
    var objs = lines.map(解析行).filter((e) => e);
    console.debug("正在添加Keys:", objs);
    await 异步循环(模拟操作添加Key, objs);
}
// async function 打开添加KeyPath窗口() {
//     var enterKeyDialog = new app.view.EnterKey({
//         addFolderView: app.addFolderView,
//     }); // we need to pass a reference to addFolderView to EnterKey
//     var child = enterKeyDialog.insert();
//     child.open();
//     return await 尝试到(60e3, () => child.el);
// }
async function 模拟操作添加Key({ key, path }) {
    console.log("正在添加:", key, path);
    console.debug("正在", "await 等元素消失(60e3, `.modal-backdrop.fade.in`);");
    await 等元素消失(60e3, `.modal-backdrop.fade.in`);
    console.debug(
        "正在",
        'await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);'
    );
    await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);
    console.debug(
        "正在",
        'await 等元素消失(60e3, `#enter-key-dialog[aria-hidden="false"]`);'
    );
    await 等元素消失(60e3, `#enter-key-dialog[aria-hidden="false"]`);
    // var panel = await 打开添加KeyPath窗口();
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        "(await 等元素(60e3, `#enter-link-button`)).click();"
    );
    (await 等元素(60e3, `#enter-link-button`)).click();
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        "(await 等元素(60e3, `#enter-key-key`)).value = key;"
    );
    (await 等元素(60e3, `#enter-key-key`)).value = key;
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        "(await 等元素(60e3, `#enter-key-next`)).click();"
    );
    (await 等元素(60e3, `#enter-key-next`)).click();
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        '(await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-directory`)).value = path;'
    );
    (
        await 等元素(
            60e3,
            `#add-folder-dialog[aria-hidden="false"] #add-directory`
        )
    ).value = path;
    // await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        '(await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-ok.btn`)).click();'
    );
    (
        await 等元素(
            60e3,
            `#add-folder-dialog[aria-hidden="false"] #add-ok.btn`
        )
    ).click();
    await 睡(200);

    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        'const 错误提示元素 = (await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-error`));'
    );
    const 错误提示元素 = await 等元素(
        60e3,
        `#add-folder-dialog[aria-hidden="false"] #add-error`
    );
    const 错误 = await 尝试到(60e3, () => 错误提示元素.innerText);
    console.error("btsync-batch err:", 错误);
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        '(await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-cancel`)).click();'
    );
    (
        await 等元素(
            60e3,
            `#add-folder-dialog[aria-hidden="false"] #add-cancel`
        )
    ).click();
    await 睡(200);
    console.debug(
        +new Date() / 1000,
        "正在",
        'await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);'
    );
    await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);
    return true;

    // var keyElement = await Promise.race([
    //     等元素(60e3, `#confirm-dialog[aria-hidden="false"] #okButton`),
    //     等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-error`),
    // ]);
    // console.log(keyElement)
    // if (keyElement.id == "add-error") {
    // }
    // throw 'X';
    // await 睡(200);
    // console.debug(+new Date() / 1000, '正在', 'const 错误提示元素 = (await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-error`));');
    // const 错误提示元素 = (await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-error`));
    // const 错误 = await 尝试到(60e3, () => 错误提示元素.innerText);
    // console.error("btsync-batch err:", 错误);
    // await 睡(200);
    // console.debug(+new Date() / 1000, '正在', '(await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-cancel`)).click();');
    // (await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-cancel`)).click();
    // await 睡(200);
    // console.debug(+new Date() / 1000, '正在', 'await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);');
    // await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);
    // return true
    // var re = await Promise.race([
    //     (async () => {
    //         await 睡(100);
    //         console.debug(
    //             +new Date() / 1000,
    //             '正在',
    //             '(await 等元素(60e3, `#confirm-dialog[aria-hidden="false"] #okButton`)).click();'
    //         );
    //         (
    //             await 等元素(
    //                 60e3,
    //                 `#confirm-dialog[aria-hidden="false"] #okButton`
    //             )
    //         ).click();
    //         console.info('已覆盖');
    //         return true;
    //     })(),
    //     (async () => {
    //         await 睡(200);
    //         console.debug(
    //             +new Date() / 1000,
    //             '正在',
    //             'const 错误提示元素 = (await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-error`));'
    //         );
    //         const 错误提示元素 = await 等元素(
    //             60e3,
    //             `#add-folder-dialog[aria-hidden="false"] #add-error`
    //         );
    //         const 错误 = await 尝试到(60e3, () => 错误提示元素.innerText);
    //         console.error('btsync-batch err:', 错误);
    //         await 睡(200);
    //         console.debug(
    //             +new Date() / 1000,
    //             '正在',
    //             '(await 等元素(60e3, `#add-folder-dialog[aria-hidden="false"] #add-cancel`)).click();'
    //         );
    //         (
    //             await 等元素(
    //                 60e3,
    //                 `#add-folder-dialog[aria-hidden="false"] #add-cancel`
    //             )
    //         ).click();
    //         await 睡(200);
    //         console.debug(
    //             +new Date() / 1000,
    //             '正在',
    //             'await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);'
    //         );
    //         await 等元素消失(60e3, `#add-folder-dialog[aria-hidden="false"]`);
    //         return true;
    //     })(),
    //     // 睡(40000)
    // ]);
    // var ret = re || console.error('btsync-batch err: 超时 at', path);
    // console.log(ret);
    // return ret;
}
// test_模拟操作添加Key()
async function openBatch添加KeyPath() {
    var enterKeyDialog = new app.view.EnterKey({
        addFolderView: app.addFolderView,
    }); // we need to pass a reference to addFolderView to EnterKey
    var child = enterKeyDialog.insert();
    child.open();
    var el = await 尝试到(60e3, () => child.el);
    (
        await 等元素(60e3, ".modal-header h2", el)
    ).innerHTML = `Enter a group of /path #key`;
    (await 等元素(60e3, ".modal-body", el)).innerHTML = `
    <div class="form-group">
        <label for="keyInput">{{#}}</label>
        <div class="input-group">
            <textarea id="enter-list-path-key" type="text" class="form-control"></textarea>
            <br>
            <br>
            <div class="input-group-btn">
                <button id="enter-list-path-key-go" class="btn btn-primary" type="button" style="min-height: 40rem;">Go</button>
            </div>
        </div>
    </div>`;
    el.querySelector(
        ".modal-body label"
    ).innerHTML = `Input your /path #key split in lines`;
    var textarea = el.querySelector(".modal-body textarea");
    textarea.style.lineHeight = "1em";
    textarea.style.minHeight = "40rem";
    textarea.style.fontSize = "1.2rem";
    textarea.placeholder = `
#key is in path:
/path/to/folder#AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder#BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder@AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder@BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder#AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder#BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder@AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder@BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#key is not in path:
/path/to/folder AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder #AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/path/to/folder #BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder #AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\\path\\to\\folder #BXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        `.trim();
    // var textarea = el.querySelector(".modal-body textarea");
    (await 等元素(60e3, ".modal-body button", el)).addEventListener(
        "click",
        async () => {
            (await 等元素(60e3, ".modal-header button.close", el)).click();
            批量添加行(textarea.value);
        }
    );
}

async function addBatchAddButton() {
    console.log("启动");
    function 尝试移除元素(e) {
        return e && e.parentElement.removeChild(e);
    }
    尝试移除元素(document.querySelector("#batch-enter-link-button"));
    var 栏 = await 等元素(60e3, "#topButtons");
    var 单个添加按钮 = await 等元素(60e3, "#enter-link-button", 栏);
    var 批量添加按钮 = 新元素(
        `
                <a  id="batch-enter-link-button" 
                    role="button"
                    class="btn btn-naked"
                    title=""
                    data-original-title="Enter a group of /path #key"
                    style="background: repeating-linear-gradient(45deg, black, transparent 100px);">
                    <span class="mycon mycon-enterlink-naked"></span>
                </a>`,
        { onclick: openBatch添加KeyPath }
    );
    栏.insertBefore(批量添加按钮, 单个添加按钮);
}
addBatchAddButton();