Compare commits

...

50 Commits

Author SHA1 Message Date
piair 49b691d736 not tested enough apparently 2024-02-28 18:22:15 +01:00
piair 9549a6dea3 not tested enough apparently 2024-02-28 18:12:32 +01:00
piair 8c224793b0 resize terminal on animation end 2024-02-28 15:04:19 +01:00
piair 36fd92f71c fix json start 2024-02-28 14:44:11 +01:00
piair 0a02eb2033 fix json start 2024-02-28 14:44:01 +01:00
piair 6122d9ee13 fix json start + improve logs 2024-02-28 14:40:12 +01:00
piair a590d0f1b5 fix json start 2024-02-28 14:29:21 +01:00
piair 64a018044c event on resize 2024-02-28 14:26:25 +01:00
piair 91e7f31bac size issues 2024-02-28 14:17:55 +01:00
piair 295f6d114d size issues 2024-02-28 14:14:29 +01:00
piair 49e0d1b599 the issue seemed to be linked to the use of table instead of div 2024-02-28 14:13:19 +01:00
piair 83eea03c73 the issue seemed to be linked to the use of table instead of div 2024-02-28 14:13:16 +01:00
piair 3d096ec34c close to working 2024-02-28 12:09:32 +01:00
piair 7bdf229fa8 je connais pas le js moi 2024-02-28 12:02:41 +01:00
piair 0abb8a3494 weird errors 2024-02-28 12:00:19 +01:00
piair 231c3b34e3 better terminal 2024-02-28 11:55:55 +01:00
piair c72aaf3fcc better terminal 2024-02-28 11:53:23 +01:00
piair 675e67055b better terminal 2024-02-28 11:41:16 +01:00
piair a089fdfdf1 better terminal 2024-02-28 11:41:13 +01:00
piair 0f60d67951 obsolete : module 2024-02-28 11:38:32 +01:00
piair 1c7d1dfcd6 typo 2024-02-28 11:38:21 +01:00
piair 19606e5f4c I'm just a clown, I didn't update... 2024-02-28 11:15:09 +01:00
piair aaafbb2257 some debug don't work at all ? 2024-02-28 11:13:09 +01:00
piair 8d332f1c3c check if discord works 2024-02-28 11:10:48 +01:00
piair ced633dd68 refactored log_points 2024-02-28 10:49:27 +01:00
piair 5fe05712bd refactored all_cards 2024-02-28 00:14:42 +01:00
piair 6ec5300c7b the logger should only log my code now 2024-02-27 23:59:39 +01:00
piair 5ca91a7075 the optimisation wasn't that great 2024-02-27 16:26:29 +01:00
piair d49742646c wrong parameter in rgpd_popup 2024-02-27 16:21:08 +01:00
piair a88ad8dd47 the issue seems to be due to MS 2024-02-27 16:13:01 +01:00
piair d9ebccebb8 well the login works, but it will cause issues later with cookies 2024-02-27 16:09:23 +01:00
piair 40f08b4c86 issue indeed fixed, but still can't log in 2024-02-27 16:05:29 +01:00
piair b072041446 issue indeed fixed, but still can't log in 2024-02-27 16:05:21 +01:00
piair 476f99b931 fix ? 2024-02-27 15:59:23 +01:00
piair 37c5d9cf43 can I go to some website ? 2024-02-27 15:57:25 +01:00
piair 9e274b6d16 weird error 2024-02-27 15:55:37 +01:00
piair 2a3878b919 bump version. Added docker compose 2024-02-27 15:38:19 +01:00
piair 7cc1b415a6 bump version. Added docker compose (thx chatGPT) 2024-02-27 15:35:31 +01:00
piair 6a2d960dd0 bump version. Added docker compose 2024-02-27 15:31:35 +01:00
piair bff43c8207 bump version. 2024-02-27 15:22:51 +01:00
piair 7a47b7ae9d bump version. 2024-02-27 15:21:30 +01:00
piair 346b9acc04 bump version. 2024-02-27 15:19:53 +01:00
piair bc94489ca0 bump version. 2024-02-27 15:18:45 +01:00
piair a601c64feb bump version. 2024-02-27 15:17:11 +01:00
piair af938eb50a bump version. 2024-02-27 15:14:14 +01:00
piair 2ae80e9c53 bump version. 2024-02-27 15:12:30 +01:00
piair 27f08b5a01 bump version. 2024-02-27 15:12:25 +01:00
piair 84ace32977 bump version. 2024-02-27 15:07:42 +01:00
piair da6ca1cdfc bump version. 2024-02-27 15:05:19 +01:00
piair 9857607eb3 implemented classes to remove global file 2024-02-27 14:52:55 +01:00
34 changed files with 998 additions and 346340 deletions

3
.gitignore vendored
View File

@ -15,3 +15,6 @@ nohup.out
points.csv points.csv
file.png file.png
user_data/configs.json user_data/configs.json
*.ts
LICENSE
README.md

View File

@ -1,5 +1,5 @@
nohup bash /app/MsRewards-Reborn/sse.sh & nohup redis-server &> nohup_redis.out &
nohup bash /app/MsRewards-Reborn/sse.sh &> nohup_sse.out &
service grafana-server start service grafana-server start
service nginx start service nginx start
nohup redis-server &
gunicorn --reload --worker-class gevent -b 0.0.0.0:6666 'app:app' gunicorn --reload --worker-class gevent -b 0.0.0.0:6666 'app:app'

20
Flask/static/node_modules/.package-lock.json generated vendored Normal file
View File

@ -0,0 +1,20 @@
{
"name": "static",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/xterm": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg=="
},
"node_modules/xterm-addon-fit": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
"integrity": "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==",
"peerDependencies": {
"xterm": "^5.0.0"
}
}
}
}

View File

@ -0,0 +1,2 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
//# sourceMappingURL=xterm-addon-fit.js.map

File diff suppressed because one or more lines are too long

26
Flask/static/node_modules/xterm-addon-fit/package.json generated vendored Normal file
View File

@ -0,0 +1,26 @@
{
"name": "xterm-addon-fit",
"version": "0.8.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-fit.js",
"types": "typings/xterm-addon-fit.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"keywords": [
"terminal",
"xterm",
"xterm.js"
],
"scripts": {
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
},
"peerDependencies": {
"xterm": "^5.0.0"
}
}

209
Flask/static/node_modules/xterm/css/xterm.css generated vendored Normal file
View File

@ -0,0 +1,209 @@
/**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*/
/**
* Default styles for xterm.js
*/
.xterm {
cursor: text;
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.xterm.focus,
.xterm:focus {
outline: none;
}
.xterm .xterm-helpers {
position: absolute;
top: 0;
/**
* The z-index of the helpers must be higher than the canvases in order for
* IMEs to appear on top.
*/
z-index: 5;
}
.xterm .xterm-helper-textarea {
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
top: 0;
width: 0;
height: 0;
z-index: -5;
/** Prevent wrapping so the IME appears against the textarea at the correct position */
white-space: nowrap;
overflow: hidden;
resize: none;
}
.xterm .composition-view {
/* TODO: Composition position got messed up somewhere */
background: #000;
color: #FFF;
display: none;
position: absolute;
white-space: nowrap;
z-index: 1;
}
.xterm .composition-view.active {
display: block;
}
.xterm .xterm-viewport {
/* On OS X this is required in order for the scroll bar to appear fully opaque */
background-color: #000;
overflow-y: scroll;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.xterm .xterm-screen {
position: relative;
}
.xterm .xterm-screen canvas {
position: absolute;
left: 0;
top: 0;
}
.xterm .xterm-scroll-area {
visibility: hidden;
}
.xterm-char-measure-element {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
left: -9999em;
line-height: normal;
}
.xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}
.xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer;
}
.xterm.column-select.focus {
/* Column selection mode */
cursor: crosshair;
}
.xterm .xterm-accessibility,
.xterm .xterm-message {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
color: transparent;
pointer-events: none;
}
.xterm .live-region {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.xterm-dim {
/* Dim should not apply to background, so the opacity of the foreground color is applied
* explicitly in the generated class and reset to 1 here */
opacity: 1 !important;
}
.xterm-underline-1 { text-decoration: underline; }
.xterm-underline-2 { text-decoration: double underline; }
.xterm-underline-3 { text-decoration: wavy underline; }
.xterm-underline-4 { text-decoration: dotted underline; }
.xterm-underline-5 { text-decoration: dashed underline; }
.xterm-overline {
text-decoration: overline;
}
.xterm-overline.xterm-underline-1 { text-decoration: overline underline; }
.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; }
.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; }
.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; }
.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; }
.xterm-strikethrough {
text-decoration: line-through;
}
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}
.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer {
z-index: 7;
}
.xterm-decoration-overview-ruler {
z-index: 8;
position: absolute;
top: 0;
right: 0;
pointer-events: none;
}
.xterm-decoration-top {
z-index: 2;
position: relative;
}

2
Flask/static/node_modules/xterm/lib/xterm.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
Flask/static/node_modules/xterm/lib/xterm.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

100
Flask/static/node_modules/xterm/package.json generated vendored Normal file
View File

@ -0,0 +1,100 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "5.3.0",
"main": "lib/xterm.js",
"style": "css/xterm.css",
"types": "typings/xterm.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"keywords": [
"cli",
"command-line",
"console",
"pty",
"shell",
"ssh",
"styles",
"terminal-emulator",
"terminal",
"tty",
"vt100",
"webgl",
"xterm"
],
"scripts": {
"prepackage": "npm run build",
"package": "webpack",
"package-headless": "webpack --config ./webpack.config.headless.js",
"postpackage-headless": "node ./bin/package_headless.js",
"start": "node demo/start",
"build-demo": "webpack --config ./demo/webpack.config.js",
"start-debug": "node --inspect-brk demo/start",
"lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
"lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
"test": "npm run test-unit",
"posttest": "npm run lint",
"test-api": "npm run test-api-chromium",
"test-api-chromium": "node ./bin/test_api.js --browser=chromium --timeout=20000",
"test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000",
"test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000",
"test-playwright": "playwright test -c ./out-test/playwright/playwright.config.js --workers 4",
"test-playwright-chromium": "playwright test -c ./out-test/playwright/playwright.config.js --workers 4 --project='Chrome Stable'",
"test-playwright-firefox": "playwright test -c ./out-test/playwright/playwright.config.js --workers 4 --project='Firefox Stable'",
"test-playwright-webkit": "playwright test -c ./out-test/playwright/playwright.config.js --workers 4 --project='WebKit'",
"test-playwright-debug": "playwright test -c ./out-test/playwright/playwright.config.js --headed --workers 1 --timeout 30000",
"test-unit": "node ./bin/test.js",
"test-unit-coverage": "node ./bin/test.js --coverage",
"test-unit-dev": "cross-env NODE_PATH='./out' mocha",
"build": "tsc -b ./tsconfig.all.json",
"install-addons": "node ./bin/install-addons.js",
"presetup": "npm run install-addons",
"setup": "npm run build",
"prepublishOnly": "npm run package",
"watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
"benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
"benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/test/benchmark/*benchmark.js",
"benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/test/benchmark/*benchmark.js",
"clean": "rm -rf lib out addons/*/lib addons/*/out",
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
},
"devDependencies": {
"@playwright/test": "^1.37.1",
"@types/chai": "^4.2.22",
"@types/debug": "^4.1.7",
"@types/deep-equal": "^1.0.1",
"@types/express": "4",
"@types/express-ws": "^3.0.1",
"@types/glob": "^7.2.0",
"@types/jsdom": "^16.2.13",
"@types/mocha": "^9.0.0",
"@types/node": "^18.16.0",
"@types/utf8": "^3.0.0",
"@types/webpack": "^5.28.0",
"@types/ws": "^8.2.0",
"@typescript-eslint/eslint-plugin": "^6.2.00",
"@typescript-eslint/parser": "^6.2.00",
"chai": "^4.3.4",
"cross-env": "^7.0.3",
"deep-equal": "^2.0.5",
"eslint": "^8.45.0",
"eslint-plugin-jsdoc": "^39.3.6",
"express": "^4.17.1",
"express-ws": "^5.0.2",
"glob": "^7.2.0",
"jsdom": "^18.0.1",
"mocha": "^10.1.0",
"mustache": "^4.2.0",
"node-pty": "^0.10.1",
"nyc": "^15.1.0",
"source-map-loader": "^3.0.0",
"source-map-support": "^0.5.20",
"ts-loader": "^9.3.1",
"typescript": "^5.1.6",
"utf8": "^3.0.0",
"webpack": "^5.61.0",
"webpack-cli": "^4.9.1",
"ws": "^8.2.3",
"xterm-benchmark": "^0.3.1"
}
}

26
Flask/static/package-lock.json generated Normal file
View File

@ -0,0 +1,26 @@
{
"name": "static",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0"
}
},
"node_modules/xterm": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg=="
},
"node_modules/xterm-addon-fit": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
"integrity": "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==",
"peerDependencies": {
"xterm": "^5.0.0"
}
}
}
}

View File

@ -0,0 +1,6 @@
{
"dependencies": {
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0"
}
}

View File

@ -1,35 +1,48 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block left_pannel %}override{% endblock %} {% block left_pannel %}override{% endblock %}
{% block content %} {% block content %}
{%if not current_user.is_authenticated %} {% if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button> <button class="unselected" onclick="location.href = '/login';">login</button>
{% else %} {% else %}
<table> <link rel="stylesheet" href="{{ url_for('static', filename='node_modules/xterm/css/xterm.css') }}"/>
<tr> <script src="{{ url_for('static', filename='node_modules/xterm/lib/xterm.js') }}"></script>
<td width="20%" height="90%"> <script src="{{ url_for('static', filename='node_modules/xterm-addon-fit/lib/xterm-addon-fit.js') }}"></script>
<div id="console"></div> <script>
</td> document.getElementsByClassName("content")[0].style.padding = "0 0"
<td width="80%"> </script>
<iframe src="/novnc/vnc.html?resize=scale&path=novnc/websockify&autoconnect=true&view_only" width="100%" height="100%" frameborder="0"></iframe> <div style="height: 100%">
</td>
</tr>
</table>
<div id="console" style="height: 100%; width: 20%; float:left;"></div>
<div style="height: 100%; width: 80%; float:left;">
<iframe src="/novnc/vnc.html?resize=scale&path=novnc/websockify&autoconnect=true&view_only"
width="100%" height="100%" frameborder="0"></iframe>
</div>
</div>
<script> <script>
const consoleElement = document.getElementById('console'); var term = new Terminal();
const eventSource = new EventSource('/stream'); const fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
term.open(document.getElementById('console'));
fitAddon.fit()
addEventListener("transitionend", (event) => {
fitAddon.fit()
});
eventSource.onmessage = (event) => { document.getElementById("console").style.textAlign = "left"
document.getElementById("console").innerHTML = event.data + document.getElementById("console").innerHTML const eventSource = new EventSource('/stream');
};
</script>
{% endif %} eventSource.onmessage = (event) => {
term.writeln(event.data)
};
addEventListener("resize", (event) => {
fitAddon.fit()
});
</script>
{%endblock %} {% endif %}
{% endblock %}

555
V6.py
View File

@ -1,84 +1,43 @@
#!/usr/bin/python3.10 #!/usr/bin/python3.10
from modules.config import *
from modules.error import *
from modules.driver_tools import *
from modules.cards import *
import modules.globals as g
from modules.Classes.Config import Config from modules.Classes.Config import Config
from modules.Classes.DiscordLogger import DiscordLogger
from modules.Classes.UserCredentials import UserCredentials from modules.Classes.UserCredentials import UserCredentials
from modules.Tools.logger import warning, info, debug, error, critical from modules.Tools.logger import warning, critical
from modules.cards import *
from modules.config import *
driver = g.driver from modules.db import add_to_database
display = g.display from modules.driver_tools import *
from modules.error import *
# create a webdriver # create a webdriver
def create_driver(mobile=False): def create_driver(mobile=False):
PC_USER_AGENT = ( pc_user_agent = (
"Mozilla/5.0 (X11; Linux x86_64)" "Mozilla/5.0 (X11; Linux x86_64)"
"AppleWebKit/537.36 (KHTML, like Gecko)" "AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/122.0.0.0 Safari/537.36 Edg/122.0.2088.46" "Chrome/122.0.0.0 Safari/537.36 Edg/122.0.2088.46"
) )
MOBILE_USER_AGENT = ( mobile_user_agent = (
"Mozilla/5.0 (Linux; Android 7.0; Nexus 5 Build/MRA58N)" "Mozilla/5.0 (Linux; Android 7.0; Nexus 5 Build/MRA58N)"
"AppleWebKit/537.36 (KHTML, like Gecko)" "AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/22 Mobile Safari/537.36" "Chrome/22 Mobile Safari/537.36"
) )
chrome_options = webdriver.ChromeOptions() chrome_options = webdriver.ChromeOptions()
if mobile: if mobile:
chrome_options.add_argument(f"--user-agent={MOBILE_USER_AGENT}") chrome_options.add_argument(f"--user-agent={mobile_user_agent}")
else: else:
chrome_options.add_argument(f"--user-agent={PC_USER_AGENT}") chrome_options.add_argument(f"--user-agent={pc_user_agent}")
# disabled as it may cause detection # disabled as it may cause detection
if g.proxy_enabled: if config.proxy.is_enabled():
chrome_options.add_argument(f'--proxy-server={g.proxy_address}:{g.proxy_port}') chrome_options.add_argument(f'--proxy-server={config.proxy.ip}:{config.proxy.port}')
driver = uc.Chrome(options=chrome_options) driver = uc.Chrome(options=chrome_options)
set_language(driver) set_language(driver)
return driver return driver
def log_error(error_message, l_driver=driver, log=g.full_log):
global driver
if l_driver is None:
l_driver = driver
if type(error_message) is not str:
error_message = format_error(error_message)
error(str(error_message))
if g.discord_enabled_error:
with open("page.html", "w") as f:
try:
f.write(l_driver.page_source)
except:
f.write("the driver has closed or crashed. Can't access page content")
try:
img = display.waitgrab()
img.save("screenshot.png")
except:
l_driver.save_screenshot("screenshot.png")
if not log:
embed = Embed(
title="An Error has occured",
description=str(error_message),
colour=Colour.red(),
)
else:
embed = Embed(
title="Full log is enabled",
description=str(error_message),
colour=Colour.blue(),
)
file = File("screenshot.png")
embed.set_image(url="attachment://screenshot.png")
embed.set_footer(text=g._mail)
webhookFailure.send(embed=embed, username="error", file=file, avatar_url=g.avatar_url)
webhookFailure.send(username="error", file=File("page.html"), avatar_url=g.avatar_url)
# close the tab currently on and go back to the one first, or the one specified # close the tab currently on and go back to the one first, or the one specified
def close_tab(tab, switch_to: int = 0) -> None: def close_tab(tab, switch_to: int = 0) -> None:
driver = config.WebDriver.driver
driver.switch_to.window(tab) driver.switch_to.window(tab)
driver.close() driver.close()
driver.switch_to.window(driver.window_handles[switch_to]) driver.switch_to.window(driver.window_handles[switch_to])
@ -89,13 +48,18 @@ def close_tab(tab, switch_to: int = 0) -> None:
# Can be useful in some case, where the program crashes before finishing the quiz # Can be useful in some case, where the program crashes before finishing the quiz
def play_quiz2(override=10) -> None: def play_quiz2(override=10) -> None:
info("Starting to play quiz 2.") info("Starting to play quiz 2.")
driver = config.WebDriver.driver
debug(f"override: {override}") debug(f"override: {override}")
for j in range(override): for j in range(override):
custom_sleep(uniform(3, 5)) custom_sleep(uniform(3, 5))
js_function = """ js_function = """
function get_correct_answer(){ function get_correct_answer(){
function br(n) { for (var r, t = 0, i = 0; i < n.length; i++)t += n.charCodeAt(i); return r = parseInt(_G.IG.substr(_G.IG.length - 2), 16), t += r, t.toString() } // Ms check function function br(n) {
function namedRAValue() { //allow calls to getRAvalue for (var r, t = 0, i = 0; i < n.length; i++)
t += n.charCodeAt(i);
return r = parseInt(_G.IG.substr(_G.IG.length - 2), 16), t += r, t.toString()
} // Ms check function
function namedRAValue() { //allow calls to getRAValue
return _w.getRAValue() return _w.getRAValue()
}; };
if (br(document.getElementById("rqAnswerOption0").attributes["data-option"].value) == namedRAValue()){ if (br(document.getElementById("rqAnswerOption0").attributes["data-option"].value) == namedRAValue()){
@ -122,6 +86,7 @@ def play_quiz2(override=10) -> None:
def play_quiz8(): def play_quiz8():
driver = config.WebDriver.driver
info(f"Starting Quiz 8") info(f"Starting Quiz 8")
override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source)) + 1 override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source)) + 1
debug(f"override : {override}") debug(f"override : {override}")
@ -130,13 +95,13 @@ def play_quiz8():
for _ in range(override): for _ in range(override):
sleep(uniform(3, 5)) sleep(uniform(3, 5))
correct_answers = [] correct_answers = []
for i in range(1, 9): # todo: remove this odd 1-offset for i in range(8):
try: try:
element = driver.find_element(By.ID, f"rqAnswerOption{i - 1}") element = driver.find_element(By.ID, f"rqAnswerOption{i}")
if 'iscorrectoption="True"' in element.get_attribute("outerHTML"): if 'iscorrectoption="True"' in element.get_attribute("outerHTML"):
correct_answers.append(f'rqAnswerOption{i - 1}') correct_answers.append(f'rqAnswerOption{i}')
except Exception as e: except Exception as e:
warning(f"can't find rqAnswerOption{i - 1}. Probably already clicked" + str(e)) warning(f"can't find rqAnswerOption{i}. Probably already clicked" + str(e))
shuffle(correct_answers) shuffle(correct_answers)
for answer_id in correct_answers: for answer_id in correct_answers:
wait_until_visible(By.ID, answer_id, timeout=20, browser=driver) wait_until_visible(By.ID, answer_id, timeout=20, browser=driver)
@ -150,22 +115,25 @@ def play_quiz8():
answer_elem = driver.find_element(By.ID, answer_id) answer_elem = driver.find_element(By.ID, answer_id)
answer_elem.click() answer_elem.click()
except ElementClickInterceptedException: except ElementClickInterceptedException:
rgpd_popup(driver) rgpd_popup(config)
correct_answers.append(answer_id) correct_answers.append(answer_id)
except Exception as e: except Exception as e:
log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}") log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}")
raise ValueError(format_error(e))
info("Quiz 8 done.") info("Quiz 8 done.")
custom_sleep(3) custom_sleep(3)
def play_quiz4(override: int = None): def play_quiz4(override: int = None):
info(f"Starting Quiz 4") info(f"Starting Quiz 4")
driver = config.WebDriver.driver
if not override: if not override:
try: # fidelity quiz are much longer than usual ones try: # fidelity quiz are much longer than usual ones
override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1]) override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1])
except: except Exception as err:
debug(err)
override = 3 override = 3
debug(f"Override : {override}") debug(f"Override : {override}")
@ -191,11 +159,14 @@ def play_quiz4(override: int = None):
# do_poll() answer a random thing to poll, on of daily activities # do_poll() answer a random thing to poll, on of daily activities
def do_poll(): def do_poll():
info("Starting poll") info("Starting poll")
driver = config.WebDriver.driver
try: try:
answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}") answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}")
try: try:
answer_elem.click() answer_elem.click()
except exceptions.ElementNotInteractableException: except exceptions.ElementNotInteractableException:
warning("element not clickable. Waiting a bit and retrying.")
custom_sleep(uniform(2, 2.5))
driver.execute_script("arguments[0].click();", answer_elem) driver.execute_script("arguments[0].click();", answer_elem)
custom_sleep(uniform(2, 2.5)) custom_sleep(uniform(2, 2.5))
except Exception as err: except Exception as err:
@ -206,106 +177,95 @@ def do_poll():
# Find each playable card and tries to click on it to earn points # Find each playable card and tries to click on it to earn points
# todo : refactor
def all_cards(): def all_cards():
driver = config.WebDriver.driver
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver) wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver)
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
custom_sleep(2) custom_sleep(2)
try: try:
promo() promo()
except Exception as e: except Exception as e:
debug(e)
info("no promo card") info("no promo card")
if (len(liste) < 10): # most likely an error during loading
if len(card_list) < 10: # most likely an error during loading
if "suspendu" in driver.page_source: if "suspendu" in driver.page_source:
raise Banned() raise Banned()
driver.refresh() driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
if (len(liste) < 10): if len(card_list) < 10:
log_error("Less than 10 cards. Most likely an error with login.", driver) log_error("Less than 10 cards. Most likely an error with login.")
return ("PAS ASSEZ DE CARTES") return "Not enough cards"
if (len(liste) < 20): # most likely not in france
printf("moins de 20 cartes. Probablement pas en France.") for i in range(len(card_list)):
for i in range(len(liste)): debug(f"carte {i}")
printf(f"carte {i}") checked = False
try: try:
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except StaleElementReferenceException: except StaleElementReferenceException:
driver.refresh() driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
printf(f"staled, {len(liste)}") warning(f"staled, {len(card_list)}")
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except IndexError: except IndexError:
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
custom_sleep(10) custom_sleep(10)
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
try: try:
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except IndexError: except IndexError:
if i == len(liste) & i > 15: if i == len(card_list) and i > 15:
checked = False checked = False
# input("2")
if checked: if checked:
custom_sleep(1.5) custom_sleep(1.5)
driver.execute_script("arguments[0].scrollIntoView();", liste[i]) driver.execute_script("arguments[0].scrollIntoView();", card_list[i])
custom_sleep(1.5) custom_sleep(1.5)
# input("3") card_list[i].click()
liste[i].click()
# input("4")
if len(driver.window_handles) > 1: if len(driver.window_handles) > 1:
driver.switch_to.window(driver.window_handles[1]) driver.switch_to.window(driver.window_handles[1])
# input("5")
try_play(driver.title) try_play(driver.title)
close_tab(driver.window_handles[1]) close_tab(driver.window_handles[1])
try:
driver.refresh() try:
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") driver.refresh()
if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")): card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
printf(f"carte {i} not okay. Retrying.")
if "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML"):
driver.execute_script("arguments[0].scrollIntoView();", card_list[i])
card_list[i].click()
driver.switch_to.window(driver.window_handles[1])
custom_sleep(10)
log_error(f"Card {i} Can't be completed. Why MS ?")
try:
try_play(driver.title) # go back to the main page
try: try:
liste[i].click() close_tab(driver.window_handles[1])
except: except Exception as e:
log_error("problème inconnu ? sauf si c'est un element obscure...", driver) debug(e)
driver.get("https://rewards.bing.com") except Exception as e:
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) debug(e)
driver.switch_to.window(driver.window_handles[1]) driver.get("https://rewards.bing.com")
try_play(driver.title) except Exception as err:
close_tab(driver.window_handles[1]) log_error(err)
if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")):
driver.execute_script("arguments[0].scrollIntoView();", liste[i])
log_error(f"Card {i} Can't be completed. Why MS ?", driver)
liste[i].click()
driver.switch_to.window(driver.window_handles[1])
log_error(f"Cart completion - log - 2", driver)
custom_sleep(10)
log_error(f"Cart completion - log - 3 - after 10 sec", driver)
try:
try_play(driver.title) # go back to the main page
try:
close_tab(driver.window_handles[1])
except:
pass
except:
driver.get("https://rewards.bing.com")
except:
pass
else:
try:
welcome_tour(liste[i], driver)
except Exception as e:
printf("no new windows" + format_error(e))
driver.get("https://rewards.bing.com")
custom_sleep(3) custom_sleep(3)
def promo(): def promo():
driver = config.WebDriver.driver
for i in range(5): for i in range(5):
elm = driver.find_element(By.ID, "promo-item") elm = driver.find_element(By.ID, "promo-item")
wait_until_visible(By.ID, "promo-item", 5, driver) wait_until_visible(By.ID, "promo-item", 5, driver)
if not elm: if not elm:
break break
if i > 3: if i > 3:
log_error("plus de 3 promo cards, probablement une pa skipable", driver) log_error("There is more than 3 promo cards, most likely an unskippable one.")
try: try:
driver.find_element(By.CSS_SELECTOR, driver.find_element(By.CSS_SELECTOR,
'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click() 'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click()
@ -315,10 +275,8 @@ def promo():
try: try:
elm.click() elm.click()
except Exception as e: except Exception as e:
# log_error(e, driver)
driver.execute_script("arguments[0].click();", elm) driver.execute_script("arguments[0].click();", elm)
# log_error(e, driver) warning(f"that shouldn't be there (promo), but the workaround seemed to work {e}")
printf(f"that should't be there (promo), but the workarround seemed to work {e}")
custom_sleep(3) custom_sleep(3)
if len(driver.window_handles) > 1: if len(driver.window_handles) > 1:
driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1]) driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1])
@ -327,16 +285,17 @@ def promo():
else: else:
try: try:
spotify(driver) spotify(driver)
except: except Exception as e:
warning("no new windows") warning(f"no new windows {format_error(e)}")
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
driver.refresh() driver.refresh()
custom_sleep(3) custom_sleep(3)
# Find out which type of action to do # Find out which type of action to do
def try_play(nom="inconnu"): def try_play(nom="unknown"):
rgpd_popup(driver) driver = config.WebDriver.driver
rgpd_popup(config)
def play(number): def play(number):
if number in [8, 9]: if number in [8, 9]:
@ -368,7 +327,7 @@ def try_play(nom="inconnu"):
custom_sleep(5) custom_sleep(5)
driver.find_element(By.CSS_SELECTOR, '[onclick="setsrchusr()"]').click() driver.find_element(By.CSS_SELECTOR, '[onclick="setsrchusr()"]').click()
custom_sleep(5) custom_sleep(5)
rgpd_popup(driver) rgpd_popup(config)
custom_sleep(5) custom_sleep(5)
debug("Detected and fixed connection popup") debug("Detected and fixed connection popup")
@ -376,11 +335,6 @@ def try_play(nom="inconnu"):
debug("Poll detected") debug("Poll detected")
do_poll() do_poll()
elif "rqQuestionState" in driver.page_source:
number = driver.page_source.count("rqAnswerOption")
warning(f"recovery détecté. quiz : {number}")
play(number - 1)
elif search("([0-9]) de ([0-9]) finalisée", driver.page_source): elif search("([0-9]) de ([0-9]) finalisée", driver.page_source):
info("On fidelity page.") info("On fidelity page.")
fidelity() fidelity()
@ -391,93 +345,102 @@ def try_play(nom="inconnu"):
answer_number = driver.page_source.count("rqAnswerOption") answer_number = driver.page_source.count("rqAnswerOption")
play(answer_number) play(answer_number)
elif "rqQuestionState" in driver.page_source:
number = driver.page_source.count("rqAnswerOption")
warning(f"recovery detected. quiz : {number}")
play(number - 1)
else: else:
printf(f"Nothing to do on page `{nom}`") info(f"Nothing to do on page `{nom}`")
custom_sleep(uniform(3, 5)) custom_sleep(uniform(3, 5))
# Login with password or with cookies. # Login with password or with cookies.
# The driver should be in the same state on both case # The driver should be in the same state on both case
def login_part_1(ldriver, cred: UserCredentials): def login_part_1():
printf("pwd_login : start") info("Starting part 1 of login")
ldriver.get("https://login.live.com") driver = config.WebDriver.driver
wait_until_visible(By.ID, "i0116", browser=ldriver) driver.get("https://login.live.com")
mail_elem = ldriver.find_element(By.ID, "i0116") wait_until_visible(By.ID, "i0116", browser=driver)
send_keys_wait(mail_elem, cred.get_mail()) mail_elem = driver.find_element(By.ID, "i0116")
send_keys_wait(mail_elem, config.UserCredentials.get_mail())
mail_elem.send_keys(Keys.ENTER) mail_elem.send_keys(Keys.ENTER)
wait_until_visible(By.ID, "i0118", browser=ldriver) wait_until_visible(By.ID, "i0118", browser=driver)
pwd_elem = ldriver.find_element(By.ID, "i0118") pwd_elem = driver.find_element(By.ID, "i0118")
send_keys_wait(pwd_elem, cred.get_password()) send_keys_wait(pwd_elem, config.UserCredentials.get_password())
pwd_elem.send_keys(Keys.ENTER) pwd_elem.send_keys(Keys.ENTER)
custom_sleep(2) custom_sleep(2)
# 2FA # 2FA
if "Entrez le code de sécurité" in ldriver.page_source: if "Entrez le code de sécurité" in driver.page_source:
try: try:
a2f_elem = ldriver.find_element(By.ID, "idTxtBx_SAOTCC_OTC") a2f_elem = driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC")
a2f_elem.send_keys(g._otp.now()) a2f_elem.send_keys(config.UserCredentials.get_tfa().now())
a2f_elem.send_keys(Keys.ENTER) a2f_elem.send_keys(Keys.ENTER)
except Exception as e: except Exception as err:
log_error(e) log_error(err)
# Accept all cookies question, and check if the account is locked # Accept all cookies question, and check if the account is locked
def login_part_2(ldriver): def login_part_2():
driver = config.WebDriver.driver
custom_sleep(5) custom_sleep(5)
if 'Abuse' in ldriver.current_url: if 'Abuse' in driver.current_url:
raise Banned() raise Banned()
if 'identity' in ldriver.current_url: if 'identity' in driver.current_url:
raise Identity() raise Identity()
if 'notice' in ldriver.current_url: if 'notice' in driver.current_url:
ldriver.find_element(By.ID, "id__0").click() driver.find_element(By.ID, "id__0").click()
if "proof" in ldriver.current_url: if "proof" in driver.current_url:
ldriver.find_element(By.ID, "iLooksGood") driver.find_element(By.ID, "iLooksGood")
for elm_id in ["iNext", "KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]: for elm_id in ["checkboxField", "KmsiCheckboxField", "acceptButton", "iNext", "id__0", "iLooksGood", "idSIButton9",
if get_domain(ldriver) == "account.microsoft.com": "iCancel"]:
if get_domain(driver) == "account.microsoft.com":
break break
try: try:
ldriver.find_element(By.ID, elm_id).click() driver.find_element(By.ID, elm_id).click()
except Exception as e: except Exception as e:
pass debug(e)
wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, ldriver) wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, driver)
# login() tries to login to your Microsoft account. # login() tries to login to your Microsoft account.
# it uses global variable g._mail and g._password to login # it uses global variable g._mail and g._password to login
def login(ldriver, cred: UserCredentials): def login():
driver = config.WebDriver.driver
try: try:
login_part_1(ldriver, cred) login_part_1()
login_part_2(ldriver) login_part_2()
ldriver.get("https://rewards.bing.com/") driver.get("https://rewards.bing.com/")
except Banned: except Banned:
raise Banned() raise Banned()
except Identity: except Identity:
raise Banned() raise Banned()
except Exception as e: except Exception as err:
critical("Error not caught during login.") critical("Error not caught during login." + format_error(err))
log_error(e) log_error(err)
ldriver.quit() driver.quit()
return False return False
# Makes 30 search as PC Edge # Makes 30 search as PC Edge
def bing_pc_search(override=randint(35, 40)): def bing_pc_search(override=randint(35, 40)):
mot = choice(Liste_de_mot).replace(" ", "+") driver = config.WebDriver.driver
driver.get(f"https://www.bing.com/search?q={mot}") driver.get(f"https://www.bing.com/search?q={config.wordlist.get_word().replace(' ', '+')}")
custom_sleep(uniform(1, 2)) custom_sleep(uniform(1, 2))
rgpd_popup(driver) rgpd_popup(config)
send_keys_wait( send_keys_wait(
driver.find_element(By.ID, "sb_form_q"), driver.find_element(By.ID, "sb_form_q"),
Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE
) )
for _ in range(override): for _ in range(override):
word = choice(Liste_de_mot) word = config.wordlist.get_word()
try: try:
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word) send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
@ -500,37 +463,25 @@ def bing_pc_search(override=randint(35, 40)):
log_error(f"clear la barre de recherche - {format_error(e)}") # what is this message ??? todo log_error(f"clear la barre de recherche - {format_error(e)}") # what is this message ??? todo
# Sends points to database, discord and whatever service you want # Sends current account's points to database
# todo: refactor def log_points():
def log_points(account="unknown"): driver = config.WebDriver.driver
def get_points(): account = config.UserCredentials.get_mail()
driver.get("https://rewards.bing.com")
custom_sleep(1) driver.get("https://rewards.bing.com")
wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver) custom_sleep(1)
try: wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver)
point = search('availablePoints\":([\d]+)', driver.page_source)[1] try:
except Exception as e: points = search('availablePoints\":([\d]+)', driver.page_source)[1]
log_error( except Exception as err:
f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}", log_error(
driver) f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(err)}")
error("Can't get points.") error(f"Can't get points. {format_error(err)}")
return -1 return -1
return point
points = get_points()
custom_sleep(uniform(3, 20)) custom_sleep(uniform(3, 20))
account_name = account.split("@")[0] account_name = account.split("@")[0]
if g.discord_enabled_success:
if g.discord_embed:
embed = Embed(
title=f"{account_name} actuellement à {str(points)} points", colour=Colour.green()
)
embed.set_footer(text=account_name)
webhookSuccess.send(embed=embed)
else:
webhookSuccess.send(f"{account_name} actuellement à {str(points)} points")
try: try:
add_to_database(account_name, points) add_to_database(account_name, points)
except Exception as e: except Exception as e:
@ -539,6 +490,8 @@ def log_points(account="unknown"):
# todo: refactor and check if it works at all # todo: refactor and check if it works at all
def fidelity(): def fidelity():
driver = config.WebDriver.driver
def sub_fidelity(): def sub_fidelity():
try: try:
wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver) wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver)
@ -558,15 +511,15 @@ def fidelity():
try: try:
button_text = search('<span class="pull-left margin-right-15">([^<^>]+)</span>', button_text = search('<span class="pull-left margin-right-15">([^<^>]+)</span>',
card_elem.get_attribute("innerHTML"))[1] card_elem.get_attribute("innerHTML"))[1]
bouton_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]') button_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]')
bouton_card.click() button_card.click()
except Exception as e1: except Exception as e1:
try: try:
recover_elem = driver.find_element(By.XPATH, recover_elem = driver.find_element(By.XPATH,
'/html/body/div[1]/div[2]/main/div[2]/div[2]/div[7]/div[3]/div[1]/a') '/html/body/div[1]/div[2]/main/div[2]/div[2]/div[7]/div[3]/div[1]/a')
recover_elem.click() recover_elem.click()
except Exception as e2: except Exception as e2:
log_error(f"fidélité - double erreur - e1 : {format_error(e1)} - e2 {format_error(e2)}") log_error(f"Fidelity: Multiples error - e1 : {format_error(e1)} - e2 {format_error(e2)}")
break break
custom_sleep(uniform(3, 5)) custom_sleep(uniform(3, 5))
driver.switch_to.window(driver.window_handles[2]) driver.switch_to.window(driver.window_handles[2])
@ -574,26 +527,25 @@ def fidelity():
custom_sleep(uniform(3, 5)) custom_sleep(uniform(3, 5))
try: try:
close_tab(driver.window_handles[2], 1) close_tab(driver.window_handles[2], 1)
except Exception as e: except Exception as err:
printf(e) error(err)
printf("fidelity - done") info("fidelity - done")
except Exception as e: except Exception as err:
log_error(e) log_error(err)
if driver.current_url != "https://rewards.bing.com": if driver.current_url != "https://rewards.bing.com":
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
try: try:
pause = driver.find_element(By.CSS_SELECTOR, pause = driver.find_element(By.CSS_SELECTOR, f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]')
f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]') # mettre le truc en pause
pause.click() pause.click()
except Exception as e: except Exception as e:
printf(f"erreur lors du click de pause: probablement pas de cartes {e}") error(f"Error while clicking pause. Probably no cards. {e}")
return ("no cards") return "no cards"
cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]') cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]')
nb_cartes = len(cartes) nb_cartes = len(cartes)
checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]') checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]')
for i in range(nb_cartes): for i in range(nb_cartes):
cartes[i].click() # affiche la bonne carte cartes[i].click()
checked_txt = checked_list_all[i].get_attribute("innerHTML") checked_txt = checked_list_all[i].get_attribute("innerHTML")
ok = checked_txt.count("StatusCircleOuter checkmark") ok = checked_txt.count("StatusCircleOuter checkmark")
total = checked_txt.count("StatusCircleOuter") total = checked_txt.count("StatusCircleOuter")
@ -610,61 +562,67 @@ def fidelity():
def mobile_alert_popup(): def mobile_alert_popup():
driver = config.WebDriver.driver
try: try:
alert = mobile_driver.switch_to.alert alert = driver.switch_to.alert
alert.dismiss() alert.dismiss()
except exceptions.NoAlertPresentException: except exceptions.NoAlertPresentException:
pass pass
except Exception as err: except Exception as err:
log_error(err, mobile_driver) log_error(err)
# todo: be coherent with pc search regarding error management # todo: be coherent with pc search regarding error management
def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)): def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)):
global mobile_driver config.WebDriver.set_mobile_driver(create_driver(mobile=True))
mobile_driver = create_driver(mobile=True) config.WebDriver.switch_to_driver("Mobile")
driver = config.WebDriver.driver
try: try:
login(mobile_driver, cred) login()
mot = choice(Liste_de_mot).replace(" ", "+") mot = config.wordlist.get_word().replace(" ", "+")
mobile_driver.get(f"https://www.bing.com/search?q={mot}") driver.get(f"https://www.bing.com/search?q={mot}")
custom_sleep(uniform(1, 2)) custom_sleep(uniform(1, 2))
rgpd_popup(mobile_driver) rgpd_popup(config)
custom_sleep(uniform(1, 1.5)) custom_sleep(uniform(1, 1.5))
for i in range(override): # 20 for i in range(override): # 20
try: try:
mot = choice(Liste_de_mot) mot = config.wordlist.get_word()
send_keys_wait(mobile_driver.find_element(By.ID, "sb_form_q"), mot) send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot)
mobile_driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
custom_sleep(uniform(3, 7)) custom_sleep(uniform(3, 7))
mobile_alert_popup() # check for alert (asking for position or for allowing notifications) mobile_alert_popup() # check for alert (asking for position or for allowing notifications)
mobile_driver.find_element(By.ID, "sb_form_q").clear() driver.find_element(By.ID, "sb_form_q").clear()
except Exception as err: except Exception as err:
error(err) error(err)
mobile_driver.refresh() driver.refresh()
custom_sleep(30) custom_sleep(30)
i -= 1 i -= 1
mobile_driver.quit() driver.quit()
except Exception as err: except Exception as err:
log_error(err, mobile_driver) log_error(err)
mobile_driver.quit() driver.quit()
finally:
config.WebDriver.switch_to_driver("PC")
def daily_routine(cred: UserCredentials, custom=False): def daily_routine(cred: UserCredentials, custom=False):
try: try:
if not custom: # custom already is logged in if not custom: # custom already is logged in
login(driver, cred) login()
except Banned: except Banned:
log_error("This account is locked.", driver) log_error("This account is locked.")
return return
except Identity: except Identity:
log_error("This account has an issue.", driver) log_error("This account has an issue.")
return return
try: try:
all_cards() all_cards()
except Banned: except Banned:
log_error("banned", driver) log_error("banned")
raise Banned raise Banned
except Exception as err: except Exception as err:
log_error(err) log_error(err)
@ -685,58 +643,59 @@ def daily_routine(cred: UserCredentials, custom=False):
log_error(err) log_error(err)
try: try:
log_points(cred.get_mail()) log_points()
except Exception as err: except Exception as err:
log_error(err) log_error(err)
def json_start(json_entry, cred: UserCredentials): def json_start(json_entry, cred: UserCredentials):
global driver json_entry = json.loads(json_entry)
display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24)
display.start()
for i in range(5): config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24))
config.display.start()
account_id = 0
while config.UserCredentials.is_valid():
start = False start = False
for j in ["unban", "tout", "pc", "mobile", "daily"]: for action in ["unban", "tout", "pc", "mobile", "daily"]:
try: try:
if str(i) in json_entry[j]: if str(account_id) in json_entry[action]:
start = True start = True
info(f"{cred.get_mail()} : {j}") info(f"{cred.get_mail()} : {action}")
except KeyError: except KeyError:
pass pass
if start: if start:
driver = create_driver() config.WebDriver.set_pc_driver(create_driver())
config.WebDriver.switch_to_driver("PC")
driver = config.WebDriver.driver
try: try:
if str(i) in json_entry["unban"]: if str(account_id) in json_entry["unban"]:
login_part_1(driver, cred) login_part_1()
print("\nGO TO example.com TO PROCEED or wait 1200 secs.") info("\nGO TO example.com TO PROCEED or wait 1200 secs.")
for _ in range(1200): for _ in range(1200):
sleep(1) sleep(1)
if driver.current_url == "https://example.com/": if driver.current_url == "https://example.com/":
print("proceeding") info("proceeding")
break break
else: else:
login(driver, cred) login()
except KeyError: except KeyError:
login(driver, cred) login()
try: try:
if str(i) in json_entry["tout"]: if str(account_id) in json_entry["tout"]:
daily_routine(cred) daily_routine(cred, True)
except KeyError: except KeyError:
pass pass
# print("none is set to \"tout\"")
else: else:
try: try:
if str(i) in json_entry["daily"]: if str(account_id) in json_entry["daily"]:
try: try:
all_cards() all_cards()
except Exception as e: except Exception as e:
log_error(e) log_error(e)
except KeyError: except KeyError:
pass pass
# print("none is set to \"daily\"")
try: try:
if str(i) in json_entry["pc"]: if str(account_id) in json_entry["pc"]:
try: try:
bing_pc_search() bing_pc_search()
except Exception as e: except Exception as e:
@ -744,7 +703,7 @@ def json_start(json_entry, cred: UserCredentials):
except KeyError: except KeyError:
pass pass
try: try:
if str(i) in json_entry["mobile"]: if str(account_id) in json_entry["mobile"]:
try: try:
bing_mobile_search(cred) bing_mobile_search(cred)
except Exception as e: except Exception as e:
@ -752,55 +711,67 @@ def json_start(json_entry, cred: UserCredentials):
except KeyError: except KeyError:
pass pass
try: try:
log_points(g._mail) log_points()
except Exception as e: except Exception as e:
printf(f"CustomStart {e}") error(f"CustomStart {e}")
driver.close() driver.close()
cred.next_account() cred.next_account()
display.stop() account_id += 1
config.display.stop()
c = Config(args) def default_start():
if config.vnc_enabled():
if g.json_start: config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=config.vnc, color_depth=24))
dict_data = json.loads(g.json_start.replace("'", "\""))
json_start(dict_data, c.UserCredentials)
else:
if g.vnc_enabled or g.dev:
display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=g.vnc_port, color_depth=24)
else: else:
display = SmartDisplay(size=(1920, 1080)) config.set_display(SmartDisplay(size=(1920, 1080)))
display.start() config.display.start()
if g.update_version != "None": while config.UserCredentials.is_valid():
if g.discord_enabled_error:
webhookFailure.send(f"Updated to {g.update_version}", username="UPDATE",
avatar_url="https://cdn-icons-png.flaticon.com/512/1688/1688988.png")
while c.UserCredentials.is_valid():
custom_sleep(1) custom_sleep(1)
info("Starting driver.") info("Starting and configuring driver.")
driver = create_driver() config.WebDriver.set_pc_driver(create_driver())
config.WebDriver.switch_to_driver("PC")
info("Driver started.") info("Driver started.")
driver.implicitly_wait(3) config.WebDriver.pc_driver.implicitly_wait(3)
try: try:
wait_time = uniform(1200, 3600) wait_time = uniform(1200, 3600)
wait_time = 10 # the display closes when I ctrl + c
info(f"Waiting for {round(wait_time / 60)}min before starting") info(f"Waiting for {round(wait_time / 60)}min before starting")
daily_routine(c.UserCredentials)
driver.quit()
custom_sleep(wait_time) custom_sleep(wait_time)
daily_routine(config.UserCredentials)
config.WebDriver.pc_driver.quit()
except KeyboardInterrupt: except KeyboardInterrupt:
critical("Canceled by user. Closing driver and display.") critical("Canceled by user. Closing driver and display.")
driver.quit() config.WebDriver.pc_driver.quit()
display.stop() config.display.stop()
break break
except Exception as e: except Exception as e:
log_error(f"Error not caught. Skipping this account. " + format_error(e), driver) log_error(f"Error not caught. Skipping this account. " + format_error(e))
critical(f"Error not caught. Skipping this account. {e}") critical(f"Error not caught. Skipping this account. {e}")
driver.quit() config.WebDriver.pc_driver.quit()
c.UserCredentials.next_account() config.UserCredentials.next_account()
config.display.stop()
display.stop()
def log_error(msg):
DiscordLogger(config).send(msg)
def check_updated():
debug(f"updated: {config.has_been_updated()}")
if config.has_been_updated():
config.discord.wh.send(f"Updated to {config.version}", username="update",
avatar_url="https://cdn-icons-png.flaticon.com/512/1688/1688988.png")
if __name__ == "__main__":
config = Config(args)
check_updated()
match config.start:
case "json":
json_start(config.json_entry, config.UserCredentials)
case "default":
default_start()

View File

@ -1 +1 @@
sudo docker build --no-cache --network host -t msrewards . && sudo docker run -d --restart unless-stopped -p 1234:1234 -ti --shm-size=2gb --name MsRewards msrewards sudo docker build --no-cache --network host -t msrewards . && sudo docker run -d --restart unless-stopped -p 1234:1234 -p 2345:2345 -ti --shm-size=2gb --name MsRewards msrewards

19
docker-compose.yml Normal file
View File

@ -0,0 +1,19 @@
version: '3.8'
services:
msrewards:
build:
context: .
dockerfile: Dockerfile
# optional if you have Dockerfile in the same directory
# arguments:
# - ARG_NAME=value # If you have build arguments
image: msrewards
container_name: MsRewards
restart: unless-stopped
ports:
- "1234:1234"
- "2345:2345"
shm_size: 2gb
volumes:
- "./data/:/data"

View File

@ -1,15 +1,79 @@
import json import json
from discord import Webhook, RequestsWebhookAdapter
from modules.Classes.DiscordConfig import DiscordConfig, FakeWebHook
from modules.Classes.Driver import Driver
from modules.Classes.Proxy import Proxy
from modules.Classes.UserCredentials import UserCredentials from modules.Classes.UserCredentials import UserCredentials
from modules.Classes.WordList import WordList
class Config: class Config:
def __init__(self, args): def __init__(self, args):
self.args = args """
self.UserCredentials = UserCredentials() open config file
"""
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
discord = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/settings.json", "r") as inFile:
settings = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
proxy = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
config = json.load(inFile)
"""
setup standalone stuff
"""
self.args = args
self.start = "json" if args.json else "default"
self.json_entry = args.json.replace("'", "\"")
self.wordlist = WordList("/usr/share/dict/french")
self.vnc = args.vnc
self.version = args.update_version
self.WebDriver = Driver()
self.display = None
"""
setup UserCredential
"""
self.UserCredentials = UserCredentials()
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile: with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
configs = json.load(inFile) configs = json.load(inFile)
for i in configs[str(args.config)]["accounts"]: for i in configs[str(args.config)]["accounts"]:
d = configs[str(args.config)]["accounts"][i] d = configs[str(args.config)]["accounts"][i]
self.UserCredentials.add(d["mail"], d["pwd"], d["2fa"]) self.UserCredentials.add(d["mail"], d["pwd"], d["2fa"])
"""
Setup discord
"""
self.discord = DiscordConfig()
self.discord.avatar_url = settings["avatarlink"]
self.discord.wh_link = discord[config[args.config]["discord"]]["errorsL"]
if self.discord.wh_link != "":
self.discord.wh = Webhook.from_url(self.discord.wh_link, adapter=RequestsWebhookAdapter())
else:
self.discord.wh = FakeWebHook()
"""
setup proxy
"""
proxy_conf = config[args.config]["proxy"]
if proxy_conf != "-1":
proxy_address = proxy[config[args.config]["proxy"]]["address"]
proxy_port = proxy[config[args.config]["proxy"]]["port"]
else:
proxy_address = ""
proxy_port = ""
self.proxy = Proxy(proxy_conf, proxy_address, proxy_port)
def vnc_enabled(self):
return self.vnc != "None"
def set_display(self, display):
self.display = display
def has_been_updated(self):
return self.version != "None"

View File

@ -0,0 +1,14 @@
from modules.Tools.logger import debug
class DiscordConfig:
def __init__(self):
self.avatar_url = ""
self.wh_link = None
self.wh = None
class FakeWebHook:
def send(self, *args):
debug(f"Used a webhook call without webhook url with {args}")

View File

@ -0,0 +1,36 @@
from discord import Embed, Colour, File
from modules.Classes.Config import Config
from modules.Tools.logger import error
from modules.Tools.tools import format_error
class DiscordLogger:
def __init__(self, config: Config):
self.config = config
def send(self, message: str):
driver = self.config.WebDriver.driver
if type(message) is not str:
message = format_error(message)
error(message)
with open("page.html", "w") as f:
try:
f.write(driver.page_source)
except Exception as e:
error(e)
f.write("the driver has closed or crashed. Can't access page content")
img = self.config.display.waitgrab()
img.save("screenshot.png")
embed = Embed(
title="An Error has occurred",
description=str(message),
colour=Colour.red(),
)
file = File("screenshot.png")
embed.set_image(url="attachment://screenshot.png")
embed.set_footer(text=self.config.UserCredentials.get_mail())
self.config.discord.wh.send(embed=embed, username="error", file=file, avatar_url=self.config.discord.avatar_url)
self.config.discord.wh.send(username="error", file=File("page.html"), avatar_url=self.config.discord.avatar_url)

22
modules/Classes/Driver.py Normal file
View File

@ -0,0 +1,22 @@
class Driver:
def __init__(self):
self.pc_driver = None
self.mobile_driver = None
self.driver = None
def set_pc_driver(self, pc_driver):
self.pc_driver = pc_driver
def set_mobile_driver(self, mobile_driver):
self.mobile_driver = mobile_driver
def switch_to_driver(self, driver: str):
match driver:
case "pc" | "PC" | "Pc":
self.driver = self.pc_driver
case "mobile" | "Mobile":
self.driver = self.mobile_driver
case _:
raise ValueError("The driver must be either pc or mobile")

9
modules/Classes/Proxy.py Normal file
View File

@ -0,0 +1,9 @@
class Proxy:
def __init__(self, enabled: str, ip: str = None, port: str = None):
self.ip = ip
self.port = port
self.enabled = enabled != "-1"
def is_enabled(self):
return self.enabled

View File

@ -1,4 +1,5 @@
import json from pyotp import TOTP
from modules.Tools.logger import debug, warning from modules.Tools.logger import debug, warning
@ -9,7 +10,8 @@ class UserCredentials:
self.total = 0 self.total = 0
def add(self, username: str, password: str, tfa: str = None): def add(self, username: str, password: str, tfa: str = None):
debug(f"adding account with data : Username: {username}, Password: {password}, 2FA: {'None' if tfa == '' else tfa}") debug(
f"adding account with data : Username: {username}, Password: {password}, 2FA: {'None' if tfa == '' else tfa}")
self.data[self.total] = { self.data[self.total] = {
"username": username, "username": username,
"password": password, "password": password,
@ -29,11 +31,14 @@ class UserCredentials:
def get_tfa(self): def get_tfa(self):
if not self.tfa_enable(): if not self.tfa_enable():
warning("Warning: TFA is not enabled. Calling get_tfa is an expected behaviour.") warning("Warning: TFA is not enabled. Calling get_tfa is an expected behaviour.")
return self.data[self.current]["tfa"] return TOTP(self.data[self.current]["tfa"])
def next_account(self): def next_account(self):
self.current += 1 self.current += 1
debug(f"New credentials: {self.data[self.current]}") if self.is_valid():
debug(f"New credentials: {self.data[self.current]}")
else:
debug("No new credentials.")
def is_valid(self): def is_valid(self):
return self.current < self.total return self.current < self.total

View File

@ -0,0 +1,13 @@
import random
class WordList:
def __init__(self, path):
with open(path, "r", encoding="utf-8") as h:
lines = h.readlines()
self.words = [x.replace('\n', "") for x in lines]
random.shuffle(self.words)
def get_word(self):
return self.words.pop(0)

View File

@ -29,8 +29,8 @@ class ColoredFormatter(logging.Formatter):
# Set up the root logger # Set up the root logger
root_logger = logging.getLogger() root_logger = logging.getLogger(__name__)
root_logger.setLevel(logging.DEBUG) root_logger.setLevel(logging.INFO)
# Create a console handler and set the formatter # Create a console handler and set the formatter
ch = logging.StreamHandler() ch = logging.StreamHandler()

36
modules/Tools/tools.py Normal file
View File

@ -0,0 +1,36 @@
from time import sleep
from modules.Tools.logger import info, error
# return current page domain
def get_domain(driver):
return driver.current_url.split("/")[2]
def custom_sleep(temps):
try:
if True: # todo: change this awful condition
points = ["", "", "", "", "", "", "", ""]
passe = 0
for _ in range(int(temps)):
for i in range(8):
sleep(0.125)
passe += 0.125
print(f"{points[i]} - {round(float(temps) - passe, 3)}", end="\r")
print(" ", end="\r")
else:
sleep(temps)
except KeyboardInterrupt:
info("Wait canceled.")
except Exception as err:
error(err)
def format_error(e) -> str:
tb = e.__traceback__
txt = ""
while tb is not None:
txt = txt + f" -> {tb.tb_frame.f_code.co_name} ({tb.tb_lineno}) "
tb = tb.tb_next
return txt + "\n" + str(e)

View File

@ -1,14 +1,5 @@
#!/usr/bin/python3.10 #!/usr/bin/python3.10
from modules.driver_tools import *
from modules.imports import * from modules.imports import *
import modules.globals as g
import json
class FakeWebHook:
def send(self, text="", username='', avatar_url='', embed="", file=""):
print(text)
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -39,69 +30,4 @@ parser.add_argument(
default="" default=""
) )
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
discord = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/settings.json", "r") as inFile:
settings = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
proxy = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
config = json.load(inFile)
args = parser.parse_args() args = parser.parse_args()
g.json_start = args.json
g.vnc_enabled = args.vnc != "None"
g.vnc_port = args.vnc
g.update_version = args.update_version
# global variables used later in the code
g.start_time = time()
# path configurations
g.mot_path = "/usr/share/dict/french"
g.credential_path = "/app/MsRewards-Reborn/user_data/login.csv"
discord_conf = config[args.config]["discord"]
# discord configuration
g.discord_success_link = discord[discord_conf]["successL"]
g.discord_error_link = discord[discord_conf]["errorsL"]
g.discord_enabled_error = discord[discord_conf]["errorsT"] == "True"
g.discord_enabled_success = discord[discord_conf]["successT"] == "True"
g.avatar_url = settings["avatarlink"]
if not g.json_start:
if g.discord_enabled_error:
webhookFailure = Webhook.from_url(g.discord_error_link, adapter=RequestsWebhookAdapter())
if g.discord_enabled_success:
webhookSuccess = Webhook.from_url(g.discord_success_link, adapter=RequestsWebhookAdapter())
else:
webhookFailure = FakeWebHook()
webhookSuccess = FakeWebHook()
# base settings
g.discord_embed = False # send new point value in an embed, fixed for now
g.headless = False
# proxy settings
g.proxy_enabled = config[args.config]["proxy"] != "-1"
if g.proxy_enabled:
g.proxy_address = proxy[config[args.config]["proxy"]]["address"]
g.proxy_port = proxy[config[args.config]["proxy"]]["port"]
# list of words
with open(g.mot_path, "r", encoding="utf-8") as h:
lines = h.readlines()
if len(lines) < 3:
Liste_de_mot = list(lines[0].split(","))
else:
Liste_de_mot = [x.replace('\n', "") for x in lines]
if g.proxy_enabled:
setup_proxy(g.proxy_address, g.proxy_port)

View File

@ -1,67 +1,66 @@
import sqlite3 import sqlite3
#Create a new row, for the account [compte] whith [points] points
def add_row(compte, points, mycursor, mydb): # Create a new row, for the account [compte] whith [points] points
def add_row(account, points, mycursor, mydb):
sql = "INSERT INTO daily (compte, points, date) VALUES (?, ?, date())" sql = "INSERT INTO daily (compte, points, date) VALUES (?, ?, date())"
val = (compte, points) val = (account, points)
mycursor.execute(sql, val) mycursor.execute(sql, val)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record created.") # printf(mycursor.rowcount, "record created.")
#update the ammount of points for the account [compte] # update the ammount of points for the account [compte]
def update_row(compte, points, mycursor, mydb): def update_row(account, points, mycursor, mydb):
sql = f"UPDATE daily SET points = {points} WHERE compte = '{compte}' AND date = date() ;" sql = f"UPDATE daily SET points = {points} WHERE compte = '{account}' AND date = date() ;"
mycursor.execute(sql) mycursor.execute(sql)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record(s) updated")
# update the value of last_pts for the table comptes # update the value of last_pts for the table comptes
def update_last(compte, points, mycursor, mydb): def update_last(account, points, mycursor, mydb):
sql1 = f"UPDATE comptes SET last_pts = {points} WHERE compte = '{compte}';" sql1 = f"UPDATE comptes SET last_pts = {points} WHERE compte = '{account}';"
sql2 = f"select * from comptes where compte = '{compte}'" sql2 = f"select * from comptes where compte = '{account}'"
sql3 = f"INSERT INTO comptes (compte, last_pts,banned) VALUES ('{compte}', {points}, 0)" sql3 = f"INSERT INTO comptes (compte, last_pts,banned) VALUES ('{account}', {points}, 0)"
cmd = mycursor.execute(sql2) cmd = mycursor.execute(sql2)
if len(list(cmd)) == 0: if len(list(cmd)) == 0:
mycursor.execute(sql3) mycursor.execute(sql3)
else : else:
mycursor.execute(sql1) mycursor.execute(sql1)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record(s) updated")
# if return if there already is a line in the database for the account [compte]. if same_point is enabled, the line must also have the same number of points
# Return if there already is a line in the database for the account [account].
# if same_point is enabled, the line must also have the same number of points
# SQLITE # SQLITE
def get_row(compte, points, mycursor, same_points = True): def get_row(account, points, mycursor, same_points=True):
if same_points : if same_points:
mycursor.execute(f"SELECT * FROM daily WHERE points = {points} AND compte = '{compte}' AND date = date() ;") mycursor.execute(f"SELECT * FROM daily WHERE points = {points} AND compte = '{account}' AND date = date() ;")
else : else:
mycursor.execute(f"SELECT * FROM daily WHERE compte = '{compte}' AND date = date() ;") mycursor.execute(f"SELECT * FROM daily WHERE compte = '{account}' AND date = date() ;")
myresult = mycursor.fetchall() myresult = mycursor.fetchall()
return(len(myresult) == 1) return (len(myresult) == 1)
def add_to_database(compte, points, save_if_fail=True): def add_to_database(account, points):
if points is None: if points is None:
pass pass
else: else:
mydb = sqlite3.connect("/app/MsRewards-Reborn/MsRewards.db") mydb = sqlite3.connect("/app/MsRewards-Reborn/MsRewards.db")
mycursor = mydb.cursor() mycursor = mydb.cursor()
if get_row(compte, points,mycursor, True): #check if the row exist with the same ammount of points and do nothind if it does
#printf("les points sont deja bon") if get_row(account, points, mycursor, True):
#return(0) # check if the row exist with the same amount of points and do nothing if it does
pass pass
elif get_row(compte, points,mycursor, False) : #check if the row exist, but without the same ammount of points and update the point account then
update_row(compte, points,mycursor,mydb) # check if the row exist, but without the same amount of points and update the point account then
#printf("row updated") elif get_row(account, points, mycursor, False):
#return(1) update_row(account, points, mycursor, mydb)
else : # if the row don't exist, create it with the good ammount of points
add_row(compte, points,mycursor,mydb) else: # if the row don't exist, create it with the good amount of points
#return(2) #printf("row added") add_row(account, points, mycursor, mydb)
if int(points) > 10 :
update_last(compte, points, mycursor, mydb) if int(points) > 10:
update_last(account, points, mycursor, mydb)
mycursor.close() mycursor.close()
mydb.close() mydb.close()

View File

@ -1,7 +1,13 @@
from modules.imports import * from random import uniform
from modules.config import *
from modules.tools import * from selenium.common import TimeoutException
import modules.globals as g from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from modules.Tools.logger import debug
from modules.Tools.tools import *
def set_language(ldriver): def set_language(ldriver):
@ -16,10 +22,10 @@ def set_language(ldriver):
# scroll down # scroll down
action.reset_actions() action.reset_actions()
elm = ldriver.find_element(By.XPATH, "/html/body") elm = ldriver.find_element(By.XPATH, "/html/body")
ActionChains(ldriver)\ ActionChains(ldriver) \
.send_keys("french")\ .send_keys("french") \
.pause(0.5)\ .pause(0.5) \
.send_keys(Keys.TAB + Keys.TAB + Keys.ENTER + Keys.TAB + Keys.TAB + Keys.ENTER)\ .send_keys(Keys.TAB + Keys.TAB + Keys.ENTER + Keys.TAB + Keys.TAB + Keys.ENTER) \
.perform() .perform()
x_coord = 1163 x_coord = 1163
y_coord = 717 y_coord = 717
@ -33,64 +39,34 @@ def set_language(ldriver):
action.click().perform() action.click().perform()
def setup_proxy(ip: str, port: str) -> None: # Deal with RGPD popup as well as some random popup like 'are you satisfied' one
PROXY = f"{ip}:{port}" def rgpd_popup(config) -> None:
webdriver.DesiredCapabilities.FIREFOX['proxy'] = { for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"]:
"httpProxy": PROXY,
"sslProxy": PROXY,
"proxyType": "MANUAL",
}
#Deal with RGPD popup as well as some random popup like 'are you satisfied' one
def rgpd_popup(driver) -> None:
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] :
try: try:
driver.find_element(By.ID, i).click() config.WebDriver.driver.find_element(By.ID, i).click()
except: except Exception as err:
pass debug(err)
# save webdriver cookies
def save_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "w")
for i in driver.get_cookies():
f.write(str(i) + "\n")
f.close()
else :
pickle.dump(driver.get_cookies(), open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "wb"))
# load cookies previously saved to the driver
def load_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "r")
lines = f.readlines()
f.close()
cookies = [literal_eval(x) for x in lines]
else :
cookies = pickle.load(open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
""" """
send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random time between each press to simulate human action. send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random
time between each press to simulate human action.
keys can be an string, but also selenium keys keys can be an string, but also selenium keys
""" """
def send_keys_wait(element, keys: str) -> None: def send_keys_wait(element, keys: str) -> None:
for i in keys: for i in keys:
element.send_keys(i) element.send_keys(i)
sleep(uniform(0.1, 0.3)) sleep(uniform(0.1, 0.3))
# Wait for the presence of the element identifier or [timeout]s # Wait for the presence of the element identifier or [timeout]s
def wait_until_visible(search_by: str, identifier: str, timeout = 20, browser = None) -> None: def wait_until_visible(search_by: str, identifier: str, timeout: int = 20, browser=None) -> bool:
try : try:
WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((search_by,identifier)), "element not found") WebDriverWait(browser, timeout).until(
return(True) expected_conditions.visibility_of_element_located((search_by, identifier)), "element not found")
return True
except TimeoutException as e: except TimeoutException as e:
printf(f"element {identifier} not found after {timeout}s") error(f"element {identifier} not found after {timeout}s")
return(False) return False

View File

@ -1,8 +1,10 @@
class Banned(Exception): class Banned(Exception):
pass pass
class NotBanned(Exception): class NotBanned(Exception):
pass pass
class Identity(Exception): class Identity(Exception):
pass pass

View File

@ -1,30 +0,0 @@
driver = None
display = None
log = False
full_log = False
vnc_enabled = False
vnc_port = 2345
points_file = "/"
update_version = False
start_time = 0
mot_path = "/"
credential_path = "/"
discord_success_link = "https://example.com"
discord_error_link = "https://example.com"
discord_enabled_error = False
discord_enabled_success = False
avatar_url = ""
fidelity_link = "None"
discord_embed = False
headless = False
proxy_enabled = False
proxy_address = "0.0.0.0"
proxy_port = "0"
sql_enabled = False
sql_usr = "None"
sql_pwd = "azerty"
sql_host = "https://example.com"
sql_database = "MsRewards"
norvege = False
database_error_override = False
json_start = ""

View File

@ -1,82 +0,0 @@
from modules.imports import *
from modules.config import *
from modules.db import *
import modules.globals as g
# add the time arround the text given in [text]&
def Timer(text: str) -> str:
return(f"[{g._mail.split('@')[0]} - {datetime.today().strftime('%d/%m')} - {timedelta(seconds = round(float(time() - g.start_time)))}] " + str(text))
# replace the function print, with more options
# [txt] : string, [driver] : selenium webdriver
def printf(txt):
print(Timer(txt))
# return current page domain
def get_domain(driver):
return(driver.current_url.split("/")[2])
# check if the user is using IPV4 using ipify.org
# [driver] : selenium webdriver
# never used here
# can be useful as Ms had issues with IPV6 at some point
def check_ipv4(driver):
driver.get("https://api64.ipify.org")
elm = driver.find_element(By.TAG_NAME, "body")
if len(elm.text.split('.')) == 4 :
return True
return False
def custom_sleep(temps):
try :
if g.log : #only print sleep when user see it
points = ["", "", "", "", "", "", "", ""]
passe = 0
for i in range(int(temps)):
for i in range(8):
sleep(0.125)
passe += 0.125
print(f"{points[i]} - {round(float(temps) - passe, 3)}", end="\r")
print(" ", end="\r")
else:
sleep(temps)
except KeyboardInterrupt :
print("attente annulée")
def format_error(e) -> str:
tb = e.__traceback__
txt = ""
while tb != None :
txt = txt + f" -> {tb.tb_frame.f_code.co_name} ({tb.tb_lineno}) "
tb = tb.tb_next
return(txt + "\n" + str(e))
def progressBar(current, total=30, barLength=20, name="Progress"):
percent = float(current + 1) * 100 / total
arrow = "-" * int(percent / 100 * barLength - 1) + ">"
spaces = " " * (barLength - len(arrow))
print(name + ": [%s%s] %d %%" % (arrow, spaces, percent), end="\r")
def save_points_from_file(file):
with open(file) as f:
read = reader(f)
points_list = list(read)
for item in points_list:
compte, points = item[0], item[1]
add_to_database(compte, points, g.sql_host,g.sql_usr,g.sql_pwd,g.sql_database, save_if_fail=False)
with open(file, "w") as f:
f.write("")
def select_accounts(multiple = True):
system("clear") # clear from previous command to allow a clean choice
emails = [x[0] for x in g._cred] # list of all email adresses
emails_selected = enquiries.choose(f"quel{'s' if multiple else ''} compte{'s' if multiple else ''} ?", emails, multi=multiple)
return([x for x in g._cred if x[0] in emails_selected])

View File

@ -4,7 +4,7 @@ selenium
pillow pillow
pyvirtualdisplay pyvirtualdisplay
undetected_chromedriver undetected_chromedriver
requests requests>=2.31.0
flask flask
flask_sse flask_sse
EasyProcess EasyProcess

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
v6.8.0 v6.8.40