eg: use NopeCHA extension to solve hcaptcha challenges

20 credits refill every 24h, but should not be needed
even if there are several games to claim every day.
This commit is contained in:
Ralf Vogler 2022-10-06 20:24:23 +02:00
parent f28c465f8f
commit d67fb59355
18 changed files with 461 additions and 5 deletions

View file

@ -23,6 +23,9 @@ const migrateDb = (user) => {
delete db.data.runs;
}
// https://www.nopecha.com extension source from https://github.com/NopeCHA/NopeCHA/releases/tag/0.1.16
const ext = path.resolve('nopecha');
// https://playwright.dev/docs/auth#multi-factor-authentication
const context = await chromium.launchPersistentContext(dirs.browser, {
// chrome will not work in linux arm64, only chromium
@ -36,6 +39,8 @@ const context = await chromium.launchPersistentContext(dirs.browser, {
// don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.'
// '--restore-last-session', // does not apply for crash/killed
'--hide-crash-restore-bubble',
`--disable-extensions-except=${ext}`,
`--load-extension=${ext}`,
],
ignoreDefaultArgs: ['--enable-automation'], // remove default arg that shows the info bar with 'Chrome is being controlled by automated test software.'
});
@ -120,11 +125,12 @@ try {
const captcha = iframe.locator('#h_captcha_challenge_checkout_free_prod iframe');
await captcha.waitFor().then(async () => {
await page.waitForTimeout(2000);
const p = path.resolve(dirs.screenshots, 'epic-games', 'captcha', `${filenamify(datetime())}.png`);
await captcha.screenshot({ path: p });
console.info(' Saved a screenshot of hcaptcha challenge to', p);
console.error(' Got hcaptcha challenge. To avoid it, get a link from https://www.hcaptcha.com/accessibility'); // TODO save this link in config and visit it daily to set accessibility cookie to avoid captcha challenge?
console.info(' Got hcaptcha challenge! NopeCHA extension will likely solve it.')
// await page.waitForTimeout(2000);
// const p = path.resolve(dirs.screenshots, 'epic-games', 'captcha', `${filenamify(datetime())}.png`);
// await captcha.screenshot({ path: p });
// console.info(' Saved a screenshot of hcaptcha challenge to', p);
// console.error(' Got hcaptcha challenge. To avoid it, get a link from https://www.hcaptcha.com/accessibility'); // TODO save this link in config and visit it daily to set accessibility cookie to avoid captcha challenge?
});
await page.waitForSelector('text=Thank you for buying'); // EU: wait, non-EU: wait again = no-op
@ -134,6 +140,7 @@ try {
context.setDefaultTimeout(TIMEOUT);
} catch (e) {
console.log(e);
console.error(' Failed to claim! Try again if NopeCHA timed out. Click the extension to see if you ran out of credits (refill after 24h). To avoid captchas try to get a new IP or set a cookie from https://www.hcaptcha.com/accessibility');
const p = path.resolve(dirs.screenshots, 'epic-games', 'failed', `${game_id}_${filenamify(datetime())}.png`);
await page.screenshot({ path: p, fullPage: true });
db.data[user][game_id].status = 'failed';

1
nopecha/background.js Normal file

File diff suppressed because one or more lines are too long

1
nopecha/hcaptcha.js Normal file
View file

@ -0,0 +1 @@
(async()=>{class d{static time(){return Date.now||(Date.now=()=>(new Date).getTime()),Date.now()}static sleep(t=1e3){return new Promise(e=>setTimeout(e,t))}static async random_sleep(e,t){t=Math.floor(Math.random()*(t-e)+e);return d.sleep(t)}static pad(e){var t=2-String(e).length+1;return 0<t?""+new Array(t).join("0")+e:""+e}static date(){return new Date}static string(e=null){return e=e||d.date(),d.pad(e.getMonth()+1)+`/${d.pad(e.getDate())}/${e.getFullYear()} ${d.pad(e.getHours()%12)}:${d.pad(e.getMinutes())}:${d.pad(e.getSeconds())} `+(12<=e.getHours()?"PM":"AM")}}class p{static exec(e,a){return new Promise(t=>{try{chrome.runtime.sendMessage({method:e,data:a},t)}catch(e){t()}})}}class h{static async fetch(e,t){return p.exec("fetch",{url:e,options:t})}}class g{static INFERENCE_URL="https://api.nopecha.com";static MAX_WAIT_POST=60;static MAX_WAIT_GET=60;static ERRORS={UNKNOWN:9,INVALID_REQUEST:10,RATE_LIIMTED:11,BANNED_USER:12,NO_JOB:13,INCOMPLETE_JOB:14,INVALID_KEY:15,NO_CREDIT:16,UPDATE_REQUIRED:17};static async post({captcha_type:e,task:t,image_urls:a,grid:r,key:n}){for(var i=Date.now(),c=await p.exec("info_tab");!(Date.now()-i>1e3*g.MAX_WAIT_POST);){const u={type:e,task:t,image_urls:a,v:chrome.runtime.getManifest().version,key:n,url:c.url};r&&(u.grid=r);var o=await h.fetch(g.INFERENCE_URL,{method:"POST",body:JSON.stringify(u),headers:{"Content-Type":"application/json"}});try{var s=JSON.parse(o);if("error"in s){if(s.error===g.ERRORS.RATE_LIMITED){await d.sleep(2e3);continue}if(s.error===g.ERRORS.INVALID_KEY)break;if(s.error===g.ERRORS.NO_CREDIT)break;break}var l="id"in s?s.id:s.data;return await g.get({job_id:l,key:n})}catch(e){break}}return{job_id:null,clicks:null}}static async get({key:e,job_id:t}){for(var a=Date.now();!(Date.now()-a>1e3*g.MAX_WAIT_GET);){await d.sleep(500);var r=await h.fetch(g.INFERENCE_URL+`?id=${t}&key=`+e);try{var n=JSON.parse(r);if("error"in n){if(n.error!==g.ERRORS.INCOMPLETE_JOB)return{job_id:t,clicks:null};continue}return{job_id:t,clicks:n.data}}catch(e){break}}return{job_id:t,clicks:null}}}function u(e){const t=e?.style.background?.trim()?.match(/(?!^)".*?"/g);return t&&0!==t.length?t[0].replaceAll('"',""):null}async function y(){let e=document.querySelector("h2.prompt-text")?.innerText?.replace(/\s+/g," ")?.trim();if(!e)return null;var t={"0430":"a","0441":"c","0501":"d","0435":"e","04bb":"h","0456":"i","0458":"j","04cf":"l","03bf":"o","043e":"o","0440":"p","0455":"s","0445":"x","0443":"y","0065":"e","0069":"i","30fc":"一","571f":"士"};const a=[];for(const i of e){var r=function(e,t,a){for(;(""+e).length<a;)e=""+t+e;return e}(i.charCodeAt(0).toString(16),"0",4);r in t?a.push(t[r]):a.push(i)}e=a.join("");var n=function(){let e=document.querySelector(".display-language .text").innerText||window.navigator.userLanguage||window.navigator.language;return e?e=(e=e.toLowerCase()).split("-")[0]:null}();return e=n&&"en"!==n?await p.exec("translate",{from:n,to:"en",text:e}):e}let f=null;async function e(e){if("block"===document.querySelector("div.check")?.style.display)return a=a||!0,void(e.debug&&window.location.reload());a=!1,await d.sleep(e.hcaptcha_open_delay),document.querySelector("#checkbox")?.click()}async function t(e){o=!(o||!function(){const e=document.querySelector(".display-error");return"true"!==e?.getAttribute("aria-hidden")}());n=100;const{task:t,cells:a,urls:r}=await new Promise(o=>{let s=!1;const l=setInterval(async()=>{if(!s){s=!0;var e=await y();if(e){var t=document.querySelector(".challenge-example > .image > .image"),t=u(t);if(t&&""!==t){var a=document.querySelectorAll(".task-image");if(9!==a.length)s=!1;else{const n=[],i=[];for(const c of a){var r=c.querySelector("div.image");if(!r)return void(s=!1);r=u(r);if(!r||""===r)return void(s=!1);n.push(c),i.push(r)}a=JSON.stringify(i);if(f!==a)return f=a,clearInterval(l),s=!1,o({task:e,task_url:t,cells:n,urls:i});s=!1}}else s=!1}else s=!1}},n)});var n,i=d.time(),c=(await g.post({captcha_type:"hcaptcha",task:t,image_urls:r,key:e.key}))["clicks"];if(c){e=e.hcaptcha_solve_delay-(d.time()-i);0<e&&await d.sleep(e);for(let e=0;e<c.length;e++)!1!==c[e]&&"true"!==a[e].getAttribute("aria-pressed")&&a[e].click();await d.sleep(200);try{document.querySelector(".button-submit").click()}catch(e){}}}let a=!1,o=!1;for(;;){await d.sleep(1e3);var r=await p.exec("get_settings");r&&(r.hcaptcha_auto_open&&null!==document.querySelector("div.check")?await e(r):r.hcaptcha_auto_solve&&null!==document.querySelector("h2.prompt-text")&&await t(r))}})();

1
nopecha/hcaptcha_fast.js Normal file
View file

@ -0,0 +1 @@
(async()=>{let a=null,t=!1,r=!1;function n(e,t,r=!1){e&&(r||a!==e)&&(!0===t&&"false"===e.getAttribute("aria-pressed")||!1===t&&"true"===e.getAttribute("aria-pressed"))&&e.click()}document.addEventListener("mousedown",e=>{"false"===e?.target?.parentNode?.getAttribute("aria-pressed")?(t=!0,r=!0):"true"===e?.target?.parentNode?.getAttribute("aria-pressed")&&(t=!0,r=!1),a=e?.target?.parentNode}),document.addEventListener("mouseup",e=>{t=!1,a=null}),document.addEventListener("mousemove",e=>{t&&(a!==e?.target?.parentNode&&null!==a&&n(a,r,!0),n(e?.target?.parentNode,r))})})();

View file

@ -0,0 +1 @@
(()=>{let e;function t(){var e=navigator.language.split("-")[0];for(const t of document.querySelectorAll('script[src*=".hcaptcha.com/1/api.js"]')){const r=new URL(t.src);"en"!==(r.searchParams.get("hl")||e)&&(r.searchParams.set("hl","en"),t.src=r.toString())}}e=new MutationObserver(t),setTimeout(()=>{t(),e.observe(document.head,{childList:!0})},0)})();

BIN
nopecha/icon/128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

BIN
nopecha/icon/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
nopecha/icon/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
nopecha/icon/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

1
nopecha/manifest.json Normal file
View file

@ -0,0 +1 @@
{"name": "NopeCHA: ReCAPTCHA & hCAPTCHA Solver", "action": {"default_title": "NopeCHA: ReCAPTCHA & hCAPTCHA Solver", "default_icon": "icon/16.png", "default_popup": "popup.html"}, "manifest_version": 3, "version": "0.1.16", "description": "Automatically solve CAPTCHAs using AI.", "permissions": ["declarativeNetRequest", "storage", "scripting"], "background": {"service_worker": "background.js"}, "content_scripts": [{"matches": ["*://*.hcaptcha.com/captcha/*"], "js": ["hcaptcha.js"], "all_frames": true, "run_at": "document_end"}, {"matches": ["*://*.hcaptcha.com/captcha/*"], "js": ["hcaptcha_fast.js"], "all_frames": true, "run_at": "document_start"}, {"matches": ["<all_urls>"], "js": ["recaptcha.js", "recaptcha_voice.js"], "all_frames": true, "run_at": "document_end"}, {"matches": ["<all_urls>"], "js": ["hcaptcha_language.js"], "all_frames": true, "run_at": "document_end"}, {"matches": ["*://*.google.com/recaptcha/*", "*://*.recaptcha.net/recaptcha/*", "*://recaptcha.net/recaptcha/*"], "js": ["recaptcha_fast.js"], "all_frames": true, "run_at": "document_start"}, {"matches": ["*://nopecha.com/setup"], "js": ["setup.js"], "all_frames": true, "run_at": "document_end"}], "host_permissions": ["<all_urls>"], "icons": {"16": "icon/16.png", "32": "icon/32.png", "48": "icon/48.png", "128": "icon/128.png"}}

289
nopecha/popup.css Normal file
View file

@ -0,0 +1,289 @@
:root {
--input_scale_x: 1;
--input_scale_y: 0.8;
}
html * {
font-family: monospace, monospaSFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 12px;
}
html, body {
margin: 0;
padding: 0;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.hidden {
display: none !important;
opacity: 0;
}
.light {
font-size: 0.9em;
opacity: 0.5;
}
.green {
/* color: #8cd47e; */
color: #1a73e8;
}
.red {
color: #ff6961;
}
.yellow {
color: #ca1;
}
.clickable {
cursor: pointer;
transition: 250ms all;
}
.clickable:hover {
opacity: 0.8;
}
#main {
padding: 8px 16px;
}
#footer {
margin-top: 8px;
width: 100%;
text-align: center;
color: #999;
height: 20px;
}
#manage {
width: 100%;
text-align: center;
background-color: #1a73e8;
color: #fff;
height: 20px;
line-height: 20px;
border-radius: 4px;
border: 1px solid #1a73e8;
padding: 8px;
font-size: 1.2em;
transition: 200ms all;
}
#manage:hover {
color: #1a73e8;
background-color: transparent;
}
.vspace {
min-height: 8px;
}
.settings_group {
width: 280px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
padding: 6px 4px;
}
.settings_group.vertical {
flex-direction: column;
}
.settings_group > .label {
flex-grow: 1;
font-size: 1.2em;
line-height: calc(34px * var(--input_scale_y));
padding-right: 16px;
}
.settings_group > .value {
font-size: 1.2em;
line-height: calc(34px * var(--input_scale_y));
}
.settings_group > input {
border-radius: 0;
}
.settings_group > input[type="text"],
.settings_group > input[type="button"],
.settings_group > select {
font-size: 0.9em;
outline: none;
border: 1px solid #999;
width: calc(60px * var(--input_scale_x));
height: calc(34px * var(--input_scale_y));
}
.settings_group > input[type="button"] {
background-color: #f0f0f0;
cursor: pointer;
transition: 200ms all;
}
.settings_group > input[type="button"]:hover {
background-color: #fff;
}
.switch {
position: relative;
display: inline-block;
width: calc(60px * var(--input_scale_x));
height: calc(34px * var(--input_scale_y));
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: calc(26px * var(--input_scale_y));
width: calc(26px * var(--input_scale_x));
left: calc(4px * var(--input_scale_x));
bottom: calc(4px * var(--input_scale_y));
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(calc(26px * var(--input_scale_x)));
-ms-transform: translateX(calc(26px * var(--input_scale_x)));
transform: translateX(calc(26px * var(--input_scale_x)));
}
#key {
padding: 4px;
border-radius: 2px;
}
.loading {
display: inline-block;
position: relative;
width: 40px;
height: 100%;
}
.loading div {
position: absolute;
top: 8px;
width: 6px;
height: 6px;
border-radius: 50%;
background: #777;
animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
.loading div:nth-child(1) {
left: 4px;
animation: loading1 0.6s infinite;
}
.loading div:nth-child(2) {
left: 4px;
animation: loading2 0.6s infinite;
}
.loading div:nth-child(3) {
left: 16px;
animation: loading2 0.6s infinite;
}
.loading div:nth-child(4) {
left: 28px;
animation: loading3 0.6s infinite;
}
@keyframes loading1 {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes loading3 {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes loading2 {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(12px, 0);
}
}
.tab_btn_row {
background-color: #efefef;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.tab_btn_row .tab_btn {
flex-grow: 1;
padding: 4px 8px;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
border-right: 1px solid transparent;
border-bottom: 1px solid #ccc;
border-radius: 4px 4px 0 0;
text-align: center;
font-size: 1.2em;
transition: 200ms all;
}
.tab_btn:not(.active):hover {
background-color: #fafafa;
}
.tab_btn.active {
background-color: #fff;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid transparent;
}
.content {
margin: 6px 0;
padding: 4px 8px 0 8px;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.tab_content.bordered {
padding: 16px 8px 8px 8px;
border-top: 1px solid transparent;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-radius: 0 0 4px 4px;
}
.footer_group {
width: 296px;
}
.warning_box {
border-color: #FCD62E;
border-radius: 0.25rem;
border-width: 0.125rem;
padding: 0 0.5rem;
margin: 0 4px;
background-color: #FEF9C3;
border-style: solid;
}

149
nopecha/popup.html Normal file
View file

@ -0,0 +1,149 @@
<html>
<head>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<!-- <div id="template" class="hidden">
<div class="loading"><div></div><div></div><div></div><div></div></div>
</div> -->
<div id="main">
<!-- <div class="settings_group">
<div class="label">Server Status</div>
<div id="server_status" class="value green">
<div class="loading"><div></div><div></div><div></div><div></div></div>
</div>
</div> -->
<div class="content">
<div class="settings_group">
<div id="manage" class="clickable">Manage Subscription</div>
</div>
<div class="settings_group vertical">
<input id="key" type="text" placeholder="Subscription Key" style="width: 280px;">
<div id="incorrect_key" class="red hidden">Incorrect Key</div>
</div>
<div id="ipbanned_warning" class="warning_box hidden">
<p>
Your IP has been flagged and is therefore illegible for free credits.
</p>
<p>
<a href="https://nopecha.com/pricing" target="_blank">Paid subscriptions</a> are not affected by this.
</p>
</div>
<div class="settings_group">
<div class="label">Subscription</div>
<div id="plan" class="value green">
<div class="loading"><div></div><div></div><div></div><div></div></div>
</div>
</div>
<div class="settings_group">
<div class="label">Credits</div>
<div id="credit" class="value">
<div class="loading"><div></div><div></div><div></div><div></div></div>
</div>
</div>
<div class="settings_group">
<div class="label">Refills</div>
<div id="refills" class="value green">
<div class="loading"><div></div><div></div><div></div><div></div></div>
</div>
</div>
</div>
<div class="vspace"></div>
<div class="tab_btn_row">
<div class="tab_btn active" data-target="#hcaptcha_tab">hCaptcha</div>
<div class="tab_btn" data-target="#recaptcha_tab">reCAPTCHA</div>
</div>
<div class="tab_content bordered">
<div id="hcaptcha_tab" class="tab">
<div class="settings_group">
<div class="label">Auto Solve</div>
<label class="switch">
<input id="hcaptcha_auto_solve" type="checkbox" data-disables="hcaptcha_solve_delay">
<span class="slider"></span>
</label>
</div>
<div class="settings_group">
<div class="label">Solve Delay <span class="light">(ms)</span></div>
<input id="hcaptcha_solve_delay" type="text" class="number">
</div>
<div class="settings_group">
<div class="label">Auto Open</div>
<label class="switch">
<input id="hcaptcha_auto_open" type="checkbox" data-disables="hcaptcha_open_delay">
<span class="slider"></span>
</label>
</div>
<div class="settings_group">
<div class="label">Open Delay <span class="light">(ms)</span></div>
<input id="hcaptcha_open_delay" type="text" class="number">
</div>
</div>
<div id="recaptcha_tab" class="tab hidden">
<div class="settings_group">
<div class="label">Auto Solve</div>
<label class="switch">
<input id="recaptcha_auto_solve" type="checkbox" data-disables="recaptcha_solve_delay,recaptcha_solve_method">
<span class="slider"></span>
</label>
</div>
<div class="settings_group">
<div class="label">Solve Delay <span class="light">(ms)</span></div>
<input id="recaptcha_solve_delay" type="text" class="number">
</div>
<div class="settings_group">
<div class="label">Auto Open</div>
<label class="switch">
<input id="recaptcha_auto_open" type="checkbox" data-disables="recaptcha_open_delay">
<span class="slider"></span>
</label>
</div>
<div class="settings_group">
<div class="label">Open Delay <span class="light">(ms)</span></div>
<input id="recaptcha_open_delay" type="text" class="number">
</div>
<div class="settings_group">
<div class="label">ReCAPTCHA Method</div>
<select id="recaptcha_solve_method">
<option value="image" selected>Image</option>
<option value="voice">Voice</option>
</select>
</div>
</div>
</div>
<!-- <div class="settings_group footer_group">
<div class="label">Debug</div>
<label class="switch">
<input id="debug" type="checkbox">
<span class="slider"></span>
</label>
</div> -->
<div class="settings_group footer_group">
<div id="footer" class="clickable">Join us on Discord</div>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>

1
nopecha/popup.js Normal file
View file

@ -0,0 +1 @@
Date.now||(Date.now=function(){return(new Date).getTime()});class BG{static exec(t,n){return new Promise(e=>{try{chrome.runtime.sendMessage({method:t,data:n},e)}catch{e()}})}}class Util{static sleep(t){return new Promise(e=>setTimeout(e,t))}static pad_left(e,t,n){for(;(""+e).length<n;)e=""+t+e;return e}static time_to_hms(e){e=Math.max(0,e);var t=Math.floor(e/3600),n=(e%=3600,Math.floor(e/60)),e=Math.floor(e%60);return`${Util.pad_left(t,"0",2)}:${Util.pad_left(n,"0",2)}:`+Util.pad_left(e,"0",2)}static capitalize(e){return e.charAt(0).toUpperCase()+e.slice(1)}}let plan=null,checking_server_plan=!1,rendering_server_plan=!1;async function check_plan(){var e=await BG.exec("get_settings");e&&!checking_server_plan&&(checking_server_plan=!0,(plan=await BG.exec("get_server_plan",{key:e.key})).error&&(plan={plan:plan.message,credit:0,quota:0,duration:null,lastreset:null}),checking_server_plan=!1)}async function initialize_ui(){var e=await BG.exec("get_settings");async function t(e,t){const n=document.querySelector(`input#${e}[type="checkbox"]`);if(n){var a=n.dataset?.disables?.split(",");if(a)for(const i of a){const r=document.querySelector("#"+i);r.disabled=!t}n.checked=t,await BG.exec("set_settings",{id:e,value:t})}}async function n(e,t){const n=document.querySelector(`input#${e}[type="text"]`);if(n){try{t=t.trim()}catch{}if(n.classList.contains("number")){try{t=parseInt(t)}catch{t=0}999999<(t=(t=isNaN(t)?0:t)<0?0:t)&&(t=999999)}n.value=t,await BG.exec("set_settings",{id:e,value:t})}}async function a(e,t){const n=document.querySelector("select#"+e);n&&(n.value=t,await BG.exec("set_settings",{id:e,value:t}))}for(const r in e)try{await t(r,e[r]),await n(r,e[r]),await a(r,e[r])}catch{}for(const s of document.querySelectorAll('.settings_group input[type="checkbox"]'))s.addEventListener("change",()=>t(s.id,s.checked));for(const c of document.querySelectorAll('.settings_group input[type="text"]'))c.addEventListener("input",()=>n(c.id,c.value));for(const l of document.querySelectorAll(".settings_group select"))l.addEventListener("change",()=>a(l.id,l.value));document.querySelector("#manage").addEventListener("click",async()=>{await BG.exec("open_tab",{url:"https://nopecha.com/manage"})}),document.querySelector("#footer").addEventListener("click",async()=>{await BG.exec("open_tab",{url:"https://nopecha.com/discord"})});let i=null;document.querySelector("#key").addEventListener("input",()=>{clearTimeout(i),i=setTimeout(check_plan,500)});for(const d of document.querySelectorAll(".tab_btn")){d.dataset.target;d.addEventListener("click",()=>{for(const e of document.querySelectorAll(".tab"))e.classList.add("hidden");for(const t of document.querySelectorAll(".tab_btn"))t.classList.remove("active");d.classList.add("active"),document.querySelector(d.dataset.target).classList.remove("hidden")})}}async function render_plan(){var t=await BG.exec("get_settings");if(t&&plan&&!rendering_server_plan){rendering_server_plan=!0;const a=document.querySelector("#plan"),i=document.querySelector("#credit"),r=document.querySelector("#refills"),s=document.querySelector("#incorrect_key"),c=document.querySelector("#ipbanned_warning");var n=Date.now()/1e3;let e=null;plan.lastreset&&plan.duration&&(e=Math.floor(Math.max(0,plan.duration-(n-plan.lastreset)))),a.innerHTML=plan.plan,"free"===plan.plan?(""!==t.key?s.classList.remove("hidden"):s.classList.add("hidden"),a.classList.remove("green"),a.classList.add("red")):(s.classList.add("hidden"),a.classList.remove("red"),a.classList.add("green")),plan.plan.includes("Banned")?c.classList.remove("hidden"):c.classList.add("hidden"),0===e?(i.classList.remove("green"),i.classList.remove("red"),i.innerHTML='<div class="loading"><div></div><div></div><div></div><div></div></div>'):(i.innerHTML=plan.credit+" / "+plan.quota,0===plan.credit?(i.classList.remove("green"),i.classList.add("red")):(i.classList.remove("red"),i.classList.add("green"))),e?(n=Util.time_to_hms(e),r.innerHTML=""+n):r.innerHTML='<div class="loading"><div></div><div></div><div></div><div></div></div>',0!==plan.duration&&0===e&&await check_plan(),rendering_server_plan=!1}}async function main(){await initialize_ui(),await check_plan(),await render_plan(),setInterval(render_plan,250)}document.addEventListener("DOMContentLoaded",main);

1
nopecha/recaptcha.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
(async()=>{let i=null,n=!1,s=!1;function a(e){let t=e;for(;t&&!t.classList?.contains("rc-imageselect-tile");)t=t.parentNode;return t}function t(e,t,n=!1){!e||!n&&i===e||(!0===t&&e.classList.contains("rc-imageselect-tileselected")||!1===t&&!e.classList.contains("rc-imageselect-tileselected"))&&e.click()}document.addEventListener("mousedown",e=>{const t=a(e?.target);t&&(s=t.classList.contains("rc-imageselect-tileselected")?n=!0:!(n=!0),i=t)}),document.addEventListener("mouseup",e=>{n=!1,i=null}),document.addEventListener("mousemove",e=>{e=a(e?.target);n&&(i!==e&&null!==i&&t(i,s,!0),t(e,s))});window.addEventListener("load",function(e){const t=document.body.appendChild(document.createElement("style")).sheet;t.insertRule(".rc-imageselect-table-33, .rc-imageselect-table-42, .rc-imageselect-table-44 {transition-duration: 0.5s !important}",0),t.insertRule(".rc-imageselect-tile {transition-duration: 2s !important}",1),t.insertRule(".rc-imageselect-dynamic-selected {transition-duration: 1s !important}",2),t.insertRule(".rc-imageselect-progress {transition-duration: 0.5s !important}",3),t.insertRule(".rc-image-tile-overlay {transition-duration: 0.5s !important}",4),t.insertRule("#rc-imageselect img {pointer-events: none !important}",5)})})();

View file

@ -0,0 +1 @@
(async()=>{class r{static time(){return Date.now||(Date.now=()=>(new Date).getTime()),Date.now()}static sleep(t=1e3){return new Promise(e=>setTimeout(e,t))}static async random_sleep(e,t){t=Math.floor(Math.random()*(t-e)+e);return r.sleep(t)}static pad(e){var t=2-String(e).length+1;return 0<t?""+new Array(t).join("0")+e:""+e}static date(){return new Date}static string(e=null){return e=e||r.date(),r.pad(e.getMonth()+1)+`/${r.pad(e.getDate())}/${e.getFullYear()} ${r.pad(e.getHours()%12)}:${r.pad(e.getMinutes())}:${r.pad(e.getSeconds())} `+(12<=e.getHours()?"PM":"AM")}}class n{static exec(e,a){return new Promise(t=>{try{chrome.runtime.sendMessage({method:e,data:a},t)}catch(e){t()}})}}class o{static async fetch(e,t){return n.exec("fetch",{url:e,options:t})}}function i(){var e,t;if(!l())return e="true"===document.querySelector(".recaptcha-checkbox")?.getAttribute("aria-checked"),t=document.querySelector("#recaptcha-verify-button")?.disabled,e||t}function l(){return"Try again later"===document.querySelector(".rc-doscaptcha-header")?.innerText}async function e(e){i()||(await r.sleep(e.recaptcha_open_delay),document.querySelector("#recaptcha-anchor")?.click())}async function t(t){var a=await n.exec("get_cache",{name:"recaptcha_visible",tab_specific:!0});if(!0===a&&!i())if(l())await n.exec("reset_recaptcha");else{a=document.querySelector(".rc-audiochallenge-tdownload-link")?.href,a=(fetch(a),document.querySelector("#audio-source")?.src?.replace("recaptcha.net","google.com"));let e=document.querySelector("html")?.getAttribute("lang")?.trim();e&&0!==e.length||(e="en");var c=r.time(),a=await o.fetch("https://engageub.pythonanywhere.com",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"input="+encodeURIComponent(a)+"&lang="+e}),a=(document.querySelector("#audio-response").value=a,t.recaptcha_solve_delay-(r.time()-c));0<a&&await r.sleep(a),document.querySelector("#recaptcha-verify-button")?.click()}}for(;;){await r.sleep(1e3);var a=await n.exec("get_settings");a&&"voice"===a.recaptcha_solve_method&&(async function(){var t=document.querySelectorAll('iframe[src*="/recaptcha/api2/bframe"]');if(0<t.length){let e=!1;for(const a of t)if(e="visible"===window.getComputedStyle(a).visibility)break;e?await n.exec("set_cache",{name:"recaptcha_visible",value:!0,tab_specific:!0}):await n.exec("set_cache",{name:"recaptcha_visible",value:!1,tab_specific:!0})}}(),a.recaptcha_auto_open&&null!==document.querySelector(".recaptcha-checkbox")?await e(a):a.recaptcha_auto_solve&&null!==document.querySelector(".rc-imageselect-instructions")?(c=a,await(!0===await n.exec("get_cache",{name:"recaptcha_visible",tab_specific:!0})&&!i()&&(await r.sleep(c.recaptcha_open_delay),!document.querySelector("#recaptcha-audio-button")?.click()))):!a.recaptcha_auto_solve||null===document.querySelector("#audio-instructions")&&null===document.querySelector(".rc-doscaptcha-header")||await t(a))}var c})();

1
nopecha/setup.js Normal file
View file

@ -0,0 +1 @@
const url=new URL(document.location);class BG{static exec(e,n){return new Promise(t=>{try{chrome.runtime.sendMessage({method:e,data:n},t)}catch(e){t()}})}}document.location.hash?(document.body.innerText="Loading...",BG.exec("set_settings",{id:"key",value:document.location.hash.substring(1)}).then(()=>document.body.innerText="Key set!")):document.body.innerText="Missing key. Please set the hash and reload the page.\nExample: https://nopecha.com/setup#sub_testkey1234";

1
nopecha/utils.js Normal file
View file

@ -0,0 +1 @@
"use strict";class Type{static _string_constructor="string".constructor;static _array_constructor=[].constructor;static _object_constructor={}.constructor;static of(e){return null===e?"null":void 0===e?"undefined":e.constructor===Type._string_constructor?"string":e.constructor===Type._array_constructor?"array":e.constructor===Type._object_constructor?"object":""}}class Logger{static debug=!0;static log(e=0){const t=new Array(...arguments).map(e=>["array","object"].includes(Type.of(e))?JSON.stringify(e,null,4):""+e);t.join(" ")}}class Time{static time(){return Date.now||(Date.now=()=>(new Date).getTime()),Date.now()}static sleep(t=1e3){return new Promise(e=>setTimeout(e,t))}static async random_sleep(e,t){t=Math.floor(Math.random()*(t-e)+e);return Time.sleep(t)}static pad(e){var t=2-String(e).length+1;return 0<t?""+new Array(t).join("0")+e:""+e}static date(){return new Date}static string(e=null){return e=e||Time.date(),Time.pad(e.getMonth()+1)+`/${Time.pad(e.getDate())}/${e.getFullYear()} ${Time.pad(e.getHours()%12)}:${Time.pad(e.getMinutes())}:${Time.pad(e.getSeconds())} `+(12<=e.getHours()?"PM":"AM")}}class BG{static exec(e,r){return new Promise(t=>{try{chrome.runtime.sendMessage({method:e,data:r},t)}catch(e){t()}})}}class Net{static async fetch(e,t){return BG.exec("fetch",{url:e,options:t})}}class Image{static encode(t){return new Promise(r=>{if(null===t)return r(null);const e=new XMLHttpRequest;e.onload=()=>{const t=new FileReader;t.onloadend=()=>{let e=t.result;if(e.startsWith("data:text/html;base64,"))return r(null);e=e.replace("data:image/jpeg;base64,",""),r(e)},t.readAsDataURL(e.response)},e.onerror=()=>{r(null)},e.onreadystatechange=()=>{4==this.readyState&&200!=this.status&&r(null)},e.open("GET",t),e.responseType="blob",e.send()})}}class NopeCHA{static INFERENCE_URL="https://api.nopecha.com";static MAX_WAIT_POST=60;static MAX_WAIT_GET=60;static ERRORS={UNKNOWN:9,INVALID_REQUEST:10,RATE_LIIMTED:11,BANNED_USER:12,NO_JOB:13,INCOMPLETE_JOB:14,INVALID_KEY:15,NO_CREDIT:16,UPDATE_REQUIRED:17};static async post({captcha_type:e,task:t,image_urls:r,grid:a,key:n}){for(var o=Date.now(),s=await BG.exec("info_tab");!(Date.now()-o>1e3*NopeCHA.MAX_WAIT_POST);){const u={type:e,task:t,image_urls:r,v:chrome.runtime.getManifest().version,key:n,url:s.url};a&&(u.grid=a);var i=await Net.fetch(NopeCHA.INFERENCE_URL,{method:"POST",body:JSON.stringify(u),headers:{"Content-Type":"application/json"}});try{var c=JSON.parse(i);if("error"in c){if(c.error===NopeCHA.ERRORS.RATE_LIMITED){await Time.sleep(2e3);continue}if(c.error===NopeCHA.ERRORS.INVALID_KEY)break;if(c.error===NopeCHA.ERRORS.NO_CREDIT)break;break}var l="id"in c?c.id:c.data;return await NopeCHA.get({job_id:l,key:n})}catch(e){break}}return{job_id:null,clicks:null}}static async get({key:e,job_id:t}){for(var r=Date.now();!(Date.now()-r>1e3*NopeCHA.MAX_WAIT_GET);){await Time.sleep(500);var a=await Net.fetch(NopeCHA.INFERENCE_URL+`?id=${t}&key=`+e);try{var n=JSON.parse(a);if("error"in n){if(n.error!==NopeCHA.ERRORS.INCOMPLETE_JOB)return{job_id:t,clicks:null};continue}return{job_id:t,clicks:n.data}}catch(e){break}}return{job_id:t,clicks:null}}}function oep(a,n=1,e=100){return new Promise(t=>{const r=setInterval(()=>{var e=document.querySelectorAll(a);if(e.length===n)return clearInterval(r),t(1===n?e[0]:e)},e)})}export{Type,Logger,Time,BG,Net,Image,NopeCHA,oep};