766 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
5fe05712bd refactored all_cards 2024-02-28 00:14:42 +01:00
6ec5300c7b the logger should only log my code now 2024-02-27 23:59:39 +01:00
5ca91a7075 the optimisation wasn't that great 2024-02-27 16:26:29 +01:00
d49742646c wrong parameter in rgpd_popup 2024-02-27 16:21:08 +01:00
a88ad8dd47 the issue seems to be due to MS 2024-02-27 16:13:01 +01:00
d9ebccebb8 well the login works, but it will cause issues later with cookies 2024-02-27 16:09:23 +01:00
40f08b4c86 issue indeed fixed, but still can't log in 2024-02-27 16:05:29 +01:00
b072041446 issue indeed fixed, but still can't log in 2024-02-27 16:05:21 +01:00
476f99b931 fix ? 2024-02-27 15:59:23 +01:00
37c5d9cf43 can I go to some website ? 2024-02-27 15:57:25 +01:00
9e274b6d16 weird error 2024-02-27 15:55:37 +01:00
2a3878b919 bump version. Added docker compose 2024-02-27 15:38:19 +01:00
7cc1b415a6 bump version. Added docker compose (thx chatGPT) 2024-02-27 15:35:31 +01:00
6a2d960dd0 bump version. Added docker compose 2024-02-27 15:31:35 +01:00
bff43c8207 bump version. 2024-02-27 15:22:51 +01:00
7a47b7ae9d bump version. 2024-02-27 15:21:30 +01:00
346b9acc04 bump version. 2024-02-27 15:19:53 +01:00
bc94489ca0 bump version. 2024-02-27 15:18:45 +01:00
a601c64feb bump version. 2024-02-27 15:17:11 +01:00
af938eb50a bump version. 2024-02-27 15:14:14 +01:00
2ae80e9c53 bump version. 2024-02-27 15:12:30 +01:00
27f08b5a01 bump version. 2024-02-27 15:12:25 +01:00
84ace32977 bump version. 2024-02-27 15:07:42 +01:00
da6ca1cdfc bump version. 2024-02-27 15:05:19 +01:00
9857607eb3 implemented classes to remove global file 2024-02-27 14:52:55 +01:00
3c9d20891c Merge branch 'master' of https://gitea.augustin64.fr/piair/MsRewards-Reborn 2024-02-27 11:34:22 +01:00
a0a4535c35 updated webUI according to param changes 2024-02-27 11:26:55 +01:00
d4920ec322 bump version. this code have not been tested, so DON'T UPDATE. 2024-02-27 01:45:35 +01:00
31e38b7258 small things here and there 2024-02-27 01:41:40 +01:00
2cc1fcbc72 removed a lot of unused command line parameters 2024-02-27 01:41:18 +01:00
35c846e671 removed a log of global variables. This file should disappear. 2024-02-27 01:40:51 +01:00
dc3e31d8d5 typo 2024-02-27 01:35:06 +01:00
f1cce097ad moved the initialisation to Config.py 2024-02-27 01:34:56 +01:00
da707ade5a moved the initialisation to Config.py 2024-02-27 01:34:51 +01:00
6be44e829a improved try_play to use logger and to be a bit faster 2024-02-27 01:03:57 +01:00
76acfb42c4 Updated play_quiz to use logger 2024-02-27 00:48:55 +01:00
a47a460a56 removing dev as it's not used anymore 2024-02-27 00:34:54 +01:00
6de49e8874 removing custom_start as it's not useful anymore with the WebUI 2024-02-27 00:34:30 +01:00
b89d3036bb implementing UserCredential class 2024-02-27 00:33:48 +01:00
cf6905b169 created config management class 2024-02-27 00:33:17 +01:00
962c2eab86 created user management class 2024-02-27 00:33:08 +01:00
26c4869830 reorganized folder struct 2024-02-27 00:32:52 +01:00
2e0f148d0c deleted old V7 2024-02-27 00:32:31 +01:00
f0acd9e2f2 deleted old V7 2024-02-27 00:32:25 +01:00
fc8e666927 Merge pull request 'Fix multiple crashes' (#7) from augustin64/MsRewards-Reborn:augustin64-patch-1 into master
Tu es dur avec le « multiple crashes »
2024-02-23 20:42:07 +01:00
9682b95001 Fix OTP not working in very custom start 2024-02-23 08:49:00 +01:00
cc051aea4c Fix error when changing password 2024-02-23 08:46:29 +01:00
ef686799a8 small changes, the real fix vas to update chrome and undetected chromedriver 2024-02-22 09:38:17 +01:00
e75a28104d Merge remote-tracking branch 'origin/master' 2024-02-22 09:13:56 +01:00
4b5b7f4b67 old V7 stuff. 2024-02-22 09:13:49 +01:00
86093ab975 Update requirements.txt 2024-01-25 21:13:52 +01:00
fa7a8376ec Update requirements.txt 2024-01-25 21:10:42 +01:00
59f7f03584 parsing input file 2024-01-18 20:15:58 +01:00
cf1dcec704 uéué, si c'est PyCharm qui le dit ca dois être bien 2024-01-18 16:36:15 +01:00
4c376acf17 implémentation de la recherche PC + du VNC + requirement.txt + joli logger + séparation en plus de fichiers 2024-01-18 16:35:17 +01:00
48e201043b je suis ptet en train de tout refaire mais chut 2024-01-17 17:24:25 +01:00
d5ec96f1e8 je suis ptet en train de tout refaire mais chut 2024-01-17 17:22:26 +01:00
7d81eb642e Merge pull request 'Add min to grafana dashboard' (#6) from augustin64/MsRewards-Reborn:augustin64-grafana-config-patch-1 into master
a peine 3 semaine pour voir que j'ai qqchose a faire, c'est pas grand chose si ?
2023-12-06 11:05:08 +01:00
24e2506e48 Add min to grafana dashboard
get an accurate scale on the grafana dashboard
2023-11-16 11:16:44 +01:00
595d232c88 updated for chrome 118 2023-11-09 19:56:26 +00:00
7b0c82ca14 chrome 119 support, IDK why it is this version and not any other one 2023-11-08 18:15:36 +00:00
e32efc1bf7 Update build.sh
pour fix les problèmes de DNS
2023-11-03 19:00:06 +01:00
b5050e6bdc Update Dockerfile
je comporend pas pourquoi ca marchais avant en fait
2023-11-03 18:54:57 +01:00
b25fa7579b Update Dockerfile
là je suis juste débile
2023-11-03 18:49:25 +01:00
8b7f17f0f2 Update Dockerfile
je suis vramiment pas sur de comprendre
2023-11-03 18:47:50 +01:00
761de5028f Update Dockerfile
-y
2023-11-03 18:45:26 +01:00
4add59f84e Update Dockerfile
je comprend meme pas
2023-11-03 18:44:11 +01:00
b0ddab6827 Update Dockerfile 2023-11-03 18:38:18 +01:00
28206865ea Update Dockerfile
uh
2023-11-03 18:36:03 +01:00
eca2012ffa Update Dockerfile
pk c'est pt
2023-11-03 18:35:32 +01:00
d3f12f2d1b Update Dockerfile
Je suis en train de tout reinstaller, donc le site principalest down pour le moment
2023-11-03 18:06:30 +01:00
59e57bc124 added random time before each account intead of after 2023-10-15 14:31:07 +02:00
d4c3e70e5f Merge pull request 'Fix login' (#5) from augustin64/MsRewards-Reborn:augustin64-fix-login into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/5
2023-10-09 18:50:25 +02:00
ccacad3c0c Changer le type de champ à password
Cela permettra à des gestionnaires de mots de passe de le détecter
2023-10-09 16:20:11 +02:00
63b40d2228 Actualiser Flask/templates/login.html
Il est actuellement impossible pour moi de me connecter, la requête POST est faite à `/login` qui cause une redirection vers `/login/`(GET) et le serveur ne traite plus la requête POST initiale contenant le mot de passe.
2023-10-09 16:17:26 +02:00
1c9697700d encore des nouveaux truc par la 2023-10-07 11:56:37 +02:00
7c19dcc974 fixing a little bug with daily not starting + trying something to fix another issue when there are a lot of logs 2023-10-05 22:06:52 +02:00
7d79b727a9 bon j'y crois, tout marche 2023-10-04 18:40:49 +02:00
35ae711c45 allez demarre tout seul 2023-10-04 18:06:58 +02:00
34bdad3721 seems fine to me 2023-10-04 18:02:27 +02:00
3bea338652 plus qu'a demarrer a par default et a rendre joli 2023-10-04 17:55:43 +02:00
2038e84654 ahhh 2023-10-03 12:27:04 +02:00
99ccdbef46 c'est ce que hje cherchais nan ? 2023-10-03 12:24:39 +02:00
ab74f5b642 non. 2023-10-03 12:08:02 +02:00
29fce1215d je tente des truc mais on a jamais été si proche 2023-10-03 12:01:59 +02:00
26faab4133 tout casser 2023-10-03 00:58:56 +02:00
9586df7ce7 ahhhhhjh 2023-10-03 00:54:56 +02:00
fe35650452 je vais regarder a quoi ca sert yield 2023-10-03 00:32:59 +02:00
e181bd1ba4 je devienne fou 2023-10-03 00:30:20 +02:00
8991e4f4c8 please 2023-10-03 00:23:06 +02:00
291b7332bc pouquoi il ne me le pull pas 2023-10-03 00:18:00 +02:00
2639e5ef53 aled je suis en train de tout casser 2023-10-03 00:17:20 +02:00
d381c5e113 pourquoi ? 2023-10-02 23:19:22 +02:00
6d91b6e491 je comprend pas pk ca marche pas 2023-10-02 23:19:17 +02:00
1e7f283e80 c'est une bien meilleure manière de faire. 2023-10-02 21:55:56 +02:00
e2ab390b01 mis dans le js + fix quelques problemes 2023-09-30 19:30:42 +02:00
43188f65ac names are back 2023-09-30 19:26:17 +02:00
7b1a4cae2c pas besoin d'afficher a chaque fois l'intégralité des mots de passe dans les logs (qui sont plus ou moins public par ailleurs) 2023-09-30 18:36:20 +02:00
213b62712a hmm chelou cette affaire 2023-09-30 18:32:02 +02:00
1bcf53b4af autoconnect test + issue with stop 2023-09-30 18:29:47 +02:00
f9d7da64c9 LET'S GO CA MARCHE (il y a plus qu'a rendre tout ca joli + faire en sorte que le vnc se connecte tout seul et c'est une dinguerie) 2023-09-30 18:22:56 +02:00
7860cfdf04 les problemes d'indices .... 2023-09-30 18:16:47 +02:00
e89368a5f4 ca marche presque, c'est une dingerue 2023-09-30 18:12:26 +02:00
7c0ed44e17 one tab away 2023-09-30 18:04:16 +02:00
642c93de86 une dingerie cette up^date en vré 2023-09-30 18:02:14 +02:00
56234f2420 on en est a deux dois la. par contre tu immagine a quoi va ressembler la 1.33 sur minecraft ? je suis hype de fou 2023-09-30 18:00:43 +02:00
1e576edc51 fin bon ca va la 2023-09-30 17:56:08 +02:00
e13c4ee429 j'y crois tellement que je push 2023-09-30 17:53:16 +02:00
8ec5aa52ba il commence a y avoir beaucoup de modifs 2023-09-30 17:41:46 +02:00
90a87d19c7 2ème problème (je ne vais commit que les modifs sur le app.py) 2023-09-30 17:33:39 +02:00
294ad75aa0 1er probleme 2023-09-30 17:31:19 +02:00
e21ee8b5a4 faire git pull = être un gros fou, j'ai rien tester 2023-09-30 17:23:37 +02:00
92ee7da9a4 ouais je pense que tu vois la ou je veux en venir 2023-09-30 16:29:50 +02:00
a7b42ab3a1 bon au moins j'ai compris le problème 2023-09-28 15:29:55 +02:00
72a9da6cac ... 2023-09-28 15:11:37 +02:00
afb93f1693 je comprend rien 2023-09-28 15:10:40 +02:00
67ac18349b WTF 2023-09-28 15:08:38 +02:00
e5183d30a6 je comprend plus rien 2023-09-28 15:08:16 +02:00
e10c933994 mais QUOI ?????????? 2023-09-28 15:07:27 +02:00
a07a07a0a2 pouquoi ca marche plus je comprend rien 2023-09-28 15:06:47 +02:00
48abf0874c ca avance 2023-09-28 15:03:08 +02:00
5d8ebc379b g tout peter mais c'est fait exprès 2023-09-27 20:20:09 +02:00
b5abd589ba on avance 2023-09-27 20:12:29 +02:00
4c78ec150b bah voila a quoi ca sert 2023-09-27 20:05:39 +02:00
11d30491c6 normalement ca marche 2023-09-27 19:59:48 +02:00
e6f3d66f7b le test a pas vraiment marché 2023-09-27 19:58:41 +02:00
a7e6a73ba5 test pour que ce soit plus joli 2023-09-27 19:57:11 +02:00
e7d8e8afa4 en vrai il y a eu d'autres tests 2023-09-27 19:55:43 +02:00
3199db3874 pas mal la 1.16 (je sais pas pk c'est cassé) 2023-09-27 19:47:08 +02:00
98bb9ad6d0 Pourquoi ca descend pas ? 2023-09-27 19:38:21 +02:00
72504e5cab oué ca update 2023-09-27 19:26:44 +02:00
8813542cfc PTDR je modifie le mauvais fichier depuis tout a l'heure 2023-09-27 12:15:08 +02:00
942bda3a29 ca va faire plus de version que minecraft a ce rythme 2023-09-27 12:11:58 +02:00
e5d8551aab oops 2023-09-27 12:04:38 +02:00
8934568b84 hmmm 2023-09-27 12:02:19 +02:00
07c37b9ae9 oh bordel qu'es ce que je fous 2023-09-27 11:58:39 +02:00
7e6062ca1c ce serait très frole si ca marche 2023-09-27 11:51:38 +02:00
1710ade2c1 j'aime toujours pas le js mais ca commence a marcher 2023-09-27 11:43:00 +02:00
e0b4560988 déjà skip la v6.6.6 ;( 2023-09-27 11:34:58 +02:00
45db9eb67c déjà skip la 6.6.6 ;( 2023-09-27 11:34:47 +02:00
dc2a9e20df OMG VERSION DE FOU 2023-09-27 11:30:50 +02:00
6bc4451684 je sais toujours pas comment marche le js mais bon 2023-09-27 11:27:58 +02:00
fb71cf7f41 je suis pas sur de savoir pourquoi ca casse, mais ce'est comme avant 2023-09-27 11:17:17 +02:00
f727c3ef86 the logs bug seems to be an iPad browser issue, but it sould be fixed now 2023-09-27 10:36:41 +02:00
e88a9e22f2 vraiment bizarre cet page de logs 2023-09-27 10:25:54 +02:00
315bf4b150 uh ca marche pas depuis quand ca ? 2023-09-27 10:19:01 +02:00
6fe3f16ead trying something 2023-09-27 10:13:47 +02:00
6e930d5241 euh wé 2023-09-25 19:19:22 +02:00
767d790344 ca a l'air ok, mais ily a toujours des prbls 2023-09-24 22:28:51 +02:00
7a02560473 c'est ptet un fix, mais encore une fois je sais pas pk 2023-09-24 22:26:03 +02:00
1a44c60202 je comprend plus rien 2023-09-24 22:23:52 +02:00
e03ef1759c meh wtf 2023-09-24 22:16:06 +02:00
1d4021edb0 where are you ? 2023-09-24 22:13:40 +02:00
799f8d0b43 hmmmmmmmm 2023-09-24 22:10:23 +02:00
611c114881 bon... 2023-09-24 21:48:35 +02:00
b5468c9ff2 related to login ? 2023-09-24 21:45:35 +02:00
c34a82639c vraiment chelou cette affaire, a la main, il n'y a pas de problèmes 2023-09-24 21:42:27 +02:00
07f6ff9c3c trying to fix that card error + fix config (merci) 2023-09-24 21:19:02 +02:00
424798c7f6 OMG C'est trop bie 2023-09-20 13:13:41 +02:00
f0447b2d1d push 2023-09-20 13:05:13 +02:00
9316317d2b push 2023-09-20 13:00:48 +02:00
2c05937663 updated 2023-09-20 12:58:33 +02:00
d166b164e6 des ptit problèmes par ci par la 2023-09-20 11:54:43 +02:00
7a59891f37 ofc j'ai oublier ca 2023-09-20 11:48:37 +02:00
192be842a3 et le app.py 2023-09-20 11:48:03 +02:00
15823c850f bump 2023-09-20 11:46:56 +02:00
a07b55fab7 euh ouais j'ai ptet rajouter un VNC, bref on verra 2023-09-20 11:46:35 +02:00
58ab110d55 aucune idée pourquoi ca a fix mais bon, fine ? 2023-09-10 11:04:28 +02:00
5a1a5b880b hmmm 2023-09-10 11:03:05 +02:00
e7f74e6882 mais quoi ?? 2023-09-10 11:02:15 +02:00
01f678a216 hmm why doesn't this work ? 2023-09-10 10:56:04 +02:00
defbc63a65 fixed error 2023-09-06 16:04:42 +02:00
ae6707ef53 whoops, btw, clicking again on stats open grafana 2023-08-29 19:34:52 +02:00
efd53fb5d9 comeback, version number 2023-08-29 19:31:29 +02:00
10e8fe1dd0 yeah i even consider that as a big update 2023-08-29 19:28:13 +02:00
fd3da49694 c'est ok ca marche, et c'est presque joli 2023-08-29 19:04:34 +02:00
bd0cb71bba whoops 2023-08-29 18:53:57 +02:00
fa45d97576 should be embeded now 2023-08-29 18:53:06 +02:00
74ea8ee854 bah tu étais passé ou toi ? 2023-08-29 18:36:22 +02:00
15103b7905 okay normalement le numero de version marche 2023-08-29 18:34:19 +02:00
2433609cd8 Merge pull request 'Ajout d'un bouton pour activer/désactiver le panneau latéral' (#2) from augustin64/MsRewards-Reborn:master into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/2
2023-08-29 18:26:36 +02:00
d06d925e27 Fix: remove version number 2023-08-29 18:24:06 +02:00
221921e3f3 Add sidebar toggling 2023-08-29 15:30:03 +02:00
fcc7f4d46e css: use variables for colors 2023-08-29 15:21:44 +02:00
7f21301da0 Merge pull request 'fix: impossible d'afficher des logs quand une seule config existe' (#1) from augustin64/MsRewards-Reborn:patch-logs into master
Reviewed-on: https://gitea.augustin64.fr/piair/MsRewards-Reborn/pulls/1
2023-08-29 11:37:48 +02:00
211dcecd23 fix: impossible d'afficher des logs quand une seule config existe 2023-08-29 10:54:58 +02:00
c072a71c83 pas mal le version control : 6.2.0 -> 6.2.10 2023-08-26 13:17:57 +02:00
fd8f972cf8 let's go ca marche je pense 2023-08-26 13:14:32 +02:00
6e25dcd115 ah la ca semble bien 2023-08-26 13:12:25 +02:00
c25a744a5c still testing 2023-08-26 13:10:57 +02:00
83a2b8f33e hmm test 2023-08-26 13:08:18 +02:00
96cb82aac4 testfix + logs style 2023-08-26 12:55:46 +02:00
cd39f7109e unrecognized token: "{" 2023-08-26 09:11:26 +02:00
217f385725 no such column: nom 2023-08-25 20:43:37 +02:00
6efc77c512 fixed things, like auto adding account to database 2023-08-25 19:40:39 +02:00
820efd8126 uéuéué j'ai oublier quoi ? 2023-08-25 16:25:17 +02:00
b0b537968c omg ca marche ? 2023-08-25 15:49:37 +02:00
f7d6b19fc6 still improving 2023-08-25 15:25:32 +02:00
4757a2957d improvement 2023-08-25 15:23:33 +02:00
f548c3030a that's what i call progress 2023-08-25 15:12:31 +02:00
c712395d39 fixed stuff 2023-08-25 14:50:38 +02:00
8acdcae7de pouyrquoi ca marche pas ? 2023-08-25 14:41:39 +02:00
33cb90f110 hmmmm 2023-08-25 14:39:13 +02:00
0516296499 okay 2023-08-25 14:06:03 +02:00
534b8f3367 BON.... 2023-08-25 13:25:02 +02:00
2d70f00c0f je devrais pas 2023-08-25 13:21:33 +02:00
d16715dbf5 uéuéué ca test des trucs (un viewer de logs) 2023-08-25 13:20:51 +02:00
466ab6d880 euh en gros :
- j'ai bougé plus de JS dans le fichier main.js
- j'ai changé le css pour que les listes soient joli
2023-08-25 12:06:52 +02:00
6fb0698d18 adding js to a separate file 2023-08-25 11:54:14 +02:00
f05d695ddb je suis désolé, c'est plus simple de commit pour voir ce que ca donne en vrai 2023-08-25 11:47:31 +02:00
79e6d9053e déja ca a fix le problème de lancement je pense 2023-08-25 11:43:09 +02:00
bfab01a1a3 Delete dev_build.sh
it's a dev file, so shouldn't be there
2023-08-24 21:22:01 +02:00
5c2fa42f51 removed database configuration page, using instead SQlite, and integrated grafana interface 2023-08-24 21:18:36 +02:00
1befff788d bon, j'ai le droit d'être débile aussi 2023-08-24 14:39:15 +02:00
a3d7a49197 added stats link 2023-08-24 14:36:24 +02:00
ff9edc2631 ptet que j'ai fix le probleme de multiple execution au passage 2023-08-24 14:31:45 +02:00
24df044e1f bon la ca marche 100% 2023-08-24 14:28:49 +02:00
2f2b4f9905 what is started????????? 2023-08-24 14:24:52 +02:00
0fa8149953 grafana only works 30sec after start 2023-08-24 14:21:51 +02:00
f6b43a9ce4 OMG CA MARCHE ? 2023-08-24 14:13:25 +02:00
11b13842dd je veuc comprendre 2023-08-24 14:09:51 +02:00
2938b83217 grzejlh 2023-08-24 14:06:53 +02:00
d3496c2fba mais qUQOIUJF OIGEZQHGIHEBOIF HBNEUHb 2023-08-24 14:04:42 +02:00
58b4b26c37 pls explain 2023-08-24 14:01:48 +02:00
b227f47953 hmmmm 2023-08-24 13:58:53 +02:00
718fd1643d pls ? 2023-08-24 13:53:51 +02:00
ab629d8dd2 meh ? 2023-08-24 13:50:37 +02:00
48225a0455 c'est un peu plus joli, et en plus ca marche (ptet?) 2023-08-24 13:45:58 +02:00
e28efad8de ca a l'air 2023-08-24 13:40:46 +02:00
1f73f6fdce c'est pas beau mais si ca marche, ... 2023-08-24 13:38:34 +02:00
74f9c5b496 pourquoi ca marche pas ? 2023-08-24 13:35:53 +02:00
2bc388e61f oops 2023-08-24 13:30:07 +02:00
55a1677fb4 c'est bon ? 2023-08-24 13:28:49 +02:00
864bf95138 need to fix api calls to grafana daashbord 2023-08-24 13:09:36 +02:00
661c76b9f7 test ou on demarre bien tout les services 2023-08-24 13:05:44 +02:00
9810381f8d ca marchera mieux si c'est au bon endroit 2023-08-24 12:38:41 +02:00
d6c49168e5 bon je sais toujours pas ce que j'ai fait mais ptet que ca marche mieux qu'avant 2023-08-24 12:37:33 +02:00
a9674a5b0a bon normalement ca marche, sauf que grafana et nginx ne se lancent pas auto 2023-08-22 16:32:37 +02:00
a426e787e3 aaaa 2023-08-22 13:35:45 +02:00
49f157436b ofc i need to commit 2023-08-22 13:33:43 +02:00
6b8f2f0cbc que suis-je en train de faire ? 2023-08-22 11:47:36 +02:00
36f8938f0f ah ? 2023-08-22 11:24:50 +02:00
bc2725a7b9 aa 2023-08-22 11:23:59 +02:00
551c2f18c9 bon 2023-08-22 11:22:50 +02:00
adbb33aa0c oulah qu'ai-je fait 2023-08-22 11:21:42 +02:00
e896d4b949 New feature : you can import and export configs 2023-08-21 21:38:27 +02:00
3132795c5e oui ca marche 2023-08-21 21:36:14 +02:00
b80d82d112 a* 2023-08-21 21:34:55 +02:00
18cc9f902c ? 2023-08-21 21:31:51 +02:00
c997dc5ebe F le JS 2023-08-21 21:29:23 +02:00
38de2f040d quoi que j'avais dit 2023-08-21 21:28:18 +02:00
aeb93e8a55 hmm? 2023-08-21 21:26:21 +02:00
b3f13399a4 aucune idée de ce que je fais 2023-08-21 21:25:05 +02:00
e099f705c8 oh bordel je connais pas le js moi 2023-08-21 21:18:24 +02:00
41f4059996 euh ué? 2023-08-21 21:16:59 +02:00
2b0e99031e on fait des tests écoute 2023-08-21 21:10:55 +02:00
02f835e755 oui 2023-08-21 21:07:54 +02:00
16f907d0db close to work 2023-08-21 21:05:49 +02:00
7b4250d444 uéuéuéuéuéué 2023-08-21 21:03:26 +02:00
bd70557062 nearly good 2023-08-21 21:00:03 +02:00
8d7a474c69 much better 2023-08-21 20:58:26 +02:00
9b411fe54e okok 2023-08-21 20:57:26 +02:00
18f0f3ec02 j'avais pas de name je suis débile 2023-08-21 20:55:29 +02:00
21599e5db5 "" 2023-08-21 20:54:39 +02:00
b6560982e6 okay cla ca marcje 2023-08-21 20:53:59 +02:00
597840d132 ... 2023-08-21 20:53:07 +02:00
259a3ad713 yeah i mean... 2023-08-21 20:51:29 +02:00
e668d312b6 as the example shows 2023-08-21 20:50:38 +02:00
60734a373e c'est quoi ca encore ? 2023-08-21 20:48:51 +02:00
1ca5ff2ec1 maintenant 2023-08-21 20:47:02 +02:00
494a58593b plus de redirect débiles 2023-08-21 20:46:09 +02:00
8f5a1ac705 logik en fait 2023-08-21 20:44:48 +02:00
8444fdbb2d chelou cette affaire 2023-08-21 20:43:55 +02:00
280d4c79c3 meh ? 2023-08-21 20:42:16 +02:00
8e9824b3d7 send files 2023-08-21 20:39:45 +02:00
f076eafec9 download files 2023-08-21 20:36:32 +02:00
d2741e8c7a still about the file backup 2023-08-21 19:59:49 +02:00
84b9c02a72 created a backup 2023-08-21 19:51:29 +02:00
f1d74b9921 tests 2023-08-21 19:46:57 +02:00
e2f47432c4 a 2023-08-21 19:43:15 +02:00
08dde1f6d2 test 2023-08-21 19:41:50 +02:00
37249ec654 test 2023-08-21 19:40:51 +02:00
2be6348273 a 2023-08-21 19:38:27 +02:00
bab3a86624 test 2023-08-21 19:37:21 +02:00
a3e993a091 a 2023-08-21 19:35:57 +02:00
5b2f882e56 a 2023-08-21 19:35:27 +02:00
0665ba2808 a 2023-08-21 19:34:04 +02:00
f65aa23021 aa 2023-08-21 19:32:02 +02:00
ca4f97c07b fix 2023-08-13 20:37:21 +02:00
659e7d3664 auto reload. added back mobile search. 2023-07-03 21:29:26 +02:00
5c23097873 fixed some issues preventing the programm to start (...) 2023-07-03 11:43:57 +02:00
11a7d6c23c whoopps 2023-07-02 19:46:37 +02:00
3a8ccb2e92 a 2023-07-02 19:45:20 +02:00
77a2ba9c65 whoops 2023-07-02 19:36:14 +02:00
835aac046f test 2023-07-02 19:34:56 +02:00
ad80de0c04 toujours pas stable 2023-07-02 19:26:24 +02:00
a9dcb7726c style update 2023-07-01 16:24:39 +02:00
55b5cff24b style update 2023-07-01 16:21:51 +02:00
49045f54a7 a 2023-07-01 14:41:07 +02:00
61eb6dfe6e aaaaaaaa 2023-07-01 14:35:33 +02:00
0d9c128a2c a 2023-07-01 14:28:04 +02:00
2253506f80 a 2023-07-01 14:22:46 +02:00
2d5cb19896 a 2023-07-01 14:16:43 +02:00
a5421f6ae4 y 2023-07-01 14:14:41 +02:00
524e412b40 tests 2023-07-01 14:06:48 +02:00
cf88ede967 dev test 2023-07-01 13:51:48 +02:00
5e2e7f9f14 Add 'user_data/logs/.gitignore' 2023-07-01 13:43:51 +02:00
fe218a1d21 Delete 'user_data/logs' 2023-07-01 13:43:34 +02:00
68d09d29af Add 'user_data/logs' 2023-07-01 13:42:31 +02:00
3c9472fe2e add logs 2023-07-01 13:41:17 +02:00
9082f9b87c auto update ? 2023-06-29 11:55:49 +02:00
b64339bdab si ca marche c'est trop bien 2023-06-26 21:51:47 +02:00
33eadaa405 still looks like beta to me 2023-06-26 21:49:30 +02:00
ca7f49e6a6 meh 2023-06-25 10:49:25 +02:00
027ca5dbdb OUI 2023-06-25 10:28:06 +02:00
5b558285af ? 2023-06-25 10:24:03 +02:00
fabd826aa8 2 or 3 changes before tomorrows exams 2023-06-25 09:56:14 +02:00
1e22cfcb4a test 2023-06-25 09:22:22 +02:00
4b0f33ae26 stable 2023-06-24 16:39:42 +02:00
f098f13242 small fix 2023-06-24 14:04:44 +02:00
51edb0c0fd yeah 2023-06-22 22:27:41 +02:00
d96ec5891f HOW TO ENABLE MOBILE PLS 2023-06-22 19:20:32 +02:00
8694c4d30b ignore pls 2023-06-21 21:30:07 +02:00
fb6bdf385e uéué 2023-06-21 21:25:36 +02:00
0281bb946d uéuéué 2023-06-21 21:24:30 +02:00
ed828e4ea0 ouo 2023-06-19 20:53:13 +02:00
54d728364e Update 'user_data/settings.json' 2023-06-19 20:37:47 +02:00
0d9366c801 default files 2023-06-18 22:22:53 +02:00
6e55189c5d meh ? 2023-06-18 22:12:35 +02:00
9bfbd744e4 ?# 2023-06-18 22:10:42 +02:00
70696ee91b some fixes 2023-06-18 22:08:16 +02:00
9b237c7ebf maybe the last update 2023-06-18 19:21:02 +02:00
4e939bec2f YEAH 2023-06-18 18:32:06 +02:00
08b593eeb9 oh boy 2023-06-18 17:40:59 +02:00
b201c68aa9 gitea test 2 2023-06-18 15:58:22 +02:00
171fa2fc77 gitea test 2023-06-18 15:57:41 +02:00
2b849ca0ca implemented different secret and password for each instances 2023-06-18 15:55:45 +02:00
d49c8031a1 de toute facon il est useless 2023-06-17 17:03:49 +02:00
1042fcf3cc bruh ? 2023-06-17 16:52:47 +02:00
550e36b954 less errors 2023-05-31 10:52:45 +02:00
4814dfed46 hotfix, but a nice one 2023-05-30 20:21:25 +02:00
67aad7921f useful untested update 2023-05-12 14:53:52 +02:00
ecd5a9f204 small fixes, testing tomorrow then releasing 2023-05-09 13:09:14 +02:00
2b1c7b985e Create CODE_OF_CONDUCT.md 2023-05-08 21:17:23 +02:00
c9c93e9828 Merge branch 'master' of https://github.com/piair338/MsRewards
what am i breaking ?
2023-05-08 20:58:58 +02:00
1a4ed4f4e7 lang + small error fix 2023-05-08 20:56:55 +02:00
0ba92798ad Update README.md
A better installation tutorial ?
2023-05-08 20:44:51 +02:00
4aef2bf948 added switches 2023-05-07 23:26:27 +02:00
68395f4314 new handeling method for fidelity. Need deeper testing, but should be fine. 2023-05-07 12:51:38 +02:00
2ca2779ec9 fixed a rare error occuring when the cookie creation isn't successful 2023-05-05 11:56:26 +02:00
5ef8d8b7ca some fixes. I believe it's stable. New release tomorrow 2023-05-05 11:40:38 +02:00
f2d08e9137 still dont know 2023-05-04 20:32:19 +02:00
d946298a38 don't know 2023-05-04 17:49:51 +02:00
ed1e91b304 ptite update 2023-04-25 21:56:29 +02:00
710c272659 better logs 2023-04-17 22:28:26 +02:00
6f325c5a6a small fix 2023-04-17 22:00:46 +02:00
3b82419d4d fixed fidelity, but a new version may come sooner or later 2023-04-15 13:10:14 +02:00
9e0514a902 only the number of the config 2023-04-15 11:18:55 +02:00
5c8730dc26 only the number of the config 2023-04-15 11:18:36 +02:00
d11ae4055c euh ué 2023-04-15 11:04:23 +02:00
2dc8cda167 euh ué 2023-04-15 11:03:47 +02:00
fbb2feae31 small but infinite error 2023-04-14 10:31:12 +02:00
8d53a2b30b ok 2023-04-13 22:38:27 +02:00
f8f3ff2382 uéuéué 2023-04-13 22:22:06 +02:00
024b556f5e bruh 2023-04-13 09:11:12 +02:00
b4c9204bf2 oh gosh 2023-04-12 18:25:12 +02:00
f810f0ee3c test 2023-04-12 14:40:32 +02:00
afac7e9539 bump 2023-04-12 13:29:40 +02:00
ae12c18270 not stable either, but something need to change 2023-04-12 13:29:06 +02:00
dfd51bc040 uéuéué faster, more reliable, ... 2023-04-12 00:01:24 +02:00
12a6968ee0 well, SadPanda is still here ;( 2023-04-09 23:41:31 +02:00
8726785dc8 random test 2023-04-08 12:08:26 +02:00
e9f629dee4 sadpanda + typo 2023-04-08 11:51:27 +02:00
c9a838d368 faster overall + better discord error + better login 2023-04-07 23:28:48 +02:00
808916ddd3 testing is everything 2023-04-07 10:04:59 +02:00
c51c463338 the passage to 5.3 wasn't justified ( at least not enough) so i added a new feature 2023-04-07 10:01:47 +02:00
a22d1e6ddb you can manually add points to database 2023-04-07 09:53:11 +02:00
93bb634f7c some fixes here and there 2023-04-06 23:41:11 +02:00
31426a1dfd well, it should be really more robust as it doesn't rely on XPATH everywhere anymore 2023-04-06 23:04:57 +02:00
f862af8699 version control 2023-04-04 21:27:02 +02:00
78e7342acf last update of the night ? 2023-04-04 21:26:40 +02:00
4d8157ba1e better stronger faster 2023-04-04 21:18:09 +02:00
661566aade no clue if that's better 2023-04-04 21:07:12 +02:00
eb2b9dc2d3 you should now start using main : it can finally pass args 2023-04-04 20:59:45 +02:00
3385540350 better way if manually updated 2023-04-04 20:50:56 +02:00
0588180dda should be good for now 2023-04-04 20:46:10 +02:00
9995bc8e25 Auto Updates ? 2023-04-04 20:37:48 +02:00
98ff0a183a always more stable (no) 2023-04-04 12:55:00 +02:00
d579a2c160 once again, should be fairly stable 2023-04-02 12:32:21 +02:00
ccf284f6e2 typo + better logic + WTF everything has failed today 2023-04-02 11:02:37 +02:00
f30832d8cd OMG finally stable ? 2023-04-01 09:51:53 +02:00
799d3d67d5 may even be stable wtf 2023-03-31 10:00:45 +02:00
f10cd8d226 still testing, but on a good way 2023-03-30 09:05:45 +02:00
e41d28c142 normalement c'est insane. Il faut juste gérer le problème de login sur le mobile. 2023-03-30 08:03:49 +02:00
b0c6a93951 bizarre l'id 2023-03-29 23:24:14 +02:00
012e923ab5 better stronger (no) 2023-03-29 23:19:57 +02:00
0cb0521da6 Don't update yet 2023-03-29 23:09:16 +02:00
c5beafe036 test 2023-03-29 14:08:44 +02:00
098b934e96 told ya 2023-03-27 22:47:29 +02:00
339775bdf4 cf previous commit 2023-03-27 22:25:35 +02:00
a2b07b9fcd well don't update till tomorrow I guess 2023-03-27 22:20:54 +02:00
d5bacd99a1 2023-03-27 16:11:17 +02:00
43035e115d sorry for the pings, 2023-03-26 23:24:59 +02:00
c1bbb26c26 no clue why this need to be addressed 2023-03-26 22:56:57 +02:00
95156bacd8 wtf was that 2023-03-26 19:47:13 +02:00
f7c6d3f65e just for me 2023-03-26 10:10:08 +02:00
4ab2530f98 Update Dockerfile 2023-03-25 18:40:17 +01:00
3ca16d1f37 Update README.md 2023-03-25 18:39:42 +01:00
db4ab3bf90 OMG I tested before commiting. (btw cookies login is now implemented) 2023-03-25 18:14:41 +01:00
6fefaca00a Create .gitignore 2023-03-25 16:34:49 +01:00
a2328c2ca7 Delete temp 2023-03-25 16:33:12 +01:00
37f002049a how to only create an empty folder ? 2023-03-25 16:32:48 +01:00
8f655a04fb well, as usual, .. 2023-03-24 20:45:13 +01:00
860c7b536a -f 2023-03-24 18:02:47 +01:00
e93d4f0baf remove some thing 2023-03-19 18:50:29 +01:00
a72c74ec05 Update README.md
ptdr not on a raspberrypi anymore
2023-03-19 12:23:42 +01:00
5282b4b434 apparently, no 2023-03-19 12:21:57 +01:00
0263f2e4c1 j'arriverais jamais a faire un truc sans 14 commits ou quoi ? 2023-03-19 10:44:00 +01:00
3324fa478d oui 2023-03-19 10:17:28 +01:00
d14e0efad9 fix ? 2023-03-18 19:43:54 +01:00
16ddd7aae9 see previous commit for explaination 2023-03-18 19:26:00 +01:00
66de4dbbd2 oh, f*ck, what have I done 2023-03-18 19:12:27 +01:00
27237354b2 didn't even worked 2023-03-18 14:21:27 +01:00
484a9692cf told you 2023-03-18 14:11:51 +01:00
ebb1847a51 maybe better, as usual, probaly don't work, wait tomorrow 2023-03-17 22:37:35 +01:00
80f6cbc919 ofc I broke something 2023-03-15 10:34:59 +01:00
dff47887bc cleaned up under the hood (better error logic) 2023-03-14 19:54:12 +01:00
d0c78d7db1 don't know 2023-03-14 16:52:46 +01:00
ebd22102ef auto remove email part 2023-03-14 16:33:44 +01:00
6ce85286dd V5 2023-03-13 13:42:40 +01:00
db557c2e3c V4 now work again. You should still switch to v5 2023-03-13 07:29:34 +01:00
2888f1d761 TODO update 2023-03-12 15:33:35 +01:00
84898cee76 fixed PlayQuizz8 (most likely ?) 2023-03-12 11:22:49 +01:00
cef0204868 removed Auto Claim feature because of ban 2023-03-12 10:59:36 +01:00
93600dd78a Merge pull request #13 from augustin64/patch-1 2023-03-09 14:30:55 +01:00
7e64604e9f Update Dockerfile
Fix dependencies
2023-03-09 14:30:29 +01:00
c28c2c573d was once again broken 2023-02-27 18:31:31 +01:00
1a4cd03ae1 some error fix 2023-02-27 13:41:54 +01:00
87195de1e5 oui 2023-02-27 13:19:46 +01:00
4631a6608c oui 2023-02-27 13:19:12 +01:00
904ad83f36 test 2023-02-27 13:16:55 +01:00
cd5ce0f6c1 Update requirements.txt 2023-02-27 13:09:01 +01:00
e28660ea7d Update requirements.txt 2023-02-27 13:08:14 +01:00
bad8be5d1f bon bah je sais pas me servir de finally 2023-02-26 12:50:23 +01:00
87b47e97fd oui 2023-02-25 19:05:47 +01:00
442dbb08d9 Merge pull request #12 from augustin64/patch-3 2023-02-13 21:03:55 +01:00
05b88945ed Update db.py
Just making sure points is not `None` (when it is not possible to get the number of points for example)
2023-02-13 19:29:54 +01:00
3770fa6451 oui:/ 2023-02-12 13:44:57 +01:00
cfbe5d7af8 Update README.md 2023-02-11 22:55:23 +01:00
510c7f7251 idk 2023-02-08 15:14:13 +01:00
5b95893bf0 oops 2023-01-30 07:32:29 +01:00
5e3282f873 euh oui 2023-01-29 00:51:30 +01:00
deb77cd3d3 now it work 2023-01-14 18:04:55 +01:00
dda61eaef9 RP support 2023-01-14 17:53:58 +01:00
8943c0e15d claim multiple things ? 2023-01-14 17:36:28 +01:00
90bcd29d36 works now 2023-01-14 17:19:52 +01:00
bb5dbb3cbd --claim amazon 2023-01-14 16:56:33 +01:00
ab8ac50fb2 finally working 2023-01-14 15:40:07 +01:00
994302d28d Update main.py 2022-12-30 16:02:48 +01:00
4723049615 Update main.py 2022-12-30 16:02:03 +01:00
dd7b62dc92 maybe better ? 2022-12-29 18:25:06 +01:00
992465c562 ok. 2022-12-29 17:56:42 +01:00
fbc8dac0e9 ya ? 2022-12-29 17:54:37 +01:00
ecfda92584 no ? 2022-12-29 17:53:45 +01:00
e4f6677da8 Please 2022-12-29 17:31:45 +01:00
9f3ccafee8 typo 2022-12-29 16:56:29 +01:00
5d64ebdb29 more logical amazon claim logic 2022-12-20 12:42:00 +01:00
45cd381c3a some things 2022-12-17 18:04:49 +01:00
ed47bae6b6 fix today's disaster 2022-12-17 17:39:48 +01:00
e7f375650d pui 2022-12-15 19:16:25 +01:00
ad513bfe9c fix languagee popup error 2022-12-11 17:15:57 +01:00
fe772048de fiexed invisible error 2022-12-11 17:04:40 +01:00
08c069ca1e je suis un pro des regexp mdrr 2022-12-03 06:33:27 +01:00
141e896cab WHY MS 2022-12-01 13:46:12 +01:00
05013cea75 fixing issues in fidelité 2022-11-26 15:07:32 +01:00
26c83c38c6 Update README.md 2022-11-26 13:18:22 +01:00
347ba86a87 pixel 2022-11-23 22:43:29 +01:00
24b2af9d10 euh uéuéué 2022-11-20 16:21:45 +01:00
dd38060253 fiexed 2022-11-19 18:11:23 +01:00
b0cdc9b779 what isn't it working 2022-11-19 18:06:19 +01:00
31ec4a1200 Update requirements.txt 2022-11-19 17:16:25 +01:00
48b4128632 Update Dockerfile 2022-11-19 17:02:28 +01:00
b9adb9c59c error handeling 2022-11-18 17:20:57 +01:00
ca0ae8917a Merge pull request #11 from augustin64/patch-2 2022-11-16 18:15:27 +01:00
80286b6a05 Update db.py 2022-11-16 18:13:36 +01:00
ebb1a8e48f Update config.py 2022-11-16 18:12:43 +01:00
f4ebb39fdf Update V4.py 2022-11-16 18:11:18 +01:00
da5e60f8b7 Please enter the commit message for your changes. Lines starting 2022-11-16 13:42:20 +01:00
0552338c22 Merge pull request #10 from augustin64/patch-1
Reset Progress
2022-11-14 22:44:34 +01:00
0aa7fd3ec0 Reset Progress
- Reset progress when "starting" an already completed task
- Reset START_TIME if override option was used
2022-11-14 22:36:56 +01:00
1be75f1987 easier to copy on discord 2022-11-14 22:21:35 +01:00
5d4dd859bd only start countdown after login (1 min later) 2022-11-12 23:48:54 +01:00
4f21ef22d4 remove some errors 2022-11-12 23:46:12 +01:00
a19e40b7e5 fixed 2022-11-12 23:31:58 +01:00
81dc0f7310 ok it's fixed 2022-11-12 23:07:51 +01:00
437afdcce4 ff override is broken don't update 2022-11-12 23:04:38 +01:00
decd289994 a tester encore un peu, mais devrais marcher 2022-11-12 23:00:45 +01:00
3c5fb6e702 SPACES 2022-11-12 21:09:07 +01:00
2f6b7f2ab9 useless 2022-11-12 17:40:03 +01:00
741a136b12 . 2022-11-11 11:29:32 +01:00
24849a9418 finally fixed 2022-11-09 22:59:12 +01:00
eae66cb163 great idee Augustin64 2022-11-09 22:54:55 +01:00
c3fc698e55 FAST DUDE 2022-11-09 19:36:22 +01:00
35db54edfc better unban 2022-11-07 22:45:26 +01:00
2fdfdb7410 Update README.md 2022-11-06 18:11:50 +01:00
368523135a Update Dockerfile 2022-11-06 18:10:44 +01:00
3189359b81 Update Dockerfile
test (wasn't really working )
2022-11-06 18:09:15 +01:00
bf675f8c96 Update Dockerfile
not useful
2022-11-06 17:57:02 +01:00
e7584702a7 test 2022-11-06 17:47:02 +01:00
c651950e7c wasn't working 2022-11-06 17:47:01 +01:00
7ad71a1cf9 Update README.md 2022-11-06 17:36:25 +01:00
8d15a555e8 should be useful 2022-11-06 13:37:12 +01:00
afec68a23e ptit truc par ci par la 2022-11-06 13:29:55 +01:00
545eea48cc better handeling of mobile login 2022-11-06 13:09:02 +01:00
f668c49e09 better 2022-11-05 15:32:13 +01:00
11eaa5189a Update README.md 2022-11-04 23:11:05 +01:00
d84ae8dd57 k 2022-11-01 10:09:12 +00:00
c9aa75e61c custom error + better code + some things 2022-10-31 14:32:39 +00:00
945497c1d4 didn't push mb 2022-10-30 11:12:00 +00:00
7882e1dbb3 finally it work again 2022-10-25 17:47:05 +00:00
92aa56aae0 some tests 2022-10-25 17:44:33 +00:00
4a434533a7 ptet que c'est utile je sais pas 2022-10-25 17:27:54 +00:00
c665144b28 I need a better solution 2022-10-25 08:03:24 +00:00
0af267e628 i was right nothing was,working as intended 2022-10-25 07:48:34 +00:00
2709d7058a OOPS 2022-10-24 19:44:32 +00:00
b28119baec kinda work, when we ignore mobile search 2022-10-24 19:35:31 +00:00
3155b545dc oh boy i probably just broke everything 2022-10-24 18:08:33 +00:00
f8e9daaedd well, not working at all is faster than working right ? 2022-10-24 08:38:11 +00:00
c71aad15df login should be two time faster 2022-10-23 17:25:04 +00:00
a7d32b6064 for me and for you (no just kidding only for me) 2022-10-22 16:15:04 +00:00
941656100c not much change, look at the code 2022-10-20 20:15:08 +00:00
170627f5a7 well user_data is made for tha 2022-10-18 14:30:27 +00:00
6796e71c5b wtf is this error 2022-10-18 10:51:55 +00:00
1505e7b756 don't send my log 2022-10-17 14:10:59 +00:00
7c4de0ff5d ouio# Please enter the commit message for your changes. Lines starting 2022-10-16 17:39:38 +00:00
8ab6c41200 Update README.md 2022-10-16 15:57:02 +02:00
ecd695f45c Update README.md 2022-10-16 15:47:58 +02:00
ac737cd048 changed name 2022-10-16 13:25:19 +00:00
48a1ca4617 forget to delete that 2022-10-16 13:21:26 +00:00
b882d0deba oui 2022-10-16 13:20:57 +00:00
ae3a89802b Merge remote-tracking branch 'refs/remotes/origin/master' 2022-10-16 13:15:29 +00:00
7137448f65 allow multiple config 2022-10-16 13:15:00 +00:00
cd94f65045 Update requirements.txt 2022-10-16 15:04:24 +02:00
a8dacf85d1 why 2022-10-16 12:57:38 +00:00
d157423bf7 Create config.default 2022-10-16 14:56:20 +02:00
fd69c86a86 test 2022-10-16 12:55:31 +00:00
e2a917925e some test as usual 2022-10-16 12:54:59 +00:00
f1b6232841 Rename config.cfg to config.default 2022-10-16 14:49:10 +02:00
6526d83e27 Rename config.cfg to user_data/config.cfg 2022-10-16 14:20:19 +02:00
14d15c4dea new structure 2022-10-16 12:19:18 +00:00
677b80f521 rename 2022-10-16 12:11:06 +00:00
65f2705726 Rename config to config.cfg
so gitignore work
2022-10-16 14:10:18 +02:00
09fd450c59 test 2022-10-16 12:08:30 +00:00
fdcc34c054 some space 2022-10-16 12:00:35 +00:00
db5973cf87 small fix, i really should make some tests 2022-10-16 11:49:06 +00:00
cec5505f3c test ? 2022-10-15 16:17:21 +02:00
ada8b95259 too fast dude 2022-10-13 07:18:08 +02:00
62f9410373 it wasn't working ? 2022-10-12 14:50:38 +02:00
23a7131792 yup 2022-10-11 21:45:47 +02:00
49cf33c780 a lot easier to edit after. 2022-10-11 21:40:41 +02:00
9f5e722a9c some space 2022-10-11 21:30:17 +02:00
6290fde32e didn't I already changed that ? 2022-10-11 21:14:53 +02:00
3d90fa64bb sometime it's in english for whatever reason 2022-10-11 13:00:44 +02:00
1e54e8af9a int_of_string points 2022-10-10 16:27:14 +02:00
43356e032a Merge branch 'master' of https://github.com/piair338/MsRewards 2022-10-10 13:37:44 +02:00
f357623a03 nice 2022-10-10 13:37:31 +02:00
4d907ba81b ofc nop 2022-10-09 13:42:45 +02:00
950f8835c3 ofc not 2022-10-09 13:36:08 +02:00
fd7feebca5 work first try ? POG 2022-10-09 13:33:13 +02:00
b8690dfd05 Check ipv6 at first start 2022-10-06 17:55:45 +02:00
7789c89d64 and functions can't be empty 2022-10-04 22:11:25 +02:00
dff9af6125 return stop function piair ... 2022-10-04 22:09:51 +02:00
6d73ba94e0 ok. 2022-09-30 16:13:36 +02:00
dac3977c71 uéuéué t'est content agustin64 2022-09-30 16:09:11 +02:00
42ad01e493 ofc 2022-09-30 15:17:29 +02:00
d4d3213db1 BON 2022-09-30 15:07:34 +02:00
a1933447f0 no 2022-09-30 15:05:58 +02:00
20f6eb6796 prevent double logpoints 2022-09-30 15:05:18 +02:00
43e970a1aa better ? 2022-09-30 14:59:54 +02:00
994af56880 i don't know what I am doing 2022-09-30 14:45:53 +02:00
712cc14368 added a risky mode, way faster 2022-09-30 14:34:50 +02:00
a1969a3e2e removed discord requirement 2022-09-30 14:26:34 +02:00
da33edb381 Merge branch 'master' of https://github.com/piair338/MsReward 2022-09-28 15:04:10 +02:00
dea767a392 some typo 2022-09-28 15:04:07 +02:00
da2471f304 Merge pull request #9 from augustin64/patch-1
Fix constant name
2022-09-25 15:37:57 +02:00
b6e30888bb Update V4.py
Fix constant name (introduced in [this commit](5b3b7c8aec))
2022-09-25 15:32:34 +02:00
d2cc6891ed Update README.md 2022-09-23 16:41:32 +02:00
556e89e2b4 finally a docker support 2022-09-23 16:34:01 +02:00
5b3b7c8aec better global constant name 2022-09-23 15:13:14 +02:00
088861e65d Update requirements.txt 2022-09-04 14:35:49 +02:00
8c1de642df Update requirements.txt 2022-09-04 14:12:37 +02:00
a4a1cb3b81 Update requirements.txt 2022-09-04 13:56:47 +02:00
2d1cc9e1c0 some tests 2022-08-30 12:00:30 +02:00
2dffe6851a date + more sleep 2022-08-30 11:28:02 +02:00
5c368ce0d0 test 2022-08-30 11:17:56 +02:00
64d70afdd5 yeah 2022-08-29 11:48:05 +02:00
c3d49cd093 fixed double login issue 2022-08-29 11:44:35 +02:00
593ddbf4fc idk anymore 2022-08-29 11:36:08 +02:00
1e33769c0d wtf 2022-08-29 11:22:45 +02:00
a3adff8130 updated to fix some things 2022-08-29 10:44:57 +02:00
2dffc31d90 accent terms 2022-08-22 11:03:20 +02:00
76c6d84105 Merge branch 'master' of https://github.com/piair338/MsReward 2022-06-28 12:27:24 +02:00
590ac8885e new user agent 2022-06-28 12:27:22 +02:00
b5e52591dd ah 2022-06-23 13:40:01 +02:00
ef5cdab883 p 2022-06-23 13:26:31 +02:00
38c24ce143 oui 2022-06-22 21:18:08 +02:00
cbdc6c9935 mistake 2022-06-22 20:22:52 +02:00
05c9d505eb test do allow docker run 2022-06-22 20:16:04 +02:00
eb3c510f82 better path handeling 2022-06-22 18:58:28 +02:00
f0f8fc324c k 2022-06-22 12:31:00 +02:00
212b92f937 yeah 2022-06-22 12:30:08 +02:00
b562930583 comming soon ® 2022-06-22 12:26:50 +02:00
776da465aa fix som issues in quiz8, where element is not found 2022-06-21 17:36:18 +02:00
a3dcf15f7d you can now cancel sleep 2022-06-21 17:22:44 +02:00
3376eaf8ac better fulllog logic 2022-06-20 18:24:29 +02:00
1eb606a62c cleander Logs 2022-06-20 18:16:15 +02:00
66d5354ac2 Check if ipv4 is used 2022-06-17 07:22:37 +02:00
ba70727b02 test smth 2022-06-17 07:10:32 +02:00
0f5c64f9d3 comments 2022-06-17 07:05:46 +02:00
fbed3ae854 not usefull messages 2022-06-16 08:21:09 +02:00
8f6f2ab5df oui. 2022-06-10 14:15:42 +02:00
a9bd8ecf9b well 2022-06-10 12:39:18 +02:00
bcb7511ecf Merge branch 'master' of https://github.com/piair338/MsReward 2022-06-10 07:07:50 +02:00
4fa9339632 reenable binmobilesearch for every computer 2022-06-10 07:07:46 +02:00
a57383b4c9 Update README.md 2022-06-09 16:35:00 +02:00
491891f4de type error 2022-06-09 16:28:30 +02:00
4f29e876b1 update point 2022-06-09 16:23:13 +02:00
b7f3bd053a fallback fidelité 2022-06-09 14:36:51 +02:00
5614a06f38 unused import + fallback logpoint 2022-06-09 14:34:02 +02:00
69e8916a05 updated login to have a fallback 2022-06-09 14:19:34 +02:00
fd22c9e176 small changes 2022-06-06 12:32:37 +02:00
fe8c1addaa oui 2022-06-02 12:39:30 +02:00
d4fcc7f769 re disabled mobile search for proxy 2022-06-02 12:29:17 +02:00
b459129d66 renabled mobile search with proxy 2022-05-31 21:33:25 +02:00
c0d2ea29c7 ... 2022-05-31 21:25:17 +02:00
c7da397f28 ? 2022-05-31 21:22:37 +02:00
e1a166ed6e some test about the proxy 2022-05-29 21:42:11 +02:00
9684a98fb3 oui 2022-05-28 11:50:45 +02:00
f5d332c26e added more delay during logging 2022-05-28 08:18:21 +02:00
bc665819e8 workarroud for now on bingMobileSearch not working with a proxy 2022-05-27 15:36:59 +02:00
e93dd60da0 still test 2022-05-27 15:28:41 +02:00
f9c5e30856 test 2022-05-27 15:26:16 +02:00
36a7fec15c oui 2022-05-27 14:54:21 +02:00
25da67077b push 2022-05-27 14:52:29 +02:00
dd0b280b28 oui 2022-05-27 14:49:25 +02:00
4dacc7b61c test 2022-05-27 14:46:23 +02:00
a85ff49f25 updated mobile login 2022-05-27 14:42:28 +02:00
e9c2ee6f95 revert modif made to mobile search 2022-05-27 14:10:29 +02:00
2bba6d8235 erreur dans la partie fidélité si le lien étais pas bon 2022-05-27 14:07:52 +02:00
cfb26f6732 test 2022-05-27 10:07:19 +02:00
e4ad601317 mobile search wtf 2022-05-27 09:50:21 +02:00
9032f56d99 test 2022-05-27 09:40:54 +02:00
b26f0c1130 test 2022-05-27 09:37:34 +02:00
365df0abcd update mobile login 2022-05-27 09:28:31 +02:00
13ab9b1acf Update README.md 2022-05-26 08:55:24 +02:00
9155fbead0 Create LICENSE 2022-05-26 08:40:03 +02:00
078bf45e67 Update issue templates 2022-05-26 08:30:50 +02:00
ac34baf215 Update README.md 2022-05-26 08:27:07 +02:00
06e65222db Updated from downloaded world list to default one 2022-05-26 08:24:36 +02:00
e5cce67a76 Merge branch 'master' of https://github.com/piair338/MsReward 2022-05-26 08:20:05 +02:00
4e4461f7f8 enable default linux worldlist support 2022-05-26 08:20:02 +02:00
54aa973d46 Defaulted to Linux default world list
You can get then with the command apt-get install wfrench
2022-05-26 07:57:53 +02:00
df0ea09662 remove trailing spaces + added some comments + dealed with error with some popus + some little things 2022-05-26 07:47:29 +02:00
5f554cc9b2 Merge pull request #8 from augustin64/patch-3
Update V4.py
2022-05-25 07:16:05 +02:00
5406b5538b may be ok 2022-05-24 22:53:02 +02:00
7e2e5cf0c2 Merge branch 'master' of https://github.com/piair338/MsReward 2022-05-24 22:43:02 +02:00
20efc9f3f6 s 2022-05-24 22:43:01 +02:00
d2ed535bf2 Update .gitignore 2022-05-24 22:42:05 +02:00
d959594e71 Create requirements.txt 2022-05-24 22:41:44 +02:00
66c979c624 STILL 2022-05-24 22:39:18 +02:00
3bebee9c13 AS WELL 2022-05-24 22:38:23 +02:00
fa8d27db0f STILL BUGGED 2022-05-24 22:38:13 +02:00
d0f76720f6 WARNING this has not beeing tested yet 2022-05-24 22:32:38 +02:00
80 changed files with 4087 additions and 1081 deletions

2
.dockerignore Normal file
View File

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

View File

@ -1,8 +1,32 @@
if you have a rare bug, i'll not fix it. If you have a reccurent bug, send :
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
| python version |
| --- |
| page.html |
screenshot of error
---
and i may try to fix it.
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem, and the html file if there is an error.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

20
.gitignore vendored
View File

@ -1,9 +1,19 @@
/old
dev_build.sh
geckodriver.log
config
.vscode/settings.json
update.sh
.vscode/
.idea
venv
**/.venv
/Git
page.html
screenshot.png
login.csv
data
**/__pycache__
user_data/*
install.sh
nohup.out
file.png
*.ts
LICENSE
README.md
venv

43
Dockerfile Normal file
View File

@ -0,0 +1,43 @@
FROM python:3.10
ENV DEBIAN_FRONTEND noninteractive
WORKDIR /app/
# 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/
CMD bash start.sh

471
Flask/app.py Normal file
View File

@ -0,0 +1,471 @@
import gevent.monkey
gevent.monkey.patch_all()
from time import sleep
import subprocess
import os
from flask import Flask, Response, redirect, url_for, request, session, abort, render_template, send_from_directory
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from flask_login import LoginManager, UserMixin, login_required, login_user, logout_user
from werkzeug.utils import secure_filename
import json
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')
try :
for message in pubsub.listen():
if message['type'] == 'message':
print(message)
yield f"data: {message['data'].decode()}\n\n"
except Exception as e:
print(f"ya eu une erreur sad {e}")
# the end
global password
with open(get_path("user_data/flask.json"), "r") as inFile:
data = json.load(inFile)
password = data["password"]
secret = data["secret"]
if secret == "":
import secrets
secret = secrets.token_hex()
with open(get_path("user_data/flask.json"), "w") as inFile:
data = {
"password": password,
"secret": secret
}
json.dump(data, inFile)
"""
#Automatic start of MsRewards
"""
def daily_command():
subprocess.Popen(["git",'pull'])
subprocess.Popen(["pkill","-9","chrome"])
subprocess.Popen(["pkill","-9","Xvfb"])
subprocess.Popen(["pkill","-9","Xvnc"])
subprocess.Popen(["pkill","-9", "undetected_chromedriver"])
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job( # on relance le job
daily_command, # ---
trigger=CronTrigger(
year="*", month="*", day="*", hour="0", minute="0", second="0"
), # ---
name="Daily refresh", # ---
id="99" # ---
)
def start_ms(i):
print("\033[32m" + f"Starting config {i}" + "\033[0m")
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(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
for i in configs:
try :
h, m = configs[i]["time"].split(":")
print("\033[36m" + f"config {i} : {h}:{m}" + "\033[0m")
TriggerDict[i] = CronTrigger(
year="*", month="*", day="*", hour=h, minute=m, second="0"
)
if configs[i]["enabled"]:
try :
scheduler.remove_job(i) # on reset le job
except Exception as e:
print(f"\033[33merror with deleting config {i} : {e}\033[0m")
try :
scheduler.add_job( # on relance le job
start_ms, # ---
trigger=TriggerDict[i], # ---
args=[i], # ---
name="Daily start", # ---
id=i # ---
)
print("\033[36m" + f"successfully created config {i}" + "\033[0m")
except Exception as e:
print(f"\033[33merror with creating config {i} : {e}\033[0m")
else :
try :
scheduler.remove_job(i)
except Exception as e :
print(f"\033[33merror with deleting config {i} : {e}\033[0m")
except Exception as e:
print(e)
"""
#Flask app
"""
app = Flask(__name__)
@app.context_processor
def inject_default_variables():
with open(get_path("version"), "r") as f:
version = f.readline().replace("\n", '')
return dict(version=version)
"""
#Login stuff
"""
# config
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.config.update(
SECRET_KEY = secret
)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
# silly user model
class User(UserMixin):
def __init__(self, id):
self.id = id
self.name = "user" + str(id)
self.password = password
def __repr__(self):
return "%d/%s/%s" % (self.id, self.name, self.password)
users = [User(1)]
@app.route('/stream')
def stream():
return Response(generate_output(), content_type='text/event-stream')
@app.route("/login/", methods=["GET", "POST"])
def login():
if request.method == 'POST':
if request.form['password'] == password:
user = User(id)
login_user(user)
if password == "ChangeMe":
return(redirect('/change_password'))
return(redirect('/schedule'))
else:
return abort(401)
else:
return(render_template("login.html"))
@app.route("/change_password/", methods=["GET", "POST"])
@login_required
def change_password():
global password
if request.method == 'POST':
password = request.form["password"]
subprocess.Popen(["grafana-cli", "admin", "reset-admin-password", password])
with open(get_path("user_data/flask.json"), "w") as inFile:
data = {
"password": password,
"secret": secret
}
json.dump(data, inFile)
return(render_template("change_password.html"))
# handle login failed
@app.errorhandler(401)
def unauthorized(e):
return(redirect("/login"))
# callback to reload the user object
@login_manager.user_loader
def load_user(userid):
return User(userid)
"""
#end of login stuff
"""
@app.route("/")
def main():
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(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(get_path("user_data/discord.json"), "r") as inFile:
data = json.load(inFile)
action = request.form
if action['DISCORD'] == "delete" :
data.pop(action["select"], None)
else :
config = action["select"]
successL = action["successL"]
try :
a = action["successT"]
successT = "True"
except:
successT = "False"
try :
a = action["errorsT"]
errorsT = "True"
except:
errorsT = "False"
errorsL = action["errorsL"]
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(get_path("user_data/discord.json"), "w") as outFile:
json.dump(data, outFile)
return(render_template("discord.html", data=data, len=maxi(data)))
@app.route("/dev/")
def dev2():
return(render_template("dev.html"))
@app.route("/settings/")
def settings_get():
with open(get_path("user_data/settings.json"), "r") as inFile:
settings = json.load(inFile)
return(render_template("settings.html", data=settings))
@app.route("/settings/", methods=["post"])
def settings_post():
settings = {}
action = request.form
settings['avatarlink'] = action["avatarlink"]
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(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(get_path("user_data/proxy.json"), "r") as inFile:
data = json.load(inFile)
action = request.form
print(action)
if action['PROXY'] == "delete" :
print(action)
data.pop(action["select"], None)
else :
try :
config = action["select"]
address = action["address"]
port = action["port"]
name = action["name"] if action["name"] else f"@unnamed{action['select']}"
data[config] = {"address" : address, "port": port, "name": name}
except :
print("error : probably bad config")
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(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(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
data = dict(request.form)
for i in configs:
try :
data[f'switch{i}']
except :
data[f'switch{i}'] = "off"
for i in configs:
configs[i]["time"] = data[f"time{i}"]
configs[i]["enabled"] = data[f"switch{i}"] == "on"
with open(get_path("user_data/configs.json"), "w") as inFile:
json.dump(configs, inFile)
update_jobs()
return(render_template("schedule.html", data=configs))
@app.route("/config/")
def config_get():
with open(get_path("user_data/proxy.json"), "r") as inFile:
proxys = json.load(inFile)
with open(get_path("user_data/discord.json"), "r") as inFile:
discords = json.load(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)))
@app.route("/config/", methods=["POST"])
def config_post():
action = request.form
with open(get_path("user_data/proxy.json"), "r") as inFile:
proxys = json.load(inFile)
with open(get_path("user_data/discord.json"), "r") as inFile:
discords = json.load(inFile)
with open(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
if action["data"] == "delete":
print(action["config"])
configs.pop(action["config"])
else :
comptes = {
"1":{"mail": action["mail1"], "pwd": action["pwd1"], "2fa": action["2fa1"]},
"2":{"mail": action["mail2"], "pwd": action["pwd2"], "2fa": action["2fa2"]},
"3":{"mail": action["mail3"], "pwd": action["pwd3"], "2fa": action["2fa3"]},
"4":{"mail": action["mail4"], "pwd": action["pwd4"], "2fa": action["2fa4"]},
"5":{"mail": action["mail5"], "pwd": action["pwd5"], "2fa": action["2fa5"]}
}
configs[action["config"]] = {
"name" : action["name"] if action["name"] != "" else f"unnamed{action['config']}",
"proxy": action["proxy"],
"discord": action["discord"],
"time":"",
"enabled":"False",
"accounts": comptes
}
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(get_path("user_data/configs.json"), "r") as inFile:
configs = json.load(inFile)
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"])
def stats():
return(render_template("stats.html"))
@app.route("/override/", methods=["POST"])
def override_post():
json = request.form.to_dict(flat=False)
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(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=get_path("user_data/"), path=filename, as_attachment=True)
def allowed_file(filename):
ALLOWED_EXTENSIONS = ["json"]
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload_file/', methods=['POST'])
@login_required
def upload_file():
print(request.files)
i = 1
while f'file{i}' in request.files :
file = request.files[f'file{i}']
if file.filename == '':
print('end of files')
return redirect(url_for('settings_get'))
elif file and allowed_file(file.filename):
filename = secure_filename(file.filename)
print(os.path.join(get_path("user_data/"), filename))
file.save(os.path.join(get_path("user_data/"), filename))
i += 1
print(i)
print(f'file{i}' in request.files)
print("requete bizarre")
return redirect(url_for('settings_get'))
def maxi(dict):
m = 0
for i in dict :
if int(i) >= m:
m = int(i)
return(m+1)
update_jobs()
subprocess.Popen(["bash", get_path("config/request.sh")])
if __name__ == "__main__":
app.run()

5
Flask/start.sh Normal file
View File

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

405
Flask/static/css/flask.css Normal file
View File

@ -0,0 +1,405 @@
@import url('https://fonts.googleapis.com/css?family=Montserrat');
/* Colors */
:root {
--color-background0: #212121;
--color-background1: #212121;
--color-background2: dimgray;
--color-border0: #FFFFFF;
--color-border1: grey;
--color-text: #FFFFFF;
--color-green: green;
--color-lime: #BADA55;
--color-red: red;
--color-switch-button: #FFFFFF;
--color-switch-background: grey;
--color-transparent: rgba(0, 0, 0, 0);
}
/* Sidebar size is the left panel size when opened */
:root {
--sidebar-size: max(20vw, 160px);
--sidebar-sz-plus10: calc(var(--sidebar-size) + 10px);
--sidebar-sz-plus30: calc(var(--sidebar-size) + 30px);
}
html {
text-align: center;
font-family: Montserrat;
height: 95%;
}
form {
width: 100%;
}
table {
width: 100%;
height: 100%;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
a {
color: var(--color-text);
}
iframe{
border: none;
}
input[type=text] {
width: 90%;
padding: 12px 20px;
margin: 8px 0;
background-color: var(--color-background1);
border: 2px solid var(--color-border1);
border-radius: 4px;
outline: none;
color: var(--color-text);
text-align: center;
}
input[type=password] {
width: 90%;
padding: 12px 20px;
margin: 8px 0;
text-align: center;
border: 2px solid var(--color-border1);
border-radius: 4px;
outline: none;
color: var(--color-text);
background-color: var(--color-background1);
}
.button{
border-radius: 4px;
border: 2px solid var(--color-border1);
background-color: var(--color-background1);
color: var(--color-text);
padding: 12px 20px;
width: 70%;
margin: 10px;
}
.left-button{
width: 10%;
}
.ban{
border-radius: 4px;
border: 2px solid var(--color-red);
background-size: 200% 100%;
background-image: linear-gradient(to right, var(--color-background1) 50%, var(--color-red) 50%);
-webkit-transition: background-position 0.5s;
-moz-transition: background-position 0.5s;
transition: background-position 0.5s;
color: var(--color-text);
padding: 12px 0px;
width: 70%;
margin: 10px;
}
.ban:hover{
background-position: -100% 0;
}
.confirm{
color: var(--color-text);
padding: 12px 20px;
width: 70%;
margin: 10px;
background-size: 200% 100%;
background-image: linear-gradient(to right, var(--color-background1) 50%, var(--color-green) 50%);
-webkit-transition: background-position 0.5s;
-moz-transition: background-position 0.5s;
transition: background-position 0.5s;
border: 2px solid var(--color-border1);
}
.confirm:hover{
background-position: -100% 0;
}
.confirm{
color: var(--color-text);
padding: 12px 20px;
width: 70%;
margin: 10px;
background-size: 200% 100%;
background-image: linear-gradient(to right, var(--color-background1) 50%, var(--color-green) 50%);
-webkit-transition: background-position 0.5s;
-moz-transition: background-position 0.5s;
transition: background-position 0.5s;
border: 2px solid var(--color-border1);
}
.confirm:hover{
background-position: -100% 0;
}
.unselected{
border-radius: 4px;
border: 2px solid var(--color-border1);
background-color: var(--color-background1);
color: var(--color-text);
padding: 12px 20px;
width: 70%;
margin: 10px;
}
.selected{
border-radius: 4px;
border: 2px solid var(--color-border1);
background-color: var(--color-background2);
color: var(--color-text);
padding: 12px 20px;
width: 70%;
margin: 10px;
}
button:hover{
border: 2px solid var(--color-border0);
cursor: pointer;
}
input:hover{
border: 2px solid var(--color-border0);
}
.submit{
border-radius: 4px;
border: 2px solid var(--color-border1);
background-color: var(--color-background1);
color: var(--color-text);
padding: 12px 20px;
width: 100%;
margin: 10px;
}
body {
background-color: var(--color-background0);
color: var(--color-text);
height: 100%;
}
.left-pannel{
flex: 1;
margin: 20px;
border: 1px solid var(--color-border0);
border-radius: 5px;
padding: 20px;
width: 80%;
height: 90%;
}
.content{
flex: 3;
margin: 20px;
border: 1px solid var(--color-border0);
border-radius: 5px;
padding: 20px;
height: 90%;
}
.content > ul {
display: inline-block;
}
.container {
display: flex;
width: 100%;
height: 100%;
}
.row-item {
margin: 10px 0;
text-align: center;
}
#image img {
display: block;
margin: auto;
width: 20%;
}
.comlumn-name{
width: 20%;
}
/*
For toggle switch
*/
input.toogle[type=checkbox]{
height: 0;
width: 0;
visibility: hidden;
}
label {
padding: 8px;
margin: auto;
cursor: pointer;
text-indent: -9999px;
width: 100px;
height: 50px;
background: var(--color-switch-background);
display: block;
border-radius: 100px;
position: relative;
}
/*
width: height of label /2 ;
height: height of label /2px;
*/
label:after {
content: '';
position: absolute;
top: 5px;
left: 5px;
width: 40px;
height: 40px;
background: var(--color-switch-button);
border-radius: 90px;
transition: 0.3s;
}
input:checked + label {
background: var(--color-lime);
}
input:checked + label:after {
left: calc(100% - 5px);
transform: translateX(-100%);
}
/*changer l'épaisseur du click */
label:active:after {
width: 30px;
}
select {
width: 90%;
/*height: 100%;*/
padding: 12px 20px;
margin: 8px 0;
background-color: var(--color-background1);
border: 2px solid var(--color-border1);
border-radius: 4px;
outline: none;
color: var(--color-text);
text-align: center;
}
select:hover {
border: 2px solid var(--color-border0);
}
input[type="time"] {
width: 70%;
padding: 8px 12px;
margin: 8px 0;
background-color: var(--color-background1);
border: 2px solid var(--color-border1);
border-radius: 4px;
outline: none;
color: var(--color-text);
text-align: center;
}
input[type="time"]::-webkit-calendar-picker-indicator {
filter: invert(1);
opacity: 0.7;
cursor: pointer;
}
input[type="time"]::-webkit-calendar-picker-indicator:hover {
opacity: 1;
}
/** Sidebar stuff */
#slide-sidebar {
display: none;
}
label[for="slide-sidebar"] {
all: initial;
z-index: 1; /* Always on top */
position: absolute;
top: 20px;
left: var(--sidebar-sz-plus30);
-moz-transition: left 0.5s ease;
transition: left 0.5s ease;
background: var(--color-transparent);
}
label[for="slide-sidebar"]:after {
all:unset;
}
input:checked + label[for="slide-sidebar"] {
background: var(--color-transparent);
}
#slide {
border-style: solid;
border-radius: 4px;
border-width: 1px;
border-color: var(--color-border0);
color: var(--color-text);
background-color: var(--color-background0);
padding: 8px 8px 2px 8px;
}
/* When opened behaviour */
.left-pannel {
width: var(--sidebar-size);
position: fixed;
top: 0;
left: 0;
bottom: 0;
}
.content {
position: absolute;
top: 0;
left: var(--sidebar-sz-plus10);
right: 0;
bottom: 0;
-moz-transition: left 0.5s ease;
transition: left 0.5s ease;
padding: 0 25px;
background-color: var(--color-background0); /* we need no transparency when switching */
overflow: hidden;
}
/* When closed behaviour */
input:checked#slide-sidebar~label {
left: 20px;
}
input:checked#slide-sidebar~.left-pannel {
display: none;
transition: display 0s 0.5s;
}
input:checked#slide-sidebar~.content {
left: 0;
}

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%;
}

BIN
Flask/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 21 0 C 19.355469 0 18 1.355469 18 3 L 18 5 L 10.1875 5 C 10.0625 4.976563 9.9375 4.976563 9.8125 5 L 8 5 C 7.96875 5 7.9375 5 7.90625 5 C 7.355469 5.027344 6.925781 5.496094 6.953125 6.046875 C 6.980469 6.597656 7.449219 7.027344 8 7 L 9.09375 7 L 12.6875 47.5 C 12.8125 48.898438 14.003906 50 15.40625 50 L 34.59375 50 C 35.996094 50 37.1875 48.898438 37.3125 47.5 L 40.90625 7 L 42 7 C 42.359375 7.003906 42.695313 6.816406 42.878906 6.503906 C 43.058594 6.191406 43.058594 5.808594 42.878906 5.496094 C 42.695313 5.183594 42.359375 4.996094 42 5 L 32 5 L 32 3 C 32 1.355469 30.644531 0 29 0 Z M 21 2 L 29 2 C 29.5625 2 30 2.4375 30 3 L 30 5 L 20 5 L 20 3 C 20 2.4375 20.4375 2 21 2 Z M 11.09375 7 L 38.90625 7 L 35.3125 47.34375 C 35.28125 47.691406 34.910156 48 34.59375 48 L 15.40625 48 C 15.089844 48 14.71875 47.691406 14.6875 47.34375 Z M 18.90625 9.96875 C 18.863281 9.976563 18.820313 9.988281 18.78125 10 C 18.316406 10.105469 17.988281 10.523438 18 11 L 18 44 C 17.996094 44.359375 18.183594 44.695313 18.496094 44.878906 C 18.808594 45.058594 19.191406 45.058594 19.503906 44.878906 C 19.816406 44.695313 20.003906 44.359375 20 44 L 20 11 C 20.011719 10.710938 19.894531 10.433594 19.6875 10.238281 C 19.476563 10.039063 19.191406 9.941406 18.90625 9.96875 Z M 24.90625 9.96875 C 24.863281 9.976563 24.820313 9.988281 24.78125 10 C 24.316406 10.105469 23.988281 10.523438 24 11 L 24 44 C 23.996094 44.359375 24.183594 44.695313 24.496094 44.878906 C 24.808594 45.058594 25.191406 45.058594 25.503906 44.878906 C 25.816406 44.695313 26.003906 44.359375 26 44 L 26 11 C 26.011719 10.710938 25.894531 10.433594 25.6875 10.238281 C 25.476563 10.039063 25.191406 9.941406 24.90625 9.96875 Z M 30.90625 9.96875 C 30.863281 9.976563 30.820313 9.988281 30.78125 10 C 30.316406 10.105469 29.988281 10.523438 30 11 L 30 44 C 29.996094 44.359375 30.183594 44.695313 30.496094 44.878906 C 30.808594 45.058594 31.191406 45.058594 31.503906 44.878906 C 31.816406 44.695313 32.003906 44.359375 32 44 L 32 11 C 32.011719 10.710938 31.894531 10.433594 31.6875 10.238281 C 31.476563 10.039063 31.191406 9.941406 30.90625 9.96875 Z"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

102
Flask/static/js/main.js Normal file
View File

@ -0,0 +1,102 @@
function addline(ligne){
var lplus = parseInt(ligne) + 1;
document.getElementById("table").insertRow(lplus).insertCell(0).innerHTML = '<input type="file" id="file' + lplus + '" name="file' + lplus + '" onchange="addline(' + lplus + ')">'
}
function change_discord(value, data, len) {
if (value == len){
document.getElementById("name").value = "";
document.getElementById("submit").value = "Create !";
document.getElementById("successT").checked = false;
document.getElementById("errorsT").checked = false;
document.getElementById("successL").value = "";
document.getElementById("errorsL").value = "";
}
else {
console.log(data[parseInt(value)]["successL"]);
document.getElementById("submit").value = "Update";
document.getElementById("successT").checked = data[parseInt(value)]["successT"] == "True";
document.getElementById("errorsT").checked = data[parseInt(value)]["errorsT"] == "True";
document.getElementById("successL").value = data[parseInt(value)]["successL"];
document.getElementById("errorsL").value = data[parseInt(value)]["errorsL"];
document.getElementById("name").value = data[parseInt(value)]["name"];
}
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function change_config(value, data, len) {
console.log(data[2]);
document.getElementById("delete").style.visibility = "hidden";
if (value == len){
document.getElementById("submit").value = "Create !";
document.getElementById("discord").value = "-1";
document.getElementById("proxy").value = "-1";
document.getElementById("name").value = "";
for (let i = 1; i < 6; i++) {
document.getElementById("mail"+ i).value = "";
document.getElementById("pwd"+ i).value = "" ;
document.getElementById("2fa"+ i).value = "" ;
}
}
else {
document.getElementById("delete").style.visibility = "visible";
document.getElementById("submit").value = "Update !";
document.getElementById("discord").value = data[parseInt(value)]["discord"];
document.getElementById("proxy").value = data[parseInt(value)]["proxy"];
document.getElementById("name").value = data[parseInt(value)]["name"];
for (let i = 1; i < 6; i++) {
document.getElementById("mail"+ i).value = data[parseInt(value)]['accounts'][i]["mail"] ;
document.getElementById("pwd"+ i).value = data[parseInt(value)]['accounts'][i]["pwd"] ;
document.getElementById("2fa"+ i).value = data[parseInt(value)]['accounts'][i]["2fa"] ;
}
}
}
function change_proxy(value, data, len) {
if (value == len){
document.getElementById("submit").value = "Create";
document.getElementById("address").value = "";
document.getElementById("port").value = "";
document.getElementById("name").value = "";
}
else {
document.getElementById("submit").value = "Update";
document.getElementById("address").value = data[parseInt(value)]["address"];
document.getElementById("port").value = data[parseInt(value)]["port"];
document.getElementById("name").value = data[parseInt(value)]["name"];
}
}
function change_override(value, data) {
for (let i = 1; i < 6; i++) {
document.getElementById("compte_"+ i).innerHTML = data[parseInt(value)]['accounts'][i]["mail"];
if (!(data[parseInt(value)]['accounts'][i]["mail"])){
console.log("hiding" + i);
for (let j = 1; j <= 5; j++) {
document.getElementById(i.toString() +j.toString()).style.visibility = "hidden";
}
} else {
console.log("showing" + i);
for (let j = 1; j <= 5; j++) {
console.log("element " + i.toString()+j.toString());
document.getElementById(i.toString()+j.toString()).style.visibility = "visible";
}
}
}
}
function change_logs(value) {
var myIframe = document.getElementById('embed');
myIframe.addEventListener("load", function() {
let doc = myIframe.contentDocument;
doc.body.innerHTML = doc.body.innerHTML + '<style>html{color:white;}</style>';
myIframe.contentWindow.scrollTo(0, myIframe.contentDocument.body.scrollHeight);
});
myIframe.src = "/static/logs/" + value + ".txt";
}

1
Flask/static/logs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.txt

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"
}
}

79
Flask/templates/base.html Normal file
View File

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<meta name="robots" content="noindex, nofollow">
<meta charset="utf-8">
<link rel="icon" type="image/png" href="{{ url_for('static', filename='favicon.ico') }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MS Rewards</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/flask.css')}}"/>
<script src="{{ url_for('static', filename='js/main.js')}}"></script>
</head>
<body>
<div class="container">
<input id="slide-sidebar" type="checkbox" role="button"/>
<label for="slide-sidebar">
<div id="slide">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-menu-2" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M4 6l16 0"></path>
<path d="M4 12l16 0"></path>
<path d="M4 18l16 0"></path>
</svg>
</div>
</label>
<div class="left-pannel">
<table>
<tr>
<td>
<button class="unselected" id="sidebar_schedule" onclick="location.href = '/schedule';">schedule</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_config" onclick="location.href = '/config';">config</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_discord" onclick="location.href = '/discord';">discord</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_proxy" onclick="location.href = '/proxy';">proxy</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_logs" onclick="location.href = '/logs';">logs</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_stats" onclick="location.href = '/stats';">stats</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_override" onclick="location.href = '/override';">Override</button>
</td>
</tr>
<tr>
<td>
<button class="unselected" id="sidebar_settings" onclick="location.href = '/settings';">settings</button>
</td>
</tr>
</table>
<script>document.getElementById("sidebar_{% block left_pannel %}{% endblock %}").className = "selected"</script>
</div>
<div class="content">
{% block content %}
{% endblock %}
</div>
</div>
<div class="footer">{{version}}</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% block left_pannel %}
{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<h1>Already logged in</h1>
{% else %}
<form method="post" action="/change_password/">
<table>
<tr>
<td class="comlumn-name">Change password</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="NewPassword" value="send" class="button"/></td>
</tr>
</table>
</form>
{% endif %}
{% endblock %}

106
Flask/templates/config.html Normal file
View File

@ -0,0 +1,106 @@
{% extends "base.html" %}
{% block left_pannel %}config{% endblock %}
{% block content %}
<script>data2 = JSON.parse('{{configs|tojson}}'); </script>
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<form method="post" action="/config/">
<table>
<tr>
<td style="width: 10%;">config : </td>
<td style="width: 40%;">
<select onchange="change_config(this.value, data2, '{{len}}')" name="config">
<option id="config" value="{{len}}">New config</option>
{% for i in configs %}
<option id="{{configs[i]['name']}}" value="{{i}}">{{configs[i]['name']}}</option>
{% endfor %}
</select>
</td>
<td style="width: 10%;">name : </td>
<td>
<input type="text" id="name" name="name" value = "">
</td>
</tr>
<tr>
<td style="width: 10%;">Proxy : </td>
<td style="width: 40%;">
<select id="proxy" name="proxy">
<option id="" value="-1">No proxy</option>
{% for i in proxys %}
<option id="{{proxys[i]['name']}}" value="{{i}}">{{proxys[i]['name']}}</option>
{% endfor %}
</select>
</td>
<td style="width: 10%;">Discord : </td>
<td>
<select id="discord" name="discord">
<option id="no discord" value="-1">No discord (not sure about the support)</option>
{% for i in discords %}
<option id="{{discords[i]['name']}}" value="{{i}}">{{discords[i]['name']}}</option>
{% endfor %}
</select>
</td>
</tr>
</table>
<br><br>
<table>
<tr>
<td>Mail</td>
<td>Password</td>
<td>2FA</td>
</tr>
<tr>
<td><input type="text" id="mail1" name="mail1" value=""></td>
<td><input type="text" id="pwd1" name="pwd1" value=""></td>
<td><input type="text" id="2fa1" name="2fa1" value=""></td>
<td class="left-button"><button class="ban" name="ban" value="">ban</button></td>
</tr>
<tr>
<td><input type="text" id="mail2" name="mail2" value=""></td>
<td><input type="text" id="pwd2" name="pwd2" value=""></td>
<td><input type="text" id="2fa2" name="2fa2" value=""></td>
<td class="left-button"><button class="ban" name="ban" value="">ban</button></td>
</tr>
<tr>
<td><input type="text" id="mail3" name="mail3" value=""></td>
<td><input type="text" id="pwd3" name="pwd3" value="" ></td>
<td><input type="text" id="2fa3" name="2fa3" value=""></td>
<td class="left-button"><button class="ban" name="ban" value="">ban</button></td>
</tr>
<tr>
<td><input type="text" id="mail4" name="mail4" value=""></td>
<td><input type="text" id="pwd4" name="pwd4" value="" ></td>
<td><input type="text" id="2fa4" name="2fa4" value=""></td>
<td class="left-button"><button class="ban" name="ban" value="">ban</button></td>
</tr>
<tr>
<td><input type="text" id="mail5" name="mail5" value=""></td>
<td><input type="text" id="pwd5" name="pwd5" value=""></td>
<td><input type="text" id="2fa5" name="2fa5" value=""></td>
<td class="left-button"><button class="ban" name="ban" value="">ban</button></td>
</tr>
</table>
<table>
<tr>
<td>
<input type="submit" class="confirm" name="data" id="submit" value="Create !" class="button" style="width:97%;"/>
</td>
<td class="left-button">
<input type="submit" name="data" id="delete" value="delete" class="ban" style="visibility: hidden;"/>
</td>
</tr>
</table>
</form>
{% endif %}
{% endblock %}

31
Flask/templates/dev.html Normal file
View File

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block left_pannel %}{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<table>
<tr>
<td width="20%" height="90%">
<div id="console"></div>
</td>
</tr>
</table>
<script>
const consoleElement = document.getElementById('console');
const eventSource = new EventSource('/stream');
eventSource.onmessage = (event) => {
console.log("je ne comprend vraiment plus rien, meme git me casse les couilles");
const newOutput = document.createElement('div');
newOutput.textContent = event.data;
consoleElement.appendChild(newOutput);
};
</script>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,56 @@
{% extends "base.html" %}
{% block left_pannel %}discord{% endblock %}
{% block content %}
<script>data = JSON.parse('{{data|tojson}}'); </script>
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<form method="post" action="/discord/">
<table>
<tr>
<td></td>
<td>
<select name="select" onchange="change_discord(this.value, data, '{{len}}')">
<option selected id="new" value="{{ len }}">Create new Discord config</option>
{% for i in data %}
<option id="{{data[i]['name']}}" value="{{i}}">{{data[i]['name']}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="comlumn-name">name</td>
<td><input type="text" id="name" name="name" value=""></td>
</tr>
<tr>
<td class="comlumn-name">Send errors</td>
<td><input type="checkbox" id="errorsT" name="errorsT" class="toogle"/><label for="errorsT">Toggle</label></td>
</tr>
<tr>
<td class="comlumn-name">Send success</td>
<td><input type="checkbox" id="successT" name="successT" class="toogle"/><label for="successT">Toggle</label></td>
</tr>
<tr>
<td class="comlumn-name">Success link</td>
<td><input type="text" id="successL" name="successL" value=""></td>
</tr>
<tr>
<td class="comlumn-name">Failure Link</td>
<td><input type="text" id="errorsL" name="errorsL" value=""></td>
</tr>
</table>
<table>
<tr>
<td class="comlumn-name"></td>
<td style="width:60%;"><input type="submit" name="DISCORD" id="submit" value="Create !" class="confirm" style="width:86%;"/></td>
<td style="padding-right: 20px;">
<input type="submit" name="DISCORD" id="submit" value="delete" class="ban" style="width:60%;"/>
</td>
</tr>
</table>
</form>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% block left_pannel %}login{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<form method="post" action="/login/">
<table>
<tr>
<td class="comlumn-name">password</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="DISCORD" value="send" class="button"/></td>
</tr>
</table>
</form>
{% else %}
<h1>Already logged in</h1>
{% endif %}
{% endblock %}

44
Flask/templates/logs.html Normal file
View File

@ -0,0 +1,44 @@
{% extends "base.html" %}
{% block left_pannel %}logs{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<h1>Already logged in</h1>
{% else %}
<select name="select" onchange="change_logs(this.value)">
<option id="null" value="0">Choisir une config</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>
<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

@ -0,0 +1,53 @@
{% extends "base.html" %}
{% block left_pannel %}proxy{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<form method="post" action="/proxy/">
<table>
<tr>
<td class="comlumn-name"></td>
<td>
<script>data = JSON.parse('{{data|tojson}}');</script>
<select name="select" onchange="change_proxy(this.value, data, '{{len}}')">
<option selected id="new" value="{{ len }}">Create new proxy</option>
{% for i in data %}
<option id="{{data[i]['name']}}" value="{{i}}">{{data[i]['name']}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="comlumn-name">name : </td>
<td><input type="text" name="name" value="" id="name"></td>
</tr>
<tr>
<td class="comlumn-name">address : </td>
<td><input type="text" name="address" value="" id="address"></td>
</tr>
<tr>
<td class="comlumn-name">port : </td>
<td><input type="text" name="port" value="" id="port"></td>
</tr>
</table>
<table>
<tr>
<td class="comlumn-name"></td>
<td style="width:60%;"><input type="submit" name="PROXY" id="submit" value="Create !" class="confirm" style="width:86%;"/></td>
<td style="padding-right: 20px;"><input type="submit" name="PROXY" id="submit" value="delete" class="ban" style="width:60%;"/></td>
</tr>
</table>
</form>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,35 @@
{% extends "base.html" %}
{% block left_pannel %}schedule{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<form method="post" action="/schedule/">
<table>
{% for i in data %}
<tr>
<td>{{data[i]['name']}}</td>
<td>
<input type="time" id="{{i}}" name="time{{i}}" value="{{data[i]['time']}}" required>
</td>
<td>
<input type="checkbox" class="toogle" id="switch{{i}}" name="switch{{i}}" {{ "checked" if data[i]['enabled'] == True else "" }} />
<label for="switch{{i}}">
Toggle
</label>
</td>
</tr>
{% endfor %}
</table>
<input type="submit" name="data" value="Update" class="button"/>
</form>
{% endif %}
{%endblock %}

View File

@ -0,0 +1,49 @@
{% extends "base.html" %}
{% block left_pannel %}settings{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<form method="post" action="/settings/">
<table>
<tr>
<td class="comlumn-name">avatar url :</td>
<td><input type="text" name="avatarlink" value="{{data['avatarlink']}}"></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="settings" id="submit" value="update" class="button"/>
</td>
</tr>
</table>
</form>
<h2>TODO</h2>
<ul>
<li>ban button</li>
</ul>
<br><br>
<h2>Backup config files</h2>
<ul>
<li><a href="/download/configs.json">download account config</a></li>
<li><a href="/download/discord.json">download discord config</a></li>
<li><a href="/download/flask.json">download flask config</a></li>
<li><a href="/download/proxy.json">download proxy config</a></li>
<li><a href="/download/settings.json">download settings</a></li>
</ul>
<br><br>
<h2>Upload your files</h2>
<form method="POST" action="/upload_file/" enctype=multipart/form-data>
<table id="table">
<tr><td><input type="file" id="file1" name="file1" onchange='addline(0)'></td></tr>
<tr><td><input type="submit" name="settings" id="submit" value="send file" class="button"/></td></tr>
</table>
</form>
{% endif %}
{%endblock %}

View File

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block left_pannel %}stats{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<iframe src="/grafana?orgId=1&kiosk" width="100%" height="100%" frameborder="0"></iframe>
{% endif %}
{%endblock %}

View File

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% block left_pannel %}override{% endblock %}
{% block content %}
{%if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% else %}
<script>data = JSON.parse('{{configs|tojson}}'); </script>
<form method="post" action="/override/" height="90%">
<select onchange="change_override(this.value, data)" name="config">
<option id="-1" value="-1" selected>Select a config</option>
{% for i in configs %}
<option id="{{configs[i]['name']}}" value="{{i}}">{{configs[i]['name']}}</option>
{% endfor %}
</select>
<table height="90%" class="lines">
<tr>
<td width="30%">name</td>
<td width="14%">Unban</td>
<td width="14%">tout</td>
<td width="14%">daily</td>
<td width="14%">pc</td>
<td width="14%">mobile</td>
</tr>
{% for i in range(0,5) %}
<tr heigh="15%">
<td id="compte_{{i+1}}"></td>
<td id="{{i+1}}1" style="visibility: hidden;"><input type="checkbox" id="compte_{{i+1}}" value="{{i}}" name="unban"></td>
<td id="{{i+1}}2" style="visibility: hidden;"><input type="checkbox" id="compte_{{i+1}}" value="{{i}}" name="tout"></td>
<td id="{{i+1}}3" style="visibility: hidden;"><input type="checkbox" id="compte_{{i+1}}" value="{{i}}" name="daily"></td>
<td id="{{i+1}}4" style="visibility: hidden;"><input type="checkbox" id="compte_{{i+1}}" value="{{i}}" name="pc"></td>
<td id="{{i+1}}5" style="visibility: hidden;"><input type="checkbox" id="compte_{{i+1}}" value="{{i}}" name="mobile"></td>
</tr>
{% endfor %}
</table>
<input type="submit" name="VNC" id="submit" value="Start" class="confirm" style="width:60%;"/>
</form>
{% endif %}
{%endblock %}

View File

@ -0,0 +1,48 @@
{% extends "base.html" %}
{% block left_pannel %}override{% endblock %}
{% block content %}
{% if not current_user.is_authenticated %}
<button class="unselected" onclick="location.href = '/login';">login</button>
{% 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>
<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()
});
document.getElementById("console").style.textAlign = "left"
const eventSource = new EventSource('/stream');
eventSource.onmessage = (event) => {
term.writeln(event.data)
};
addEventListener("resize", (event) => {
fitAddon.fit()
});
</script>
{% endif %}
{% endblock %}

View File

@ -1,18 +0,0 @@
# MsReward
A Microsoft reward automator, designed to work headless on a raspberry pi. Tested with a pi 3b+ and a pi 4 2Gb .
Using a discord webhook to log everything.
Using Selenium and geckodriver.
You have to fill the config file.
you have to put your credentials in the same folder as the script, in a `.csv` file. You have to put login and password this way :
```
email1,password1
email2,password2
```
You have to put a list with a dictionnary in the same folder as the script, in a `.txt` file. It should have a lot of words, used to make random search on bing, as shown in the example file.
Tou can add a link to a website where content is only the link of the monthly fidelity card
You should limit to 6 account per IP.
![image](https://user-images.githubusercontent.com/74496300/155960737-061229ca-db8c-4e66-9aef-542d9e709bb2.png)

1021
V4.py

File diff suppressed because it is too large Load Diff

953
V6.py Executable file
View File

@ -0,0 +1,953 @@
#!/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 critical, warning
from modules.cards import *
from modules.config import *
from modules.db import add_to_database
from modules.driver_tools import *
from modules.error import *
# create a webdriver
def create_driver(mobile=False):
pc_user_agent = (
"Mozilla/5.0 (X11; Linux x86_64)"
"AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/122.0.0.0 Safari/537.36 Edg/122.0.2088.46"
)
mobile_user_agent = (
"Mozilla/5.0 (Linux; Android 7.0; Nexus 5 Build/MRA58N)"
"AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/22 Mobile Safari/537.36"
)
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:
arguments.append(f"--user-agent={mobile_user_agent}")
else:
arguments.append(f"--user-agent={pc_user_agent}")
# disabled as it may cause detection
if config.proxy.is_enabled():
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)
return driver
# 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:
driver = config.WebDriver.driver
driver.switch_to.window(tab)
driver.close()
driver.switch_to.window(driver.window_handles[switch_to])
# play_quiz[N]([int : override]) make the quiz with N choice each time. They usually have between 4 and 10 questions.
# override is the number of question, by default, it's the number of question in this specific quiz.
# Can be useful in some case, where the program crashes before finishing the quiz
def play_quiz2(override=10) -> None:
info("Starting to play quiz 2.")
driver = config.WebDriver.driver
debug(f"override: {override}")
for j in range(override):
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
return _w.getRAValue()
};
if (br(document.getElementById("rqAnswerOption0").attributes["data-option"].value) == namedRAValue()){
return(0);
}
else {
return(1);
}
};
return(get_correct_answer())
"""
correct_answer_value = driver.execute_script(js_function)
try:
answer_elem = driver.find_element(By.ID, f"rqAnswerOption{correct_answer_value}")
answer_elem.click()
except exceptions.ElementNotInteractableException:
answer_elem = driver.find_element(By.ID, f"rqAnswerOption{correct_answer_value}")
driver.execute_script("arguments[0].click();", answer_elem)
except Exception as e:
log_error(e)
break
info("Quiz 2 done.")
custom_sleep(3)
def play_quiz8():
driver = config.WebDriver.driver
info(f"Starting Quiz 8")
override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source)) + 1
debug(f"override : {override}")
correct_answers = ["Should", "be", "reset", "before", "you", "see", "this."] # supress warning
try:
for _ in range(override):
sleep(uniform(3, 5))
correct_answers = []
for i in range(8):
try:
element = driver.find_element(By.ID, f"rqAnswerOption{i}")
if 'iscorrectoption="True"' in element.get_attribute("outerHTML"):
correct_answers.append(f'rqAnswerOption{i}')
except Exception as e:
warning(f"can't find rqAnswerOption{i}. Probably already clicked" + str(e))
shuffle(correct_answers)
for answer_id in correct_answers:
wait_until_visible(By.ID, answer_id, timeout=20, browser=driver)
try:
answer_elem = driver.find_element(By.ID, answer_id)
answer_elem.click()
sleep(1)
except exceptions.NoSuchElementException:
driver.refresh()
sleep(10)
answer_elem = driver.find_element(By.ID, answer_id)
answer_elem.click()
except ElementClickInterceptedException:
rgpd_popup(config)
correct_answers.append(answer_id)
except Exception as e:
log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}")
raise ValueError(format_error(e))
info("Quiz 8 done.")
custom_sleep(3)
def play_quiz4(override: int = None):
info(f"Starting Quiz 4")
driver = config.WebDriver.driver
if not override:
try: # fidelity quiz are much longer than usual ones
override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1])
except Exception as err:
debug(err)
override = 3
debug(f"Override : {override}")
try:
for i in range(override):
custom_sleep(uniform(3, 5))
txt = driver.page_source
answer_option = search('correctAnswer":"([^"]+)', txt)[1]
answer_option = answer_option.replace("\\u0027", "'") # replace Unicode weird symbols
answer_element = driver.find_element(By.CSS_SELECTOR, f'[data-option="{answer_option}"]')
try:
answer_element.click()
except exceptions.ElementNotInteractableException:
driver.execute_script("arguments[0].click();", answer_element)
except Exception as e:
log_error(e)
raise ValueError(e)
info("Quiz 4 done.")
custom_sleep(3)
# do_poll() answer a random thing to poll, on of daily activities
def do_poll():
info("Starting poll")
driver = config.WebDriver.driver
try:
answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}")
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:
log_error(err)
raise ValueError(err)
info("Poll done.")
custom_sleep(3)
# 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)
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
custom_sleep(2)
try:
promo()
except Exception as e:
debug(e)
info("no promo card")
if len(card_list) < 10: # most likely an error during loading
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")
if len(card_list) < 10:
log_error("Less than 10 cards. Most likely an error with login.")
return "Not enough cards"
for i in range(len(card_list)):
debug(f"carte {i}")
checked = False
try:
checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except StaleElementReferenceException:
driver.refresh()
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
warning(f"staled, {len(card_list)}")
checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except IndexError:
driver.get("https://rewards.bing.com")
custom_sleep(10)
card_list = driver.find_elements(By.CLASS_NAME, "c-card-content")
try:
checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML")
except IndexError:
if i == len(card_list) and i > 15:
checked = False
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, 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" 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 ?")
try:
try_play(driver.title) # go back to the main page
try:
close_tab(driver.window_handles[1])
except Exception as e:
debug(e)
except Exception as e:
debug(e)
driver.get("https://rewards.bing.com")
except Exception as err:
log_error(err)
custom_sleep(3)
def promo():
driver = config.WebDriver.driver
for i in range(5):
elm = driver.find_element(By.ID, "promo-item")
wait_until_visible(By.ID, "promo-item", 5, driver)
if not elm:
break
if i > 3:
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()
except Exception as e:
log_error(f"can't click to close : {e}")
return ()
try:
elm.click()
except Exception as e:
driver.execute_script("arguments[0].click();", elm)
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])
try_play(driver.title)
close_tab(driver.window_handles[1])
else:
try:
spotify(driver)
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="unknown", activity=""):
driver = config.WebDriver.driver
rgpd_popup(config)
def play(number):
if number in [8, 9]:
try:
debug(f"Quiz 8 detected on `{nom}`.")
play_quiz8()
except Exception as err:
error(f"fail of PlayQuiz 8. Aborted {err}")
elif number in [4, 5]:
try:
debug(f"Quiz 4 detected on `{nom}`")
play_quiz4()
except Exception as err:
error(f"Fail of PlayQuiz 4. Aborted {err}.")
elif number in [2, 3]:
try:
debug(f"\033[96mQuiz 2 detected on `{nom}`\033[0m")
play_quiz2()
except Exception as err:
error(f"fail of PlayQuiz 2. Aborted {err}")
else:
error("`rqAnswerOption` present in page but no action to do.")
custom_sleep(uniform(3, 5))
if "pas connecté à Microsoft Rewards" in driver.page_source:
custom_sleep(5)
driver.find_element(By.CSS_SELECTOR, '[onclick="setsrchusr()"]').click()
custom_sleep(5)
rgpd_popup(config)
custom_sleep(5)
debug("Detected and fixed connection popup")
if "bt_PollRadio" in driver.page_source:
debug("Poll detected")
do_poll()
elif search("([0-9]) de ([0-9]) finalisée", driver.page_source):
info("On fidelity page.")
fidelity()
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")
play(answer_number)
elif "rqQuestionState" in driver.page_source:
number = driver.page_source.count("rqAnswerOption")
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 obvious to do on page `{nom}`.")
custom_sleep(uniform(3, 5))
# Login with password or with cookies.
# The driver should be in the same state on both case
def login_part_1():
info("Starting part 1 of login")
driver = config.WebDriver.driver
driver.get("https://login.live.com")
wait_until_visible(By.ID, "i0116", browser=driver)
send_wait_and_confirm(
driver.find_element(By.ID, "i0116"),
config.UserCredentials.get_mail()
)
wait_until_visible(By.ID, "i0118", browser=driver)
send_wait_and_confirm(
driver.find_element(By.ID, "i0118"),
config.UserCredentials.get_password()
)
# 2FA
try:
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)
# Accept all cookies question, and check if the account is locked
def login_part_2():
driver = config.WebDriver.driver
custom_sleep(5)
if 'Abuse' in driver.current_url:
raise Banned()
if 'identity' in driver.current_url:
raise Identity()
if 'notice' in driver.current_url:
driver.find_element(By.ID, "id__0").click()
if "proof" in driver.current_url:
driver.find_element(By.ID, "iLooksGood")
for elm_id in ["checkboxField", "KmsiCheckboxField", "acceptButton", "iNext", "id__0", "iLooksGood", "idSIButton9",
"iCancel"]:
if get_domain(driver) == "account.microsoft.com":
break
try:
driver.find_element(By.ID, elm_id).click()
except Exception as e:
debug(e)
wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, driver)
# 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/")
except Banned:
raise Banned()
except Identity:
raise Banned()
except Exception as err:
critical("Error not caught during login." + format_error(err))
log_error(err)
driver.quit()
return False
# Makes 30 search as PC Edge
def bing_pc_search(override=randint(35, 40)):
driver = config.WebDriver.driver
driver.get(f"https://www.bing.com/search?q={config.wordlist.get_word().replace(' ', '+')}")
custom_sleep(uniform(1, 2))
rgpd_popup(config)
send_keys_wait(
driver.find_element(By.ID, "sb_form_q"),
Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE
)
for _ in range(override):
word = config.wordlist.get_word()
try:
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
except Exception as e:
error(e)
sleep(10)
driver.get(f'https://www.bing.com/search?q={word}')
sleep(3)
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
custom_sleep(uniform(3, 7))
try:
driver.find_element(By.ID, "sb_form_q").clear()
except Exception as e:
error(e)
try:
driver.get('https://www.bing.com/search?q=plans')
driver.find_element(By.ID, "sb_form_q").clear()
except Exception as e:
log_error(f"clear la barre de recherche - {format_error(e)}") # what is this message ??? todo
# Sends current account's points to database
def log_points():
driver = config.WebDriver.driver
account = config.UserCredentials.get_mail()
driver.get("https://rewards.bing.com")
custom_sleep(1)
wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver)
try:
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(err)}")
error(f"Can't get points. {format_error(err)}")
return -1
custom_sleep(uniform(3, 20))
account_name = account.split("@")[0]
try:
add_to_database(account_name, points)
except Exception as e:
log_error(e)
# todo: refactor and check if it works at all
def fidelity():
driver = config.WebDriver.driver
def sub_fidelity():
try:
wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver)
answer_number = search("([0-9]) of ([0-9]) completed", driver.page_source)
if answer_number is None:
answer_number = search("([0-9])&nbsp;défi\(s\) terminé\(s\) sur ([0-9])", driver.page_source)
if answer_number is None:
answer_number = search("([0-9]) de ([0-9]) finalisé", driver.page_source)
if answer_number is None:
answer_number = search("([0-9]) licence\(s\) sur ([0-9]) disponible\(s\)", driver.page_source)
if answer_number is None:
answer_number = [0, 0, 0]
for _ in range(int(answer_number[2]) - int(answer_number[1])):
driver.refresh()
custom_sleep(2)
card_elem = driver.find_element(By.CLASS_NAME, "spacer-48-bottom")
try:
button_text = search('<span class="pull-left margin-right-15">([^<^>]+)</span>',
card_elem.get_attribute("innerHTML"))[1]
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"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])
try_play(driver.title)
custom_sleep(uniform(3, 5))
try:
close_tab(driver.window_handles[2], 1)
except Exception as err:
error(err)
info("fidelity - done")
except Exception as err:
log_error(err)
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"]')
pause.click()
except Exception as e:
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()
checked_txt = checked_list_all[i].get_attribute("innerHTML")
ok = checked_txt.count("StatusCircleOuter checkmark")
total = checked_txt.count("StatusCircleOuter")
if ok != total:
elm = driver.find_elements(By.CLASS_NAME, 'clickable-link')[i]
# 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()
close_tab(driver.window_handles[1])
custom_sleep(1)
cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]')
checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]')
def mobile_alert_popup():
driver = config.WebDriver.driver
try:
alert = driver.switch_to.alert
alert.dismiss()
except exceptions.NoAlertPresentException:
pass
except Exception as err:
log_error(err)
# todo: be coherent with pc search regarding error management
def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)):
config.WebDriver.set_mobile_driver(create_driver(mobile=True))
config.WebDriver.switch_to_driver("Mobile")
driver = config.WebDriver.driver
try:
login()
mot = config.wordlist.get_word().replace(" ", "+")
driver.get(f"https://www.bing.com/search?q={mot}")
custom_sleep(uniform(1, 2))
rgpd_popup(config)
custom_sleep(uniform(1, 1.5))
for i in range(override): # 20
try:
mot = config.wordlist.get_word()
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
custom_sleep(uniform(3, 7))
mobile_alert_popup() # check for alert (asking for position or for allowing notifications)
driver.find_element(By.ID, "sb_form_q").clear()
except Exception as err:
error(err)
driver.refresh()
custom_sleep(30)
i -= 1
driver.quit()
except Exception as err:
log_error(err)
driver.quit()
finally:
config.WebDriver.switch_to_driver("PC")
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.")
raise Banned()
except Identity:
log_error("This account has an issue.")
return
try:
all_cards()
except Banned:
log_error("banned")
raise Banned
except Exception as err:
log_error(err)
try:
fidelity()
except Exception as err:
log_error(err)
try:
bing_pc_search()
except Exception as err:
log_error(err)
try:
bing_mobile_search(cred)
except Exception as err:
log_error(err)
try:
log_points()
except Exception as err:
log_error(err)
def json_start(json_entry, cred: UserCredentials):
json_entry = json.loads(json_entry)
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
for action in ["unban", "tout", "pc", "mobile", "daily"]:
try:
if str(account_id) in json_entry[action]:
start = True
info(f"{cred.get_mail()} : {action}")
except KeyError:
pass
if start:
config.WebDriver.set_pc_driver(create_driver())
config.WebDriver.switch_to_driver("PC")
driver = config.WebDriver.driver
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)
if driver.current_url == "https://example.com/":
info("proceeding")
break
else:
login()
try:
if str(account_id) in json_entry["tout"]:
daily_routine(cred, True)
else:
try:
if str(account_id) in json_entry["daily"]:
try:
all_cards()
except Exception as e:
log_error(e)
except KeyError:
pass
try:
if str(account_id) in json_entry["pc"]:
try:
bing_pc_search()
except Exception as e:
log_error(e)
except KeyError:
pass
try:
if str(account_id) in json_entry["mobile"]:
try:
bing_mobile_search(cred)
except Exception as e:
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()
def default_start():
if config.vnc_enabled():
config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=config.vnc, color_depth=24))
else:
config.set_display(SmartDisplay(size=(1920, 1080)))
config.display.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)
info(f"Waiting for {round(wait_time / 60)}min before starting")
custom_sleep(wait_time)
daily_routine(config.UserCredentials)
config.WebDriver.pc_driver.quit()
except KeyboardInterrupt:
critical("Canceled by user. Closing driver and display.")
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()
def log_error(msg):
DiscordLogger(config).send(msg)
def check_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()

12
build.sh Executable file
View File

@ -0,0 +1,12 @@
#!/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

29
config
View File

@ -1,29 +0,0 @@
[PATH]
motpath = /your/path/to/words_list.txt
logpath = /your/path/to/loginandpass.csv
[SETTINGS]
FidelityLink = Null
embeds = False
Headless = True
[DISCORD]
successlink = https://discord.com/api/webhooks/[put your webhook here]
errorlink =https://discord.com/api/webhooks/[put your webhook here]
[PROXY]
enabled = False
url = Null
port = 0
[DATABASE]
enabled = False
host = Null
database = MsRewards
usr = root
pwd = password

193
config/Stats-dashbord.json Normal file
View File

@ -0,0 +1,193 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": false,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 1,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "bed26262-6b98-4dfc-a95d-f8bd39b5d09c"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"max": 10000,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "dark-red",
"value": null
},
{
"color": "dark-yellow",
"value": 2000
},
{
"color": "green",
"value": 7500
},
{
"color": "blue",
"value": 10000
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 24,
"x": 0,
"y": 0
},
"id": 3,
"options": {
"displayMode": "gradient",
"minVizHeight": 10,
"minVizWidth": 0,
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showUnfilled": true,
"valueMode": "color"
},
"pluginVersion": "10.0.3",
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "bed26262-6b98-4dfc-a95d-f8bd39b5d09c"
},
"queryText": "SELECT\n unixepoch() as time,\n c.compte,\n c.last_pts as \"\"\nFROM \n comptes c;\n",
"queryType": "time series",
"rawQueryText": "SELECT\n unixepoch() as time,\n c.compte,\n c.last_pts as \"\"\nFROM \n comptes c;\n",
"refId": "A",
"timeColumns": [
"time",
"ts"
]
}
],
"title": "Account points",
"type": "bargauge"
},
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "bed26262-6b98-4dfc-a95d-f8bd39b5d09c"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"max": 300,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "dark-red",
"value": null
},
{
"color": "dark-green",
"value": 200
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 24,
"x": 0,
"y": 11
},
"id": 4,
"options": {
"displayMode": "gradient",
"minVizHeight": 10,
"minVizWidth": 0,
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showUnfilled": true,
"valueMode": "color"
},
"pluginVersion": "10.0.3",
"targets": [
{
"datasource": {
"type": "frser-sqlite-datasource",
"uid": "bed26262-6b98-4dfc-a95d-f8bd39b5d09c"
},
"queryText": "SELECT\n unixepoch() as time,\n c.compte as metric,\n c.last_pts - d2.points as ''\nFROM \n comptes c \nLEFT OUTER JOIN \n daily d1 \nON \n c.compte = d1.compte \nAND \n d1.date = date() \n LEFT OUTER JOIN daily d2 ON c.compte = d2.compte AND d2.date = DATE('now','-1 day')\nORDER BY d1.points DESC",
"queryType": "time series",
"rawQueryText": "SELECT\n unixepoch() as time,\n c.compte as metric,\n c.last_pts - d2.points as ''\nFROM \n comptes c \nLEFT OUTER JOIN \n daily d1 \nON \n c.compte = d1.compte \nAND \n d1.date = date() \n LEFT OUTER JOIN daily d2 ON c.compte = d2.compte AND d2.date = DATE('now','-1 day')\nORDER BY d1.points DESC",
"refId": "A",
"timeColumns": [
"time",
"ts"
]
}
],
"title": "Daily progress",
"type": "bargauge"
}
],
"refresh": "",
"schemaVersion": 38,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Stats",
"uid": "e70d4980-36d1-4107-90b0-d9164ae8ead4",
"version": 14,
"weekStart": ""
}

66
config/config.sh Normal file
View File

@ -0,0 +1,66 @@
printf "\nsetting up NGINX\n"
rm /etc/nginx/sites-available/default
echo "
map \$http_upgrade \$connection_upgrade {
default upgrade;
'' close;
}
upstream grafana {
server localhost:3000;
}
server {
listen 1234;
server_name localhost;
location /grafana {
proxy_pass http://localhost:3000;
rewrite ^/grafana/(.*) /\$1 break;
proxy_set_header Host \$host;
}
location /grafana/api/live/ {
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection \$connection_upgrade;
proxy_set_header Host \$http_host;
proxy_pass http://grafana;
rewrite ^/grafana/(.*) /\$1 break;
}
location /novnc/ {
proxy_pass http://127.0.0.1:6080/;
}
location /novnc/websockify {
proxy_pass http://127.0.0.1:6080/;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host \$host;
}
location / {
proxy_set_header X-Forwarded-For \$remote_addr;
proxy_set_header Host \$http_host;
proxy_pass "http://127.0.0.1:6666";
chunked_transfer_encoding off;
proxy_buffering off;
add_header X-Accel-Buffering no;
}
}
" >> /etc/nginx/sites-available/default
printf "\nNGINX configuration successfull\n"
printf "\ncreating sqlite databases\n"
sqlite3 /app/MsRewards-Reborn/MsRewards.db "CREATE TABLE daily (id INTEGER PRIMARY KEY,compte TEXT,points int,date TEXT);"
sqlite3 /app/MsRewards-Reborn/MsRewards.db "CREATE TABLE comptes (id INTEGER PRIMARY KEY,compte TEXT,last_pts int, banned int);"
printf "\nconfigurating grafana\n"
cp /app/MsRewards-Reborn/config/grafana.ini /etc/grafana/
printf "setting up default dashboard"
cp /app/MsRewards-Reborn/config/Stats-dashbord.json /usr/share/grafana/public/dashboards/home.json

10
config/grafana.ini Executable file
View File

@ -0,0 +1,10 @@
[server]
root_url = %(protocol)s://localhost:3000/grafana/
[security]
allow_embedding = true
[auth.anonymous]
enabled = true
org_name = Main Org.

19
config/request.sh Normal file
View File

@ -0,0 +1,19 @@
sleep 30
curl -X "POST" "http://localhost:1234/grafana/api/datasources" \
-H "Content-Type: application/json" \
--user admin:admin \
--data-raw $'{"id":1,"uid":"bed26262-6b98-4dfc-a95d-f8bd39b5d09c","orgId":1,"name":"SQLite","type":"frser-sqlite-datasource","typeName":"SQLite","typeLogoUrl":"public/plugins/frser-sqlite-datasource/img/logo.svg","access":"proxy","url":"","user":"","database":"","basicAuth":false,"isDefault":true,"jsonData":{"attachLimit":0,"path":"/app/MsRewards-Reborn/MsRewards.db","pathPefix":"file:"},"readOnly":false}'
curl 'http://localhost:1234/grafana/api/dashboards/import' \
-H 'content-type: application/json' \
-H 'x-grafana-org-id: 1' \
--user admin:admin \
--data-raw $'{"dashboard":{"annotations":{"list":[{"builtIn":1,"datasource":{"type":"grafana","uid":"-- Grafana --"},"enable":true,"hide":true,"iconColor":"rgba(0, 211, 255, 1)","name":"Annotations & Alerts","type":"dashboard"}]},"editable":true,"fiscalYearStartMonth":0,"graphTooltip":0,"id":null,"links":[],"liveNow":false,"panels":[{"datasource":{"type":"frser-sqlite-datasource","uid":"bed26262-6b98-4dfc-a95d-f8bd39b5d09c"},"fieldConfig":{"defaults":{"color":{"mode":"thresholds"},"mappings":[],"max":10000,"thresholds":{"mode":"absolute","steps":[{"color":"dark-red","value":null},{"color":"dark-yellow","value":2000},{"color":"green","value":7500},{"color":"blue","value":10000}]}},"overrides":[]},"gridPos":{"h":11,"w":24,"x":0,"y":0},"id":3,"options":{"displayMode":"gradient","minVizHeight":10,"minVizWidth":0,"orientation":"auto","reduceOptions":{"calcs":["lastNotNull"],"fields":"","values":false},"showUnfilled":true,"valueMode":"color"},"pluginVersion":"10.0.3","targets":[{"datasource":{"type":"frser-sqlite-datasource","uid":"bed26262-6b98-4dfc-a95d-f8bd39b5d09c"},"queryText":"SELECT\\n unixepoch() as time,\\n c.compte,\\n c.last_pts as \\"\\"\\nFROM \\n comptes c;\\n","queryType":"time series","rawQueryText":"SELECT\\n unixepoch() as time,\\n c.compte,\\n c.last_pts as \\"\\"\\nFROM \\n comptes c;\\n","refId":"A","timeColumns":["time","ts"]}],"title":"Account points","type":"bargauge"},{"datasource":{"type":"frser-sqlite-datasource","uid":"bed26262-6b98-4dfc-a95d-f8bd39b5d09c"},"fieldConfig":{"defaults":{"color":{"mode":"thresholds"},"mappings":[],"max":300,"thresholds":{"mode":"absolute","steps":[{"color":"dark-red","value":null},{"color":"dark-green","value":200}]}},"overrides":[]},"gridPos":{"h":11,"w":24,"x":0,"y":11},"id":4,"options":{"displayMode":"gradient","minVizHeight":10,"minVizWidth":0,"orientation":"auto","reduceOptions":{"calcs":["lastNotNull"],"fields":"","values":false},"showUnfilled":true,"valueMode":"color"},"pluginVersion":"10.0.3","targets":[{"datasource":{"type":"frser-sqlite-datasource","uid":"bed26262-6b98-4dfc-a95d-f8bd39b5d09c"},"queryText":"SELECT\\n unixepoch() as time,\\n c.compte as metric,\\n c.last_pts - d2.points as \'\'\\nFROM \\n comptes c \\nLEFT OUTER JOIN \\n daily d1 \\nON \\n c.compte = d1.compte \\nAND \\n d1.date = date() \\n LEFT OUTER JOIN daily d2 ON c.compte = d2.compte AND d2.date = DATE(\'now\',\'-1 day\')\\nORDER BY d1.points DESC","queryType":"time series","rawQueryText":"SELECT\\n unixepoch() as time,\\n c.compte as metric,\\n c.last_pts - d2.points as \'\'\\nFROM \\n comptes c \\nLEFT OUTER JOIN \\n daily d1 \\nON \\n c.compte = d1.compte \\nAND \\n d1.date = date() \\n LEFT OUTER JOIN daily d2 ON c.compte = d2.compte AND d2.date = DATE(\'now\',\'-1 day\')\\nORDER BY d1.points DESC","refId":"A","timeColumns":["time","ts"]}],"title":"Daily progress","type":"bargauge"}],"refresh":"","schemaVersion":38,"style":"dark","tags":[],"templating":{"list":[]},"time":{"from":"now-6h","to":"now"},"timepicker":{},"timezone":"","title":"main","uid":"stats","version":14,"weekStart":""},"overwrite":true,"inputs":[],"folderUid":""}' \
--compressed \
--insecure
websockify -D \
--web /usr/share/novnc/ \
6080 \
localhost:2345

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"

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

@ -1 +0,0 @@
you,have,to,add,a,lots,of,words,like,this,separated,with,a,coma

91
modules/Classes/Config.py Normal file
View File

@ -0,0 +1,91 @@
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.WordList import WordList
class Config:
def __init__(self, args):
"""
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)
with open("/app/MsRewards-Reborn/user_data/version", "r") as inFile:
version = inFile.readline()
"""
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.WebDriver = Driver()
self.display = None
self.version = version
"""
setup UserCredential
"""
self.UserCredentials = UserCredentials()
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
configs = json.load(inFile)
for i in configs[str(args.config)]["accounts"]:
d = configs[str(args.config)]["accounts"][i]
self.UserCredentials.add(d["mail"], d["pwd"], d["2fa"])
"""
Setup discord
"""
self.discord = DiscordConfig()
self.discord.avatar_url = settings["avatarlink"]
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()
"""
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):
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

@ -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, **kwargs):
debug(f"Used a webhook call without webhook url with {args} {kwargs}")

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.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)

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

@ -0,0 +1,25 @@
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.lower():
case "pc":
self.driver = self.pc_driver
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"

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

@ -0,0 +1,46 @@
from pyotp import TOTP
from modules.Tools.logger import debug, warning
class UserCredentials:
def __init__(self):
self.data = {}
self.current = 0
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}")
self.data[self.total] = {
"username": username,
"password": password,
"2fa": None if tfa == '' else tfa
}
self.total += 1
def tfa_enable(self):
return self.data[self.current]["2fa"] is not None
def get_mail(self):
return self.data[self.current]["username"]
def get_password(self):
return self.data[self.current]["password"]
def get_tfa(self):
if not self.tfa_enable():
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
and self.get_mail() != "" and self.get_mail is not None)

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

@ -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()

47
modules/Tools/logger.py Normal file
View File

@ -0,0 +1,47 @@
import logging
# ANSI escape codes for colors
COLOR_CODES = {
'RESET': '\033[0m',
'BOLD': '\033[1m',
'RED': '\033[31m',
'GREEN': '\033[32m',
'YELLOW': '\033[33m',
'BLUE': '\033[34m',
}
# Define colors for each log level
LOG_COLORS = {
'DEBUG': COLOR_CODES['BLUE'],
'INFO': COLOR_CODES['GREEN'],
'WARNING': COLOR_CODES['YELLOW'],
'ERROR': COLOR_CODES['RED'],
'CRITICAL': COLOR_CODES['BOLD'] + COLOR_CODES['RED'],
}
# Create a formatter with colors
class ColoredFormatter(logging.Formatter):
def format(self, record):
log_level = record.levelname
record.levelname = f"{LOG_COLORS.get(log_level, '')}{record.levelname}{COLOR_CODES['RESET']}"
return super().format(record)
# Set up the root logger
root_logger = logging.getLogger(__name__)
root_logger.setLevel(logging.INFO)
# Create a console handler and set the formatter
ch = logging.StreamHandler()
ch.setFormatter(ColoredFormatter('%(levelname)s: %(message)s'))
# Add the console handler to the root logger
root_logger.addHandler(ch)
# Define log level functions
debug = root_logger.debug
info = root_logger.info
warning = root_logger.warning
error = root_logger.error
critical = root_logger.critical

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 False: # 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

@ -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")

34
modules/cards.py Normal file
View File

@ -0,0 +1,34 @@
from modules.imports import *
def welcome_tour(elm, driver):
try :
driver.find_element(By.CSS_SELECTOR, '[class="welcome-tour-next-button c-call-to-action c-glyph"]').click()
except :
pass
driver.find_element(By.CSS_SELECTOR, '[class="quiz-link gray-button c-call-to-action c-glyph f-lightweight"]').click()
sleep(5)
driver.find_element(By.CSS_SELECTOR, '[class="c-glyph glyph-cancel"]').click()
elm.click()
driver.find_element(By.CSS_SELECTOR, '[class="quiz-link gray-button c-call-to-action c-glyph f-lightweight"]').click()
sleep(5)
driver.find_element(By.CSS_SELECTOR, '[class="c-glyph glyph-cancel"]').click()
elm.click()
driver.find_element(By.CSS_SELECTOR, '[class="quiz-link gray-button c-call-to-action c-glyph f-lightweight"]').click()
sleep(5)
driver.find_element(By.CSS_SELECTOR, '[class="c-glyph glyph-cancel"]').click()
def welcome_tour_NO(driver):
try :
driver.find_element(By.CSS_SELECTOR, '[class="welcome-tour-next-button c-call-to-action c-glyph"]').click()
except :
pass
driver.find_element(By.CSS_SELECTOR, '[class="c-glyph glyph-cancel"]').click()
sleep(5)
def spotify(driver):
sleep(5)
driver.find_element(By.CSS_SELECTOR, '[data-bi-id="spotify-premium gratuit"]').click()
sleep(5)
close_tab(driver.window_handles[1])

33
modules/config.py Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/python3.10
from modules.imports import *
parser = argparse.ArgumentParser()
parser.add_argument(
"-c",
"--config",
help="Choose a specific config file",
default=""
)
parser.add_argument(
"-v",
"--vnc",
help="enable VNC",
dest="vnc"
)
parser.add_argument(
"--version",
help="display a message on discord to tell that the bot have been updated",
dest="update_version",
default="None"
)
parser.add_argument(
"--json",
help="input json to start the bot with custom parameters",
default=""
)
args = parser.parse_args()

66
modules/db.py Normal file
View File

@ -0,0 +1,66 @@
import sqlite3
# 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())"
val = (account, points)
mycursor.execute(sql, val)
mydb.commit()
# printf(mycursor.rowcount, "record created.")
# update the ammount of points for the account [compte]
def update_row(account, points, mycursor, mydb):
sql = f"UPDATE daily SET points = {points} WHERE compte = '{account}' AND date = date() ;"
mycursor.execute(sql)
mydb.commit()
# update the value of last_pts for the table comptes
def update_last(account, points, mycursor, mydb):
sql1 = f"UPDATE comptes SET last_pts = {points} WHERE compte = '{account}';"
sql2 = f"select * from comptes where compte = '{account}'"
sql3 = f"INSERT INTO comptes (compte, last_pts,banned) VALUES ('{account}', {points}, 0)"
cmd = mycursor.execute(sql2)
if len(list(cmd)) == 0:
mycursor.execute(sql3)
else:
mycursor.execute(sql1)
mydb.commit()
# 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
def get_row(account, points, mycursor, same_points=True):
if same_points:
mycursor.execute(f"SELECT * FROM daily WHERE points = {points} AND compte = '{account}' AND date = date() ;")
else:
mycursor.execute(f"SELECT * FROM daily WHERE compte = '{account}' AND date = date() ;")
myresult = mycursor.fetchall()
return (len(myresult) == 1)
def add_to_database(account, points):
if points is None:
pass
else:
mydb = sqlite3.connect("/app/MsRewards-Reborn/MsRewards.db")
mycursor = mydb.cursor()
if get_row(account, points, mycursor, True):
# check if the row exist with the same amount of points and do nothing if it does
pass
# check if the row exist, but without the same amount of points and update the point account then
elif get_row(account, points, mycursor, False):
update_row(account, points, mycursor, mydb)
else: # if the row don't exist, create it with the good amount of points
add_row(account, points, mycursor, mydb)
if int(points) > 10:
update_last(account, points, mycursor, mydb)
mycursor.close()
mydb.close()

87
modules/driver_tools.py Normal file
View File

@ -0,0 +1,87 @@
import json
import os
from random import uniform
from selenium.common import TimeoutException
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
from modules.Tools.logger import debug
from modules.Tools.tools import *
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
def rgpd_popup(config) -> None:
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"]:
try:
config.WebDriver.driver.find_element(By.ID, i).click()
except Exception as err:
debug(err)
"""
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
"""
def send_keys_wait(element, keys: str) -> None:
for i in keys:
element.send_keys(i)
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, 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:
f = error if raise_error else debug
f(f"element {identifier} not found after {timeout}s")
return False

10
modules/error.py Normal file
View File

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

36
modules/imports.py Normal file
View File

@ -0,0 +1,36 @@
import argparse
import asyncio
import json
import configparser
import pickle
from csv import reader
from datetime import datetime, timedelta
from os import path, sys, system
from random import choice, randint, shuffle, uniform
from re import findall, search
from sys import platform
from time import sleep, time
from discord import Colour, Embed, File, RequestsWebhookAdapter, Webhook
from pyotp import TOTP
from pyvirtualdisplay import Display
from pyvirtualdisplay.smartdisplay import SmartDisplay
from requests import get
from selenium import webdriver
from selenium.common import exceptions
from selenium.common.exceptions import (ElementClickInterceptedException,
NoSuchElementException,
StaleElementReferenceException,
TimeoutException, WebDriverException)
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
from ast import literal_eval
try:
import enquiries
except:
system("") # enable colors in windows cmd
import undetected_chromedriver as uc

17
requirements.txt Normal file
View File

@ -0,0 +1,17 @@
argparse
discord.py==1.7.3
selenium
pillow
pyvirtualdisplay
undetected_chromedriver
requests>=2.31.0
flask
flask_sse
EasyProcess
pyotp
packaging
apscheduler
flask_login
gunicorn
gevent
redis

3
sse.sh Normal file
View File

@ -0,0 +1,3 @@
while IFS= read -r newline; do
redis-cli publish console "$newline"
done < <(tail -f /app/MsRewards-Reborn/Flask/static/logs/custom.txt)

4
user_data/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

1
user_data/configs.json Normal file
View File

@ -0,0 +1 @@
{}

4
user_data/cookies/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

1
user_data/discord.json Normal file
View File

@ -0,0 +1 @@
{}

4
user_data/flask.json Normal file
View File

@ -0,0 +1,4 @@
{
"password": "ChangeMe",
"secret": ""
}

1
user_data/logs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*

View File

1
user_data/proxy.json Normal file
View File

@ -0,0 +1 @@
{}

1
user_data/settings.json Normal file
View File

@ -0,0 +1 @@
{"avatarlink":"https://cdn.discordapp.com/icons/793934298977009674/d8055bccef6eca4855c349e808d0d788.webp"}

1
user_data/version Normal file
View File

@ -0,0 +1 @@
0.0.0

1
version Normal file
View File

@ -0,0 +1 @@
v6.8.57