diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..73dcc67
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,25 @@
+{
+ "env": {
+ "browser": true,
+ "es2021": true
+ },
+ "globals": {
+ "$": "readonly",
+ "jQuery": "readonly"
+ },
+ "extends": ["eslint:recommended"],
+ "parserOptions": {
+ "ecmaVersion": 12,
+ "sourceType": "module"
+ },
+ "rules": {
+ "no-unused-vars": "warn",
+ "no-undef": "warn",
+ "semi": "off",
+ "no-empty": "off",
+ "no-extra-semi": "off",
+ "no-unsafe-optional-chaining": "off",
+ "no-redeclare": "off",
+ "no-constant-condition": "off"
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2bacfd0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.DS_Store
+
+# Build artifacts
+/dist/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..051416d
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,4 @@
+{
+ "proseWrap": "preserve",
+ "singleQuote": true
+}
diff --git a/README.md b/README.md
index fd61012..4f8bf24 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
@@ -12,7 +11,6 @@
KeydropPlus v2 is an unofficial extension for [keydrop.com](https://key-drop.com/) that adds new features and improves the user interface.
-
## 💡 List of current functions
- Automatic joining of 'Amateur' giveaways [Does not work on reCATCH].
@@ -27,7 +25,6 @@ KeydropPlus v2 is an unofficial extension for [keydrop.com](https://key-drop.com
- Display of pre-selected user giveaways.
- Automatic clicking on the receive gold code button at the 'direct link' (?code=).
-
## 📁 How to add an extension
1. Extract the files to a folder
@@ -36,7 +33,6 @@ KeydropPlus v2 is an unofficial extension for [keydrop.com](https://key-drop.com
4. Click the "Upload unzipped" button
5. Select the folder with the extracted extension
-
## 🌐 Works on these browsers
- Google Chrome
@@ -46,7 +42,6 @@ KeydropPlus v2 is an unofficial extension for [keydrop.com](https://key-drop.com
- Brave Browser
- And others based on Chromium
-
## 🌍 Available languages
- English
@@ -56,13 +51,14 @@ KeydropPlus v2 is an unofficial extension for [keydrop.com](https://key-drop.com
## 🛠️ Configuration - Correctly setting prices from Steam
To get everything working without a problem, you need to:
+
- Set the currency on the key-drop page to PLN, EUR or USD
- Log in to Steam in your browser and set the currency to PLN, EUR or USD
_Refreshing prices too often can temporarily block the Steam Market API._
-
## ✨ Usage
+
- [Keydrop API](key-drop.com)
- [Steam API](https://steamcommunity.com/market/)
- [Skinport API](https://docs.skinport.com/#introduction)
@@ -70,7 +66,6 @@ _Refreshing prices too often can temporarily block the Steam Market API._
- [jQuery](https://jquery.com)
- [Chart.js](https://github.com/chartjs/Chart.js)
-
## 🔥 Screenshots

@@ -78,13 +73,28 @@ _Refreshing prices too often can temporarily block the Steam Market API._


+## 🧑💻 Development
+
+This project uses Node.js tooling to keep the codebase consistent.
+
+```bash
+npm install # install dependencies
+npm run lint # check JavaScript style
+npm run format # verify formatting
+```
+
+## 🤝 Contributing
+
+Issues and feature requests are tracked on the [GitHub issue tracker](https://github.com/Juzlus/KeydropPlus/issues).
+
+Pull requests are welcome! Please fork the repository, create a topic branch for your work and open a pull request. Remember to run the linter and formatter before submitting.
## 📝 Feedback
If you have any Feedback or questions, please contact me at juzlus.biznes@gmail.com or [Discord](https://discordapp.com/users/284780352042434570).
-
## 💝 Donate
+
@@ -95,10 +105,8 @@ If you have any Feedback or questions, please contact me at juzlus.biznes@gmail.
-
## ⚠️ Disclaimer
_The KeydropPlus v2 is an independent project developed by an individual and is not endorsed or affiliated with [key-drop.com](https://key-drop.com/)._
_The author of the extension is not responsible for any consequences resulting from its use._
-
diff --git a/css/style.css b/css/style.css
index 0fddac2..fcafe02 100644
--- a/css/style.css
+++ b/css/style.css
@@ -346,13 +346,23 @@ tbody .fullTd {
}
.keydorp-plus-change-language {
+ display: inline-block;
+ height: 34px;
+ cursor: pointer;
+ filter: opacity(0.5);
transition: 0.25s;
}
-.keydorp-plus-change-language:hover {
+.keydorp-plus-change-language:hover,
+.keydorp-plus-change-language.active {
filter: opacity(1) !important;
}
+.keydorp-plus-change-language.active {
+ border: 1px solid gold;
+ border-radius: 4px;
+}
+
div.hidden.overflow-hidden.md\:block.bg-navy-700 {
height: 76px;
}
diff --git a/data/lang/english.json b/data/lang/english.json
index 7cff24a..3bea35b 100644
--- a/data/lang/english.json
+++ b/data/lang/english.json
@@ -22,6 +22,8 @@
"autogiveaway_settings_a2": "You can only join up to 20 giveaways per day",
"autogiveaway_settings_p5": "Minimum Amount",
"autogiveaway_settings_a5": "Minimum amount of the giveaway",
+ "autogiveaway_settings_p6": "Search pages",
+ "autogiveaway_settings_a6": "Number of pages to scan for giveaways",
"autogiveaway_settings_p3": "Won Giveaways",
"autogiveaway_settings_a3": "Counted won giveaways",
"autogiveaway_settings_p4": "Earnings from Giveaways",
diff --git a/data/lang/polish.json b/data/lang/polish.json
index f94073e..45ea971 100644
--- a/data/lang/polish.json
+++ b/data/lang/polish.json
@@ -22,6 +22,8 @@
"autogiveaway_settings_a2": "Codziennie można dołączyć tylko do 20 konkursów",
"autogiveaway_settings_p5": "Minimalna kwota",
"autogiveaway_settings_a5": "Minimalna kwota konkursu",
+ "autogiveaway_settings_p6": "Liczba stron",
+ "autogiveaway_settings_a6": "Ilość stron do przeszukania konkursów",
"autogiveaway_settings_p3": "Wygrane konkursy",
"autogiveaway_settings_a3": "Zliczone wygrane konkursy",
"autogiveaway_settings_p4": "Zarobek z konkursów",
diff --git a/data/lang/portuguese.json b/data/lang/portuguese.json
index e5b4ca7..1c8f6e8 100644
--- a/data/lang/portuguese.json
+++ b/data/lang/portuguese.json
@@ -22,6 +22,8 @@
"autogiveaway_settings_a2": "Você só pode participar de até 20 sorteios por dia",
"autogiveaway_settings_p5": "Quantidade mínima",
"autogiveaway_settings_a5": "Quantidade mínima do sorteio",
+ "autogiveaway_settings_p6": "Páginas de busca",
+ "autogiveaway_settings_a6": "Número de páginas para procurar sorteios",
"autogiveaway_settings_p3": "Sorteios Ganhos",
"autogiveaway_settings_a3": "Número de sorteios ganhos",
"autogiveaway_settings_p4": "Ganhos com sorteios",
diff --git a/js/caseInfo.js b/js/caseInfo.js
index 04b3645..ebb245b 100644
--- a/js/caseInfo.js
+++ b/js/caseInfo.js
@@ -295,7 +295,7 @@ const caseDataCombine = async(caseJSON, languageText) => {
const casesFetch = await fetchUrl('GET', `${githubUrl}/cases.json`)
if(!casesFetch) return;
- const cases = JSON.parse(`{"cases": ${casesFetch}}`)?.cases;
+ const cases = Array.isArray(casesFetch) ? casesFetch : casesFetch?.cases;
if(!cases?.length) return;
const goldenCases = cases?.filter(el => el?.goldProfit !== undefined);
diff --git a/js/caseOdds.js b/js/caseOdds.js
index 864e9a9..ab973ac 100644
--- a/js/caseOdds.js
+++ b/js/caseOdds.js
@@ -2,7 +2,7 @@ $( document ).ready(async() => {
const config = await getConfigData();
const casesFetch = await fetchUrl('GET', `${githubUrl}/cases.json`)
if(!casesFetch || !config) return;
- const cases = JSON.parse(`{"cases": ${casesFetch}}`)?.cases;
+ const cases = Array.isArray(casesFetch) ? casesFetch : casesFetch?.cases;
if(!cases?.length) return;
waitForElm('section#gold-area').then(async() => {
@@ -20,6 +20,22 @@ $( document ).ready(async() => {
addObserverIfDesiredNodeAvailable();
});
+const goldProfitThresholds = [
+ { max: 11111111, label: '0/5' },
+ { max: 13209876, label: '0.5/5' },
+ { max: 15308641, label: '1/5' },
+ { max: 17407407, label: '1.5/5' },
+ { max: 19506172, label: '2/5' },
+ { max: 21604937, label: '2.5/5' },
+ { max: 23703703, label: '3/5' },
+ { max: 25802468, label: '3.5/5' },
+ { max: 27901233, label: '4/5' },
+ { max: 29999999, label: '4.5/5' },
+ { max: Infinity, label: '5/5' },
+];
+
+const calculateGoldOdds = (profit) => goldProfitThresholds.find(t => profit <= t.max).label;
+
const refreshOdds = async(config, cases, init) => {
const index = await getIndexData();
const currencyRates = index?.currencyRates;
@@ -62,49 +78,23 @@ const createCaseOdds = async(config, currentRate, currency, cases, thisElement,
const caseName = $(thisElement)?.find('div[data-testid=case-card-badge-btn] p')?.last()?.text();
if(!caseName) return;
- let odds;
const jokerCase = config?.showJokerOdds ? cases?.filter(el => el?.name == `${caseName} JOKER`) : null;
- const thisCase = config?.showJokerOdds && jokerCase && jokerCase?.length ? jokerCase : cases?.filter(el => el?.name == caseName);
- if(!thisCase || !thisCase?.length) return;
- if (thisCase[0]?.goldProfit !== undefined) {
- const profit = thisCase[0]?.goldProfit;
- if(profit <= 11111111)
- odds = `0/5`;
- else if(profit <= 13209876)
- odds = `0.5/5`;
- else if(profit <= 15308641)
- odds = `1/5`;
- else if(profit <= 17407407)
- odds = `1.5/5`;
- else if(profit <= 19506172)
- odds = `2/5`;
- else if(profit <= 21604937)
- odds = `2.5/5`;
- else if(profit <= 23703703)
- odds = `3/5`;
- else if(profit <= 25802468)
- odds = `3.5/5`;
- else if(profit <= 27901233)
- odds = `4/5`;
- else if(profit <= 29999999)
- odds = `4.5/5`;
- else
- odds = `5/5`;
- } else
- odds = `${thisCase[0]?.odds}%`;
-
- const isJoker = thisCase[0]?.name?.endsWith(' JOKER') || false;
- const cardEl = $(thisElement)?.find(eventCase ? 'div[data-testid="case-card-price-btn"]' : 'div.absolute.right-3.rounded.bg-navy-900.px-3.text-xs.font-semibold.text-gold-500')
- ?.eq(0);
-
+ const thisCaseArr = config?.showJokerOdds && jokerCase && jokerCase?.length ? jokerCase : cases?.filter(el => el?.name == caseName);
+ const caseData = thisCaseArr?.[0];
+ if(!caseData) return;
+
+ const odds = caseData?.goldProfit !== undefined ? calculateGoldOdds(caseData.goldProfit) : `${caseData?.odds}%`;
+ const isJoker = caseData?.name?.endsWith(' JOKER') || false;
+ const cardEl = $(thisElement)?.find(eventCase ? 'div[data-testid="case-card-price-btn"]' : 'div.absolute.right-3.rounded.bg-navy-900.px-3.text-xs.font-semibold.text-gold-500')?.eq(0);
+
if (init)
$(cardEl).after($(document?.createElement('div'))
?.addClass(eventCase ? 'cardOdds absolute right-3 top-3 rounded bg-navy-900 px-3 py-1.5 text-xs font-semibold text-white' : 'cardOdds absolute right-3 rounded bg-navy-900 px-3 py-1.5 text-xs font-semibold text-gold-500')
?.css({ 'margin-top': eventCase ? '35px' : '45px', 'background': isJoker ? 'rgb(129 72 234)' : 'rgb(23 23 28)' })
- ?.text($(thisElement)?.attr('case-orginal') ? odds : (thisCase[0]?.lang || odds))
+ ?.text($(thisElement)?.attr('case-orginal') ? odds : (caseData?.lang || odds))
);
- $(thisElement)?.find('.cardOdds')?.text($(thisElement)?.attr('case-orginal') ? odds : (thisCase[0]?.lang || odds))
+ $(thisElement)?.find('.cardOdds')?.text($(thisElement)?.attr('case-orginal') ? odds : (caseData?.lang || odds))
$(thisElement)?.find('.cardOdds')?.css({ 'background': isJoker ? 'rgb(129 72 234)' : 'rgb(23 23 28)' })
$(thisElement)?.find('div[data-testid=case-card-badge-btn] p')
@@ -121,12 +111,7 @@ const createCaseOdds = async(config, currentRate, currency, cases, thisElement,
$(thisElement)?.find('div.css-hmmmg1')
?.css({ 'background': isJoker ? 'rgb(129 72 234)' : 'rgb(23 23 28)' })
- const formattedPrice = new Intl.NumberFormat('en-US', {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- }).format(thisCase[0]?.price_USD * currentRate);
-
- const priceText = `${formattedPrice} ${currency}`;
+ const priceText = formatCurrency(caseData?.price_USD * currentRate, currency);
if (isJoker || !init)
$(thisElement)?.find('[data-testid="case-card-price-btn"]')
?.text(priceText);
@@ -138,12 +123,7 @@ const createYTcases = async(currentRate, currency, cases) => {
if(!YTcases || !YTcases?.length) return;
YTcases?.forEach(el => {
- const formattedPrice = new Intl.NumberFormat('en-US', {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- }).format(el?.price_USD * currentRate);
-
- const priceText = `${formattedPrice} ${currency}`;
+ const priceText = formatCurrency(el?.price_USD * currentRate, currency);
$('section#youtubers-cases div.grid.gap-6')?.eq(0)?.append($(document.createElement('div'))
?.addClass("keydrop-plus-ytcases group relative transition-all duration-200 will-change-transform hover:-translate-y-0.5 aspect-[270/375] col-span-2")
?.html(`
`)
diff --git a/js/dailyCaseTimer.js b/js/dailyCaseTimer.js
index 55d6ac9..535471c 100644
--- a/js/dailyCaseTimer.js
+++ b/js/dailyCaseTimer.js
@@ -61,7 +61,7 @@ const createSkinsValueDiv = async() => {
const fetch = await fetchUrl("GET", "https://key-drop.com/en/panel/profil/eq_value");
if(!fetch) return;
- const data = JSON.parse(fetch);
+ const data = fetch;
const skinsValue = `${(data?.fullPrice).toFixed(2).toString().replace('.',',')} ${data?.currency}`;
$('div[data-testid="balance"]')
diff --git a/js/giveawaysList.js b/js/giveawaysList.js
index 0439311..63bea15 100644
--- a/js/giveawaysList.js
+++ b/js/giveawaysList.js
@@ -57,11 +57,13 @@ const createGiveawayListPanel = async() => {
endDate: language?.autogiveaway_endDate,
};
- $('#main-view div.min-h-screen.pb-16 div.container').eq(2)
- .after($(document.createElement('div'))
- .addClass('container giveaway-keydropPlus-info')
- .html(`
`)
- ) //
${panelText?.settings_p2}: 0
${panelText?.settings_a2}
+ $('#main-view div.min-h-screen.pb-16 div.container').eq(2)
+ .after($(document.createElement('div'))
+ .addClass('container giveaway-keydropPlus-info')
+ .html(`
`)
+ ) //
${panelText?.settings_p2}: 0
${panelText?.settings_a2}
+
+ $('#giveawayPagesWrapper').html(`
${panelText?.settings_p6}:
${panelText?.settings_a6}`);
if(autoGiveawayConfig?.winNotification)
$('#notificationSwitch').prop('checked', true);
@@ -74,13 +76,15 @@ const createGiveawayListPanel = async() => {
const autoGiveawayConfigData = await getAutoGiveawayConfigData();
if(!autoGiveawayConfigData) return;
autoGiveawayConfigData.winNotification = e?.target?.checked;
- try { chrome.storage.sync.set({ autoGiveawayConfig: autoGiveawayConfigData }); } catch(e) {};
+ setStorageData('sync', { autoGiveawayConfig: autoGiveawayConfigData });
});
- if(autoGiveawayConfig?.minPrice)
- $('#giveawayMinPrice').val(autoGiveawayConfig?.minPrice);
+ if(autoGiveawayConfig?.minPrice)
+ $('#giveawayMinPrice').val(autoGiveawayConfig?.minPrice);
+ if(autoGiveawayConfig?.pagesToCheck)
+ $('#giveawayPages').val(autoGiveawayConfig?.pagesToCheck);
- $('#autoGiveawayButton').on('click', async() => {
+ $('#autoGiveawayButton').on('click', async() => {
const autoGiveawayConfigData = await getAutoGiveawayConfigData();
const checked = autoGiveawayConfigData?.active;
$('#autoGiveawayButton').removeClass(checked ? 'button-primary' : 'button-light-green');
@@ -88,11 +92,12 @@ const createGiveawayListPanel = async() => {
$('#autoGiveawayButton').text(checked ? panelText?.start : panelText?.disable);
$('#giveawaySearch').css('display', checked ? 'none' : 'block');
$('#main-view div.grid-stack.relative.grid.overflow-hidden').eq(4).css('display', checked ? 'block' : 'none')
- autoGiveawayConfigData.active = !autoGiveawayConfigData?.active;
- autoGiveawayConfigData.minPrice = $('#giveawayMinPrice')?.val();
- try { chrome.storage.sync.set({ autoGiveawayConfig: autoGiveawayConfigData }); } catch(e) {};
- createToast('info', checked ? 'autogiveaway_deactivate' : 'autogiveaway_active');
- });
+ autoGiveawayConfigData.active = !autoGiveawayConfigData?.active;
+ autoGiveawayConfigData.minPrice = $('#giveawayMinPrice')?.val();
+ autoGiveawayConfigData.pagesToCheck = $('#giveawayPages')?.val();
+ setStorageData('sync', { autoGiveawayConfig: autoGiveawayConfigData });
+ createToast('info', checked ? 'autogiveaway_deactivate' : 'autogiveaway_active');
+ });
refreshGiveawaysPanel(panelText);
};
@@ -101,7 +106,7 @@ const refreshGiveawaysPanel = async(panelText) => {
if(!config?.active) return;
const index = await getIndexData();
- let giveawaysHistory = await getStorageData('local', 'giveawaysHistory');
+ let giveawaysHistory = await getStorageData('local', 'giveawaysHistory', []);
const userSkins = await getUserSkinsData(config?.token);
const giveawayWinnersTab = userSkins?.length !== 0 ? userSkins?.filter(el => el?.sourceType == 'giveaway') : [];
@@ -122,7 +127,7 @@ const refreshGiveawaysPanel = async(panelText) => {
if(giveawaysHistory?.length >= 100) {
giveawaysHistory = giveawaysHistory?.slice(1, 100);
- try { chrome.storage.local.set({ giveawaysHistory: giveawaysHistory }); } catch(e) {};
+ setStorageData('local', { giveawaysHistory: giveawaysHistory });
}
// let joinsCount = 20;
@@ -161,7 +166,7 @@ const refreshGiveawaysPanel = async(panelText) => {
$('#autoGiveawayButton').text(panelText?.start);
$('#giveawaySearch').css('display', 'none');
$('#main-view div.grid-stack.relative.grid.overflow-hidden').eq(4).css('display', 'block');
- try { chrome.storage.sync.set({ autoGiveawayConfig: autoGiveawayConfig }); } catch(e) {};
+ setStorageData('sync', { autoGiveawayConfig: autoGiveawayConfig });
}*/
if(autoGiveawayConfig?.active) {
diff --git a/js/joinCaseBattle.js b/js/joinCaseBattle.js
index 952658f..51b564e 100644
--- a/js/joinCaseBattle.js
+++ b/js/joinCaseBattle.js
@@ -66,7 +66,13 @@ const createAutoCaseBattlePanel = async() => {
let lastCaseBattleId;
const findFreeCaseBattle = async(fastCaseBattleConfig) => {
- const fetch = await fetchUrl('GET', 'https://key-drop.app/v2/battle?type=active&page=0&priceFrom=0&priceTo=undefined&searchText=&sort=latest&roundsCount=all', null, true);
+ // Request all active battles without limiting price or round count
+ const fetch = await fetchUrl(
+ 'GET',
+ 'https://key-drop.app/v2/battle?type=active&page=0&priceFrom=0&searchText=&sort=latest',
+ null,
+ true
+ );
if(!fetch || !fetch?.data) return 'end';
let filtered = await fetch?.data?.filter(el => el?.status == 'new' && el?.roundsCount >= fastCaseBattleConfig?.minCaseCount && el?.users?.length == 0 && el?.isFreeBattle == true && (fastCaseBattleConfig?.casesName?.includes(el?.cases[0]?.name) || fastCaseBattleConfig?.casesName?.includes(el?.cases[1]?.name)));
@@ -155,7 +161,7 @@ function autoJoinCaseBattle() {
return createToast('error', 'autoJoinFreeCaseBattle_noPlayers');
if(fastCaseBattleConfig?.casesName?.length <= 0) return createToast('error', 'autoJoinFreeCaseBattle_noCaseName');
- try { chrome.storage.sync.set({ fastCaseBattleConfig: fastCaseBattleConfig }) } catch(e) {};
+ setStorageData('sync', { fastCaseBattleConfig: fastCaseBattleConfig });
fastCaseBattleData = fastCaseBattleConfig;
autoJoinActive = !autoJoinActive;
diff --git a/js/joinGiveaway.js b/js/joinGiveaway.js
index e2ce43c..ee23474 100644
--- a/js/joinGiveaway.js
+++ b/js/joinGiveaway.js
@@ -1,5 +1,6 @@
let giveawayInterval = null;
-const refreshGiveawayTime = 45 * 1000;
+const refreshGiveawayTime = 45 * 1000;
+const getRefreshDelay = () => refreshGiveawayTime + Math.floor(Math.random() * 10 * 1000);
const giveawayStart = async(isFirst) => {
const config = await getConfigData();
@@ -37,7 +38,7 @@ const runAutoGiveaway = async(language, port, currentRate, isFirst) => {
//const waitingTime = (autoGiveawayConfig?.currentGiveaway?.deadlineTimestamp - new Date().getTime()) + Math.floor(Math.random() * 60000) + 60000;
setTimeout(async() => {
return runAutoGiveaway(language, port, currentRate);
- }, refreshGiveawayTime);// waitingTime > 0 ? waitingTime : (15 * 60 * 1000));
+ }, getRefreshDelay());// waitingTime > 0 ? waitingTime : (15 * 60 * 1000));
};
const getGiveawayData = async(language, gConfig, port, token) => {
@@ -71,27 +72,32 @@ const getGiveawayData = async(language, gConfig, port, token) => {
gConfig.currentGiveaway.haveIJoined = false;
gConfig.currentGiveaway.captcha = false;
gConfig.currentGiveaway.maxPrice = null;
- try { chrome.storage.sync.set({ autoGiveawayConfig: gConfig }); } catch(e) {};
+ setStorageData('sync', { autoGiveawayConfig: gConfig });
const giveawaysHistory = await getStorageData('local', 'giveawaysHistory') || [];
giveawaysHistory.push(giveaway);
- try { chrome.storage.local.set({ giveawaysHistory: giveawaysHistory }); } catch(e) {};
+ setStorageData('local', { giveawaysHistory: giveawaysHistory });
return gConfig;
};
const findNewGiveaway = async(gConfig, port, token) => {
- const fetch = JSON.parse(JSON.stringify(await fetchUrl('GET', `https://wss-${port || 2061}.key-drop.com/v1/giveaway//list?type=active&page=0&perPage=5&status=active&sort=latest`, token)));
- if(!fetch || !fetch?.data) return createToast('error', 'error_fetch');
+ const pages = gConfig?.pagesToCheck || 1;
+ let amateurGiveaways = null;
+
+ for(let page = 0; page < pages && !amateurGiveaways; page++) {
+ const fetch = JSON.parse(JSON.stringify(await fetchUrl('GET', `https://wss-${port || 2061}.key-drop.com/v1/giveaway//list?type=active&page=${page}&perPage=5&status=active&sort=latest`, token)));
+ if(!fetch || !fetch?.data) continue;
+ amateurGiveaways = fetch?.data?.find(el => el?.frequency == 'amateur');
+ }
- const amateurGiveaways = fetch?.data?.find(el => el?.frequency == 'amateur');
if(!amateurGiveaways) return createToast('error', 'error_fetch');
gConfig.currentGiveaway.id = amateurGiveaways?.id;
gConfig.currentGiveaway.deadlineTimestamp = amateurGiveaways?.deadlineTimestamp;
gConfig.currentGiveaway.haveIJoined = amateurGiveaways?.haveIJoined;
gConfig.currentGiveaway.maxPrice = amateurGiveaways?.prizes[0]?.price;
- try { chrome.storage.sync.set({ autoGiveawayConfig: gConfig }); } catch(e) {};
+ setStorageData('sync', { autoGiveawayConfig: gConfig });
return gConfig;
};
@@ -111,7 +117,7 @@ const joinGiveaway = async(language, gConfig, token) => {
} else
createToast('error', null, idText, giveawayUrl, `${language?.autogiveaway_error} ${fetch?.message}`);
- try { chrome.storage.sync.set({ autoGiveawayConfig: gConfig }); } catch(e) {};
+ setStorageData('sync', { autoGiveawayConfig: gConfig });
return gConfig;
};
diff --git a/js/main.js b/js/main.js
index f6b92e7..a17a393 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1,3 +1,4 @@
+/* global fetchUrl, getStorageData, setStorageData, clearStorageData */
const active = true;
const version = "F2.11";
const toastCooldown = 4 * 1000
@@ -12,40 +13,13 @@ $('body').append($(document.createElement('div'))
.css({ position: 'fixed', right: 0, 'margin-right': '10px', 'margin-bottom': '11px', bottom: 0, 'z-index': 999 })
);
-const fetchUrl = async(type, url, token, noTime, data) => {
- try {
- const result = await $.ajax({
- type: type,
- url: `${url}${noTime ? '' : `?t=${new Date().getTime()}`}`,
- data: data ? JSON.stringify(data) : '',
- beforeSend: async (xhr) => {
- if(token)
- xhr.setRequestHeader('authorization', `Bearer ${token}`);
- },
- success: function (response, textStatus, jqXHR) {
- if(!response)
- return createToast('error', 'error_fetch');
- return JSON.parse(JSON.stringify(response)) || undefined;
- },
- error: function(error) {
- return;
- }
- });
- return result;
- } catch(e) { if(e?.status == 403) return window?.location?.reload(); };
-};
-
-const getStorageData = async(type, name) => {
- try {
- const storageData =
- (type === 'local' || type === 0) ? await chrome.storage.local.get([name]).then((result) => { return result[name]; })
- : await chrome.storage.sync.get([name]).then((result) => { return result[name] });
- return storageData;
- } catch(e) {
- return;// console.log(e);
- };
-}
+/**
+ * Retrieve user index data from storage or remote endpoint.
+ * Cached values expire after a predefined period.
+ *
+ * @returns {Promise