Last active
January 28, 2025 08:47
-
-
Save Bizarrus/f05f3b2b930855087957131c5030f468 to your computer and use it in GitHub Desktop.
K3-Register
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import FileSystem from 'node:fs'; | |
import HTTPS from 'node:https'; | |
import { parse as HTMLParser } from 'node-html-parser'; | |
export default (new class ClientProperties { | |
File = './client.json'; | |
BaseURL = 'https://app.knuddels.de/'; | |
Properties = { | |
build: null, | |
version: null, | |
platform: 'Web', | |
type: 'K3GraphQl', | |
browser: { | |
name: 'Firefox', | |
version: 132, | |
useragent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0' | |
}, | |
urls: { | |
login: 'https://www.knuddels.de/logincheck.html', | |
graph: null, | |
subscription: null, | |
origin: 'https://app.knuddels.de', | |
referer: 'https://app.knuddels.de', | |
photo: { | |
login: { | |
page: 'https://photo.knuddels.de/photos-login.html?d=knuddels.de', | |
action: 'https://photo.knuddels.de/photos-login_submit.html' | |
}, | |
upload: { | |
page: 'https://photo.knuddels.de/photos-settings.html?mode=uploadprofilephoto', | |
action: 'https://upload.knuddels.de' | |
}, | |
delete: 'https://photo.knuddels.de/photos-delete.html?id=' | |
}, | |
register: { | |
check: 'https://www.knuddels.de/registration/registration_submit.html', | |
origin: 'https://www.knuddels.de', | |
} | |
} | |
}; | |
constructor() { | |
if(this.exists()) { | |
try { | |
this.Properties = Object.assign({}, this.Properties, JSON.parse(FileSystem.readFileSync(this.File, 'utf8'))); | |
//console.log('Loaded ClientProperties:', this.Properties); | |
} catch(error) { | |
console.warn('Can\'t parse', this.File, ':', error); | |
} | |
} | |
} | |
exists() { | |
return FileSystem.existsSync(this.File); | |
} | |
resolve() { | |
console.log('Trying to resolve ClientProperties from ' + this.BaseURL + '...'); | |
return new Promise((success, failure) => { | |
this.requesting(this.BaseURL, (data) => { | |
const document = HTMLParser(data); | |
const scripts = document.getElementsByTagName('script'); | |
let found = null; | |
scripts.forEach((script) => { | |
let src = script.getAttribute('src'); | |
if(src.match(/index\-([a-zA-Z0-9]+)\.js/g)) { | |
found = src; | |
} | |
}); | |
if(found === null) { | |
failure('Can\'t found main-script on ' + this.BaseURL); | |
return; | |
} | |
this.requesting(this.BaseURL + found, (data) => { | |
let build = null; | |
let version = null; | |
let url_graph = null; | |
let url_subscr = null; | |
if(data.match(/(gitRevision):"([^"]+)",(version):"([^"]+)"/gi)) { | |
const matches = /(gitRevision):"([^"]+)",(version):"([^"]+)"/gi.exec(data); | |
build = matches[2]; | |
version = matches[4]; | |
} else { | |
failure('Can\'t found Revision or Version on main-script'); | |
return; | |
} | |
if(data.match(/(graphQl):"([^"]+)"/gi)) { | |
const matches = /(graphQl):"([^"]+)"/gi.exec(data); | |
url_graph = matches[2]; | |
} else { | |
failure('Can\'t found graphQl on main-script'); | |
return; | |
} | |
if(data.match(/(graphQlSubscription):"([^"]+)"/gi)) { | |
const matches = /(graphQlSubscription):"([^"]+)"/gi.exec(data); | |
url_subscr = matches[2]; | |
} else { | |
failure('Can\'t found graphQlSubscription on main-script'); | |
return; | |
} | |
if(build !== null) { | |
this.Properties.build = build; | |
} | |
if(version !== null) { | |
this.Properties.version = version; | |
} | |
if(url_graph !== null) { | |
this.Properties.urls.graph = url_graph; | |
} | |
if(url_subscr !== null) { | |
this.Properties.urls.subscription = url_subscr; | |
} | |
//console.log('Updated ClientProperties:', this.Properties); | |
FileSystem.writeFile(this.File, JSON.stringify(this.Properties, null, 4), (error) => { | |
if(error) { | |
console.error('Can\'t save', this.File, ':', error); | |
return; | |
} | |
console.warn(this.File, 'was saved on root-directory!'); | |
}); | |
success(); | |
}); | |
}); | |
}); | |
} | |
requesting(file, callback) { | |
HTTPS.get(file, (response) => { | |
let data = ''; | |
response.on('data', (chunk) => { | |
data += chunk; | |
}); | |
response.on('end', () => { | |
callback(data); | |
}); | |
}).on('error', (error) => { | |
console.log('HTTP-Error:', error.message); | |
}) | |
} | |
get(key) { | |
if(key.indexOf('.') !== -1) { | |
return key.split('.').reduce((current, key) => current && current[key], this.Properties); | |
} | |
if(typeof(this.Properties[key]) !== 'undefined') { | |
return this.Properties[key]; | |
} | |
return null; | |
} | |
}()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
npm install --save puppeteer-extra puppeteer puppeteer-extra-plugin-stealth node-html-parser |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import HTTPS from 'node:https'; | |
import ClientProperties from '../ClientProperties.class.js'; | |
import puppeteer from 'puppeteer-extra'; | |
import { executablePath } from 'puppeteer'; | |
import pluginStealth from 'puppeteer-extra-plugin-stealth'; | |
import FileSystem from 'node:fs'; | |
import Readline from 'node:readline'; | |
import Process from 'node:process'; | |
export const Register = (new class Register { | |
RecaptchaKey = '6LcTjIoUAAAAAD0Xd19UnkbArq-qb2nQWdFiG6IX'; | |
checkNick(nickname) { | |
return this.request({ | |
submitElement: 'nick', | |
nick: nickname, | |
resultAsJSON: true, | |
isAjax: true | |
}); | |
} | |
registerNick(nickname, password, age, gender) { | |
return new Promise((success, failure) => { | |
let data = { | |
submitElement: 'fullRegV1', | |
nick: nickname, | |
password: password, | |
age: age, | |
dsgvoQuestion: true, | |
category: 'chat', | |
platform: 'web', | |
flags: 'RegistrationEroticContentDecision_Hide', | |
gender: gender, | |
uids: '', | |
resultAsJSON: true, | |
isAjax: true | |
}; | |
this.startRecaptchaInjector(this.RecaptchaKey).then((token) => { | |
data.recaptchaToken = token; | |
this.request(data).then((response) => { | |
console.log("REG", response); | |
//success(); @ToDo? | |
}).catch((error) => { | |
switch(error.code) { | |
case 'VERIFICATION_REQUIRED': | |
this.createVerify(data); | |
break; | |
default: | |
failure(error); | |
break; | |
} | |
}); | |
}).catch(failure); | |
}); | |
} | |
createVerify(regdata, number) { | |
if(typeof(number) !== 'undefined') { | |
this.receiveCode(regdata, number); | |
return; | |
} | |
this.CLI.question('Knuddels need a verified Telephone-Number.\nPlease enter your Telephone Number (Sample: +491234567890):', telephone => { | |
this.receiveCode(regdata, telephone); | |
}); | |
} | |
receiveCode(regdata, telephone) { | |
this.request({ | |
submitElement: 'phone-verify', | |
phoneNumber: telephone, | |
regionCode: 'DE', | |
resultAsJSON: true, | |
isAjax: true | |
}).then((phoneid) => { | |
this.validateVerify(regdata, phoneid); | |
}).catch((error) => { | |
switch(error.code) { | |
case 'PHONE_NUMBER_INVALID': | |
console.error('The entered Telephone Number is invalid!'); | |
this.createVerify(regdata); | |
break; | |
case 'PHONE_NUMBER_QUOTA_EXCEEDED': | |
console.error('You have entered the wrong phone number too often!\nTry again later!'); | |
this.CLI.close(); | |
break; | |
case 'PHONE_NUMBER_COUNTRY_BLOCKED': | |
console.error('The Country of entered Telephone Number is BLOCKED!'); | |
this.createVerify(regdata); | |
break; | |
case 'PHONE_NUMBER_OF_BLOCKED_USER_SOFT': | |
console.error('The entered Telephone Number has already an User registred and these is temporary BLOCKED!'); | |
this.createVerify(regdata); | |
break; | |
case 'PHONE_NUMBER_OF_BLOCKED_USER_HARD': | |
console.error('The entered Telephone Number has already an User registred and these is permanently BLOCKED!'); | |
this.createVerify(regdata); | |
break; | |
case 'VERIFICATION_CODE_WRONG': | |
console.error('The Code is Wrong!'); | |
this.validateVerify(regdata, error.phoneid); | |
break; | |
case 'VERIFICATION_CODE_EXPIRED': | |
console.error('The Code is Expired!'); | |
this.createVerify(regdata, telephone); | |
break; | |
case 'VERIFICATION_TOO_MANY_RETRIES': | |
console.error('You have tried the verificationtoo often!\nTry again later!'); | |
this.CLI.close(); | |
break; | |
default: | |
console.log(error); | |
break; | |
} | |
}); | |
} | |
validateVerify(regdata, phoneid) { | |
this.CLI.question('Enter Verification-Code:', code => { | |
this.startRecaptchaInjector(this.RecaptchaKey).then((token) => { | |
regdata.recaptchaToken = token; | |
regdata.phoneVerificationRegId = phoneid | |
regdata.phoneVerificationCode = code; | |
this.request(regdata).then((nickname) => { | |
console.log("REG Finished:", nickname); | |
}).catch((error) => { | |
switch(error.code) { | |
case 'VERIFICATION_REQUIRED': | |
this.createVerify(regdata); | |
break; | |
default: | |
console.log("Error: ", error); | |
break; | |
} | |
}); | |
}).catch((error) => { | |
console.log("Error: ", error); | |
}); | |
}); | |
} | |
request(data) { | |
return new Promise((success, failure) => { | |
let body = new URLSearchParams(data).toString(); | |
let request = HTTPS.request(ClientProperties.get('urls.register.check'), { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', | |
'Content-Length': body.length, | |
'Accept': 'application/json', | |
'Origin': ClientProperties.get('urls.register.origin'), | |
'Referer': ClientProperties.get('urls.referer'), | |
'User-Agent': ClientProperties.get('browser.useragent'), | |
'X-Requested-With': 'XMLHttpRequest' | |
}, | |
}, (response) => { | |
let data = ''; | |
response.on('data', (chunk) => { | |
data += chunk; | |
}); | |
response.on('end', () => { | |
console.log(data); | |
try { | |
let json = JSON.parse(data); | |
if(typeof(json.errors) !== 'undefined') { | |
failure({ | |
code: json.errors[0].errorType, | |
text: null | |
}); | |
} else if(typeof(json.JSONData) !== 'undefined') { | |
success(json.JSONData.nick); | |
} else if(typeof(json.FormData) !== 'undefined') { | |
let form = json.FormData; | |
if(typeof(form.errors) === 'undefined') { | |
success(json.nickContext); | |
return; | |
} | |
failure({ | |
code: form.errors.nick.error, | |
text: form.errors.nick.text.trim() | |
}); | |
} else if(typeof(json.regId) !== 'undefined') { | |
switch(json.status) { | |
case 'PHONE_NUMBER_INVALID': | |
case 'PHONE_NUMBER_QUOTA_EXCEEDED': | |
case 'PHONE_NUMBER_COUNTRY_BLOCKED': | |
case 'PHONE_NUMBER_OF_BLOCKED_USER_SOFT': | |
case 'PHONE_NUMBER_OF_BLOCKED_USER_HARD': | |
case 'VERIFICATION_CODE_WRONG': | |
case 'VERIFICATION_CODE_EXPIRED': | |
case 'VERIFICATION_TOO_MANY_RETRIES': | |
failure({ | |
code: json.status, | |
text: null, | |
phoneid: json.regId | |
}); | |
break; | |
default: | |
success(json.regId); | |
break; | |
} | |
} | |
} catch(error) { | |
failure({ | |
code: 'BAD_RESPONSE', | |
text: error | |
}); | |
} | |
}); | |
}); | |
request.on('error', (error) => { | |
failure('BAD_RESPONSE', error.message); | |
}); | |
request.write(body); | |
request.end(); | |
}); | |
} | |
startRecaptchaInjector(key) { | |
return new Promise((success, failure) => { | |
puppeteer.use(pluginStealth()); | |
puppeteer.launch({ | |
executablePath: executablePath(), | |
headless: true, | |
ignoreHTTPSErrors: true | |
}).then(async (browser) => { | |
try { | |
browser.newPage().then(async (page) => { | |
await page.setUserAgent(ClientProperties.get('browser.useragent')); | |
await page.setViewport({ | |
width: 1920 + Math.floor(Math.random() * 100), | |
height: 3000 + Math.floor(Math.random() * 100), | |
deviceScaleFactor: 1, | |
hasTouch: false, | |
isLandscape: false, | |
isMobile: false | |
}); | |
await page.setJavaScriptEnabled(true); | |
await page.setDefaultNavigationTimeout(0) | |
await page.evaluateOnNewDocument(() => { | |
window.chrome = { | |
runtime: {} | |
}; | |
}); | |
await page.setRequestInterception(true); | |
page.on('request', request => { | |
request.continue(); | |
}); | |
await page.setContent(`<script src="https://www.google.com/recaptcha/api.js?render=${key}"></script> | |
<script> | |
window.CAPTCHA = null; | |
let watcher = setInterval(() => { | |
if(window.CAPTCHA !== null) { | |
clearInterval(watcher); | |
return; | |
} | |
window.grecaptcha.ready(() => { | |
window.grecaptcha.execute('${key}', { | |
action: 'submit' | |
}).then(token => { | |
window.CAPTCHA = { | |
token: token, | |
error: null | |
}; | |
}).catch(error => { | |
window.CAPTCHA = { | |
token: null, | |
error: error | |
}; | |
}) | |
}); | |
}, 1500); | |
</script>`); | |
const waitForVariable = (page, variableName) => { | |
return page.evaluate((name) => { | |
return new Promise((resolve) => { | |
const checkVariable = () => { | |
if (window[name] !== undefined) { | |
resolve(window[name]); | |
} else { | |
setTimeout(checkVariable, 50); | |
} | |
}; | |
checkVariable(); | |
}); | |
}, variableName); | |
}; | |
let watch = setInterval(async () => { | |
const CAPTCHA = await waitForVariable(page, 'CAPTCHA'); | |
if(CAPTCHA == null) { | |
return; | |
} | |
clearInterval(watch); | |
if(CAPTCHA.token !== null) { | |
success(CAPTCHA.token); | |
} else if(CAPTCHA.error !== null) { | |
failure(CAPTCHA.error); | |
} | |
await browser.close(); | |
}, 1000); | |
}); | |
} catch (e) { | |
failure(e); | |
} | |
}); | |
}); | |
} | |
}()); | |
export default Register; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Register from './Register.class.js'; | |
Register.checkNick('Testnickname 1').then((nickname) => { | |
Register.registerNick(nickname, 'Passwort1234', 20, 'female').then(() => { | |
console.log('Nickname Successfully registred! :-)'); | |
}).catch((error) => { | |
console.error('[FEHLER]', error); | |
}); | |
}).catch((error) => { | |
console.error('[FEHLER]', error); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment