您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Удобства пользования сайтом
当前为
// ==UserScript== // @name jetlend // @description Удобства пользования сайтом // @author Я // @match *://jetlend.ru/* // @icon https://www.google.com/s2/favicons?sz=64&domain=jetlend.ru // @grant none // @license MIT // @version 0.0.1.20240207165553 // @namespace https://gf.qytechs.cn/users/1256967 // ==/UserScript== /* document.querySelectorAll('[data-colindex="3"]').forEach((item, i)=>{ if (i > 1) { if (Number(item.textContent) < 16) { item.closest('tr').style.background = "pink"; console.log(item.textContent) } } }) */ (function () { "use strict"; })(); // Инфо обо мне const urlDetails = "https://jetlend.ru/invest/api/account/details?exclude_npd=true"; // Инфо о Первичном рынке const urlReqWaiting = "https://jetlend.ru/invest/api/requests/waiting"; // Инфо о Вторичном рынке const urlLoans = "https://jetlend.ru/invest/api/exchange/loans"; // Инфо о всех нотификациях const urlNotifications = "https://jetlend.ru/invest/api/account/notifications/v3"; // Инфо о конкретном займе const urlLoanOverview = "https://jetlend.ru/invest/api/exchange/loans/11988/overview"; // инфо о стакане займа const url6 = "https://jetlend.ru/invest/api/exchange/loans/11988/dom/records"; // Аналитика по id займа https://jetlend.ru/invest/api/requests/18163/analytics // На сколько использован лимит на платформе https://jetlend.ru/invest/api/requests/18163/limits // Инфо о займе по id, в том числе статус Игнора https://jetlend.ru/invest/api/requests/18163/info window.levelBigInterest = 0.4; window.loanOptions = { interest_rate: 0.19, financial_discipline: 0.8, term: 720, term_left: 1000, ytm: 0.3, progress: 0.3, min_price: 0.99, status: "active", status2: "restructured", invested_company_debt: 200, }; window.loans = []; window.bigDataLoans = []; window.filteredLoans = []; window.filteredGoodLoans = []; window.overviewCounter = 0; window.loansSlice = 100; window.totalLoans = 0; window.offsetLoans = 0; window.makeBigOverview = () => makeBigOverview(); window.makeGlobalOverview = () => makeGlobalOverview(); window.updateBigOverview = () => updateBigOverview(); window.updateGoodLoansOverview = () => updateGoodLoansOverview(); window.makeOverviewById = (id) => makeOverviewById(id); window.loanPreview = (odt) => loanPreview(odt); window.clearPriceByODT = (odt) => clearPriceByODT(odt); window.buyLoanByODT = (odt) => buyLoanByODT(odt); window.sellLoanByODT = (odt) => sellLoanByODT(odt); window.findIndexById = (id) => findIndexById(id); async function reqMyDetails() { const data = await fetchAsync(urlDetails); /* console.log("myDetails:", data?.data); */ window.myDetails = data?.data; return data?.data; } // получить первичный рынок и записать с большим процентом. async function reqWaiting() { const data = await fetchAsync(urlReqWaiting); /* console.log("Req Waiting:", data?.requests); */ window.loanReqWaiting = data?.requests; window.levelBigInterest = window.levelBigInterest || 0.3; window.bigInterestReqWaiting = window.loanReqWaiting.filter((element) => { return ( element.interest_rate > window.levelBigInterest && element.investing_amount === null && element.company_investing_amount === null ); }); if (window.bigInterestReqWaiting.length === 0) { console.log("Новых займов выше " + window.levelBigInterest + " нет."); window.levelBigInterest = (window.levelBigInterest - 0.01).toFixed(2); } else { console.log(window.bigInterestReqWaiting); } /* window.bigInterestReqWaiting.forEach((loan) => { if (loan.interest_rate > 0.35) { sendMessage(loan); } }); */ return data?.requests; } function updateBigIntReqWaiting() { window.bigInterestReqWaiting = window.loanReqWaiting.filter((element) => { return ( element.interest_rate > window.levelBigInterest && element.investing_amount === null ); }); if (window.bigInterestReqWaiting.length === 0) { console.log("Новых займов выше " + window.levelBigInterest + " нет."); } else { console.log("Найден первичный займ с большой ставкой."); console.log(window.bigInterestReqWaiting); } } // ------------------------------------ // получить Вторичный рынок и фильтрануть по опциям. async function fetchLoans() { let data = await fetchAsync( `https://jetlend.ru/invest/api/exchange/loans?limit=100&offset=${window.offsetLoans}` ); /* console.log("Loans:", data?.data); */ window.loans = data?.data; window.totalLoans = data?.total; // сдвигаем счётчик уже загруженных займов, или начинаем заново. if (window.offsetLoans > window.totalLoans) { window.offsetLoans = 0; } else { window.offsetLoans = window.offsetLoans + 100; } window.filteredLoans = getLoansByOptions(window.loanOptions); const bigDataFilteredByClearPrice = window.bigDataLoans.filter( (item) => item.clear_price ); bigDataFilteredByClearPrice.forEach((item) => { window.filteredLoans.forEach((innerItem) => { if (innerItem.loan_id === item.loan_id) { innerItem.clear_price = item.clear_price; innerItem.commission = item.commission; innerItem.ndfl = item.ndfl; innerItem.available_count = item.available_count; innerItem.summary_interest_revenue = item.summary_interest_revenue; } }); }); return data?.data; } // ------------------------------------ // получить данные по займу. async function fetchLoanOverview(loanId) { const data = await fetchAsync( `https://jetlend.ru/invest/api/exchange/loans/${loanId}/overview` ); const loanIndex = window.bigDataLoans.findIndex( (el) => el.loan_id === loanId ); window.bigDataLoans[loanIndex].recommended_price = data?.data.sell.recommended_price; window.bigDataLoans[loanIndex].best_price = data?.data.sell.best_price; window.bigDataLoans[loanIndex].has_any_overdue = data?.data.has_any_overdue; window.bigDataLoans[loanIndex].history_overdue_days = data?.data.loan.history_overdue_days; window.bigDataLoans[loanIndex].best_price_count = data?.data.sell.best_price_count; window.bigDataLoans[loanIndex].best_price_amount = data?.data.sell.best_price_amount; window.currentLoanOverview = data?.data; return data?.data; } // ------------------------------------ // получить данные по займам по которым нет данных function updateBigOverview() { console.log("updateBigOverview()"); window.bigDataLoans.forEach((loan) => { if (!loan.best_price) { fetchLoanOverview(loan.loan_id); } }); } async function fetchAsync(url) { const response = await fetch(url); const data = await response.json(); return data; } function createMyInfoBlock() { const htmlBlock = document.createElement("DIV"); htmlBlock.id = "infoblock"; // htmlBlock.style.overflow = "auto"; htmlBlock.style.position = "relative"; htmlBlock.style.zIndex = "999"; const blockContent1El = document.querySelectorAll( 'div [class^="block_content__"]' )[0]; blockContent1El.appendChild(htmlBlock); window.myInfoBlockEl = document.getElementById("infoblock"); /* console.log("InfoBlockEl created"); */ } function updateMyInfoBlock() { window.myInfoBlockEl.innerHTML = createMyInfoBlockEl(); } function createMyInfoBlockEl() { if (window.myDetails) { return `<div> <table> <tr> <td> <div>Свободно сейчас = <b style="font-size: 1.25rem;">${window.myDetails?.balance.free.toFixed( 2 )} руб</b></div> <div>ПРОФИТ = <b style="color: green; font-size: 1.25rem;">${window.myDetails?.summary.profit.toFixed( 2 )} руб</b></div> <div>В сейфе = <b>${window.myDetails?.balance.safe.toFixed( 2 )} руб</b></div> <div>Потери / Дефолты = <b style="color: red;">${window.myDetails?.summary.loss.toFixed( 2 )} руб</b></div> <div>Моя доходность = <b>${( window.myDetails?.summary.yield_rate * 100 ).toFixed(2)}%</b></div> <div>Мой XIRR = <b>${( window.myDetails?.summary.yield_rate_xirr * 100 ).toFixed(2)}%</b></div> <div>В резерве = <b>${window.myDetails?.balance.reserved.toFixed( 2 )} руб</b></div> <div>Interest / APY = <b>${window.myDetails?.summary_year.details.interest.toFixed( 2 )}%</b></div> <div>Fine = <b>${( window.myDetails?.summary_year.details.fine * 100 ).toFixed(2)}%</b></div> <div>Годовой процент = <b>${window.myDetails?.summary_year.yield_rate.toFixed( 2 )}%</b></div> <div>Годовой процент xirr = <b>${window.myDetails?.summary_year.yield_rate_xirr.toFixed( 2 )}%</b></div> </td> <td> <div>${ window?.loanReqWaiting?.length } - Всего займов на первичке</div> <div>${window?.totalLoans} - Всего займов на вторичке</div> <div>${window?.bigDataLoans.length} - Всего займов загружено</div> <div>${window?.filteredLoans?.length} - Отфильтровано займов</div> <form> <div> <input value='${ window.loanOptions.interest_rate }' onchange='window.loanOptions.interest_rate=this.value' /> <span>Ставка</span> </div> <div> <input value='${ window.loanOptions.ytm }' onchange='window.loanOptions.ytm=this.value' /> <span>YTM</span> </div> <div> <input value='${ window.loanOptions.min_price }' onchange='window.loanOptions.min_price=this.value' /> <span>Мин.цена</span> </div> <div> <input value='${ window.loanOptions.progress }' onchange='window.loanOptions.progress=this.value' /> <span>Прогресс</span> </div> <div> <input value='${ window.loanOptions.term_left }' onchange='window.loanOptions.term_left=this.value' /> <span>Дн.ост-сь</span> </div> <div> <input value='${ window.loanOptions.financial_discipline }' onchange='window.loanOptions.financial_discipline=this.value' /> <span>ФД</span> </div> <div> <input value='${ window.loanOptions.invested_company_debt }' onchange='window.loanOptions.invested_company_debt=this.value' /> <span>Отсчечка по долгу</span> </div> <div> <input value='${ window.loansSlice }' onchange='window.loansSlice=this.value' /> <span>Сколько выводить?</span> </div> </form> </td> <td> <button style='cursor: pointer;' type='button' onclick='window.makeGlobalOverview()'>Overview глобал</button> <hr> <button style='cursor: pointer;' type='button' onclick='window.updateBigOverview()'>Overview обновить</button> <hr> <button style='cursor: pointer;' type='button' onclick='window.updateGoodLoansOverview()'>Overview обн-ть хор.</button> </td> </tr> </table> </div> <hr> <div>Новые займы с % выше <b>${window.levelBigInterest}</b></div> <table>${makeAnkerTable(window.bigInterestReqWaiting).innerHTML}</table> <hr> <div>Хороший процент</div> <table id='filtered-good-loans'>${ makeAnkerTable(window.filteredGoodLoans).innerHTML }</table> <hr> <div>Отфильтрованные займы</div> <table id='filtered-loans'>${ makeAnkerTable(window.filteredLoans.slice(0, window.loansSlice)) .innerHTML }</table> `; } else { console.log("window.myDetails is ", window.myDetails); } } // сделать читаемую ссылку function makeAnker(array) { const newBlocks = array.map((el) => { return `<div>${el.company} | <a href="/invest/v3/company/${ el.id || el.loan_id }">${el.id || el.loan_id}</a> | ${(el.interest_rate * 100).toFixed(2)}% | ${ el.ytm ? "ytm " + (el.ytm * 100).toFixed(2) + "% |" : "" } ${ el.progress ? "progress " + (el.progress * 100).toFixed() + "% |" : "" } ${ el.min_price ? "min_price " + (el.min_price * 100).toFixed(2) + "% |" : "" } ${el.term} дн. | ${el.financial_discipline}</div>`; }); //console.log(newBlocks); return newBlocks; } function makeAnkerTable(array) { const table = document.createElement("TABLE"); const newTrs = array.map((el, i) => { const tr = `<tr style='${ el.invested_company_debt === null ? "background-color: rgba(96, 245, 39, 0.15);" : "" }'> <td>${i}</td> <td style="font-style: 0.6rem;">${el.rating} | ${el.company}</td> <!--<td>${el.rating}</td>--> <td> <a href="/invest/v3/company/${el.id || el.loan_id}">${ el.id || el.loan_id }</a> </td> <td>Ставка <br> ${(el.interest_rate * 100).toFixed(2)}%</td> ${ el.ytm && el.ytm >= 0.35 ? "<td style='color: green; font-size: 1.25rem;'>YTM <br>" + (el.ytm * 100).toFixed(2) + "% </td>" : el.ytm ? "<td>YTM <br>" + (el.ytm * 100).toFixed(2) + "% </td>" : "" } ${ el.min_price ? "<td>Мин.цена <br> " + (el.min_price * 100).toFixed(2) + "% </td>" : "" } ${ el.progress ? "<td>Прогресс <br> " + (el.progress * 100).toFixed() + "% </td>" : "" } <!--<td>Дней всего <br>${el.term}</td>--> ${el.term_left ? "<td>Дней остсь <br> " + el.term_left + "</td>" : ""} <td>ФД <br>${el.financial_discipline}</td> ${ el.invested_company_debt ? "<td>Долг <br> " + el.invested_company_debt + " ₽ </td>" : "<td></td>" } ${ el.recommended_price ? "<td>Рек.цена <br> " + (el.recommended_price * 100).toFixed(2) + "% </td>" : "" } ${ el.recommended_price && el.recommended_price - el.min_price >= 0.01 ? "<td style='color: green;font-weight: bold;'>Разница <br> " + ((el.recommended_price - el.min_price) * 100).toFixed(2) + "% </td>" : "" } ${ el.recommended_price && el.recommended_price - el.min_price < 0.01 ? "<td>Разница <br> " + ((el.recommended_price - el.min_price) * 100).toFixed(2) + "% </td>" : "" } <!-- ${ el.has_any_overdue ? "<td>Просрочки? <br> " + el.has_any_overdue + " </td>" : "<td></td>" } --> ${ el.history_overdue_days ? "<td>Всего дн. просрочки <br> " + el.history_overdue_days + " </td>" : "<td></td>" } ${ el.best_price_count ? "<td>best price count <br> " + el.best_price_count + " </td>" : "<td></td>" } ${ el.best_price_amount ? "<td>best price amount <br> " + el.best_price_amount + " </td>" : "<td></td>" } ${ el.best_price_amount && el.best_price_count ? "<td>Лучшая цена <br> " + ( (el.best_price_amount * el.min_price) / el.best_price_count ).toFixed(2) + " </td>" : "<td></td>" } ${ el.min_price ? "<td><button type='button' onclick='window.makeOverviewById(" + el.loan_id + ")'>update overview</button></td>" : "<td></td>" } ${ el.clear_price ? "<td> Точная цена <br>" + el.clear_price.toFixed(2) + "</td>" : "<td></td>" } ${ el.best_price ? "<td><button type='button' onclick='window.clearPriceByODT(" + JSON.stringify({ loanId: el.loan_id, count: 1, maxPrice: el.best_price, }) + ")'>Уточнить цену</button></td>" : "<td></td>" } ${ el.best_price ? "<td><button style='border-color: green; cursor: pointer;' type='button' onclick='window.buyLoanByODT(" + JSON.stringify({ loanId: el.loan_id, count: 1, maxPrice: el.min_price, }) + ")'>Купить</button></td>" : "<td></td>" } ${ el.best_price ? "<td><button style='border-color: red; cursor: pointer;' type='button' onclick='window.sellLoanByODT(" + JSON.stringify({ loanId: el.loan_id, count: 1, recommededPrice: el.recommended_price, }) + ")'>Продать</button></td>" : "<td></td>" } </tr>`; return tr; }); table.innerHTML = newTrs.join(" "); return table; } // Получить займы по опциям. function getLoansByOptions(options) { const loansArray = window.bigDataLoans.filter((loan) => { return ( loan?.financial_discipline > options?.financial_discipline && loan?.progress > options?.progress && loan?.interest_rate > options?.interest_rate && loan?.min_price < options?.min_price && loan?.ytm > options?.ytm && loan?.loan_id > 9999 && loan?.status === "active" && (loan?.invested_company_debt === null || loan?.invested_company_debt < options.invested_company_debt) && loan?.term_left < options?.term_left ); }); // сортировка по YTM loansArray.sort((a, b) => { if (a.ytm <= b.ytm) { return 1; } if (a.ytm > b.ytm) { return -1; } return 0; }); loansArray.forEach((loan) => { // Попытка найти займ в большом списке const oldLoan = window?.bigDataLoans.find( (item, i) => item.loan_id === loan.loan_id ); // Если займа есть в списке, то взять данные из него, если его нет в списке, то добавить его if (oldLoan) { loan.recommended_price = oldLoan.recommended_price; loan.best_price = oldLoan.best_price; loan.has_any_overdue = oldLoan.has_any_overdue; loan.history_overdue_days = oldLoan.history_overdue_days; loan.best_price_count = oldLoan.best_price_count; loan.best_price_amount = oldLoan.best_price_amount; } else { window?.bigDataLoans.push(loan); } window.filteredGoodLoans = loansArray.filter((loan) => { return loan?.recommended_price - loan?.min_price >= 0.01; }); // сортировка по разнец в процентах минимальной цены от рекомендованной window.filteredGoodLoans.sort((a, b) => { if ( a.recommended_price - a.min_price <= b.recommended_price - b.min_price ) { return 1; } if ( a.recommended_price - a.min_price > b.recommended_price - b.min_price ) { return -1; } return 0; }); if (loan.ytm > 0.35) { sendMessage(loan); } if (loan.recommended_price - loan.min_price >= 0.01) { sendMessageDiffPrice(loan); } }); /* console.log("Отфильтрованные займы"); console.log(loansArray); */ if (loansArray?.length === 0) { console.log("Нет займов соответствующих фильтру поиска."); } return loansArray; } // подтянуть данные по займам по одному function makeBigOverview() { console.log("makeBigOverview()"); if (window.bigDataLoans.length > 0) { const loan = window.bigDataLoans[window.overviewCounter]; fetchLoanOverview(loan.loan_id); // если дошли до последнего элемента в массиве, то обнулим счётчик, иначе +1 if (window.bigDataLoans.length - 1 <= window.overviewCounter) { window.overviewCounter = 0; } else { window.overviewCounter++; } } } function makeGlobalOverview() { console.log("makeGlobalOverview()"); if (window.bigDataLoans.length > 0) { window.bigDataLoans.forEach((loan) => { fetchLoanOverview(loan.loan_id); }); } } function updateGoodLoansOverview() { if (window?.filteredGoodLoans?.length > 0) { console.log("updateGoodLoansOverview()"); window.filteredGoodLoans.forEach((loan) => { fetchLoanOverview(loan.loan_id); }); } } function makeOverviewById(id) { if (window.bigDataLoans.length > 0) { fetchLoanOverview(id); } else { console.log("no loans in bigDataLoans"); } } function updateFilteredLoans() { window.filteredLoans = getLoansByOptions(window.loanOptions); window.filteredLoans.forEach((loan) => { if (loan.ytm > 0.35) { sendMessage(loan); } }); } // ------------------------------------ function sendMessage(data) { //console.log("-----------------"); //console.log("Появились займы с большой эффективной ставкой"); //console.log(data); const odt = { title: "Появились займы с большой эффективной ставкой", text: (data.loan_id || data.id) + " YTM:" + data.ytm, }; notifyMe(odt); //console.log("-----------------"); } function sendMessageDiffPrice(data) { //console.log("-----------------"); //console.log("Появились займы с разницей в ставке"); //console.log(data.loan_id || data.id); //console.log(data.recommended_price - data.min_price); //console.log(data); const odt = { title: "Появились займы с разницей в ставке", text: (data.loan_id || data.id) + " YTM:" + data.ytm, }; notifyMe(odt); //console.log("-----------------"); } function tikTak() { console.log("TitTak"); reqMyDetails(); reqWaiting(); fetchLoans(); updateMyInfoBlock(); updateGoodLoansOverview(); setTimeout(() => { tikTak(); }, 5000); } function tikTak2() { console.log("TitTak2"); window.levelBigInterest = 0.4; window.updateBigOverview(); setTimeout(() => { tikTak2(); }, 30000); } if (window.location.href === "https://jetlend.ru/invest/v3") { // window.location.href.includes("jetlend.ru/invest") createMyInfoBlock(); tikTak(); tikTak2(); console.log("jetlend.ru/invest"); } const notifyMe = function (odt) { //playSound("bing"); beep(100, 110, 1); const notification = new Notification(odt?.title || "title", { tag: odt?.tag || "tag", body: odt?.text || "text", silent: true, icon: odt?.icon || "https://w7.pngwing.com/pngs/225/161/png-transparent-money-banknote-ruble-coin-money-horse-saving-payment.png", }); }; function playSound(url) { const audio = new Audio(url); audio.play(); } // Превью конкретного займа async function loanPreview(odt) { const csrftoken = document.cookie .split(";") .find((el) => { return el.includes("csrftoken"); }) .slice(-32); const response = await fetch( `https://jetlend.ru/invest/api/exchange/loans/${odt.loanId}/buy/preview`, { headers: { accept: "application/json, text/plain, */*", "accept-language": "ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7", "content-type": "application/json;charset=UTF-8", "x-csrftoken": csrftoken, }, body: `{"count":${odt.count},"max_price":${odt.maxPrice}}`, method: "POST", } ); const data = await response.json(); if (data.status === "error") { console.log(data.error); } //console.log("this loan preview", data?.data); return data?.data; /* { loanId: number, count: number, maxPrice: number, } */ /* { "status": "OK", "data": { "amount": 36.98, "overall_amount": 36.98, "summary_interest_revenue": 0.43, "ytm": 0.3047752462782121, "available_count": 1, "left_count": 0, "commission": 0, "ndfl": 0.15 } } */ } /* { loanId: number, count: number, maxPrice: number, } */ async function clearPriceByODT(odt) { console.log("clearPriceByODT()"); //console.log(odt); const data = await loanPreview(odt); const loanIndex = window.bigDataLoans.findIndex( (el) => el.loan_id === odt.loanId ); window.bigDataLoans[loanIndex].commission = data?.commission; window.bigDataLoans[loanIndex].ndfl = data?.ndfl; window.bigDataLoans[loanIndex].available_count = data?.available_count; window.bigDataLoans[loanIndex].summary_interest_revenue = data?.summary_interest_revenue; window.bigDataLoans[loanIndex].clear_price = data?.amount + data?.commission + data?.ndfl + data?.summary_interest_revenue; //console.log("price is:", window.bigDataLoans[loanIndex].clear_price); return ( data?.amount + data?.commission + data?.ndfl + data?.summary_interest_revenue ); } function findIndexById(id) { const index = window.bigDataLoans.findIndex((el) => el.loan_id == id); console.log(index); return index; } async function buyLoanByODT(odt) { const csrftoken = document.cookie .split(";") .find((el) => { return el.includes("csrftoken"); }) .slice(-32); const response = await fetch( `https://jetlend.ru/invest/api/exchange/loans/${odt.loanId}/buy`, { headers: { accept: "application/json, text/plain, */*", "accept-language": "ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7", "content-type": "application/json;charset=UTF-8", "x-csrftoken": csrftoken, }, body: `{"count":${odt.count}, "max_price":${odt.maxPrice}}`, method: "POST", } ); const data = await response.json(); console.log("loan buyed", data?.data); return data?.data; /* { "amount": 77.17, "overall_amount": 77.17, "summary_interest_revenue": 0.94, "ytm": 0.3050130983567512, "available_count": 1, "left_count": 0, "commission": 0, "ndfl": 0.14 } */ } async function sellLoanByODT(odt) { const csrftoken = document.cookie .split(";") .find((el) => { return el.includes("csrftoken"); }) .slice(-32); const response = await fetch( `https://jetlend.ru/invest/api/exchange/loans/${odt.loanId}/sell`, { headers: { accept: "application/json, text/plain, */*", "accept-language": "ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7", "content-type": "application/json;charset=UTF-8", "x-csrftoken": csrftoken, }, body: `{"count":${odt.count}, "min_price":${ odt.recommededPrice - 0.0001 }}`, method: "POST", } ); const data = await response.json(); console.log("loan selled", data?.data); return data?.data; /* { "amount": 0, "overall_amount": 68.31, "summary_interest_revenue": 0, "ytm": 0.30476719534430446, "available_count": 0, "left_count": 1, "commission": 0.12, "ndfl": 0 } */ } const myAudioContext = new AudioContext(); /** * Helper function to emit a beep sound in the browser using the Web Audio API. * * @param {number} duration - The duration of the beep sound in milliseconds. * @param {number} frequency - The frequency of the beep sound. * @param {number} volume - The volume of the beep sound. * * @returns {Promise} - A promise that resolves when the beep sound is finished. */ function beep(duration, frequency, volume) { return new Promise((resolve, reject) => { // Set default duration if not provided duration = duration || 200; frequency = frequency || 440; volume = volume || 100; try { let oscillatorNode = myAudioContext.createOscillator(); let gainNode = myAudioContext.createGain(); oscillatorNode.connect(gainNode); // Set the oscillator frequency in hertz oscillatorNode.frequency.value = frequency; // Set the type of oscillator oscillatorNode.type = "square"; gainNode.connect(myAudioContext.destination); // Set the gain to the volume gainNode.gain.value = volume * 0.01; // Start audio with the desired duration oscillatorNode.start(myAudioContext.currentTime); oscillatorNode.stop(myAudioContext.currentTime + duration * 0.001); // Resolve the promise when the sound is finished oscillatorNode.onended = () => { resolve(); }; } catch (error) { reject(error); } }); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址