Скрипты на JavaScript для Алиэкспресс

Тема закреплена бессрочно

Пользуетесь ли этими скриптами?

  • Да

    Голосов: 290 64,6%
  • Нет

    Голосов: 159 35,4%

  • Всего проголосовало
    449
Этому скрипту скоро год будет, я не знаю. Пробуй, потом нам расскажешь.
Ok
---------Двойное сообщение соединено: ---------
Этому скрипту скоро год будет, я не знаю. Пробуй, потом нам расскажешь.
Страну не сменил, валюту на доллар сменил, разлогина нет.
---------Двойное сообщение соединено: ---------
Ok
---------Двойное сообщение соединено: ---------

Страну не сменил, валюту на доллар сменил, разлогина нет.
видимо de.aliexpress.com не понимает
---------Двойное сообщение соединено: ---------
Этому скрипту скоро год будет, я не знаю. Пробуй, потом нам расскажешь.
Может поменять что то нужно?
 
Последнее редактирование:
Доработал скрипт показывающий только залайканые сообщения для mipped.com.
1. На последней странице сообщения не скрываются.
2. Добавил кнопку "Показать скрытые", чтобы показать все сообщения.

JavaScript:
// ==UserScript==
// @name         Miped show only liked messages
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Показывает только залайканые сообщения
// @author       Andronio
// @match        https://mipped.com/f/threads/*
// @grant        none
// @run-at       document-end
// ==/UserScript==
(function repeat() {
    'use strict';

/*
 * Здесь начинать править настройки
*/

let showAfterLikes = 2;
let lastPageFilter = 0;

/*
 * Далее не трогать
*/

    let nextPage = document.querySelector(".pageNav-jump--next");
    let hasLikes = false;
    if (lastPageFilter || nextPage) {

        let messages = document.querySelectorAll(".message");
        let filtered = false
        messages.forEach(message => {
            let likes = message.querySelector('.reactionsBar-link');
            if (!likes) {
                message.style.display = 'none';
                filtered = true;
            } else {
                let likesCount = likes.innerText.split(/,|\sи\s(?!ещё)/).length;
                if (likesCount == 3) {
                    let addLikes = likes.innerText.match(/(?<=и\sещё\s)\d{1,4}/);
                    if (addLikes) likesCount += +addLikes;
                }
                if (likesCount >= showAfterLikes) hasLikes = true;
                else message.style.display = 'none';
                filtered = true;
            }
        });
        if (filtered) {
            let showBtn = document.createElement('div');
            showBtn.innerHTML = '<button id="liked-show-all" class="button button--cta">Показать скрытые</button>';
            showBtn.style.paddingBottom = '10px';
            document.querySelector('.block-outer').after(showBtn);
            document.getElementById('liked-show-all').addEventListener('click', () => {
                messages.forEach(message => {
                    message.style.display = null;
                });
            });
        }
    }
    if (!hasLikes) {
        if (nextPage) nextPage.click();
    }
})();
 
Накидал для себя удобный скриптик для оплаты картой из заказов. Нужно дойти до вот этого окна и ждать заполнения
1618472500491.png

JavaScript:
// ==UserScript==
// @name         Aliexpress order card filler
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  try to take over the world!
// @author       Andronio
// @match        https://shoppingcart.aliexpress.com/order/secondPayment.htm?cashierRequestToken=*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    setTimeout(cardFunc, 7000);

    async function cardFunc() {
        let myCard = '1234 5678 9012 3456, 2021/11, xxx, JOHN SMITH';
        let cardNumber = document.getElementById('cardNum');
        let cardHold   = document.getElementById('cardHolder');
        let dateExpire = document.getElementById('expires');
        let codeCVC    = document.getElementById('cvv');
        let mass;

        mass = myCard.split(', ');
        setInput(cardNumber, mass[0]);
        setInput(cardHold, mass[3]);
        let date = mass[1].slice(5,7) + '/' + mass[1].slice(2,4);
        setInput(dateExpire, date);
        setInput(codeCVC, mass[2]);
        document.querySelector('input.next-checkbox-input').click(); // Снять галку
        await waitForElement('.save-card-info-confirm button:nth-child(1)', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10, true);
        await sleep(200);
        document.querySelector('.save-card-info-confirm button:nth-child(1)').click();
        await waitForElement('input.next-checkbox-input:checked', 500, 10, true);
        await sleep(200);
        document.querySelector('button').click();
    }


    function setInput(input, value) {
        if (!input) {
            return;
        }

        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
        nativeInputValueSetter.call(input, value);
        input.dispatchEvent(new Event('change', {bubbles: true}));
        input.dispatchEvent(new Event('keyup', {bubbles: true}));
        input.dispatchEvent(new Event('keydown', {bubbles: true}));
        input.dispatchEvent(new Event('keypress', {bubbles: true}));
        input.dispatchEvent(new Event('input', {bubbles: true}));
        input.dispatchEvent(new Event('blur', {bubbles: true}));
    };

    function waitForElement(selectors, interval = 250, seconds = 0, waitForDisappear = false) {

        return new Promise((resolve) => {
            if (!Array.isArray(selectors)) {
                selectors = [selectors];
            }

            seconds = seconds * 1000;

            const startTime = Date.now();
            const check = () => {
                let found = selectors.some(s => {
                    const el = document.querySelector(s);
                    return !!(el && isVisible(el));
                })

                if (!waitForDisappear && found || waitForDisappear && !found) {
                    return resolve(true);
                }

                if (seconds > 0 && Date.now() - startTime > seconds) {
                    return resolve(false);
                }

                setTimeout(check, interval);
            };

            check();
        });
    };
    function isVisible(e) {
        return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
    };
    async function sleep(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    };

})();
 
Подправьте Скрипт рандомного адреса, алиекспрес ввел обновление, через раз выдает другие поля для ввода адреса, которые скрипт не может заполнить.
 
@Andronio
На данный момент в скриптах ничего не понимаю. Полный ноль.

С чего хотя бы начать. Гуглить про яваскрипт?
Подскажи, может есть у тебя в закладках какая-нибудь методичка как писать скрипты.
Или хотя бы как ЧИТАТЬ и написанные кем-то скрипты.

Спасибо.
 
@Andronio
На данный момент в скриптах ничего не понимаю. Полный ноль.

С чего хотя бы начать. Гуглить про яваскрипт?
Подскажи, может есть у тебя в закладках какая-нибудь методичка как писать скрипты.
Или хотя бы как ЧИТАТЬ и написанные кем-то скрипты.

Спасибо.
Я здесь учил
 
Доброго дня, а привинтить отдельно выделенный скрипт к BAS можно ? В каком месте.. ?
 
Привет. Я помню видел где-то здесь скрипт, который убирал лишние хвосты у товаров после html. имеется ли такой? найти не могу, хотя помню, что видел...
 
Привет. Я помню видел где-то здесь скрипт, который убирал лишние хвосты у товаров после html. имеется ли такой? найти не могу, хотя помню, что видел...

JavaScript:
// ==UserScript==
// @name         Aliexpress URL Cleaner
// @version      0.4
// @description  Removes unnecessary parameters from Aliexpress URLs
// @match        *://*.aliexpress.com/*
// @match        *://*.aliexpress.ru/*
// @namespace    https://greasyfork.org/users/168
// @run-at       document-start
// @noframes
// ==/UserScript==


function whenReady() {
    return new Promise((resolve) => {
        function completed() {
            document.removeEventListener('DOMContentLoaded', completed);
            window.removeEventListener('load', completed);
            resolve();
        }

        if (document.readyState === 'complete'
            || document.readyState === 'interactive') {
            resolve();
        } else {
            document.addEventListener('DOMContentLoaded', completed);
            window.addEventListener('load', completed);
        }
    });
}


whenReady().then(() => {

    let reg = /((?:https?:)?\/\/(?:\w+\.)?aliexpress\.(?:com|ru)\/(?:store\/product\/[^\/]+\/[0-9_]+|item\/(?:[^\/]+\/)?[0-9_]+)\.html)(\?[^#\r\n]+)?(#.+)?/i;

    function toCanonical(original) {
        let match = original.match(reg);
        if (match) {
            return match[1] + (match[3] || '');
        }
        return null;
    }


    // For current tab URL.
    let canonical = toCanonical(window.location.href);
    if (!canonical) {
        let link = document.querySelector('head > link[rel=canonical]');
        if (link) {
            canonical = toCanonical(link.href + window.location.hash);
        }
    }
    if (canonical) {
        window.history.replaceState(history.state, document.title, canonical);
    }


    // For static html links.
    document.querySelectorAll('a').forEach((e) => {
        let canonical = toCanonical(e.href);
        if (canonical) {
            e.href = canonical;
        }
    });


    // For lazy-loaded links.
    let observer = new MutationObserver(function (mutationsList) {
        for (let i = 0; i < mutationsList.length; i++) {
            const mutation = mutationsList[i];
            const addedNodes = mutation.addedNodes;
            for (let j = 0; j < addedNodes.length; j++) {
                cleanAndTraverse(addedNodes[j]);
            }
            if (mutation.type === 'attributes') {
                cleanNodeHref(mutation.target)
            }
        }
    });

    function cleanAndTraverse(root) {
        cleanNodeHref(root);
        let children = root.children;
        if (children) {
            for (let k = 0; k < children.length; k++) {
                cleanAndTraverse(children[k]);
            }
        }
    }

    function cleanNodeHref(elem) {
        if (elem.tagName === 'A') {
            const original = elem.href;
            const canonical = toCanonical(elem.href);
            if (canonical && original !== canonical) {
                elem.href = canonical;
            }
        }
    }

    observer.observe(document.documentElement, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['href']
    });
});
 
Накидал для себя удобный скриптик для оплаты картой из заказов. Нужно дойти до вот этого окна и ждать заполнения
Посмотреть вложение 289353

JavaScript:
// ==UserScript==
// @name         Aliexpress order card filler
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  try to take over the world!
// @author       Andronio
// @match        https://shoppingcart.aliexpress.com/order/secondPayment.htm?cashierRequestToken=*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    setTimeout(cardFunc, 7000);

    async function cardFunc() {
        let myCard = '1234 5678 9012 3456, 2021/11, xxx, JOHN SMITH';
        let cardNumber = document.getElementById('cardNum');
        let cardHold   = document.getElementById('cardHolder');
        let dateExpire = document.getElementById('expires');
        let codeCVC    = document.getElementById('cvv');
        let mass;

        mass = myCard.split(', ');
        setInput(cardNumber, mass[0]);
        setInput(cardHold, mass[3]);
        let date = mass[1].slice(5,7) + '/' + mass[1].slice(2,4);
        setInput(dateExpire, date);
        setInput(codeCVC, mass[2]);
        document.querySelector('input.next-checkbox-input').click(); // Снять галку
        await waitForElement('.save-card-info-confirm button:nth-child(1)', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10, true);
        await sleep(200);
        document.querySelector('.save-card-info-confirm button:nth-child(1)').click();
        await waitForElement('input.next-checkbox-input:checked', 500, 10, true);
        await sleep(200);
        document.querySelector('button').click();
    }


    function setInput(input, value) {
        if (!input) {
            return;
        }

        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
        nativeInputValueSetter.call(input, value);
        input.dispatchEvent(new Event('change', {bubbles: true}));
        input.dispatchEvent(new Event('keyup', {bubbles: true}));
        input.dispatchEvent(new Event('keydown', {bubbles: true}));
        input.dispatchEvent(new Event('keypress', {bubbles: true}));
        input.dispatchEvent(new Event('input', {bubbles: true}));
        input.dispatchEvent(new Event('blur', {bubbles: true}));
    };

    function waitForElement(selectors, interval = 250, seconds = 0, waitForDisappear = false) {

        return new Promise((resolve) => {
            if (!Array.isArray(selectors)) {
                selectors = [selectors];
            }

            seconds = seconds * 1000;

            const startTime = Date.now();
            const check = () => {
                let found = selectors.some(s => {
                    const el = document.querySelector(s);
                    return !!(el && isVisible(el));
                })

                if (!waitForDisappear && found || waitForDisappear && !found) {
                    return resolve(true);
                }

                if (seconds > 0 && Date.now() - startTime > seconds) {
                    return resolve(false);
                }

                setTimeout(check, interval);
            };

            check();
        });
    };
    function isVisible(e) {
        return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
    };
    async function sleep(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    };

})();


В этот скрипт можно добавить возможность указать несколько карт, что бы они заполнялись по очереди? Каждый раз что бы заполнялась следующая карта из списка, когда карты закончились, начинает с начала. Был бы на много полезней скрипт.
 
Последнее редактирование:
  • Like
Реакции: HackXr
В этот скрипт можно добавить возможность указать несколько карт, что бы они заполнялись по очереди? Каждый раз что бы заполнялась следующая карта из списка, когда карты закончились, начинает с начала. Был бы на много полезней скрипт.
Нет, нельзя, потому что в режиме инкогнито сохранять информацию о том какая карта уже была использована просто негде.
 
Скрипт для отключения появления новой формы адреса на странице оформления 😼
JavaScript:
// ==UserScript==
// @name        AliExpress - Disable New Address Form
// @description Отключает появление новой формы адреса на странице оформления
// @author      longnull
// @namespace   longnull
// @version     1.0
// @grant       none
// @match       https://shoppingcart.aliexpress.com/orders.htm
// @match       https://shoppingcart.aliexpress.com/order/confirm_order.htm
// ==/UserScript==

if (!window.runParams) {
  window.runParams = {};
}
window.runParams._ajax_sdk_country_list_ = [];
---------Двойное сообщение соединено: ---------
Скрипт для отключения появления новой формы адреса на странице оформления 😼
Сорян, не протестил в Tampermonkey, забываю, что Violentmonkey от него отличается в каких-то моментах 🙈

Вот так должно работать нормально
JavaScript:
// ==UserScript==
// @name        AliExpress - Disable New Address Form
// @description Отключает появление новой формы адреса на странице оформления
// @author      longnull
// @namespace   longnull
// @version     1.0
// @match       https://shoppingcart.aliexpress.com/orders.htm*
// @match       https://shoppingcart.aliexpress.com/order/confirm_order.htm*
// ==/UserScript==

const timer = setInterval(() => {
  if (unsafeWindow.runParams && unsafeWindow.runParams._ajax_sdk_country_list_) {
    unsafeWindow.runParams._ajax_sdk_country_list_ = [];
    clearInterval(timer);
  }
}, 500);
 
Последнее редактирование:
Добрый день. Сегодня при вводе адреса здесь
https://ilogisticsaddress.aliexpress.com/addressList.htm
через скрипт "Aliexpress address filler 2.1" появилось вот такое и в общем, оно не кликается теперь.
1619105285107.png

Upd: Заработало! )
 
Последнее редактирование:
---------Двойное сообщение соединено: ---------
Код:
// ==UserScript==
// @name         Aliexpress Order info getter track
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Получение информации из заказа и трека
// @author       Andronio
// @match        https://trade.aliexpress.ru/orderList.htm*
// @match        https://trade.aliexpress.ru/order_list.htm*
// @match        https://trade.aliexpress.com/orderList.htm*
// @match        https://trade.aliexpress.com/order_list.htm*
// @noframes
// ==/UserScript==
/*
prodName  - Название товара
picURL    - URL-ссылка на картинку-превью товара
prodPrice - Цена товара
today     - Сегодняшняя дата
orderNum  - Номер заказа
\t        - Табуляция, переход к следующей ячейке
picPrefix - 1 - добавлять префик picURL= для адреса картинки, 0 - не добавлять
track     - Трек-номер заказа
date      - Дата автозакрытия заказа
Строка должна начинаться и заканчиваться символом обратной кавычки
*/
var orderStr  = `prodName + '\t' + picURL + '\t' + prodPrice + '\t' + today +  '\t' + orderNum`;
var trackStr  = `track + '\t' + date`;
let picPrefix = 1;
/*
Далее не трогать
*/
let ordersMass = [];
let trackMass = [];
(function () {
    'use strict';
// Рисуем окно с кнопками
    var div = document.createElement('div');
    div.className = 'mybox';
    let product = document.querySelectorAll('.order-item-wraper');
    let hasTrackable = false;
    if (product.length == 0) {
        div.innerHTML = '<p class="noorders">Нет заказов</p>';
    } else {
        let str = document.body.innerHTML.split("var appealInfoParams = encodeURIComponent('")[1].split("');")[0];
        if (str.match(/\[(\{("\w+":["\w]+,)+"\w+":["\w]+\},){0,30}\{("\w+":["\w]+,)+"\w+":["\w]+\}\]/g)) {
            ordersMass = eval(str);
            ordersMass.forEach(order => {
                if (order.orderStatus == "WAIT_BUYER_ACCEPT_GOODS") {
                    hasTrackable = true;
                }
            });
        }
        div.innerHTML = `<button class="infoGetter" myattr="-1">Все заказы</button>`;
        if (hasTrackable) div.innerHTML +=`<button class="trackGetter" myattr="99" disabled>Треки</button>`;
        for (let i = 0; i < product.length; i++) {
            let productName = product[i].querySelectorAll(".product-title > a.baobei-name")[0].getAttribute("title").substr(0,20);
            div.innerHTML += `<br><button class="infoGetter" myattr="${i}">${i+1} - <span style="color:green">${productName}</span></button>`;
            if (hasTrackable && ordersMass[i].orderStatus == 'WAIT_BUYER_ACCEPT_GOODS')
                div.innerHTML += `<button class="trackGetter" myattr="${i+100}" disabled>Трек</button>`;
        }
    }
    document.body.append(div);
    var styles = `
    .mybox {
    position: fixed;
    top: 0;
    right: 0;
    background: white;
    box-shadow: 1px -1px 4px 1px;
    max-width: 40%;
    max-height: 400px;
    padding: 10px 10px;
    overflow-y: auto;
    overflow-x: hidden;
    z-index:9999;
    }
    .noorders {
    color: red;
    text-align: center;
    font-size: 1.5em;
    padding: 5px;
    margin: 0;
    }
    .infoGetter {
    display: inline;
    margin-right:auto;
    margin-top: 2px;
    cursor:pointer;
    padding: 5px;
    width: 180px;
    text-align: left;
    }
    .trackGetter {
    display: inline;
    margin-right:auto;
    margin-top: 2px;
    cursor:pointer;
    padding: 5px;
    width: 46px;
    text-align: left;
    }
    .greenbutton{
    background-color: LightGreen;
    }`
    var styleSheet = document.createElement("style")
    styleSheet.type = "text/css"
    styleSheet.innerText = styles
    document.head.append(styleSheet)
    div.addEventListener('click', buttonClick);
    if (hasTrackable) getTracks();
})();
function buttonClick(event) {
    let elem = event.target;
    if (elem.tagName != "BUTTON") {
        elem = elem.parentNode;
        if (elem.tagName != "BUTTON") return;
    }
    let orderString;
    let num = +elem.getAttribute('myattr');
    if (num > 98) return trackBuff(num, elem);
    else {
        let product = document.querySelectorAll('.order-item-wraper');
        let productPrice = document.querySelectorAll(".amount-num");
        let orderNumber = document.querySelectorAll(".order-info > .first-row > span.info-body");
        let today = formatDate();
        let prodName, prodPrice, orderNum;
        if (num > -1) {
            // один заказ
            let productName = product[num].querySelectorAll(".product-title > a.baobei-name");
            let picURL = product[num].querySelectorAll(".pic.s50 > img")[0].src;
            if (picPrefix) picURL = "picURL=" + picURL;
            prodName = `=ГИПЕРССЫЛКА("https:\/\/www.aliexpress.ru\/item\/${productName[0].getAttribute("productid")}.html";` +
                `"${productName[0].getAttribute("title").substr(0,80)}")`;
            prodPrice = productPrice[num].innerText.match(/\d+\.\d+/);
            if (prodPrice)
                prodPrice = prodPrice[0].replace(/\./,",");
            else
                prodPrice = productPrice[num].innerText.trim();
            orderNum = orderNumber[num].innerText;
            orderString = eval(orderStr);
        } else {
            // много заказов
            orderString = "";
            for (let num = 0; num < orderNumber.length; num++) {
                let productName = product[num].querySelectorAll(".product-title > a.baobei-name");
                let picURL = product[num].querySelectorAll(".pic.s50 > img")[0].src;
                if (picPrefix) picURL = "picURL=" + picURL;
                prodName = `=ГИПЕРССЫЛКА("https:\/\/www.aliexpress.ru\/item\/${productName[0].getAttribute("productid")}.html";` +
                    `"${productName[0].getAttribute("title").substr(0,80)}")`;
                prodPrice = productPrice[num].innerText.match(/\d+\.\d+/);
                if (prodPrice)
                    prodPrice = prodPrice[0].replace(/\./,",");
                else
                    prodPrice = productPrice[num].innerText.trim();
                orderNum = orderNumber[num].innerText;
                orderString += eval(orderStr);
                orderString += "\r\n";
            }
        }
    }
    navigator.clipboard.writeText(orderString).then(function () {
        console.log('Async: Copying to clipboard was successful!');
        window.mybtn = elem;
        window.mybtn.classList.add("greenbutton");
        setTimeout(() => window.mybtn.classList.remove("greenbutton"), 500);
    }, function (err) {
        console.error('Async: Could not copy text: ', err);
    });
}
function trackBuff(num, elem){
    num -= 100;
    let date, track, orderString = "";
    let trackMassCopy = trackMass.slice();
    if (num > -1) {
        let el = trackMassCopy.find(index => index.id == ordersMass[num].id);
        date = el.date;
        track = el.track;
        orderString = eval(trackStr);
    } else {
        for (let i = 0; i < ordersMass.length; i++) {
            if (ordersMass[i].orderStatus == "WAIT_BUYER_ACCEPT_GOODS") {
                let el = trackMassCopy.shift();
                date = el.date;
                track = el.track;
                orderString += eval(trackStr);
            }
            orderString += "\r\n";
        }
    }
    navigator.clipboard.writeText(orderString).then(function () {
        console.log('Async: Copying to clipboard was successful!');
        window.mybtn = elem;
        window.mybtn.classList.add("greenbutton");
        setTimeout(() => window.mybtn.classList.remove("greenbutton"), 500);
    }, function (err) {
        console.error('Async: Could not copy text: ', err);
    });
}
function getTracks() {
    ordersMass.forEach(order => {
        if (order.orderStatus == "WAIT_BUYER_ACCEPT_GOODS") {
            trackMass.push({id: order.id, track: "", date: ""});
        }
    });
    let requests = trackMass.map(order => fetch(`${location.protocol}//${location.hostname}/order_detail.htm?orderId=${order.id}`));
    Promise.all(requests)
        .then(responses => Promise.all(responses.map(r => r.text())))
        .then(texts => {
            for (let i = 0; i < texts.length; i++) {
                let obj = document.createElement('html');
                obj.innerHTML = texts[i];
                let track = obj.querySelector(".flush-btn").getAttribute("logisticsNo");
                let date = obj.querySelector('.order-reminder');
                if (!track || !date) return alert("Не получил информацию о заказе");
                date = date.innerText.match(/\d{4}-\d\d-\d\d/g);
                if (date.length > 0) date = date[0].replace(/\d\d(\d\d)-(\d\d)-(\d\d)/, '$3.$2.$1');
                else return alert("Не правильная дата в заказе");
                trackMass[i].track = track;
                trackMass[i].date = date;
            }
            document.querySelectorAll(".trackGetter").forEach(elem => elem.removeAttribute("disabled"));
        })
        .catch(err => alert(`Ошибка ${err}`));
}
function formatDate() {
    let date = new Date();
    let dd = date.getDate();
    if (dd < 10)
        dd = '0' + dd;
    let mm = date.getMonth() + 1;
    if (mm < 10)
        mm = '0' + mm;
    let yy = date.getFullYear() % 100;
    if (yy < 10)
        yy = '0' + yy;
    return dd + '.' + mm + '.' + yy;
}
Для Google Таблиц что бы картинка сразу вставлялась в ячейку и отображалась без лишних дополнительных кнопок, нужно:
1- включить picPrefix -> let picPrefix = 1;
2- затем заменить строку if (picPrefix) picURL = "picURL=" + picURL;
на if (picPrefix) picURL = "=IMAGE(\"" + picURL + "\")"; в двух кнопках
 
Последнее редактирование:
Накидал для себя удобный скриптик для оплаты картой из заказов. Нужно дойти до вот этого окна и ждать заполнения
Посмотреть вложение 289353

JavaScript:
// ==UserScript==
// @name         Aliexpress order card filler
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  try to take over the world!
// @author       Andronio
// @match        https://shoppingcart.aliexpress.com/order/secondPayment.htm?cashierRequestToken=*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    setTimeout(cardFunc, 7000);

    async function cardFunc() {
        let myCard = '1234 5678 9012 3456, 2021/11, xxx, JOHN SMITH';
        let cardNumber = document.getElementById('cardNum');
        let cardHold   = document.getElementById('cardHolder');
        let dateExpire = document.getElementById('expires');
        let codeCVC    = document.getElementById('cvv');
        let mass;

        mass = myCard.split(', ');
        setInput(cardNumber, mass[0]);
        setInput(cardHold, mass[3]);
        let date = mass[1].slice(5,7) + '/' + mass[1].slice(2,4);
        setInput(dateExpire, date);
        setInput(codeCVC, mass[2]);
        document.querySelector('input.next-checkbox-input').click(); // Снять галку
        await waitForElement('.save-card-info-confirm button:nth-child(1)', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10);
        await waitForElement('.next-loading-tip', 500, 10, true);
        await sleep(200);
        document.querySelector('.save-card-info-confirm button:nth-child(1)').click();
        await waitForElement('input.next-checkbox-input:checked', 500, 10, true);
        await sleep(200);
        document.querySelector('button').click();
    }


    function setInput(input, value) {
        if (!input) {
            return;
        }

        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
        nativeInputValueSetter.call(input, value);
        input.dispatchEvent(new Event('change', {bubbles: true}));
        input.dispatchEvent(new Event('keyup', {bubbles: true}));
        input.dispatchEvent(new Event('keydown', {bubbles: true}));
        input.dispatchEvent(new Event('keypress', {bubbles: true}));
        input.dispatchEvent(new Event('input', {bubbles: true}));
        input.dispatchEvent(new Event('blur', {bubbles: true}));
    };

    function waitForElement(selectors, interval = 250, seconds = 0, waitForDisappear = false) {

        return new Promise((resolve) => {
            if (!Array.isArray(selectors)) {
                selectors = [selectors];
            }

            seconds = seconds * 1000;

            const startTime = Date.now();
            const check = () => {
                let found = selectors.some(s => {
                    const el = document.querySelector(s);
                    return !!(el && isVisible(el));
                })

                if (!waitForDisappear && found || waitForDisappear && !found) {
                    return resolve(true);
                }

                if (seconds > 0 && Date.now() - startTime > seconds) {
                    return resolve(false);
                }

                setTimeout(check, interval);
            };

            check();
        });
    };
    function isVisible(e) {
        return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
    };
    async function sleep(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    };

})();
А можно что-то подобное, только чтобы данные карты рандом подставлял?
 
Накидал для себя удобный скриптик для оплаты картой из заказов. Нужно дойти до вот этого окна и ждать заполнения
Посмотреть вложение 289353
Эх... Пол года назад просил такой скрипт, когда одной картой можно было платить бесконечно.
Сейчас не знаю какой от него толк. Особенно в том виде, как он есть.
Сохраню для коллекции.