93 Commits

Author SHA1 Message Date
a197d44768 Added package tracking card 2024-06-18 20:37:14 +02:00
c7e110787b Debugging auto update 2024-05-16 17:52:12 +02:00
1db1de9606 oops, bad syntax 2024-05-15 10:03:01 +02:00
10d75f9d78 version bump 2024-05-15 09:52:56 +02:00
87fb791436 Explore on Bing: solve more challenges 2024-05-15 09:52:39 +02:00
6995bde8a6 Actualiser version 2024-05-12 18:55:51 +02:00
92069a013e Merge pull request 'Handle Streak-Protection Popup' (#12) from streak-protection into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/12
2024-05-12 18:55:34 +02:00
906d3e7822 catch another exception 2024-05-12 18:16:24 +02:00
778adc67d2 Et si on l'active ? 2024-05-12 18:07:36 +02:00
402b8cd3ef Close streak protection 2024-05-12 17:55:56 +02:00
3c74aa025e trying to fix web start 2024-04-26 16:06:33 +02:00
3123a1dbd0 trying to auto update chrome + fixed web override ? 2024-04-26 15:51:52 +02:00
27d45e88dd added more exploreOnBing 2024-04-26 15:43:23 +02:00
0685a42922 making scripts executables 2024-04-26 15:37:32 +02:00
6729703827 auto update hooks 2024-04-26 15:35:37 +02:00
304a222de1 fixed readlines ? 2024-04-26 14:51:23 +02:00
04d33f4ecd fixed readlines ? 2024-04-26 14:45:41 +02:00
ac22814605 fixed readlines ? 2024-04-26 14:41:00 +02:00
b7a89b56d0 fixed typo 2024-04-26 14:36:04 +02:00
127d16afea Changed version update logik 2024-04-26 14:32:01 +02:00
9bcbc81c2f Changement des musiques pour celles que Bing connais 2024-04-26 14:13:50 +02:00
12eba5cde7 top habitué au JS 2024-04-26 14:00:33 +02:00
22ea727c47 progress 2024-04-26 13:55:20 +02:00
05a1fd8557 pourquoi les custom attributes 2024-04-26 12:12:28 +02:00
39e226b564 pourquoi les custom attributes 2024-04-26 12:06:55 +02:00
cd00c8ca88 detecting which cutom search to do 2024-04-26 12:03:49 +02:00
43793d2c2c detecting which cutom search to do 2024-04-26 11:51:50 +02:00
ee6ec458fc switched to login on custom start 2024-04-26 11:27:16 +02:00
e6e8bdaa06 Trying to find out why the part1 is starting 2024-04-26 11:17:18 +02:00
9bd96ad876 version bump 2024-04-13 11:09:30 +02:00
ed517e7b03 Fix 'Welcome Tour'
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/11
2024-04-13 11:07:04 +02:00
01416c0e11 Check before scrolling, but should be good to merge ! 2024-04-13 11:01:25 +02:00
19cf77c6bd make an actual choice 2024-04-13 10:57:32 +02:00
feb7834d1f sleep a bit 2024-04-13 10:26:53 +02:00
1ea1ff776e wait until visible 2024-04-13 10:26:21 +02:00
ae023688a4 welcome-tour: URL check 2024-04-13 10:15:26 +02:00
fcb40537dc Use newer method 2024-04-13 10:06:21 +02:00
d7d2f49a3f pas la seule occurrence évidemment 2024-04-12 23:46:26 +02:00
68b5de32d6 fix de la popup "explorer le programme"
peu satisfaisant, consiste juste à fermer la popup à chaque fois qu'elle apparaît sans s'en débarrasser définitivement
2024-04-12 23:28:46 +02:00
c5e9fb1267 version bump ? 2024-04-12 20:01:53 +02:00
6ade73617a Make console resizable 2024-04-12 20:01:34 +02:00
37e8f6f61b Fix fake_popen 2024-04-12 16:20:25 +02:00
db6fa9b6b0 Add env variables arguments to flask app
- NO_SUBPROCESS to fake subprocesses calls
- APP_ROOT to use the app outside of Docker
2024-04-12 15:55:14 +02:00
d6988c03b4 Oops.. fixed nginx config 2024-04-12 15:51:20 +02:00
449d2da410 Use a different profile for mobile browser 2024-04-12 09:31:50 +02:00
3eb193eca3 Disable stream buffering on upstream nginx server 2024-04-10 14:24:57 +02:00
f566b2eeda Potentially fix no-discord 2024-04-10 12:15:14 +02:00
52e88f81b9 More checks on TFA 2024-04-10 12:14:41 +02:00
1a8137783c Even faster cached build 2024-04-10 11:43:54 +02:00
6f13b2532d Add clean.sh 2024-04-10 11:36:33 +02:00
3978c44bbc Use chrome profile to change language 2024-04-10 11:35:46 +02:00
49dc53ed32 Fix 2FA (language setting is not always working) 2024-04-10 11:04:54 +02:00
ba66a96c65 Check if creds are not empty 2024-04-10 10:29:53 +02:00
db157771de Merge flags 2024-04-08 16:51:43 +02:00
cbd1ad93a6 version bump 2024-04-08 16:38:16 +02:00
afabd94f0d Re-implement cookie login
with chrome profiles
2024-04-08 16:36:38 +02:00
81deaf05b0 Update chrome.deb URL 2024-04-08 16:34:36 +02:00
9af0f4aadb build.sh: check permissions 2024-04-03 15:42:14 +02:00
1d16294c04 Add more logs (custom.txt..) to logs view 2024-04-03 15:34:46 +02:00
fae2033061 Simplify Dockerfile to cache building layers 2024-04-03 15:26:02 +02:00
50c4036c73 Merge pull request 'Fix ANSI code formatting' (#9) from augustin64/MsRewards-Reborn:master into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/9
2024-03-31 12:05:17 +02:00
c683472895 Fix ANSI code formatting 2024-03-29 16:53:59 +01:00
178f2d472a Merge pull request 'Mise en forme des codes ANSI dans les logs' (#8) from augustin64/MsRewards-Reborn:augustin64-ansi-up into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/8
2024-03-28 23:56:33 +01:00
d3137f858a Mise en forme des codes ANSI dans les logs 2024-03-25 10:41:34 +01:00
d2ad467d4e Oops, pas push le bon fichier 2024-03-24 20:30:09 +01:00
b45e9e549f mise à jour automatique de chrome 2024-03-24 20:27:40 +01:00
200b0d8a86 Trying to fix an issue when an account fail 2024-03-05 21:18:39 +01:00
4a5af6455d Fixed 2FA issue + added better logs 2024-03-01 17:29:15 +01:00
49b691d736 not tested enough apparently 2024-02-28 18:22:15 +01:00
9549a6dea3 not tested enough apparently 2024-02-28 18:12:32 +01:00
8c224793b0 resize terminal on animation end 2024-02-28 15:04:19 +01:00
36fd92f71c fix json start 2024-02-28 14:44:11 +01:00
0a02eb2033 fix json start 2024-02-28 14:44:01 +01:00
6122d9ee13 fix json start + improve logs 2024-02-28 14:40:12 +01:00
a590d0f1b5 fix json start 2024-02-28 14:29:21 +01:00
64a018044c event on resize 2024-02-28 14:26:25 +01:00
91e7f31bac size issues 2024-02-28 14:17:55 +01:00
295f6d114d size issues 2024-02-28 14:14:29 +01:00
49e0d1b599 the issue seemed to be linked to the use of table instead of div 2024-02-28 14:13:19 +01:00
83eea03c73 the issue seemed to be linked to the use of table instead of div 2024-02-28 14:13:16 +01:00
3d096ec34c close to working 2024-02-28 12:09:32 +01:00
7bdf229fa8 je connais pas le js moi 2024-02-28 12:02:41 +01:00
0abb8a3494 weird errors 2024-02-28 12:00:19 +01:00
231c3b34e3 better terminal 2024-02-28 11:55:55 +01:00
c72aaf3fcc better terminal 2024-02-28 11:53:23 +01:00
675e67055b better terminal 2024-02-28 11:41:16 +01:00
a089fdfdf1 better terminal 2024-02-28 11:41:13 +01:00
0f60d67951 obsolete : module 2024-02-28 11:38:32 +01:00
1c7d1dfcd6 typo 2024-02-28 11:38:21 +01:00
19606e5f4c I'm just a clown, I didn't update... 2024-02-28 11:15:09 +01:00
aaafbb2257 some debug don't work at all ? 2024-02-28 11:13:09 +01:00
8d332f1c3c check if discord works 2024-02-28 11:10:48 +01:00
ced633dd68 refactored log_points 2024-02-28 10:49:27 +01:00
40 changed files with 1088 additions and 1746 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
**/.venv
user_data/*

8
.gitignore vendored
View File

@ -3,15 +3,17 @@ geckodriver.log
.vscode/
.idea
venv
**/.venv
/Git
page.html
screenshot.png
login.csv
data
**/__pycache__
user_data/*
install.sh
nohup.out
points.csv
file.png
user_data/configs.json
*.ts
LICENSE
README.md
venv

View File

@ -1,21 +1,42 @@
FROM python:3.10
ENV DEBIAN_FRONTEND noninteractive
WORKDIR /app/
RUN apt update \
&& wget http://security.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb \
&& dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb \
&& apt install redis libgtk-4-1 libvulkan1 libxdamage1 -y \
&& curl -sSLO https://nc.piair.xyz/s/BKLsBWoZkTdYjfq/download/chrome.deb \
&& ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime \
&& git clone https://gitea.augustin64.fr/piair/MsRewards-Reborn \
&& python3 -m pip install -r MsRewards-Reborn/requirements.txt \
&& wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key \
&& curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee -a /etc/apt/sources.list.d/grafana.list \
&& apt update \
&& apt install novnc websockify grafana xvfb nginx nano tzdata sqlite3 apt-transport-https software-properties-common wget wfrench tigervnc-standalone-server libasound2 libatk-bridge2.0-0 libnss3 libnspr4 xvfb libgbm1 libatk1.0-0 libu2f-udev libatspi2.0-0 libcups2 libxkbcommon0 libxrandr2 libdbus-1-3 xdg-utils fonts-liberation libdrm2 -y \
&& bash MsRewards-Reborn/config/config.sh \
# Initial apt install
RUN apt update
RUN apt install -y libgtk-4-1 libvulkan1 libxdamage1 \
novnc websockify xvfb nginx nano tzdata \
sqlite3 apt-transport-https software-properties-common \
wget wfrench tigervnc-standalone-server libasound2 \
libatk-bridge2.0-0 libnss3 libnspr4 xvfb libgbm1 libatk1.0-0 \
libu2f-udev libatspi2.0-0 libcups2 libxkbcommon0 libxrandr2 \
libdbus-1-3 xdg-utils fonts-liberation libdrm2
# Additional repos and packages
RUN wget http://security.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb \
&& dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb
RUN curl -sSL http://mirror.cs.uchicago.edu/google-chrome/pool/main/g/google-chrome-stable/google-chrome-stable_123.0.6312.86-1_amd64.deb -o chrome.deb \
&& dpkg -i chrome.deb
RUN ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime
RUN wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key \
&& echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee -a /etc/apt/sources.list.d/grafana.list
RUN curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
# Install from new repo
RUN apt update \
&& apt install -y redis grafana
# Configure Grafana
RUN grafana-cli plugins install frser-sqlite-datasource
COPY requirements.txt /app/requirements.txt
RUN python3 -m pip install -r requirements.txt
# Setup app
RUN git clone https://gitea.augustin64.fr/piair/MsRewards-Reborn
# Use this instead when developping locally:
# COPY . /app/MsRewards-Reborn
RUN bash MsRewards-Reborn/config/config.sh
ENV TZ="Europe/Paris"
WORKDIR /app/MsRewards-Reborn/Flask/

View File

@ -13,11 +13,27 @@ import re
from requests import get
import redis
APP_ROOT = os.getenv("APP_ROOT")
if APP_ROOT is None:
APP_ROOT = "/app/MsRewards-Reborn/"
NO_SUBPROCESS = os.getenv("NO_SUBPROCESS")
if NO_SUBPROCESS is not None:
def fake_popen(*args, **kwargs):
print("Calling subprocess.Popen with", args, kwargs)
subprocess.Popen = fake_popen
print("Faking subprocess calls")
# redis part for live update
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
def get_path(path):
return os.path.join(APP_ROOT, path)
def generate_output():
pubsub = r.pubsub()
pubsub.subscribe('console')
@ -32,7 +48,7 @@ def generate_output():
# the end
global password
with open("/app/MsRewards-Reborn/user_data/flask.json", "r") as inFile:
with open(get_path("user_data/flask.json"), "r") as inFile:
data = json.load(inFile)
password = data["password"]
@ -40,7 +56,7 @@ secret = data["secret"]
if secret == "":
import secrets
secret = secrets.token_hex()
with open("/app/MsRewards-Reborn/user_data/flask.json", "w") as inFile:
with open(get_path("user_data/flask.json"), "w") as inFile:
data = {
"password": password,
"secret": secret
@ -70,14 +86,14 @@ scheduler.add_job( # on relance le job
def start_ms(i):
print("\033[32m" + f"Starting config {i}" + "\033[0m")
log = open(f"/app/MsRewards-Reborn/Flask/static/logs/{i}.txt", 'a') # so that data written to it will be appended
subprocess.Popen([f"python3 -u /app/MsRewards-Reborn/V6.py -c {i}"], stdout=log, stderr=log, shell=True)
log = open(get_path(f"Flask/static/logs/{i}.txt"), 'a') # so that data written to it will be appended
subprocess.Popen([f"python3 -u {get_path('V6.py')} -c {i}"], stdout=log, stderr=log, shell=True)
log.close()
TriggerDict = {}
def update_jobs():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
for i in configs:
try :
@ -120,7 +136,7 @@ app = Flask(__name__)
@app.context_processor
def inject_default_variables():
with open("/app/MsRewards-Reborn/version", "r") as f:
with open(get_path("version"), "r") as f:
version = f.readline().replace("\n", '')
return dict(version=version)
"""
@ -175,7 +191,7 @@ def change_password():
if request.method == 'POST':
password = request.form["password"]
subprocess.Popen(["grafana-cli", "admin", "reset-admin-password", password])
with open("/app/MsRewards-Reborn/user_data/flask.json", "w") as inFile:
with open(get_path("user_data/flask.json"), "w") as inFile:
data = {
"password": password,
"secret": secret
@ -201,21 +217,21 @@ def load_user(userid):
@app.route("/")
def main():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
return(render_template("schedule.html", data=configs))
@app.route("/discord/")
def discord_get():
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
with open(get_path("user_data/discord.json"), "r") as inFile:
data = json.load(inFile)
return(render_template("discord.html", data=data, len=maxi(data)))
@app.route("/discord/", methods=["post"])
def discord_post():
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
with open(get_path("user_data/discord.json"), "r") as inFile:
data = json.load(inFile)
action = request.form
if action['DISCORD'] == "delete" :
@ -237,7 +253,7 @@ def discord_post():
name = action["name"] if action["name"] else f"unnamed{action['select']}"
data[config] = {"errorsL" : errorsL, "errorsT": errorsT, "successT": successT, "successL": successL, "name": name}
with open("/app/MsRewards-Reborn/user_data/discord.json", "w") as outFile:
with open(get_path("user_data/discord.json"), "w") as outFile:
json.dump(data, outFile)
return(render_template("discord.html", data=data, len=maxi(data)))
@ -249,7 +265,7 @@ def dev2():
@app.route("/settings/")
def settings_get():
with open("/app/MsRewards-Reborn/user_data/settings.json", "r") as inFile:
with open(get_path("user_data/settings.json"), "r") as inFile:
settings = json.load(inFile)
return(render_template("settings.html", data=settings))
@ -259,21 +275,21 @@ def settings_post():
settings = {}
action = request.form
settings['avatarlink'] = action["avatarlink"]
with open("/app/MsRewards-Reborn/user_data/settings.json", "w") as inFile:
with open(get_path("user_data/settings.json"), "w") as inFile:
json.dump(settings, inFile)
return(render_template("settings.html", data=settings))
@app.route("/proxy/")
def proxy_get():
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
with open(get_path("user_data/proxy.json"), "r") as inFile:
j = json.load(inFile)
return(render_template("proxy.html", data=j, len=maxi(j)))
@app.route("/proxy/", methods=["post"])
def proxy_post():
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
with open(get_path("user_data/proxy.json"), "r") as inFile:
data = json.load(inFile)
action = request.form
print(action)
@ -290,21 +306,21 @@ def proxy_post():
except :
print("error : probably bad config")
with open("/app/MsRewards-Reborn/user_data/proxy.json", "w") as outFile:
with open(get_path("user_data/proxy.json"), "w") as outFile:
json.dump(data, outFile)
return(render_template("proxy.html", data=data, len=maxi(data)))
@app.route("/schedule/")
def schedule_get():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
return(render_template("schedule.html", data=configs))
@app.route("/schedule/", methods=["post"])
def schedule_post():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
data = dict(request.form)
@ -318,7 +334,7 @@ def schedule_post():
configs[i]["time"] = data[f"time{i}"]
configs[i]["enabled"] = data[f"switch{i}"] == "on"
with open("/app/MsRewards-Reborn/user_data/configs.json", "w") as inFile:
with open(get_path("user_data/configs.json"), "w") as inFile:
json.dump(configs, inFile)
update_jobs()
return(render_template("schedule.html", data=configs))
@ -326,11 +342,11 @@ def schedule_post():
@app.route("/config/")
def config_get():
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
with open(get_path("user_data/proxy.json"), "r") as inFile:
proxys = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
with open(get_path("user_data/discord.json"), "r") as inFile:
discords = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
return(render_template("config.html", data=configs, discords=discords, proxys=proxys, configs=configs, len=maxi(configs)))
@ -338,11 +354,11 @@ def config_get():
@app.route("/config/", methods=["POST"])
def config_post():
action = request.form
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
with open(get_path("user_data/proxy.json"), "r") as inFile:
proxys = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
with open(get_path("user_data/discord.json"), "r") as inFile:
discords = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
if action["data"] == "delete":
@ -365,16 +381,26 @@ def config_post():
"enabled":"False",
"accounts": comptes
}
with open("/app/MsRewards-Reborn/user_data/configs.json", "w") as outFile:
with open(get_path("user_data/configs.json"), "w") as outFile:
json.dump(configs, outFile)
return(render_template("config.html", data=configs, discords=discords, proxys=proxys, configs=configs, len=maxi(configs)))
@app.route("/logs/", methods=["GET", "POST"])
def logs():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
print(configs)
return(render_template("logs.html", data=configs))
files = [(configs[i]["name"], i) for i in configs]
config_files = [i[1] for i in files]
for f in os.listdir(get_path("Flask/static/logs")):
fid = ".".join(f.split(".")[:-1]) # filename without .txt
if f != ".gitignore" and fid not in config_files:
files.append((f, fid))
return render_template(
"logs.html",
files=files
)
@app.route("/stats/", methods=["GET", "POST"])
@ -385,21 +411,21 @@ def stats():
@app.route("/override/", methods=["POST"])
def override_post():
json = request.form.to_dict(flat=False)
log = open(f"/app/MsRewards-Reborn/Flask/static/logs/custom.txt", 'w') # so that data written to it will be appended
subprocess.Popen([f"python3 -u /app/MsRewards-Reborn/V6.py -c {json['config'][0]} --json \"{json}\""], stdout=log, stderr=log, shell=True)
log = open(get_path("Flask/static/logs/custom.txt"), 'w') # so that data written to it will be appended
subprocess.Popen([f"python3 -u {get_path('V6.py')} -c {json['config'][0]} --json \"{json}\""], stdout=log, stderr=log, shell=True)
log.close()
return(render_template("vnc_post.html"))
@app.route("/override/", methods=["GET"])
def override_get():
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
return(render_template("vnc_get.html", configs=configs))
@app.route('/download/<path:filename>', methods=['GET', 'POST'])
@login_required
def download(filename):
return send_from_directory(directory='/app/MsRewards-Reborn/user_data/', path=filename, as_attachment=True)
return send_from_directory(directory=get_path("user_data/"), path=filename, as_attachment=True)
def allowed_file(filename):
@ -420,8 +446,8 @@ def upload_file():
elif file and allowed_file(file.filename):
filename = secure_filename(file.filename)
print(os.path.join('/app/MsRewards-Reborn/user_data/', filename))
file.save(os.path.join('/app/MsRewards-Reborn/user_data/', filename))
print(os.path.join(get_path("user_data/"), filename))
file.save(os.path.join(get_path("user_data/"), filename))
i += 1
print(i)
@ -439,4 +465,7 @@ def maxi(dict):
update_jobs()
subprocess.Popen(["bash",'/app/MsRewards-Reborn/config/request.sh'])
subprocess.Popen(["bash", get_path("config/request.sh")])
if __name__ == "__main__":
app.run()

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 nginx start
nohup redis-server &
gunicorn --reload --worker-class gevent -b 0.0.0.0:6666 'app:app'

View File

@ -0,0 +1,17 @@
#console {
height: 100%;
width: 20%;
float: left;
resize: horizontal;
overflow: auto;
}
#vnc-container {
height: 100%;
width: 80%;
float: left;
}
.container {
height: 100%;
}

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

@ -8,14 +8,37 @@
<select name="select" onchange="change_logs(this.value)">
<option id="null" value="0">Choisir une config</option>
{% for i in data %}
<option id="{{data[i]['name']}}" value="{{i}}">{{data[i]['name']}}</option>
{% for file in files %}
<option id="{{ file[0] }}" value="{{ file[1] }}">{{ file[0] }}</option>
{% endfor %}
</select>
<br><br>
<iframe type="text/html" src="{{url_for('static', filename='logs/1.txt')}}" width="100%" height="85%" id="embed">
<iframe type="text/html" src="{{url_for('static', filename='logs/1.txt')}}" width="100%" height="85%" id="embed"></iframe>
<script defer>
const iframe = document.getElementsByTagName("iframe")[0];
var script = document.createElement('script');
// Wait until ansi_up load
script.onload = function () {
// Wait until iframe load
iframe.onload = function() {
const subdoc = iframe.contentWindow.document;
const subBody = subdoc.getElementsByTagName("body")[0]
let ansiOutput = subBody;
// Depending on the content encoding (and maybe on the browser)
// a <pre> is added around the content of the file
if (subBody.getElementsByTagName("pre").length > 0) {
ansiOutput = subBody.getElementsByTagName("pre")[0];
}
const ansi_up = new AnsiUp();
ansiOutput.innerHTML = ansi_up.ansi_to_html(ansiOutput.innerText);
}
};
script.src = "https://cdn.jsdelivr.net/npm/ansi_up@4.0.4/ansi_up.js";
document.head.appendChild(script);
</script>
{% endif %}
{% endblock %}

View File

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

311
V6.py
View File

@ -1,8 +1,11 @@
#!/usr/bin/python3.10
#!/usr/bin/python3
import random
import subprocess
from modules.Classes.Config import Config
from modules.Classes.DiscordLogger import DiscordLogger
from modules.Classes.UserCredentials import UserCredentials
from modules.Tools.logger import warning, critical
from modules.Tools.logger import critical, warning
from modules.cards import *
from modules.config import *
from modules.db import add_to_database
@ -22,16 +25,33 @@ def create_driver(mobile=False):
"AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/22 Mobile Safari/537.36"
)
chrome_options = webdriver.ChromeOptions()
chrome_profile_dir = init_profile(config.UserCredentials.get_mail(), mobile=mobile)
# Full list on https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
arguments = [
"--no-first-run",
"--ash-no-nudges",
"--no-default-browser-check",
"--disable-features=PrivacySandboxSettings4,Translate",
"--disable-search-engine-choice-screen",
f"--user-data-dir={chrome_profile_dir}/"
]
if mobile:
chrome_options.add_argument(f"--user-agent={mobile_user_agent}")
arguments.append(f"--user-agent={mobile_user_agent}")
else:
chrome_options.add_argument(f"--user-agent={pc_user_agent}")
arguments.append(f"--user-agent={pc_user_agent}")
# disabled as it may cause detection
if config.proxy.is_enabled():
chrome_options.add_argument(f'--proxy-server={config.proxy.ip}:{config.proxy.port}')
arguments.append(f'--proxy-server={config.proxy.ip}:{config.proxy.port}')
chrome_options = webdriver.ChromeOptions()
for arg in arguments:
chrome_options.add_argument(arg)
driver = uc.Chrome(options=chrome_options)
set_language(driver)
return driver
@ -54,8 +74,12 @@ def play_quiz2(override=10) -> None:
custom_sleep(uniform(3, 5))
js_function = """
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 namedRAValue() { //allow calls to getRAvalue
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 namedRAValue() { //allow calls to getRAValue
return _w.getRAValue()
};
if (br(document.getElementById("rqAnswerOption0").attributes["data-option"].value) == namedRAValue()){
@ -148,7 +172,7 @@ def play_quiz4(override: int = None):
except Exception as e:
log_error(e)
raise ValueError(e)
info("Quiz 8 done.")
info("Quiz 4 done.")
custom_sleep(3)
@ -161,6 +185,8 @@ def do_poll():
try:
answer_elem.click()
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)
custom_sleep(uniform(2, 2.5))
except Exception as err:
@ -173,6 +199,43 @@ def do_poll():
# Find each playable card and tries to click on it to earn points
def all_cards():
driver = config.WebDriver.driver
def check_welcome_tour() -> bool:
if "rewards.bing.com/welcometour" not in driver.current_url:
return False
info("Popup 'Explorer le programme' reçue")
wait_until_visible(By.ID, "welcome-tour", timeout=5, browser=driver)
custom_sleep(1.5)
welcome_tour = driver.find_element(By.ID, "welcome-tour")
interest_button_box = welcome_tour.find_element(By.CLASS_NAME, "interest-buttons")
interests = interest_button_box.find_elements(By.CLASS_NAME, "ng-binding")
debug("Got the following interests: " + str(interests))
random.choice(interests).click() # Choose interest
custom_sleep(1.5)
claim_button = welcome_tour.find_element(By.ID, "claim-button")
claim_button.click() # submit
custom_sleep(1.5)
return True
def check_streak_protection() -> bool:
"""
Ne perdez plus jamais votre série !
"""
try:
streak_protection_close = driver.find_element(By.ID, "streak-protection-popup-close-cross")
streak_protection_activate = driver.find_elements(By.CLASS_NAME, "earningPagePopUpPopUpSelectButton")
streak_protection_activate[0].click()
info("Popup 'Streak Protection' reçue")
custom_sleep(1.5)
return True
except (exceptions.NoSuchElementException, exceptions.ElementNotInteractableException, IndexError):
# les éléments sont présents dans le DOM même quand la popup n'est pas visible apparemment
return False
driver.get("https://rewards.bing.com")
wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver)
@ -186,7 +249,7 @@ def all_cards():
info("no promo card")
if len(card_list) < 10: # most likely an error during loading
if "suspendu" in driver.page_source:
if "suspendu" in driver.page_source or "suspended" in driver.page_source:
raise Banned()
driver.refresh()
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
@ -216,24 +279,39 @@ def all_cards():
if i == len(card_list) and i > 15:
checked = False
if checked:
if not checked:
continue
try:
activity = findall("data-bi-id=\"([^\"]+)\"", card_list[i].get_attribute("innerHTML"))[0]
except Exception as e:
warning("Can't find activity." + str(e))
activity = ""
custom_sleep(1.5)
check_welcome_tour()
check_streak_protection()
driver.execute_script("arguments[0].scrollIntoView();", card_list[i])
custom_sleep(1.5)
card_list[i].click()
if len(driver.window_handles) > 1:
driver.switch_to.window(driver.window_handles[1])
try_play(driver.title)
try_play(driver.title, activity)
close_tab(driver.window_handles[1])
try:
driver.refresh()
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
if "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML"):
if "mee-icon-AddMedium" not in card_list[i].get_attribute("innerHTML"):
continue
check_welcome_tour()
check_streak_protection()
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 ?")
@ -246,6 +324,7 @@ def all_cards():
except Exception as e:
debug(e)
driver.get("https://rewards.bing.com")
except Exception as err:
log_error(err)
custom_sleep(3)
@ -259,7 +338,7 @@ def promo():
if not elm:
break
if i > 3:
log_error("plus de 3 promo cards, probablement une pa skipable")
log_error("There is more than 3 promo cards, most likely an unskippable one.")
try:
driver.find_element(By.CSS_SELECTOR,
'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click()
@ -270,7 +349,7 @@ def promo():
elm.click()
except Exception as e:
driver.execute_script("arguments[0].click();", elm)
warning(f"that should't be there (promo), but the workarround seemed to work {e}")
warning(f"that shouldn't be there (promo), but the workaround seemed to work {e}")
custom_sleep(3)
if len(driver.window_handles) > 1:
driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1])
@ -279,15 +358,79 @@ def promo():
else:
try:
spotify(driver)
except:
warning("no new windows")
except Exception as e:
warning(f"no new windows {format_error(e)}")
driver.get("https://rewards.bing.com")
driver.refresh()
custom_sleep(3)
def explore_on_bing(activity: str, config: Config):
driver = config.WebDriver.driver
def search_bing(txt):
search_elm = driver.find_element(By.ID, "sb_form_q")
send_keys_wait(search_elm, txt)
send_keys_wait(search_elm, Keys.ENTER)
if "lyrics" in activity:
search_bing(
f"paroles de {['Gata', 'Pyramide', 'Dolce Camara', 'Position', 'Mami Wata'][randint(0, 4)]}") # merci bing copilot pour les titres
elif "flight" in activity:
search_bing(
f"vol {['Paris - New York', 'Londres Amsterdam', 'Bora-Bora Miami', 'Los Angeles Toulouse', 'Rome Dubai'][randint(0, 4)]}")
elif "shopping" in activity:
search_bing(f"idée cadeau {['Noel', 'Anniversaire'][randint(0, 1)]}")
elif "movie" in activity:
search_bing(
f"Distribution {['Code 8 part 2', 'The Hunger Games: The ballad of Songbirds & Snakes', 'Rebel Moon: Part Two', 'Dune II', 'Wonka'][randint(0, 4)]}")
elif "translator" in activity:
search_bing(f"traduction {config.wordlist.get_word()} en anglais")
elif "map" in activity:
search_bing(f"{['Paris', 'Nice', 'Marseille', 'Bordeaux', 'Lyon'][randint(0, 4)]} carte")
elif "restaurant" in activity:
search_bing(random.choice([
"restaurant à proximité",
"restaurant pas loin",
"manger dans le coin"
]))
elif "recipe" in activity:
search_bing("recette de " + random.choice([
"cake aux olives",
"tarte tatin",
"Kouign Amann",
"poulet au Curry",
"lasagnes aux épinards et ricotta",
"Boeuf Bourguignon",
"dessert",
"gateau au chocolat",
"crêpe sucrée"
])) # Merci llama pour les idées
elif "currency" in activity:
currencies = [
"euros",
"dollars canadiens",
"dollars",
"livres",
"francs suisses",
"roubles",
"pesos",
"bitcoin",
"anciens francs"
]
chosen = random.sample(currencies, k=2)
search_bing(f"convertir {random.randint(2, 120)} {chosen[0]} en {chosen[1]}")
elif "weather" in activity:
search_bing(f"météo {['Paris', 'Nice', 'Marseille', 'Bordeaux', 'Lyon'][randint(0, 4)]}")
elif "packagetracking" in activity:
driver.get("https://www.bing.com/?setmkt=en-US&setlang=en-US")
search_bing(f"{['fedex', 'UPS', '']} package tracking")
else:
log_error(f"Explore on bing: {activity} not found.")
# Find out which type of action to do
def try_play(nom="inconnu"):
def try_play(nom="unknown", activity=""):
driver = config.WebDriver.driver
rgpd_popup(config)
@ -333,7 +476,7 @@ def try_play(nom="inconnu"):
info("On fidelity page.")
fidelity()
elif wait_until_visible(By.ID, "rqStartQuiz", 5, driver):
elif wait_until_visible(By.ID, "rqStartQuiz", 5, driver, raise_error=False):
custom_sleep(3)
driver.find_element(By.ID, "rqStartQuiz").click() # start the quiz
answer_number = driver.page_source.count("rqAnswerOption")
@ -341,11 +484,14 @@ def try_play(nom="inconnu"):
elif "rqQuestionState" in driver.page_source:
number = driver.page_source.count("rqAnswerOption")
warning(f"recovery détecté. quiz : {number}")
warning(f"recovery detected. quiz : {number}")
play(number - 1)
elif "exploreonbing" in activity:
info(f"Explore on bing: {activity}")
explore_on_bing(activity, config)
custom_sleep(uniform(3, 5))
else:
info(f"Nothing to do on page `{nom}`")
info(f"Nothing obvious to do on page `{nom}`.")
custom_sleep(uniform(3, 5))
@ -356,20 +502,33 @@ def login_part_1():
driver = config.WebDriver.driver
driver.get("https://login.live.com")
wait_until_visible(By.ID, "i0116", browser=driver)
mail_elem = driver.find_element(By.ID, "i0116")
send_keys_wait(mail_elem, config.UserCredentials.get_mail())
mail_elem.send_keys(Keys.ENTER)
send_wait_and_confirm(
driver.find_element(By.ID, "i0116"),
config.UserCredentials.get_mail()
)
wait_until_visible(By.ID, "i0118", browser=driver)
pwd_elem = driver.find_element(By.ID, "i0118")
send_keys_wait(pwd_elem, config.UserCredentials.get_password())
pwd_elem.send_keys(Keys.ENTER)
custom_sleep(2)
send_wait_and_confirm(
driver.find_element(By.ID, "i0118"),
config.UserCredentials.get_password()
)
# 2FA
if "Entrez le code de sécurité" in driver.page_source:
try:
a2f_elem = driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC")
a2f_elem.send_keys(config.UserCredentials.get_tfa().now())
a2f_elem.send_keys(Keys.ENTER)
if not wait_until_visible(By.ID, "idTxtBx_SAOTCC_OTC", browser=driver, timeout=5, raise_error=False):
custom_sleep(2)
return
tfa = config.UserCredentials.get_tfa()
if tfa is None:
error("2FA needed but no code available for this account, sending error")
raise ValueError("2FA needed but no code available for this account")
else:
a2f_code = tfa.now()
info(f"Need 2FA, I have code: {a2f_code}")
send_wait_and_confirm(
driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC"),
a2f_code
)
except Exception as err:
log_error(err)
@ -406,8 +565,18 @@ def login_part_2():
# login() tries to login to your Microsoft account.
# it uses global variable g._mail and g._password to login
def login():
def logged_in():
driver.get("https://login.live.com")
custom_sleep(10)
debug(get_domain(driver))
if get_domain(driver) == "account.microsoft.com":
return True
return False
info("Logging in...")
driver = config.WebDriver.driver
try:
if not logged_in():
login_part_1()
login_part_2()
driver.get("https://rewards.bing.com/")
@ -457,26 +626,22 @@ def bing_pc_search(override=randint(35, 40)):
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
# todo: refactor
# Sends current account's points to database
def log_points():
driver = config.WebDriver.driver
account = config.UserCredentials.get_mail()
def get_points():
driver.get("https://rewards.bing.com")
custom_sleep(1)
wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver)
try:
point = search('availablePoints\":([\d]+)', driver.page_source)[1]
except Exception as e:
points = search('availablePoints\":([\d]+)', driver.page_source)[1]
except Exception as err:
log_error(
f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}")
error("Can't get points.")
f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(err)}")
error(f"Can't get points. {format_error(err)}")
return -1
return point
points = get_points()
custom_sleep(uniform(3, 20))
account_name = account.split("@")[0]
@ -509,15 +674,15 @@ def fidelity():
try:
button_text = search('<span class="pull-left margin-right-15">([^<^>]+)</span>',
card_elem.get_attribute("innerHTML"))[1]
bouton_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]')
bouton_card.click()
button_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]')
button_card.click()
except Exception as e1:
try:
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')
recover_elem.click()
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
custom_sleep(uniform(3, 5))
driver.switch_to.window(driver.window_handles[2])
@ -534,23 +699,26 @@ def fidelity():
if driver.current_url != "https://rewards.bing.com":
driver.get("https://rewards.bing.com")
try:
pause = driver.find_element(By.CSS_SELECTOR,
f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]') # mettre le truc en pause
pause = driver.find_element(By.CSS_SELECTOR, f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]')
pause.click()
except Exception as e:
error(f"erreur lors du click de pause: probablement pas de cartes {e}")
return "no cards"
debug("No pause button.")
cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]')
nb_cartes = len(cartes)
if nb_cartes == 0:
warning("No fidelity cards detected")
return "No cards."
checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]')
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")
ok = checked_txt.count("StatusCircleOuter checkmark")
total = checked_txt.count("StatusCircleOuter")
if (ok != total):
if ok != total:
elm = driver.find_elements(By.CLASS_NAME, 'clickable-link')[i]
if not "moviesandtv" in elm.get_attribute("innerHTML"): # not the film card
# legacy code. Should be removed
if "moviesandtv" not in elm.get_attribute("innerHTML"): # not the film card
elm.click()
driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1])
sub_fidelity()
@ -611,9 +779,11 @@ def daily_routine(cred: UserCredentials, custom=False):
try:
if not custom: # custom already is logged in
login()
except Banned:
log_error("This account is locked.")
return
raise Banned()
except Identity:
log_error("This account has an issue.")
return
@ -652,8 +822,8 @@ def json_start(json_entry, cred: UserCredentials):
config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24))
config.display.start()
for account_id in range(5):
account_id = 0
while config.UserCredentials.is_valid():
start = False
for action in ["unban", "tout", "pc", "mobile", "daily"]:
try:
@ -664,10 +834,10 @@ def json_start(json_entry, cred: UserCredentials):
pass
if start:
config.WebDriver.set_pc_driver(create_driver())
config.WebDriver.switch_to_driver("PC")
driver = config.WebDriver.driver
try:
if str(account_id) in json_entry["unban"]:
login_part_1()
if "unban" in json_entry and str(account_id) in json_entry["unban"]:
login()
info("\nGO TO example.com TO PROCEED or wait 1200 secs.")
for _ in range(1200):
sleep(1)
@ -676,13 +846,10 @@ def json_start(json_entry, cred: UserCredentials):
break
else:
login()
except KeyError:
login()
try:
if str(account_id) in json_entry["tout"]:
daily_routine(cred)
except KeyError:
pass
daily_routine(cred, True)
else:
try:
if str(account_id) in json_entry["daily"]:
@ -708,12 +875,17 @@ def json_start(json_entry, cred: UserCredentials):
log_error(e)
except KeyError:
pass
except KeyError:
pass
try:
log_points()
except Exception as e:
error(f"CustomStart {e}")
driver.close()
cred.next_account()
account_id += 1
config.display.stop()
@ -727,13 +899,17 @@ def default_start():
while config.UserCredentials.is_valid():
custom_sleep(1)
info("Starting and configuring driver.")
try:
config.WebDriver.set_pc_driver(create_driver())
except:
info("Could not configure driver. Trying to update it.")
subprocess.Popen(["python3", "/app/MsRewards-Reborn/modules/Tools/update_chrome.py"])
config.WebDriver.set_pc_driver(create_driver())
config.WebDriver.switch_to_driver("PC")
info("Driver started.")
config.WebDriver.pc_driver.implicitly_wait(3)
try:
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")
custom_sleep(wait_time)
daily_routine(config.UserCredentials)
@ -743,12 +919,16 @@ def default_start():
config.WebDriver.pc_driver.quit()
config.display.stop()
break
except Banned:
warning("this account is banned. Switching to next account")
except Exception as e:
log_error(f"Error not caught. Skipping this account. " + format_error(e))
critical(f"Error not caught. Skipping this account. {e}")
config.WebDriver.pc_driver.quit()
finally:
config.UserCredentials.next_account()
config.display.stop()
@ -765,7 +945,6 @@ def check_updated():
if __name__ == "__main__":
config = Config(args)
check_updated()
match config.start:
case "json":
json_start(config.json_entry, config.UserCredentials)

View File

@ -1 +1,12 @@
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
#!/bin/bash
docker-do () { # Check if sudo needs to be used
if id -nG "$(whoami)" | grep -qw "docker"; then
docker $@
else
sudo docker $@
fi
}
docker-do build --network host -t msrewards .
docker-do run -d --restart unless-stopped -p 1234:1234 -p 2345:2345 -ti --shm-size=2gb --name MsRewards msrewards

13
clean.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
docker-do () { # Check if sudo needs to be used
if id -nG "$(whoami)" | grep -qw "docker"; then
docker $@
else
sudo docker $@
fi
}
docker-do stop MsRewards
docker-do rm MsRewards
docker-do image rm msrewards

View File

@ -46,6 +46,7 @@ server {
proxy_pass "http://127.0.0.1:6666";
chunked_transfer_encoding off;
proxy_buffering off;
add_header X-Accel-Buffering no;
}
}
@ -59,7 +60,6 @@ sqlite3 /app/MsRewards-Reborn/MsRewards.db "CREATE TABLE comptes (id INTEGER PRI
printf "\nconfigurating grafana\n"
cp /app/MsRewards-Reborn/config/grafana.ini /etc/grafana/
grafana-cli plugins install frser-sqlite-datasource
printf "setting up default dashboard"
cp /app/MsRewards-Reborn/config/Stats-dashbord.json /usr/share/grafana/public/dashboards/home.json

File diff suppressed because it is too large Load Diff

View File

@ -16,4 +16,4 @@ services:
- "2345:2345"
shm_size: 2gb
volumes:
- "./:/data"
- "./data/:/data"

12
hooks/bump.sh Executable file
View File

@ -0,0 +1,12 @@
file=version
if [ "$(git diff HEAD version | wc -w)" -eq 0 ]
then
echo 'updating minor version'
new_path=$(cat $file | awk -F . '{print $1"."$2"."$3+1 }')
echo $new_path > $file
git add version
else
echo 'Version have been updated manually'
fi
echo Version: $(cat $file)

1
hooks/pre-commit Executable file
View File

@ -0,0 +1 @@
sh hooks/bump.sh

View File

@ -22,7 +22,8 @@ class Config:
proxy = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
config = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/version", "r") as inFile:
version = inFile.readline()
"""
setup standalone stuff
"""
@ -31,10 +32,9 @@ class Config:
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
self.version = version
"""
setup UserCredential
"""
@ -50,9 +50,14 @@ class Config:
"""
self.discord = DiscordConfig()
self.discord.avatar_url = settings["avatarlink"]
self.discord.wh_link = discord[config[args.config]["discord"]]["errorsL"]
if self.discord.wh_link != "":
if (
"discord" in config[args.config]
and config[args.config]["discord"] in discord
and "errorsL" in discord[config[args.config]["discord"]]
and discord[config[args.config]["discord"]]["errorsL"] != ""
):
self.discord.wh_link = discord[config[args.config]["discord"]]["errorsL"]
self.discord.wh = Webhook.from_url(self.discord.wh_link, adapter=RequestsWebhookAdapter())
else:
self.discord.wh = FakeWebHook()
@ -76,4 +81,11 @@ class Config:
self.display = display
def has_been_updated(self):
return self.version != "None"
with open('/app/MsRewards-Reborn/version', "r") as inFile:
in_file_content = inFile.readlines()
if self.version != in_file_content[0]:
self.version = in_file_content[0]
with open('/app/MsRewards-Reborn/user_data/version', "w") as outFile:
outFile.write(self.version)
return True
return False

View File

@ -9,6 +9,6 @@ class DiscordConfig:
class FakeWebHook:
def send(self, *args):
debug(f"Used a webhook call without webhook url with {args}")
def send(self, *args, **kwargs):
debug(f"Used a webhook call without webhook url with {args} {kwargs}")

View File

@ -1,8 +1,7 @@
from discord import Embed, Colour, File
from modules.Classes.Config import Config
from modules.Classes.UserCredentials import UserCredentials
from modules.Tools.logger import info, warning, error, critical
from modules.Tools.logger import error
from modules.Tools.tools import format_error
@ -25,14 +24,13 @@ class DiscordLogger:
img.save("screenshot.png")
embed = Embed(
title="An Error has occured",
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.creds.get_mail())
embed.set_footer(text=self.config.UserCredentials.get_mail() + " - " + self.config.WebDriver.current_driver())
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)

View File

@ -11,12 +11,15 @@ class Driver:
self.mobile_driver = mobile_driver
def switch_to_driver(self, driver: str):
match driver:
case "pc" | "PC" | "Pc":
match driver.lower():
case "pc":
self.driver = self.pc_driver
case "mobile" | "Mobile":
case "mobile":
self.driver = self.mobile_driver
case _:
raise ValueError("The driver must be either pc or mobile")
def current_driver(self):
return "PC" if self.pc_driver == self.driver else "Mobile"

View File

@ -1,5 +1,3 @@
import json
from pyotp import TOTP
from modules.Tools.logger import debug, warning
@ -12,7 +10,8 @@ class UserCredentials:
self.total = 0
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] = {
"username": username,
"password": password,
@ -31,12 +30,17 @@ class UserCredentials:
def get_tfa(self):
if not self.tfa_enable():
warning("Warning: TFA is not enabled. Calling get_tfa is an expected behaviour.")
return TOTP(self.data[self.current]["tfa"])
warning("Warning: TFA is not enabled. Can't get a TFA code.")
return None
return TOTP(self.data[self.current]["2fa"])
def next_account(self):
self.current += 1
if self.is_valid():
debug(f"New credentials: {self.data[self.current]}")
else:
debug("No new credentials.")
def is_valid(self):
return self.current < self.total
return (self.current < self.total
and self.get_mail() != "" and self.get_mail is not None)

View File

@ -0,0 +1,8 @@
import undetected_chromedriver as uc
from pyvirtualdisplay.smartdisplay import SmartDisplay
display = SmartDisplay(size=(1920, 1080))
display.start()
driver = uc.Chrome()
driver.close()
driver.close()

View File

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

View File

@ -10,7 +10,7 @@ def get_domain(driver):
def custom_sleep(temps):
try:
if True: # todo: change this awful condition
if False: # todo: change this awful condition
points = ["", "", "", "", "", "", "", ""]
passe = 0
for _ in range(int(temps)):

View File

@ -0,0 +1,50 @@
import requests
import re
from packaging import version
import subprocess
from logger import critical, info, error
errorMessage = subprocess.run(['python3', 'generate_error.py'], check=False, stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stderr.decode("utf-8")
versionPattern = "This version of ChromeDriver only supports Chrome version ([0-9]+)"
try:
versionN = re.search(versionPattern, errorMessage)[1]
except Exception as e:
critical("Can't get version number from error")
error(e)
info("error message")
info(errorMessage)
exit(0)
info(f"Needed version : '{versionN}'")
downloadUrl = "http://mirror.cs.uchicago.edu/google-chrome/pool/main/g/google-chrome-stable/"
r = requests.get(downloadUrl)
content = r.text
exactVersionList = re.findall(f"(google-chrome-stable_({versionN}.[0-9.]+)[^<^>^\"]+)", content)
try:
best = exactVersionList[0]
except Exception as e:
critical("No version matches required version")
error(e)
exit(0)
for i in exactVersionList:
if version.parse(i[1]) > version.parse(best[1]):
best = i
chromeDebURL = f"http://mirror.cs.uchicago.edu/google-chrome/pool/main/g/google-chrome-stable/{best[0]}"
info(f"chrome deb URL : {chromeDebURL}")
info("downloading chrome")
subprocess.call(['wget', "-O", "/tmp/chrome.deb", chromeDebURL])
info("Chrome deb downloaded. Installing chrome")
subprocess.call(["dpkg", "-i", "/tmp/chrome.deb"])
info("Chrome installed")

View File

@ -1,7 +1,9 @@
import json
import os
from random import uniform
from selenium.common import TimeoutException
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
@ -10,33 +12,40 @@ from modules.Tools.logger import debug
from modules.Tools.tools import *
def set_language(ldriver):
ldriver.get("chrome://settings/languages")
action = ActionChains(ldriver)
action.reset_actions()
# select language
x_coord = 1200
y_coord = 150
action.move_by_offset(x_coord, y_coord).click().perform()
sleep(0.5)
# scroll down
action.reset_actions()
elm = ldriver.find_element(By.XPATH, "/html/body")
ActionChains(ldriver) \
.send_keys("french") \
.pause(0.5) \
.send_keys(Keys.TAB + Keys.TAB + Keys.ENTER + Keys.TAB + Keys.TAB + Keys.ENTER) \
.perform()
x_coord = 1163
y_coord = 717
action.move_by_offset(x_coord, y_coord).click().perform()
# put to the top
sleep(0.5)
action.reset_actions()
x_coord = 1257
y_coord = 328
action.move_by_offset(x_coord, y_coord).click().perform()
action.click().perform()
def init_profile(mail, mobile=False):
if not mobile:
chrome_profile_dir = "/app/MsRewards-Reborn/user_data/profile/" + mail
else:
chrome_profile_dir = "/app/MsRewards-Reborn/user_data/profile/mobile-" + mail
os.makedirs(chrome_profile_dir, exist_ok=True)
preferences_file = os.path.join(chrome_profile_dir, "Default", "Preferences")
if not os.path.exists(preferences_file):
os.makedirs(os.path.join(chrome_profile_dir, "Default"), exist_ok=True)
with open(preferences_file, "w") as f:
json.dump(
{
"intl": {
"accept_languages": "fr-FR,en-US,en",
"selected_languages": "fr-FR,en-US,en"
}
}, f
)
else:
with open(preferences_file, "r") as f:
settings = json.load(f)
if "intl" not in settings:
settings["intl"] = {}
settings["intl"]["accept_languages"] = "fr-FR,en-US,en"
settings["intl"]["selected_languages"] = "fr-FR,en-US,en"
with open(preferences_file, "w") as f:
json.dump(settings, f)
return chrome_profile_dir
# Deal with RGPD popup as well as some random popup like 'are you satisfied' one
@ -61,12 +70,18 @@ def send_keys_wait(element, keys: str) -> None:
sleep(uniform(0.1, 0.3))
def send_wait_and_confirm(element, keys: str) -> None:
send_keys_wait(element, keys)
element.send_keys(Keys.ENTER)
# Wait for the presence of the element identifier or [timeout]s
def wait_until_visible(search_by: str, identifier: str, timeout: int = 20, browser=None) -> bool:
def wait_until_visible(search_by: str, identifier: str, timeout: int = 20, browser=None, raise_error=True) -> bool:
try:
WebDriverWait(browser, timeout).until(
expected_conditions.visibility_of_element_located((search_by, identifier)), "element not found")
return True
except TimeoutException as e:
error(f"element {identifier} not found after {timeout}s")
f = error if raise_error else debug
f(f"element {identifier} not found after {timeout}s")
return False

View File

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

View File

@ -1,6 +0,0 @@
from modules.Classes.WordList import WordList
w = WordList("/usr/share/dict/french")
for i in range(100):
print(w.get_word())

1
user_data/version Normal file
View File

@ -0,0 +1 @@
0.0.0

View File

@ -1 +1 @@
v6.8.22
v6.8.57