144 Commits

Author SHA1 Message Date
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
21 changed files with 1595 additions and 1252 deletions

6
.gitignore vendored
View File

@ -1,12 +1,14 @@
/old
geckodriver.log
.vscode/
update.sh
/Git
page.html
screenshot.png
login.csv
requirements.txt
data
**/__pycache__
/user_data
install.sh
nohup.out
points.csv
/dev

127
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,127 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at piair338@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@ -4,28 +4,35 @@ ENV DEBIAN_FRONTEND noninteractive
ENV GECKODRIVER_VER v0.31.0
ENV FIREFOX_VER 87.0
WORKDIR /app
RUN set -x \
&& apt update \
&& apt upgrade -y \
&& apt install -y \
tzdata \
wfrench \
git \
&& git clone https://github.com/piair338/MsRewards \
&& pip install -r MsRewards/requirements.txt \
&& apt install -y \
libx11-xcb1 \
libdbus-glib-1-2 \
libasound2 \
libgtk-3-0 \
xvfb \
nano \
tigervnc-standalone-server \
&& git clone https://github.com/piair338/MsRewards \
&& ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime \
&& pip install -r MsRewards/requirements.txt \
&& curl -sSLO https://download-installer.cdn.mozilla.net/pub/firefox/releases/91.9.1esr/linux-x86_64/en-US/firefox-91.9.1esr.tar.bz2 \
&& tar -jxf firefox-* \
&& mv firefox /opt/ \
&& chmod 755 /opt/firefox \
&& chmod 755 /opt/firefox/firefox \
&& ln -s /opt/firefox/firefox /usr/bin/firefox \
&& curl -sSLO https://github.com/mozilla/geckodriver/releases/download/${GECKODRIVER_VER}/geckodriver-${GECKODRIVER_VER}-linux64.tar.gz \
&& tar zxf geckodriver-*.tar.gz \
&& mv geckodriver /usr/bin/
WORKDIR /app/MsReward
ENV TZ="Europe/Paris"
WORKDIR /app/MsRewards
CMD python main.py

View File

@ -1,45 +1,92 @@
# 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 or SQL to log points everydays.
Using Selenium and geckodriver.
A Microsoft reward automator, designed to work headless on any x64 server.
Using a discord webhook or SQL to log points everyday.
Using Selenium and Geckodriver.
# Installation instruction
Make sure your contry is [supported by MS Rewards](https://support.microsoft.com/en-us/topic/microsoft-rewards-regions-9795ec47-c0f4-a33e-aede-738903359d63).
Create 5 Microsoft accounts, that the programm will use.
- [linux](#linux)
- [Windows](#windows)
- [MacOS](#macos)
- [Database configuration](#database)
- [Options](#options)
- [Flags](#flags)
## Linux
## If you're using docker (way easier)
to use docker, run
### Using docker (Recommended)
Make sure that [docker](https://docs.docker.com/get-docker/) and [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) are installed.
Clone the repository:
```
sudo docker build .
#copy the build id
sudo docker run -ti --name MsRewards [build id]
git clone https://github.com/piair338/MsRewards
```
Then, fill the config and start the programm everydays with
Build the docker container:
```
sudo docker start MsRewards
cd MsRewards
sudo docker build -t msrewards .
```
Run the app for the first time to configure it.
```
sudo docker run -ti --name MsRewards msrewards
```
Then to run it everyday, you can use cron and add the line:
```
10 10 * * * sudo docker start MsRewards
```
## Other configuration
To use the database, I recommand MySql, Create a database with the name you want and create a table `daily`, like the one from the image :
![B96F2F6D-7257-4F12-BFA7-0BEC3FB72993](https://user-images.githubusercontent.com/74496300/172872979-05396b6b-b682-471a-b71b-41602d816504.jpeg)
You have to use the default worldlist (`sudo apt install wfrench`). The language is french by default, but you can change it if you want.
You 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, and DON'T USE outlook account, they are banned.
![image](https://user-images.githubusercontent.com/74496300/155960737-061229ca-db8c-4e66-9aef-542d9e709bb2.png)
## If you're **not** using docker
installation recommandation :
### **not** using docker (not recommended)
**This is only a recommandation and shouldn't be used !**
```
sudo apt-get install xdg-utils libdbus-glib-1-2 bzip2 wfrench tigervnc-standalone-server xvnc -y
curl -sSLO https://download-installer.cdn.mozilla.net/pub/firefox/releases/91.9.1esr/linux-x86_64/en-US/firefox-91.9.1esr.tar.bz2
tar -xjf firefox-91.9.1esr.tar.bz2
sudo mv firefox /opt/
sudo ln -s /opt/firefox/firefox /usr/bin/firefox
curl -sSLO https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux64.tar.gz
tar zxf geckodriver-v0.31.0-linux64.tar.gz
sudo mv geckodriver /usr/bin/
rm geckodriver-v0.31.0-linux64.tar.gz
rm firefox-91.9.1esr.tar.bz2
```
## Windows
Not yet tested, but using docker should work.
## MacOS
I don't have a mac (yet) so i can't test, but again, install docker and follow the linux installation.
# Database
To use the database, I recommend MySql, Create a database with the name `MsRewards` and create a table `daily`, like the one from the image :
![B96F2F6D-7257-4F12-BFA7-0BEC3FB72993](https://user-images.githubusercontent.com/74496300/172872979-05396b6b-b682-471a-b71b-41602d816504.jpeg)
# Options
TODO
# Flags
## Override
Enable you to choose what action to perform on which account. **Linux only**
```
python3 main.py -o
```
## VNC
Enble a vnc to a specific port
```
python3 main.py -v 1234
```
## config
Tell the programm which config to use.
Default to ./user_data/config.cfg
Putting only a number is equivalent to ./user_data/config[number].cfg
```
python3 main.py -c 12
```
## Add points to database
Add points to the database using the credentials provided in the default config file.
argument : file with a list of `account,points`
```
python3 main.py -a file.csv
```

986
V4.py
View File

@ -1,986 +0,0 @@
#!/usr/bin/python3.10
import asyncio
import csv
from os import sys, system, path
from random import choice, randint, shuffle, uniform
from re import findall, search
from sys import platform
from time import sleep
from requests import get
from selenium import webdriver
from selenium.common import exceptions
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.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from rich.progress import BarColumn, Progress, TextColumn, Progress, TimeElapsedColumn, TaskProgressColumn, TimeRemainingColumn
from modules.db import add_to_database
from modules.config import *
from modules.tools import *
from modules.error import *
import modules.progress
global driver
def printf(x):
printf2(x, _mail)
def WaitUntilVisible(by, id, to = 20, browser = driver):
try :
WebDriverWait(browser, to).until(EC.visibility_of_element_located((by,id)), "element not found")
except TimeoutException as e:
print(f"element not found after {to}s")
def claim_amazon():
try :
driver.get("https://rewards.microsoft.com/redeem/000803000031")
try :
driver.find_element(By.XPATH, "//span[contains( text( ), 'ÉCHANGER UNE RÉCOMPENSE')]").click()
except :
driver.find_element(By.XPATH, "//span[contains( text( ), 'REDEEM REWARD')]").click()
sleep(5)
try :
driver.find_element(By.XPATH, "//span[contains( text( ), 'CONFIRMER LA RÉCOMPENSE')]").click()
except :
driver.find_element(By.XPATH, "//span[contains( text( ), 'CONFIRM REWARD')]").click()
sleep(5)
if ("/rewards/redeem/orderhistory" in driver.page_source) :
driver.get("https://rewards.microsoft.com/redeem/orderhistory")
try :
driver.find_element(By.XPATH, "//span[contains( text( ), 'Détails de la commande')]").click()
except :
driver.find_element(By.XPATH, "//span[contains( text( ), 'Get code')]").click()
sleep(5)
code = driver.find_element(By.CLASS_NAME, "tango-credential-value").get_attribute('innerHTML')
lien = driver.find_elements(By.CLASS_NAME, "tango-credential-key")[1].get_attribute('innerHTML')
lien = search('\"([^\"]+)\"',lien)[1]
driver.get(lien)
sleep(10)
box = driver.find_element(By.ID, "input-45")
box.click()
box.send_keys(code)
driver.find_element(By.XPATH, "//span[contains( text( ), 'Déverrouillez votre récompense')]").click()
sleep(5)
#amazon = search("> ([^ ]+) <", fcode)[1]
fcode = driver.find_element(By.XPATH, "/html/body/div[1]/div[1]/main/div/div/div/div/div[1]/div/div[1]/div[2]/div[2]/div/div/div/div/div/div[2]/span").get_attribute("innerHTML")
if fcode :
webhookFailure.send(_mail)
webhookFailure.send(fcode)
return(1)
else :
LogError("impossible de localiser le code ", driver, _mail)
return(1)
else :
LogError("la recuperation ne peux pas être automatique", driver, _mail)
return(0)
except Exception as e :
LogError(f'problème dans la recuperation : {str(e)}', driver, _mail)
def setup_proxy(ip, port, socks=False) :
PROXY = f"{ip}:{port}"
if socks :
options.set_preference('network.proxy.type', 1)
options.set_preference('network.proxy.socks', ip)
options.set_preference('network.proxy.socks_port', int(port))
options.set_preference("browser.link.open_newwindow", 3)
else :
webdriver.DesiredCapabilities.FIREFOX['proxy'] = {
"httpProxy": PROXY,
"sslProxy": PROXY,
"proxyType": "MANUAL",
}
def FirefoxDriver(mobile=False, Headless=Headless):
if proxy_enabled :
setup_proxy(proxy_address,proxy_port)
PC_USER_AGENT = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
"AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.70"
)
MOBILE_USER_AGENT = (
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X)"
"AppleWebKit/605.1.15 (KHTML, like Gecko)"
"CriOS/103.0.5060.63 Mobile/15E148 Safari/604.1"
)
options = Options()
options.set_preference("browser.link.open_newwindow", 3)
if FAST :
options.set_preference("permissions.default.image", 2) #disable image loading. May add this without the fast option soon
if Headless:
options.add_argument("-headless")
if mobile :
options.set_preference("general.useragent.override", MOBILE_USER_AGENT)
else :
options.set_preference("general.useragent.override", PC_USER_AGENT)
driver = webdriver.Firefox(options=options)
driver.set_window_size(1900 + hash(_mail)%20 , 1070 + hash(_password + "salt")%10)
return driver
def Close(fenetre, SwitchTo=0):
driver.switch_to.window(fenetre)
driver.close()
driver.switch_to.window(driver.window_handles[SwitchTo])
#Deal with RGPD popup as well as some random popup like 'are you satisfied' one
def RGPD():
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] :
try:
driver.find_element(By.ID, i).click()
except:
pass
"""
PlayQuiz[N]([int : override]) make the quizz 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 quizz. Can be usefull in some case, where the programm crashes before finishing the quizz
"""
def PlayQuiz2(override=10):
printf("début de PlayQuiz2")
for j in range(override):
try:
RGPD()
CustomSleep(uniform(3, 5))
txt = driver.page_source
secret = search('IG:"([^"]+)"', txt)[1] # variable dans la page, pour calculer le offset
reponse1 = search('data-option="([^"]+)"', txt)[1]
offset = int(secret[-2:], 16) # la conversion ec decimal des deux dernier caracteres de IG
reponse = search('correctAnswer":"([0-9]+)', txt)[1]
somme = 0
for i in reponse1:
somme += ord(i)
if somme + offset == int(reponse):
elem = driver.find_element(By.ID, "rqAnswerOption0")
elem.click()
progressBar(j, 10, name="quiz 2")
else:
elem = driver.find_element(By.ID, "rqAnswerOption1")
elem.click()
progressBar(j, 10, name="quiz 2")
except exceptions.ElementNotInteractableException as e:
driver.execute_script("arguments[0].click();", elem)
except Exception as e:
LogError("PlayQuiz2" + str(e), driver, _mail)
break
printf("PlayQuiz2 finis")
def PlayQuiz8(task = None):
override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source))+1
printf(f"PlayQuiz8 : start, override : {override}")
try:
c = 0
RGPD()
for i in range(override):
CustomSleep(uniform(3, 5))
AnswerOptions = [ (driver.find_element(By.ID, f"rqAnswerOption{i-1}"),f'rqAnswerOption{i-1}') for i in range(1,9)]
isCorrect = [x[1] for x in AnswerOptions if 'iscorrectoption="True" ' in x[0].get_attribute("outerHTML") ]
shuffle(isCorrect)
for i in isCorrect:
WaitUntilVisible(By.ID, i, to = 20, browser=driver)
c += 1
progressBar(c, 16, name="Quiz 8 ")
try:
elem = driver.find_element(By.ID, i)
elem.click()
if not task is None:
AdvanceTask(task, 1/override / len(isCorrect) * 100)
except exceptions.NoSuchElementException :
driver.refresh()
CustomSleep(10)
elem = driver.find_element(By.ID, i)
elem.click()
except ElementClickInterceptedException :
RGPD()
isCorrect.append(i)
except Exception as e:
LogError(f"PlayQuiz8 - 4 - {e} \n ListOfGood : {str(isCorrect)}", driver, _mail)
printf("PlayQuiz8 : fin ")
def PlayQuiz4(override=None):
printf("PlayQuiz4 : start")
if not override:
try: # permet de gerer les truc de fidélité, qui sont plus long
override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1])
printf(f"Override : {override}")
except:
override = 3
try:
for i in range(override):
CustomSleep(uniform(3, 5))
txt = driver.page_source
RGPD()
reponse = search('correctAnswer":"([^"]+)', txt)[1] # je suis pas sur qu'il y ait un espace
reponse = reponse.replace("\\u0027", "'") # il faut cancel l'unicode avec un double \ (on replacer les caracteres en unicode en caracteres utf-8)
printf(f"validation de la reponse ")
printf(f"validation de la reponse {i+1}/{override} {reponse}")
try:
elem = driver.find_element(
By.CSS_SELECTOR, f'[data-option="{reponse}"]'
)
elem.click()
except exceptions.ElementNotInteractableException:
driver.execute_script("arguments[0].click();", elem)
except Exception as e:
LogError(f"PlayQuiz4 {str(e)}", driver, _mail)
raise ValueError(e)
printf("PlayQuiz4 : end")
"""
PlayPoll() reply a random thing to poll, on of daily activities
"""
def PlayPoll():
printf("PlayPoll : start")
try:
try:
elem = driver.find_element(By.ID, f"btoption{choice([0,1])}")
elem.click()
except exceptions.ElementNotInteractableException as e:
driver.execute_script("arguments[0].click();", elem)
CustomSleep(uniform(2, 2.5))
except Exception as e:
LogError("PlayPoll" + str(e), driver, _mail)
raise ValueError(e)
printf("PlayPoll : end")
def AllCard(): # fonction qui clique sur les cartes
def reset(Partie2=False): # retourne sur la page de depart apres avoir finis
if len(driver.window_handles) == 1:
driver.get("https://www.bing.com/rewardsapp/flyout")
if Partie2:
driver.find_element(
By.XPATH, "/html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1]"
).click()
else:
driver.switch_to.window(driver.window_handles[1])
printf(f"fermeture : {driver.current_url}")
driver.close()
driver.switch_to.window(driver.window_handles[0])
reset(Partie2)
def dailyCards():
try:
StartTask(task["daily"][f"all"])
for i in range(3):
StartTask(task["daily"][f"carte{i}"])
CustomSleep(uniform(3, 5))
try:
titre = "erreur"
driver.find_element(
By.XPATH,f"/html/body/div/div/div[3]/div[2]/div[1]/div[2]/div/div[{i+1}]/a/div/div[2]",
).click()
sleep(1)
titre = driver.title
TryPlay(titre, task=task["daily"][f"carte{i}"])
AdvanceTask(task["daily"][f"carte{i}"], 100)
ChangeColor(task["daily"][f"carte{i}"], "green")
sleep(1)
reset()
printf(f"DailyCard {titre} ok ")
except Exception as e:
printf(f"Allcard card {titre} error ({e})")
except Exception as e:
LogError(f"Dailycards {e}", driver, _mail)
try:
dailyCards()
except Exception as e:
printf(f"erreur dans les quetes de la semaine {e}")
def weekly_cards():
try:
driver.find_element(
By.XPATH, "/html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1]"
).click() # declenche la premiere partie ?
except:
reset()
try:
driver.find_element(
By.XPATH, "/html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1]"
).click() # declenche la deuxieme partie ?
except:
pass
for i in range(20):
printf("début de l'une des cartes")
driver.find_element(
By.XPATH,
"/html/body/div/div/div[3]/div[2]/div[2]/div[3]/div/div[1]/a/div/div[2]",
).click()
printf("carte cliquée")
driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1])
sleep(1)
titre = driver.title
print(f"carte {titre} en cours")
TryPlay(titre)
reset(True)
sleep(1)
try:
link = findall('href="([^<]+)" title=""', driver.page_source)[
3
] # verifie si on a toujours des cartes
except:
break
for i in range(2): # don't seem useful for fixing error
try :
weekly_cards()
break
except Exception as e:
LogError(f"weekly_cards, try n°{i+1} \n {e}", driver, _mail)
if i == 0 :
driver.refresh()
else :
CustomSleep(1800)
driver.refresh()
"""
login() tries to login to your micrososft account.
it uses global variable _mail and _password to login
"""
def login():
global driver
def sub_login():
printf("sublogin : start")
driver.get("https://www.bing.com/rewardsapp/flyout")
for i in [f'[title="Rejoindre"]', f'[title="Join now"]', f'[title="Rejoindre maintenant"]'] :
try:
driver.find_element(By.CSS_SELECTOR, i).click() # depend of the language of the page
break
except:
pass
WaitUntilVisible(By.ID, "i0116", browser = driver)
mail = driver.find_element(By.ID, "i0116")
send_keys_wait(mail, _mail)
mail.send_keys(Keys.ENTER)
WaitUntilVisible(By.ID, "i0118", browser = driver)
pwd = driver.find_element(By.ID, "i0118")
send_keys_wait(pwd, _password)
pwd.send_keys(Keys.ENTER)
CustomSleep(5)
if ('Abuse' in driver.current_url) :
LogError("account suspended", driver, _mail)
raise Banned()
for i in ["KmsiCheckboxField","iLooksGood", "idSIButton9", "iCancel"]:
try:
driver.find_element(By.ID, i).click()
except Exception as e:
pass
try :
elm = driver.find_element(By.TAG_NAME, "body")
elm.send_keys(Keys.ENTER)
except :
pass
printf("login completed")
RGPD()
CustomSleep(uniform(3,5))
driver.get("https://www.bing.com/rewardsapp/flyout")
CustomSleep(uniform(3,5))
for i in range(3) :
try :
sub_login()
return (driver.current_window_handle)
except Banned:
raise Banned()
except Exception as e:
LogError("login - 3 - " + str(e), driver, _mail)
driver.close()
CustomSleep(1200)
driver = FirefoxDriver()
return("STOP")
def BingPcSearch(override=randint(35, 40)):
StartTask(task["PC"])
driver.get(f"https://www.bing.com/search?q=test") # {choice(Liste_de_mot)}')
CustomSleep(uniform(1, 2))
RGPD()
send_keys_wait(
driver.find_element(By.ID, "sb_form_q"),
Keys.BACKSPACE
+ Keys.BACKSPACE
+ Keys.BACKSPACE
+ Keys.BACKSPACE
+ Keys.BACKSPACE
+ Keys.BACKSPACE,
)
for i in range(override):
mot = choice(Liste_de_mot)
try:
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
except Exception as e :
printf(e)
sleep(10)
driver.get('https://www.bing.com/search?q=pls')
sleep(3)
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
AdvanceTask(task["PC"], 1/override * 100 )
CustomSleep(uniform(5, 20))
try:
driver.find_element(By.ID, "sb_form_q").clear()
except Exception as e:
printf(e)
try:
driver.get('https://www.bing.com/search?q=pls')
driver.find_element(By.ID, "sb_form_q").clear()
except Exception as e:
LogError(f"BingPcSearch - clear la barre de recherche - {e}", driver, _mail)
ChangeColor(task["PC"], "green")
def unban():
driver.find_element(By.ID, "StartAction").click()
CustomSleep(10)
txt = driver.page_source
uuid0 = findall('wlspispHIPCountrySelect([a-z0-9]+)', txt)[0]
uuid1 = findall('wlspispHIPPhoneInput([a-z0-9]+)', txt)[0]
uuid2 = findall('wlspispHipSendCode([a-z0-9]+)', txt)[0]
uuid3 = findall('wlspispSolutionElement([a-z0-9]+)', txt)[0]
sel = Select(driver.find_element(By.ID, "wlspispHIPCountrySelect" + uuid0))
CC = input("enter Contry code (FR, ...) ")
sel.select_by_value(CC)
WaitUntilVisible(By.ID, "wlspispHIPPhoneInput" + uuid1, browser=driver)
phone = input("entrez le numero de téléphone : +33")
phone_box = driver.find_element(By.ID, "wlspispHIPPhoneInput" + uuid1)
phone_box.send_keys(phone)
WaitUntilVisible(By.ID, "wlspispHipSendCode" + uuid2, browser=driver)
send_link = driver.find_element(By.ID, "wlspispHipSendCode" + uuid2)
send_link.click()
WaitUntilVisible(By.ID, "wlspispSolutionElement" + uuid3, browser=driver)
LogError("test", driver,"phone test")
answer_box = driver.find_element(By.ID, "wlspispSolutionElement" + uuid3)
answer = input("entrez le contenu du msg : ")
answer_box.send_keys(answer)
send_box = driver.find_element(By.ID, "ProofAction")
send_box.click()
WaitUntilVisible(By.ID, "FinishAction", browser=driver)
continue_box = driver.find_element(By.ID, "FinishAction")
continue_box.click()
def TryPlay(nom="inconnu", task = None):
RGPD()
printf("TryPlay en cours")
def play(number):
if number == 8 or number == 9:
try:
printf(f"\033[96m Quiz 8 détecté sur la page {nom} \033[0m")
PlayQuiz8(task=task)
printf(f"\033[92m Quiz 8 reussit sur {nom} \033[0m")
except Exception as e:
printf(f"echec de PlayQuiz 8. Aborted {e} \033[0m")
elif number == 5 or number == 4:
try:
printf(f"\033[96m Quiz 4 détecté sur la page {nom} \033[0m")
PlayQuiz4()
printf(f"\033[92m Quiz 4 reussit sur {nom} \033[0m")
except Exception as e:
printf(f"echec de PlayQuiz 4. Aborted {e} \033[0m")
elif number == 3 or number == 2:
try:
printf(f"\033[96m Quiz 2 détecté sur la page {nom}\033[0m")
PlayQuiz2()
printf(f"\033[92m Quiz 2 reussit sur la page {nom}\033[0m")
except Exception as e:
printf(f"echec de PlayQuiz 2. Aborted {e}")
else:
LogError("probleme dans la carte : il y a un bouton play et aucun quiz detecté", driver, _mail)
try:
driver.find_element(By.ID, "rqStartQuiz").click() # start the quiz
number = driver.page_source.count("rqAnswerOption")
play(number)
except Exception as e:
# printf(e) normal error here
if "bt_PollRadio" in driver.page_source:
try:
printf("Poll détected")
RGPD()
PlayPoll()
printf("Poll reussit ")
except Exception as e:
printf(f"TryPlay - 1 - Poll aborted {e}")
elif "rqQuestionState" in driver.page_source:
try:
number = driver.page_source.count("rqAnswerOption")
printf(f"recovery détecté. quiz : {number}")
play(number-1, override=restant + 1)
except Exception as e:
printf("TryPlay - 2 - " + e)
elif search("([0-9]) de ([0-9]) finalisée", driver.page_source):
print("fidélité")
RGPD()
Fidelite()
else:
printf(f"rien à faire sur la page {nom}")
RGPD()
CustomSleep(uniform(3, 5))
def LogPoint(account="unknown"): # log des points sur discord
def get_points():
driver.get("https://www.bing.com/rewardsapp/flyout")
if not LINUX_HOST:
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
else:
asyncio.set_event_loop(asyncio.new_event_loop())
regex1 = '<a href="https://rewards\.bing\.com/" title="((.{1,3}),(.{1,3})) points" target="_blank"'
try:
point = search(regex1, driver.page_source)[1].replace(",", "")
except Exception as e:
elem = driver.find_element(By.CSS_SELECTOR, '[title="Microsoft Rewards"]')
elem.click()
CustomSleep(5)
driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1])
CustomSleep(uniform(5,7))
point = search('availablePoints":([\d]+)', driver.page_source)[1]
return(point)
for i in range (3):
try :
points = get_points()
break
except Exception as e:
CustomSleep(300)
printf(f"LogPoints : {e}")
points = None
if not points :
LogError(f"impossible d'avoir les points : {e}", driver, _mail)
CustomSleep(uniform(3, 20))
account = account.split("@")[0]
if DISCORD_ENABLED_SUCCESS:
if DISCORD_EMBED:
embed = discord.Embed(
title=f"{account} actuellement à {str(points)} points", colour=Colour.green()
)
embed.set_footer(text=account)
webhookSuccess.send(embed=embed)
else:
webhookSuccess.send(f"{account} actuellement à {str(points)} points")
if CLAIM_AMAZON and int(points) >= 7500:
if (claim_amazon() == 1) :
points = str( int(points) - 7500)
if sql_enabled :
add_to_database(account, points, sql_host, sql_usr, sql_pwd, sql_database)
def Fidelite():
try:
while 1: #close all tabs
try:
Close(1)
except:
break
try :
result = get(FidelityLink) #get the url of fidelity page
except Exception as e :
printf(e)
result = False
if result :
lien = result.content.decode("UTF-8")
printf(lien)
if (lien.split(":")[0] == "https") or (lien.split(":")[0] == "http") :
driver.get(lien)
WaitUntilVisible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver)
choix = driver.find_element(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]') # pull-left spacer-48-bottom punchcard-row? USELESS ?
nb = search("([0-9]) of ([0-9]) completed", driver.page_source)
if not nb:
nb = search("([0-9]) de ([0-9]) finalisé", driver.page_source)
for i in range(int(nb[2]) - int(nb[1])):
driver.refresh()
CustomSleep(2)
choix = driver.find_element(By.CLASS_NAME, "spacer-48-bottom")
try :
ButtonText = search('<span class="pull-left margin-right-15">([^<^>]+)</span>',choix.get_attribute("innerHTML"))[1]
bouton = driver.find_element(By.XPATH, f'//span[text()="{ButtonText}"]')
bouton.click()
except Exception as e1 :
try :
t = driver.find_element(By.XPATH,'/html/body/div[1]/div[2]/main/div[2]/div[2]/div[7]/div[3]/div[1]')
t.click()
except Exception as e2 :
LogError(f"fidélité - double erreur - e1 : {e1} - e2 {e2}", driver, _mail)
break
CustomSleep(uniform(3, 5))
driver.switch_to.window(driver.window_handles[1])
TryPlay(driver.title)
driver.get(lien) # USELESS ?
CustomSleep(uniform(3, 5))
try:
Close(driver.window_handles[1])
except Exception as e:
printf(e)
printf("fidelité - done")
else :
printf("lien invalide")
except Exception as e:
LogError("Fidélité" + str(e), driver, _mail)
def Mlogin(echec):
try:
MobileDriver.get("https://www.bing.com/search?q=test+speed")
MRGPD()
printf("start of Mobile login")
MobileDriver.find_element(By.ID, "mHamburger").click()
WaitUntilVisible(By.ID, "hb_s", browser=MobileDriver)
MobileDriver.find_element(By.ID, "hb_s").click()
WaitUntilVisible(By.ID, "i0116", browser=MobileDriver)
mail = MobileDriver.find_element(By.ID, "i0116")
send_keys_wait(mail, _mail)
mail.send_keys(Keys.ENTER)
WaitUntilVisible(By.ID, "i0118", browser=MobileDriver)
pwd = MobileDriver.find_element(By.ID, "i0118")
send_keys_wait(pwd, _password)
pwd.send_keys(Keys.ENTER)
CustomSleep(uniform(1, 2))
for i in ["KmsiCheckboxField", "iLooksGood", "idSIButton9"]:
try:
MobileDriver.find_element(By.ID,i ).click()
except Exception as e:
pass
printf("end of Mobile login")
except Exception as e:
echec += 1
if echec <= 3:
printf(f"echec du login sur la version mobile. on reesaye ({echec}/3), {e}")
CustomSleep(uniform(5, 10))
Mlogin(echec)
else:
LogError(
f"login impossible 3 fois de suite. {e}", MobileDriver, _mail
)
MobileDriver.quit()
return True
def MRGPD():
try:
MobileDriver.find_element(By.ID, "bnp_btn_accept").click()
except Exception as e:
pass
try:
MobileDriver.find_element(By.ID, "bnp_hfly_cta2").click()
except Exception as e:
pass
def Alerte():
try:
alert = MobileDriver.switch_to.alert
alert.dismiss()
except exceptions.NoAlertPresentException as e:
pass
except Exception as e:
LogError(f"mobile.py -> Alerte : {e}", MobileDriver, _mail)
def BingMobileSearch(override=randint(22, 25)):
global MobileDriver
MobileDriver = "unable to start"
try:
try:
MobileDriver = FirefoxDriver(mobile=True)
MobileDriver.implicitly_wait(15)
except Exception as e:
LogError("BingMobileSearch - 1 - echec de la creation du driver mobile", MobileDriver, _mail)
ChangeColor(task["Mobile"], "red")
echec = 0
if not Mlogin(echec):
StartTask(task["Mobile"])
CustomSleep(uniform(1, 2))
MRGPD()
CustomSleep(uniform(1, 1.5))
for i in range(override): # 20
try :
mot = choice(Liste_de_mot)
send_keys_wait(MobileDriver.find_element(By.ID, "sb_form_q"), mot)
MobileDriver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
AdvanceTask(task["Mobile"], 1/override * 100)
#printf(MobileDriver.current_url)
CustomSleep(uniform(5, 20))
Alerte() # verifie si il y a des alertes (demande de positions ....)
MobileDriver.find_element(By.ID, "sb_form_q").clear()
except :
driver.refresh()
CustomSleep(30)
i -= 1
MobileDriver.quit()
ChangeColor(task["Mobile"], "green")
except Exception as e:
LogError("BingMobileSearch - 4 - " + str(e), MobileDriver, _mail)
MobileDriver.quit()
def DailyRoutine(custom = False):
ShowDefaultTask()
try :
if not custom: # custom already login
login()
except Banned :
LogError("THIS ACCOUND IS BANNED. FIX THIS ISSUE WITH -U", driver, _mail)
return()
try:
AllCard()
except Exception as e:
LogError(f"DailyRoutine - AllCard - \n{e}", driver, _mail)
try:
BingPcSearch()
except Exception as e:
LogError(f"DailyRoutine - BingPcSearch - \n{e}", driver, _mail)
try:
BingMobileSearch()
except Exception as e:
LogError(f"DailyRoutine - BingMobileSearch - \n{e}", driver, _mail)
try:
Fidelite()
except Exception as e:
LogError(f"DailyRoutine - Fidelité - \n{e}", driver, _mail)
try:
LogPoint(_mail)
except Exception as e:
LogError(f"DailyRoutine - LogPoint - \n{e}", driver, _mail)
def close():
driver.quit()
quit()
def dev():
pass
def CustomStart(Credentials):
global START_TIME
if not LINUX_HOST :
raise NameError('You need to be on linux to do that, due to the utilisation of a module named enquieries, sorry.')
global driver, _mail, _password, p, task
system("clear") # clear from previous command to allow a clean choice
actions = ["tout", "daily", "pc", "mobile", "LogPoint","Fidelite", "dev"]
Actions = enquiries.choose("quels Actions ?", actions, multi=True)
liste = SelectAccount()
START_TIME = time() # Reset timer to the start of the actions
with Progress(
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TaskProgressColumn(),
TimeRemainingColumn(),
TimeElapsedColumn(),
) as p:
task = modules.progress.dico(p)
for _mail, _password in liste:
driver = FirefoxDriver()
driver.implicitly_wait(10)
if login() != "STOP":
if "tout" in Actions:
DailyRoutine(True)
if "daily" in Actions:
try:
AllCard()
except Exception as e:
LogError(f"AllCards - {e} -- override", driver, _mail)
if "pc" in Actions:
try:
ShowTask(task["PC"])
BingPcSearch()
except Exception as e:
LogError(f"il y a eu une erreur dans BingPcSearch, {e} -- override", driver, _mail)
if "mobile" in Actions:
try:
ShowTask(task["Mobile"])
BingMobileSearch()
except Exception as e:
LogError(f"BingMobileSearch - {e} -- override", driver, _mail)
if "Fidelite" in Actions:
try :
Fidelite()
except Exception as e :
LogError(f"Fidelite - {e} -- override", driver, _mail)
if "dev" in Actions:
try:
dev()
except Exception as e:
printf(e)
break
if not "tout" in Actions:
try:
LogPoint(_mail)
except Exception as e:
print("CustomStart " + str(e))
driver.close()
def SelectAccount(multiple = True):
system("clear") # clear from previous command to allow a clean choice
emails = [x[0] for x in Credentials] # list of all email adresses
emailsSelected = enquiries.choose("quels comptes ?", emails, multi=multiple)
return([x for x in Credentials if x[0] in emailsSelected])
def unban2():
global _mail, _password
_mail, _password = SelectAccount(False)[0]
try :
driver = FirefoxDriver()
login()
raise NotBanned
except Banned :
unban()
except NotBanned :
printf("you are not currently banned on this account")
def SavePointsFromFile(file):
with open(file) as f:
reader = csv.reader(f)
points_list = list(reader)
for item in points_list:
compte, points = item[0], item[1]
add_to_database(compte, points, sql_host,sql_usr,sql_pwd,sql_database, save_if_fail=False)
with open(file, "w") as f:
f.write("")
def StartTask(task):
ChangeColor(task, "blue")
p.start_task(task)
p.update(task, advance=0) # Reset the Task if it was already filled to 100%
def ShowTask(task):
p.update(task, visible=True)
def AdvanceTask(task, pourcentage):
p.update(task, advance=pourcentage)
def ChangeColor(task, newcolor):
old = p.tasks[task].description
old = old.split(']')
old[0] = f"[{newcolor}"
new = "]".join(old)
p.update(task,description=new)
def ShowDefaultTask():
for i in ["all", "carte1", "carte2", "carte0"]:
ShowTask(task["daily"][i])
for i in ["PC", "Mobile"]:
ShowTask(task[i])
if CUSTOM_START:
CustomStart(Credentials)
elif UNBAN:
unban2()
elif POINTS_FILE != "":
SavePointsFromFile(POINTS_FILE)
else:
with Progress(
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TaskProgressColumn(),
TimeRemainingColumn(),
TimeElapsedColumn(),
) as p:
task = modules.progress.dico(p)
for _mail, _password in Credentials:
#system("pkill -9 firefox")
print("\n\n")
print(_mail)
CustomSleep(1)
printf("début du driver")
driver = FirefoxDriver()
printf("driver demarré")
driver.implicitly_wait(7)
try:
DailyRoutine()
driver.quit()
attente = uniform(1200, 3600)
printf(f"finis. attente de {round(attente/60)}min")
CustomSleep(attente)
except KeyboardInterrupt:
print("canceled")
close()

865
V5.py Executable file
View File

@ -0,0 +1,865 @@
#!/usr/bin/python3.10
from modules.imports import *
from modules.config import *
from modules.db import add_to_database
from modules.tools import *
from modules.error import *
from modules.driver_tools import *
from modules.cards import *
import modules.globals as g
driver = g.driver
display = g.display
# create a webdriver
def firefox_driver(mobile=False, headless=False):
PC_USER_AGENT = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
"AppleWebKit/537.36 (KHTML, like Gecko)"
"Chrome/112.0.0.0 Safari/537.36 Edg/110.0.1587.56")
MOBILE_USER_AGENT = (
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X)"
"AppleWebKit/606.0.2 (KHTML, like Gecko)"
"CriOS/107.0.5060.64 Mobile/15E148 Safari/604.1"
)
options = Options()
options.set_preference('intl.accept_languages', 'fr-FR, fr')
options.set_preference("browser.link.open_newwindow", 3)
options.set_preference("dom.confirm_repost.testing.always_accept", True)
if g.fast:
options.set_preference("permissions.default.image", 2)
if headless:
options.add_argument("-headless")
if mobile :
options.set_preference("general.useragent.override", MOBILE_USER_AGENT)
driver = webdriver.Firefox(options=options)
driver.set_window_size(1070 + hash(g._mail)%10 , 1900 + hash(g._password + "salt")%20) # mobile resolution are crazy high now, right ?
else :
options.set_preference("general.useragent.override", PC_USER_AGENT)
driver = webdriver.Firefox(options=options)
driver.set_window_size(1900 + hash(g._mail)%20 , 1070 + hash(g._password + "salt")%10)
return(driver)
def log_error(error, ldriver=driver, log=g.full_log):
global driver
if ldriver is None:
ldriver = driver
if type(error) != str :
error = format_error(error)
printf(f"\n\n\033[93m Erreur : {str(error)} \033[0m\n\n")
if g.discord_enabled_error:
with open("page.html", "w") as f:
try :
f.write(ldriver.page_source)
except :
f.write("the driver has closed or crashed. Can't access page content")
try :
img = display.waitgrab()
img.save("screenshot.png")
except :
ldriver.save_screenshot("screenshot.png")
if not log:
embed = Embed(
title="An Error has occured",
description=str(error),
colour=Colour.red(),
)
else:
embed = Embed(
title="Full log is enabled",
description=str(error),
colour=Colour.blue(),
)
file = File("screenshot.png")
embed.set_image(url="attachment://screenshot.png")
embed.set_footer(text=g._mail)
webhookFailure.send(embed=embed, username="error", file=file, avatar_url = g.avatar_url)
webhookFailure.send(username="error", file=File("page.html"), avatar_url = g.avatar_url)
# close the tab currently on and go back to the one first, or the one specified
def close_tab(tab, SwitchTo=0) -> None:
driver.switch_to.window(tab)
driver.close()
driver.switch_to.window(driver.window_handles[SwitchTo])
# 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:
printf("starting play_quiz2")
for j in range(override):
try:
# rgpd_popup(driver)
custom_sleep(uniform(3, 5))
page_html = driver.page_source
secret_answer = search('IG:"([^"]+)"', page_html)[1] # variable used to calculate offset
answers_values = search('data-option="([^"]+)"', page_html)[1]
offset = int(secret_answer[-2:], 16) # the last two character converted to int are the offset
correct_answer_value = search('correctAnswer":"([0-9]+)', page_html)[1]
somme = 0
for answer in answers_values:
somme += ord(answer)
if somme + offset == int(correct_answer_value):
answer_elem = driver.find_element(By.ID, "rqAnswerOption0")
answer_elem.click()
if g.log:
progressBar(j, 10, name="quiz 2")
else:
answer_elem = driver.find_element(By.ID, "rqAnswerOption1")
answer_elem.click()
if g.log:
progressBar(j, 10, name="quiz 2")
except exceptions.ElementNotInteractableException as e:
driver.execute_script("arguments[0].click();", answer_elem)
except Exception as e:
log_error(e)
break
printf("play_quiz2 done")
custom_sleep(3)
def play_quiz8():
override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source))+1
printf(f"play_quiz8 : start, override : {override}")
try:
counter = 0
# rgpd_popup(driver)
for _ in range(override):
sleep(uniform(3, 5))
correct_answers = []
for i in range(1,9):
try :
element = driver.find_element(By.ID, f"rqAnswerOption{i-1}")
if 'iscorrectoption="True"' in element.get_attribute("outerHTML"):
correct_answers.append(f'rqAnswerOption{i-1}')
except Exception as e :
printf(f"can't find rqAnswerOption{i-1}. 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)
counter += 1
if g.log :
progressBar(counter, 16, name="Quiz 8")
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(driver)
correct_answers.append(answer_id)
except Exception as e:
log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}")
printf("play_quiz8 : fin ")
custom_sleep(3)
def play_quiz4(override=None):
printf("play_quiz4 : start")
if not override:
try: # fidelity quiz are much longer than usual ones
override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1])
printf(f"Override : {override}")
except:
override = 3
try:
for i in range(override):
custom_sleep(uniform(3, 5))
txt = driver.page_source
# rgpd_popup(driver)
answer_option = search('correctAnswer":"([^"]+)', txt)[1]
answer_option = answer_option.replace("\\u0027", "'") # replace Unicode weird symbols
try:
answer_element = driver.find_element(By.CSS_SELECTOR, f'[data-option="{answer_option}"]')
answer_element.click()
except exceptions.ElementNotInteractableException:
driver.execute_script("arguments[0].click();", answer_element)
except Exception as e:
log_error(e)
raise ValueError(e)
printf("play_quiz4 : end")
custom_sleep(3)
# do_poll() answer a random thing to poll, on of daily activities
def do_poll():
printf("do_poll : start")
try:
try:
answer_elem = driver.find_element(By.ID, f"btoption{choice([0,1])}")
answer_elem.click()
except exceptions.ElementNotInteractableException:
driver.execute_script("arguments[0].click();", answer_elem)
custom_sleep(uniform(2, 2.5))
except Exception as error:
log_error(error)
raise ValueError(error)
printf("do_poll : end")
custom_sleep(3)
def all_cards():
driver.get("https://rewards.bing.com")
wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver)
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
custom_sleep(2)
if "welcometour" in driver.current_url:
welcome_tour_NO(driver)
try :
promo()
except Exception as e:
printf("no promo card")
if(len(liste) < 10): #most likely an error during loading
if "suspendu" in driver.page_source:
raise Banned()
driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
if(len(liste) < 10):
log_error("Less than 10 cards. Most likely an error with login.", driver)
return("PAS ASSEZ DE CARTES")
if (len(liste) < 20): # most likely not in france
printf("moins de 20 cartes. Probablement pas en France.")
for i in range(len(liste)):
printf(f"carte {i}")
try :
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML"))
except StaleElementReferenceException :
driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
printf(f"staled, {len(liste)}")
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML"))
except IndexError:
driver.get("https://rewards.bing.com")
custom_sleep(10)
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
try :
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML"))
except IndexError :
if i == len(liste) & i > 15 :
checked = False
if checked:
custom_sleep(1.5)
driver.execute_script("arguments[0].scrollIntoView();", liste[i])
custom_sleep(1.5)
liste[i].click()
if len(driver.window_handles) > 1 :
driver.switch_to.window(driver.window_handles[1])
try_play(driver.title)
close_tab(driver.window_handles[1])
try :
driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) :
printf(f"carte {i} not okay. Retrying.")
try :
liste[i].click()
except :
log_error("problème inconnu ? sauf si c'est un element obscure...", driver)
driver.get("https://rewards.bing.com")
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML"))
driver.switch_to.window(driver.window_handles[1])
try_play(driver.title)
close_tab(driver.window_handles[1])
if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")):
driver.execute_script("arguments[0].scrollIntoView();", liste[i])
log_error(f"Card {i} Can't be completed. Why MS ?", driver)
liste[i].click()
driver.switch_to.window(driver.window_handles[1])
log_error(f"Cart completion - log - 2", driver)
custom_sleep(10)
log_error(f"Cart completion - log - 3 - after 10 sec", driver)
try:
try_play(driver.title) # go back to the main page
except :
driver.get("https://rewards.bing.com")
except :
pass
else :
try :
welcome_tour(liste[i], driver)
except Exception as e:
printf("no new windows" + format_error(e))
driver.get("https://rewards.bing.com")
custom_sleep(3)
def promo():
for i in range(10):
elm = driver.find_element(By.ID, "promo-item")
wait_until_visible(By.ID, "promo-item", 5, driver)
if not elm:
break
if i > 8 :
log_error("chelou, plus de 8 truc", driver)
try :
elm.click()
except Exception as e:
#log_error(e, driver)
driver.execute_script("arguments[0].click();", elm)
#log_error(e, driver)
printf(f"that should't be there (promo), but the workarround 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 :
printf("no new windows", driver)
driver.get("https://rewards.bing.com")
driver.refresh()
custom_sleep(3)
# Find out which type of action to do
def try_play(nom="inconnu"):
def play(number):
if number == 8 or number == 9:
try:
printf(f"\033[96mQuiz 8 detected on `{nom}` \033[0m")
play_quiz8()
printf(f"\033[92mQuiz 8 succeeded on `{nom}` \033[0m")
custom_sleep(uniform(3, 5))
except Exception as e:
printf(f"fail of PlayQuiz 8. Aborted {e} \033[0m")
elif number == 5 or number == 4:
try:
printf(f"\033[96mQuiz 4 detected on `{nom}` \033[0m")
play_quiz4()
printf(f"\033[92mQuiz 4 succeeded on `{nom}` \033[0m")
custom_sleep(uniform(3, 5))
except Exception as e:
printf(f"Fail of PlayQuiz 4. Aborted {e} \033[0m")
elif number == 3 or number == 2:
try:
printf(f"\033[96mQuiz 2 detected on `{nom}`\033[0m")
play_quiz2()
printf(f"\033[92mQuiz 2 succeeded on `{nom}`\033[0m")
except Exception as e:
printf(f"fail of PlayQuiz 2. Aborted {e}")
else:
printf("There is an error. rqAnswerOption present in page but no action to do. skipping.")
if "pas connecté à Microsoft Rewards" in driver.page_source:
driver.find_element(By.CSS_SELECTOR, '[onclick="setsrchusr()"]').click()
custom_sleep(5)
printf("not connected, fixed")
try:
if wait_until_visible(By.ID, "rqStartQuiz", 5, driver):
custom_sleep(3)
driver.find_element(By.ID, "rqStartQuiz").click() # start the quiz
answer_number = driver.page_source.count("rqAnswerOption")
play(answer_number)
else :
raise(NameError("going to next part"))
except Exception as e: # if there is no start button, an error is thrown
if "bt_PollRadio" in driver.page_source:
try:
printf("Poll detected")
do_poll()
printf("Poll succeeded")
except Exception as e:
printf(f"try_play - 1 - Poll aborted {e}")
elif "rqQuestionState" in driver.page_source:
try:
number = driver.page_source.count("rqAnswerOption")
printf(f"recovery détecté. quiz : {number}")
play(number-1)
except Exception as e:
printf(f"try_play - 2 - {e}")
elif search("([0-9]) de ([0-9]) finalisée", driver.page_source):
printf("fidélité")
fidelity()
else:
printf(f"rien à faire sur la 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 pwd_login(ldriver):
printf("pwd_login : start")
ldriver.get("https://login.live.com")
wait_until_visible(By.ID, "i0116", browser = ldriver)
mail_elem = ldriver.find_element(By.ID, "i0116")
send_keys_wait(mail_elem, g._mail)
mail_elem.send_keys(Keys.ENTER)
wait_until_visible(By.ID, "i0118", browser = ldriver)
pwd_elem = ldriver.find_element(By.ID, "i0118")
send_keys_wait(pwd_elem, g._password)
pwd_elem.send_keys(Keys.ENTER)
custom_sleep(2)
# 2FA
if "Entrez le code de sécurité" in ldriver.page_source :
try :
a2f_elem = ldriver.find_element(By.ID, "idTxtBx_SAOTCC_OTC")
a2f_elem.send_keys(g._otp.now())
a2f_elem.send_keys(Keys.ENTER)
except Exception as e :
log_error(e)
def cookie_login(ldriver):
printf("cookies_login : start")
ldriver.get("https://login.live.com")
try :
load_cookies(ldriver)
except FileNotFoundError :
printf("No cookies file Found.")
return(False)
except Exception as e:
log_error(f"Error performing cookies login. Trying with password instead. \n{str(e)}", driver)
return(False)
try :
ldriver.refresh()
except Exception as e:
printf(format_error(e))
printf("FIX YOUR SITE MS.......")
return(True)
# Accept all cookies question, and check if the account is locked
def login_part_2(ldriver, cookies = False):
custom_sleep(5)
if ('Abuse' in ldriver.current_url) :
raise Banned()
if ('identity' in ldriver.current_url) :
raise Identity()
if ('notice' in ldriver.current_url) :
ldriver.find_element(By.ID, "id__0").click()
if ("proof" in ldriver.current_url):
ldriver.find_element(BY.ID, "iLooksGood")
if cookies:
save_cookies(ldriver)
for id in ["KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]:
if get_domain(ldriver) == "account.microsoft.com":
break
try:
ldriver.find_element(By.ID, id).click()
restart = True
except Exception as e:
pass
wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, ldriver)
ldriver.get("https://www.bing.com/")
rgpd_popup(ldriver)
ldriver.refresh()
rgpd_popup(ldriver)
# login() tries to login to your Microsoft account.
# it uses global variable g._mail and g._password to login
def login(ldriver):
try :
success_cookies = cookie_login(ldriver)
if not success_cookies:
pwd_login(ldriver)
login_part_2(ldriver, not success_cookies)
ldriver.get("https://rewards.bing.com/")
except Banned:
raise Banned()
except Identity:
raise Banned()
except Exception as e:
log_error(e)
ldriver.quit()
return(False)
# Makes 30 search as PC Edge
def bing_pc_search(override=randint(35, 40)):
mot = choice(Liste_de_mot).replace(" ","+")
driver.get(f"https://www.bing.com/search?q={mot}") # {choice(Liste_de_mot)}')
custom_sleep(uniform(1, 2))
rgpd_popup(driver)
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 = choice(Liste_de_mot)
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 :
printf(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:
printf(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)}")
# Unban an account, called with -u parameter. You will need a phone number
def unban() -> None:
driver.find_element(By.ID, "StartAction").click()
custom_sleep(2)
txt = driver.page_source
uuid0 = findall('wlspispHIPCountrySelect([a-z0-9]+)', txt)[0]
uuid1 = findall('wlspispHIPPhoneInput([a-z0-9]+)', txt)[0]
uuid2 = findall('wlspispHipSendCode([a-z0-9]+)', txt)[0]
uuid3 = findall('wlspispSolutionElement([a-z0-9]+)', txt)[0]
country_code_select = Select(driver.find_element(By.ID, "wlspispHIPCountrySelect" + uuid0))
country_code_input = input("enter Country code (FR, ...) ")
country_code_select.select_by_value(country_code_input)
wait_until_visible(By.ID, "wlspispHIPPhoneInput" + uuid1, browser=driver)
phone_input = input("phone number : +33")
phone_elem = driver.find_element(By.ID, "wlspispHIPPhoneInput" + uuid1)
phone_elem.send_keys(phone_input)
wait_until_visible(By.ID, "wlspispHipSendCode" + uuid2, browser=driver)
send_sms_elem = driver.find_element(By.ID, "wlspispHipSendCode" + uuid2)
send_sms_elem.click()
wait_until_visible(By.ID, "wlspispSolutionElement" + uuid3, browser=driver)
sms_code_elem = driver.find_element(By.ID, "wlspispSolutionElement" + uuid3)
sms_code_input = input("entrez le contenu du msg : ")
sms_code_elem.send_keys(sms_code_input)
send_box = driver.find_element(By.ID, "ProofAction")
send_box.click()
wait_until_visible(By.ID, "FinishAction", browser=driver)
end_elem = driver.find_element(By.ID, "FinishAction")
end_elem.click()
# Sends points to database, discord and whatever service you want
def log_points(account="unknown"):
def get_points():
driver.get("https://rewards.bing.com")
custom_sleep(1)
if "/proofs/" in driver.current_url:
for id in ["KmsiCheckboxField","iLooksGood", "idSIButton9", "iCancel"]:
try:
driver.find_element(By.ID, id).click()
restart = True
except Exception as e:
pass
wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver)
try :
point = search('availablePoints\":([\d]+)', driver.page_source)[1]
except Exception as e:
sleep(5)
log_error(f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}", driver, True)
driver.refresh()
sleep(5)
point = search('availablePoints\":([\d]+)', driver.page_source)[1]
return(point)
for _ in range (3):
try :
points = get_points()
break
except Exception as e:
custom_sleep(300)
log_error(e)
points = None
if not points :
log_error(f"impossible d'avoir les points")
custom_sleep(uniform(3, 20))
account_name = account.split("@")[0]
if g.discord_enabled_success:
if g.discord_embed:
embed = Embed(
title=f"{account_name} actuellement à {str(points)} points", colour=Colour.green()
)
embed.set_footer(text=account_name)
webhookSuccess.send(embed=embed)
else:
webhookSuccess.send(f"{account_name} actuellement à {str(points)} points")
if g.sql_enabled :
try :
add_to_database(account_name, points, g.sql_host, g.sql_usr, g.sql_pwd, g.sql_database)
except Exception as e:
if g.database_error_override:
printf("database error.")
else :
log_error(e)
def fidelity():
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]
bouton_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]')
bouton_card.click()
except Exception as e1 :
try :
recover_elem = driver.find_element(By.XPATH,'/html/body/div[1]/div[2]/main/div[2]/div[2]/div[7]/div[3]/div[1]/a')
recover_elem.click()
except Exception as e2 :
log_error(f"fidélité - double erreur - e1 : {format_error(e1)} - e2 {format_error(e2)}")
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 e:
printf(e)
printf("fidelity - done")
except Exception as e:
log_error(e)
if driver.current_url != "https://rewards.bing.com":
driver.get("https://rewards.bing.com")
pause = driver.find_element(By.CSS_SELECTOR, f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]') # mettre le truc en pause
pause.click()
cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]')
nb_cartes = len(cartes)
checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]')
for i in range(nb_cartes):
cartes[i].click() # affiche la bonne carte
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]
if not "moviesandtv" 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():
try:
alert = mobile_driver.switch_to.alert
alert.dismiss()
except exceptions.NoAlertPresentException as e:
pass
except Exception as e:
log_error(e, mobile_driver)
def bing_mobile_search(override=randint(22, 25)):
global mobile_driver
mobile_driver = firefox_driver(mobile=True)
try:
login(mobile_driver)
mot = choice(Liste_de_mot).replace(" ","+")
mobile_driver.get(f"https://www.bing.com/search?q={mot}")
custom_sleep(uniform(1, 2))
rgpd_popup(mobile_driver)
custom_sleep(uniform(1, 1.5))
for i in range(override): # 20
try :
mot = choice(Liste_de_mot)
send_keys_wait(mobile_driver.find_element(By.ID, "sb_form_q"), mot)
mobile_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)
mobile_driver.find_element(By.ID, "sb_form_q").clear()
except Exception as e:
printf(e)
mobile_driver.refresh()
custom_sleep(30)
i -= 1
mobile_driver.quit()
except Exception as e:
log_error(e, mobile_driver)
mobile_driver.quit()
def daily_routine(custom = False):
try :
if not custom: # custom already login
login(driver)
except Banned :
log_error("This account is locked. Fix that. (-U ?)", driver)
return()
except Identity :
log_error("This account has an issue. Fix that.", driver)
return()
try:
all_cards()
except Banned:
log_error("banned", driver)
return("BANNED")
except Exception as e:
log_error(e)
try:
fidelity()
except Exception as e:
log_error(e)
try:
bing_pc_search()
except Exception as e:
log_error(e)
try:
bing_mobile_search()
except Exception as e:
log_error(e)
try:
log_points(g._mail)
except Exception as e:
log_error(e)
def dev():
pass
def CustomStart():
if not g.islinux :
raise NameError('You need to be on linux to do that, due to the utilisation of a module named enquieries, sorry.')
global driver
system("clear") # clear from previous command to allow a clean choice
actions = ["tout", "daily", "pc", "mobile", "log_points","fidelity", "dev"]
Actions = enquiries.choose("quels Actions ?", actions, multi=True)
liste = select_accounts()
g.start_time = time() # Reset timer to the start of the actions
for cred in liste:
g._mail = cred[0]
g._password = cred[1]
if len(cred) == 3:
g._otp = TOTP(cred[2])
driver = firefox_driver()
driver.implicitly_wait(3)
if login(driver) != "STOP":
if "tout" in Actions:
daily_routine(True)
if "daily" in Actions:
try:
all_cards()
except Exception as e:
log_error(e)
if "pc" in Actions:
try:
bing_pc_search()
except Exception as e:
log_error(e)
if "mobile" in Actions:
try:
bing_mobile_search()
except Exception as e:
log_error(e)
if "fidelity" in Actions:
try :
fidelity()
except Exception as e :
log_error(e)
if "dev" in Actions:
try:
dev()
except Exception as e:
printf(e)
break
if not "tout" in Actions:
try:
log_points(g._mail)
except Exception as e:
printf(f"CustomStart {e}")
driver.quit()
if g.vnc_enabled :
display = SmartDisplay(backend="xvnc", size=(2160, 2160), rfbport=g.vnc_port, color_depth=24)
else :
display = SmartDisplay(size=(2160, 2160))
display.start()
if g.custom_start:
CustomStart()
elif g.unban:
g._mail, g._password = select_accounts(False)[0]
driver = firefox_driver()
try :
login(driver)
except Banned:
unban()
driver.quit()
elif g.points_file != "":
save_points_from_file(g.points_file)
else:
if g.update_version != "None":
if g.discord_enabled_error:
webhookFailure.send(f"Updated to {g.update_version}", username="UPDATE", avatar_url="https://cdn-icons-png.flaticon.com/512/1688/1688988.png")
for cred in g._cred:
g._mail = cred[0]
g._password = cred[1]
if len(cred) == 3:
g._otp = TOTP(cred[2])
custom_sleep(1)
printf("Début du driver.")
driver = firefox_driver()
printf("Driver demarré.")
driver.implicitly_wait(3)
try:
daily_routine()
driver.quit()
attente = uniform(1200, 3600)
printf(f"finis. attente de {round(attente/60)}min")
custom_sleep(attente)
except KeyboardInterrupt:
printf("Canceled. Closing driver and display.")
driver.quit()
display.stop()
except Exception as e:
log_error(f"Error not catched. Skipping this account. " + format_error(e), driver)
printf(f"Error not catched. Skipping this account. {e}")
driver.quit()
display.stop()

92
database.py Normal file
View File

@ -0,0 +1,92 @@
import mysql.connector
import configparser
from os import path
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-f",
"--file",
help="Choose a file",
type=argparse.FileType('r')
)
parser.add_argument(
"-m",
"--manual",
help="add point manually do database",
dest="manual",
action="store_true"
)
args = parser.parse_args()
MANUAL = args.manual
config_path = "./user_data/config.cfg"
config = configparser.ConfigParser()
config.read(config_path)
sql_usr = config["SQL"]["usr"]
sql_pwd = config["SQL"]["pwd"]
sql_host = config["SQL"]["host"]
sql_database = config["SQL"]["database"]
mydb = mysql.connector.connect(
host=sql_host,
user=sql_usr,
password=sql_pwd,
database = sql_database
)
mycursor = mydb.cursor()
def add_account(name: str, endroit: str, proprio: str):
command = f'INSERT INTO comptes (compte, proprio, endroit, last_pts) VALUES ("{name}", "{proprio}", "{endroit}",0);'
mycursor.execute(command)
def ban_account(name: str, pts = 0):
command1 = f"INSERT INTO banned (nom, total) VALUES ('{name}', {pts});"
command2 = f'DELETE FROM comptes WHERE compte = "{name}";'
mycursor.execute(command1)
mycursor.execute(command2)
def update_pts(name: str, pts = 0):
pass
if not MANUAL :
print("ajouter un compte : 1\nban un compte : 2")
i = input()
if i == "1":
if args.file :
l =[x.split(",")[0].split("@")[0] for x in args.file.readlines()]
endroit = input("ou est le bot ? ")
proprio = input("qui est le proprio ? ")
for name in l :
add_account(name, endroit, proprio)
else :
name = input("quel est le nom ? ").split("@")[0]
endroit = input("ou est le bot ? ")
proprio = input("qui est le proprio ? ")
add_account(name, endroit, proprio)
elif i == '2':
name = input("quel est le compte qui a été ban ? ")
pts = input("il avait combien de points ? ")
ban_account(name, pts)
mydb.commit()
mycursor.close()
mydb.close()
else :
import modules.db as datab
config_path = f"{path.abspath(path.dirname(path.dirname( __file__ )))}/MsRewards/user_data/config.cfg"
print(config_path)
config = configparser.ConfigParser()
config.read(config_path)
sql_usr = config["SQL"]["usr"]
sql_pwd = config["SQL"]["pwd"]
sql_host = config["SQL"]["host"]
sql_database = config["SQL"]["database"]
account_name = input("compte ? ")
points = int(input("points ? "))
datab.add_to_database(account_name, points, sql_host, sql_usr, sql_pwd, sql_database)

82
main.py
View File

@ -1,8 +1,11 @@
#/usr/bin/python3.10
from packaging.version import parse as parse_version
import configparser
import os
import shutil
import requests
import sys
config = configparser.ConfigParser()
@ -16,8 +19,6 @@ except :
config.read(config_path)
def confirm(texte, default = False):
if default :
txt = '[Y/n]'
@ -33,7 +34,7 @@ def confirm(texte, default = False):
return False
return default
lang = "fr"
lang = "en"
text = {"fr" : {
"compte" : "entrer l'adresse mail du compte ",
@ -41,12 +42,12 @@ text = {"fr" : {
"next" : "voulez vous ajouter un compte ? ",
"finc" : "comptes en cours d'ajout ",
"ajout" : "comptes ajouté ",
"fidelity" : "avez vous un lien sur lequel le lien vers la page fidelité du mois est le seul contenu de la page ? ",
"fidelity" : "avez vous un lien sur lequel le lien vers la page fidélité du mois est le seul contenu de la page ? ",
"lien" : "entrez le lien ",
"discorde" : "voulez vous envoyer les erreurs sur discord ? ",
"w1" : "entrez le lien du WebHook pour envoyer les points ",
"w2" : "entrez le lien du WebHook pour envoyer les erreurs ",
"msqle" : "voulez vous untiliser une base de donnée ",
"msqle" : "voulez vous utiliser une base de donnée ",
"msqll" : "entrez le lien de la base de donnée ",
"msqlu" : "entrez l'utilisateur de la base de donnée ",
"msqlp" : "entrez le mot de passe de la base de donnée ",
@ -54,6 +55,24 @@ text = {"fr" : {
"proxye" : "voulez vous utiliser un proxy ",
"proxyl" : "entrez le lien du proxy ",
"proxyp" : "entrez le port du proxy "
},
"en" : {
"compte" : "enter email of an account",
"mdp" : "enter password of this account ",
"next" : "Add another account ? ",
"finc" : "Adding accounts ",
"ajout" : "Accounts added ",
"discorde" : "Do you want to use discord ? (Highly recommended as it's untested without)",
"w1" : "Enter Webhook link for sending points everyday",
"w2" : "Enter Webhook link for errors ",
"msqle" : "Do you want to use a database ? ",
"msqll" : "database link ",
"msqlu" : "database username ",
"msqlp" : "database password ",
"msqlt" : "database name (should be MsRewards) ",
"proxye" : "Do you want to use a proxy ",
"proxyl" : "Proxy address ",
"proxyp" : "Proxy port "
}
}
@ -73,17 +92,16 @@ def setup_comptes():
if confirm(t["next"], default = True):
compte = input(t["compte"])
mdp = input(t["mdp"])
lc.append(f"{compte},{mdp}\n")
lc.append(f"{compte},{mdp}")
else:
print(t["finc"])
break
f = open('./user_data/login.csv', "w")
for i in lc :
f.write(i)
f.write("\n")
f.close()
print(t["ajout"])
#modifie le fichier de configuration
edit_config_txt("logpath",f'{os.getcwd()}/user_data/login.csv')
@ -92,7 +110,7 @@ def edit_config_txt(ligne, contenu):
txt = f.readlines()
f.close()
if txt.count(txt) >1:
raise NameError("il y a plus d'une occurence, echec de la modification")
raise NameError("Fail")
for i in range(len(txt)) :
name = txt[i].split(" = ")[0]
@ -106,17 +124,13 @@ def edit_config_txt(ligne, contenu):
def setup_settings():
general()
discord()
proxy()
sql()
amazon()
def general():
if confirm(t["fidelity"]):
lien = input(t["lien"])
edit_config_txt('FidelityLink',lien)
def discord():
enabled = confirm(t["discorde"], default = True)
if enabled :
@ -128,6 +142,7 @@ def discord():
w2 = input(t["w2"])
edit_config_txt("errorlink",w2)
def sql() :
enabled = confirm(t["msqle"], default = False)
if enabled :
@ -140,7 +155,8 @@ def sql() :
edit_config_txt("usr",user)
pwd = input(t["msqlp"])
edit_config_txt("pwd",pwd)
def proxy() :
enabled = confirm(t["proxye"], default = False)
if enabled :
@ -149,14 +165,34 @@ def proxy() :
edit_config_txt("url",lien)
port = input(t["proxyp"])
edit_config_txt("port",port)
def amazon():
enabled = confirm("claim les recompenses automatiquement sur amazon ?", default = False)
edit_config_txt("claim_amazon",enabled)
def check_update(args):
try :
latest = requests.get("https://api.github.com/repos/piair338/MsRewards/releases").json()[0]["tag_name"]
latest = parse_version(latest)
except Exception as e :
print(e)
return (args)
f = open("./version", 'r')
txt = f.readlines()[0].replace("\n","")
f.close()
cur = parse_version(txt)
if not (cur < latest) :
print("Already up to date.")
return(args)
else :
print(f"updating to {latest}")
os.system("git reset --hard")
os.system("git pull")
os.system("python3 -m pip install -r requirements.txt > update.result")
print(f"updated to {latest}")
return(args + f" --version {latest}")
LogPath = config["PATH"]["logpath"]
if LogPath == "/your/path/to/loginandpass.csv" :
setup()
else :
os.system("python3.10 V4.py")
args = " ".join(sys.argv[1::])
args = check_update(args)
os.system("python3 V5.py " + args)

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

View File

@ -1,16 +1,7 @@
#!/usr/bin/python3.10
import configparser
from csv import reader
from os import sys, system, path
from sys import platform
import argparse
from discord import ( # Importing discord.Webhook and discord.RequestsWebhookAdapter
RequestsWebhookAdapter,
Webhook,
)
from time import time
from random import shuffle
from modules.driver_tools import *
from modules.imports import *
import modules.globals as g
"""
Setup for option, like --override or --fulllog
"""
@ -33,7 +24,6 @@ parser.add_argument(
action="store_true"
)
parser.add_argument(
"-l",
"--log",
@ -49,19 +39,12 @@ parser.add_argument(
help="enable full logging in discord",
action="store_true",
)
parser.add_argument(
"-r",
"--risky",
help="make the program faster, probably better risk of ban",
dest="fast",
action="store_true"
)
parser.add_argument(
"-c",
"--config",
help="Choose a specific config file",
type=argparse.FileType('r')
default=""
)
parser.add_argument(
@ -72,87 +55,125 @@ parser.add_argument(
default=""
)
parser.add_argument(
"-v",
"--vnc",
help="enable VNC",
dest="vnc",
default="None"
)
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(
"--dev",
help="dev option",
dest="dev",
action="store_true"
)
args = parser.parse_args()
CUSTOM_START = args.override
UNBAN = args.unban
LOG = args.log
FULL_LOG = args.fulllog
FAST = args.fast
if CUSTOM_START :
LOG = True
POINTS_FILE = args.points_file
g.custom_start = args.override
g.unban = args.unban
g.log = args.log
g.full_log = args.fulllog
g.dev = args.dev
if g.custom_start :
g.log = True
g.vnc_enabled = args.vnc != "None"
g.vnc_port = args.vnc
g.points_file = args.points_file
g.update_version = args.update_version
# global variables used later in the code
LINUX_HOST = platform == "linux" # if the computer running this programm is linux, it allow more things
START_TIME = time()
driver = None
if LINUX_HOST:
import enquiries
else:
system("") # enable colors in windows cmd
g.islinux = platform == "linux" # if the computer running this program is Linux, it allow more things
g.start_time = time()
#reading configuration
config_path = f"{path.abspath(path.dirname(path.dirname( __file__ )))}/user_data/config.cfg"
if args.config :
config_path = path.abspath(args.config.name)
config = configparser.ConfigParser()
config.read(config_path)
if args.config :
try :
config_path =f"{path.abspath(path.dirname(path.dirname( __file__ )))}/user_data/config{args.config}.cfg"
config.read(config_path)
g.mot_path = config["PATH"]["motpath"]
except :
config_path = path.abspath(args.config)
config.read(config_path)
else :
config_path = f"{path.abspath(path.dirname(path.dirname( __file__ )))}/user_data/config.cfg"
config.read(config_path)
# path configurations
MotPath = config["PATH"]["motpath"]
CREDENTIALS_PATH = config["PATH"]["logpath"]
g.mot_path = config["PATH"]["motpath"]
g.credential_path = config["PATH"]["logpath"]
# discord configuration
DISCORD_SUCCESS_LINK = config["DISCORD"]["successlink"]
DISCORD_ERROR_LINK = config["DISCORD"]["errorlink"]
DISCORD_ENABLED_ERROR = config["DISCORD"]["DiscordErrorEnabled"] == "True"
DISCORD_ENABLED_SUCCESS = config["DISCORD"]["DiscordSuccessEnabled"]== "True"
if DISCORD_ENABLED_ERROR:
webhookFailure = Webhook.from_url(DISCORD_ERROR_LINK, adapter=RequestsWebhookAdapter())
if DISCORD_ENABLED_SUCCESS:
webhookSuccess = Webhook.from_url(DISCORD_SUCCESS_LINK, adapter=RequestsWebhookAdapter())
g.discord_success_link = config["DISCORD"]["successlink"]
g.discord_error_link = config["DISCORD"]["errorlink"]
g.discord_enabled_error = config["DISCORD"]["DiscordErrorEnabled"] == "True"
g.discord_enabled_success = config["DISCORD"]["DiscordSuccessEnabled"]== "True"
try :
g.avatar_url = config["OTHER"]["avatar"]
except :
g.avatar_url = "https://cdn.discordapp.com/icons/793934298977009674/d8055bccef6eca4855c349e808d0d788.webp"
if g.discord_enabled_error:
webhookFailure = Webhook.from_url(g.discord_error_link, adapter=RequestsWebhookAdapter())
if g.discord_enabled_success:
webhookSuccess = Webhook.from_url(g.discord_success_link, adapter=RequestsWebhookAdapter())
# base settings
FidelityLink = config["SETTINGS"]["FidelityLink"]
DISCORD_EMBED = config["SETTINGS"]["embeds"] == "True" #print new point value in an embed
Headless = config["SETTINGS"]["headless"] == "True"
g.fidelity_link = config["SETTINGS"]["FidelityLink"]
g.discord_embed = config["SETTINGS"]["embeds"] == "True" #print new point value in an embed
g.headless = config["SETTINGS"]["headless"] == "True"
# proxy settings
proxy_enabled = config["PROXY"]["proxy_enabled"] == "True"
proxy_address = config["PROXY"]["url"]
proxy_port = config["PROXY"]["port"]
g.proxy_enabled = config["PROXY"]["proxy_enabled"] == "True"
g.proxy_address = config["PROXY"]["url"]
g.proxy_port = config["PROXY"]["port"]
# MySQL settings
sql_enabled = config["SQL"]["sql_enabled"] == "True"
sql_usr = config["SQL"]["usr"]
sql_pwd = config["SQL"]["pwd"]
sql_host = config["SQL"]["host"]
sql_database = config["SQL"]["database"]
# Other seetings
IPV6_CHECKED = config["OTHER"]["ipv6"]
CLAIM_AMAZON = config["OTHER"]["claim_amazon"] == "True"
g.sql_enabled = config["SQL"]["sql_enabled"] == "True"
g.sql_usr = config["SQL"]["usr"]
g.sql_pwd = config["SQL"]["pwd"]
g.sql_host = config["SQL"]["host"]
g.sql_database = config["SQL"]["database"]
g = open(MotPath, "r", encoding="utf-8")
lines = g.readlines()
try :
g.database_error_override = config["OTHER"]["database_override"] == "True"
except :
pass
try :
g.fast = config["OTHER"]["fast"] == "True"
except :
pass
h = open(g.mot_path, "r", encoding="utf-8")
lines = h.readlines()
if len(lines) < 3 :
Liste_de_mot = list(lines[0].split(","))
else :
Liste_de_mot = [x.replace('\n', "") for x in lines]
g.close()
h.close()
with open(CREDENTIALS_PATH) as f:
with open(g.credential_path) as f:
reader = reader(f)
Credentials = list(reader)
shuffle(Credentials)
g._cred = Credentials
if g.proxy_enabled :
setup_proxy(g.proxy_address,g.proxy_port)

View File

@ -33,35 +33,38 @@ def get_row(compte, points, mycursor, same_points = True): #return if there is a
def add_to_database(compte, points, sql_host,sql_usr,sql_pwd,sql_database, save_if_fail=True):
try:
mydb = mysql.connector.connect(
host=sql_host,
user=sql_usr,
password=sql_pwd,
database = sql_database
)
mycursor = mydb.cursor()
if points is None:
pass
else:
try:
mydb = mysql.connector.connect(
host=sql_host,
user=sql_usr,
password=sql_pwd,
database = sql_database
)
mycursor = mydb.cursor()
if get_row(compte, points,mycursor, True): #check if the row exist with the same ammount of points and do nothind if it does
#printf("les points sont deja bon")
#return(0)
pass
elif get_row(compte, points,mycursor, False) : #check if the row exist, but without the same ammount of points and update the point account then
update_row(compte, points,mycursor,mydb)
#printf("row updated")
#return(1)
else : # if the row don't exist, create it with the good ammount of points
add_row(compte, points,mycursor,mydb)
#return(2) #printf("row added")
if int(points) > 10 :
update_last(compte, points, mycursor, mydb)
if get_row(compte, points,mycursor, True): #check if the row exist with the same ammount of points and do nothind if it does
#printf("les points sont deja bon")
#return(0)
pass
elif get_row(compte, points,mycursor, False) : #check if the row exist, but without the same ammount of points and update the point account then
update_row(compte, points,mycursor,mydb)
#printf("row updated")
#return(1)
else : # if the row don't exist, create it with the good ammount of points
add_row(compte, points,mycursor,mydb)
#return(2) #printf("row added")
if int(points) > 10 :
update_last(compte, points, mycursor, mydb)
mycursor.close()
mydb.close()
except BaseException as e:
if save_if_fail:
print("\nLes points n'ont pas pu être ajoutés, enregistrement dans le fichier 'points.csv'\n")
with open("points.csv", "a") as file:
file.write(f"{compte},{points}\n")
raise e
mycursor.close()
mydb.close()
except BaseException as e:
if save_if_fail:
print("\nLes points n'ont pas pu être ajoutés, enregistrement dans le fichier 'points.csv'\n")
with open("points.csv", "a") as file:
file.write(f"{compte},{points}\n")
raise e

67
modules/driver_tools.py Normal file
View File

@ -0,0 +1,67 @@
from modules.imports import *
from modules.config import *
from modules.tools import *
import modules.globals as g
def setup_proxy(ip: str, port: str) -> None:
PROXY = f"{ip}:{port}"
webdriver.DesiredCapabilities.FIREFOX['proxy'] = {
"httpProxy": PROXY,
"sslProxy": PROXY,
"proxyType": "MANUAL",
}
#Deal with RGPD popup as well as some random popup like 'are you satisfied' one
def rgpd_popup(driver) -> None:
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] :
try:
driver.find_element(By.ID, i).click()
except:
pass
# save webdriver cookies
def save_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "w")
for i in driver.get_cookies():
f.write(str(i) + "\n")
f.close()
else :
pickle.dump(driver.get_cookies(), open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "wb"))
# load cookies previously saved to the driver
def load_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "r")
lines = f.readlines()
f.close()
cookies = [literal_eval(x) for x in lines]
else :
cookies = pickle.load(open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
"""
send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random time between each press to simulate human action.
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))
# Wait for the presence of the element identifier or [timeout]s
def wait_until_visible(search_by: str, identifier: str, timeout = 20, browser = None) -> None:
try :
WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((search_by,identifier)), "element not found")
return(True)
except TimeoutException as e:
printf(f"element {identifier} not found after {timeout}s")
return(False)

View File

@ -1,7 +1,8 @@
from selenium.common.exceptions import TimeoutException, NoSuchElementException, ElementClickInterceptedException
class Banned(Exception):
pass
class NotBanned(Exception):
pass
class Identity(Exception):
pass

38
modules/globals.py Normal file
View File

@ -0,0 +1,38 @@
driver = None
_mail = '_mail temp'
_password = '_password temp'
_otp = '_otp temp'
display = None
_cred = []
custom_start = False
unban = False
log = False
full_log = False
vnc_enabled = False
vnc_port = 0
points_file = "/"
update_version = False
islinux = True
start_time = 0
mot_path = "/"
credential_path = "/"
discord_success_link = "https://example.com"
discord_error_link = "https://example.com"
discord_enabled_error = False
discord_enabled_success = False
avatar_url = ""
fidelity_link = "None"
discord_embed = False
headless = False
proxy_enabled = False
proxy_address = "0.0.0.0"
proxy_port = "0"
sql_enabled = False
sql_usr = "None"
sql_pwd = "azerty"
sql_host = "https://example.com"
sql_database = "MsRewards"
dev = False
norvege = False
database_error_override = False
fast = False

33
modules/imports.py Normal file
View File

@ -0,0 +1,33 @@
import argparse
import asyncio
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.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

View File

@ -1,32 +0,0 @@
#add return a string witx tabs
def tabs(x):
return(x*4*" ")
#create dictionnary with all progress bars
def dico(progress):
dico_task = {
"daily" : {
"all" : progress.add_task("[yellow]daily", total=100, start=False, visible=False),
"carte0" : progress.add_task(f"[yellow]{tabs(1)}carte 1", total=100, start=False, visible = False),
"carte1" : progress.add_task(f"[yellow]{tabs(1)}carte 2", total=100, start=False, visible = False),
"carte2" : progress.add_task(f"[yellow]{tabs(1)}carte 3", total=100, start=False, visible = False)
},
"weekly" : {
"all" : progress.add_task("[yellow]weekly", total=100, start=False, visible=False),
"carte1" : progress.add_task(f"[yellow]{tabs(1)}carte 1", total=100, start=False, visible = False),
"carte2" : progress.add_task(f"[yellow]{tabs(1)}carte 2", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 3", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 4", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 5", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 6", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 7", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 8", total=100, start=False, visible = False),
"carte3" : progress.add_task(f"[yellow]{tabs(1)}carte 9", total=100, start=False, visible = False),
},
"PC" : progress.add_task(f"[yellow]PC", total=100, start=False, visible = False),
"Mobile" : progress.add_task(f"[yellow]Mobile", total=100, start=False, visible = False),
}
return(dico_task)

View File

@ -1,72 +1,27 @@
from time import sleep
from datetime import timedelta
from random import uniform
import discord
from discord import ( # Importing discord.Webhook and discord.RequestsWebhookAdapter
Colour,
Webhook,
)
from modules.imports import *
from modules.config import *
"""
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 alos selenium keys
"""
def send_keys_wait(element, keys):
for i in keys:
element.send_keys(i)
if FAST :
pass
else :
sleep(uniform(0.1, 0.3))
def LogError(message, driver, mail, log=FULL_LOG):
print(f"\n\n\033[93m Erreur : {str(message)} \033[0m\n\n")
if DISCORD_ENABLED_ERROR:
with open("page.html", "w") as f:
f.write(driver.page_source)
driver.save_screenshot("screenshot.png")
if not log:
embed = discord.Embed(
title="An Error has occured",
description=str(message),
colour=Colour.red(),
)
else:
embed = discord.Embed(
title="Full log is enabled",
description=str(message),
colour=Colour.blue(),
)
file = discord.File("screenshot.png")
embed.set_image(url="attachment://screenshot.png")
embed.set_footer(text=mail)
webhookFailure.send(embed=embed, file=file)
webhookFailure.send(file=discord.File("page.html"))
# add the time arround the text given in [text]
# [text] : string
def Timer(text, mail):
return(f"[{mail} - {timedelta(seconds = round(float(time() - START_TIME)))}] " + str(text))
from modules.db import *
import modules.globals as g
# add the time arround the text given in [text]&
def Timer(text: str) -> str:
return(f"[{g._mail.split('@')[0]} - {datetime.today().strftime('%d/%m')} - {timedelta(seconds = round(float(time() - g.start_time)))}] " + str(text))
# replace the function print, with more options
# [txt] : string, [driver] : selenium wbdriver
def printf2(txt, mail, LOG = LOG):
if LOG:
print(Timer(txt, mail))
# [txt] : string, [driver] : selenium webdriver
def printf(txt):
print(Timer(txt))
# return current page domain
def get_domain(driver):
return(driver.current_url.split("/")[2])
# check if the user is using IPV4 using ipify.org
# [driver] : selenium webdriver
# never used here
# can be useful as Ms had issues with IPV6 at some point
def check_ipv4(driver):
driver.get("https://api64.ipify.org")
elm = driver.find_element(By.TAG_NAME, "body")
@ -75,13 +30,9 @@ def check_ipv4(driver):
return False
def CustomSleep(temps):
def custom_sleep(temps):
try :
if FAST and temps > 50:
sleep(temps/10)
return()
if not LOG or not LINUX_HOST: #only print sleep when user see it
if g.log : #only print sleep when user see it
points = ["", "", "", "", "", "", "", ""]
passe = 0
for i in range(int(temps)):
@ -96,7 +47,13 @@ def CustomSleep(temps):
print("attente annulée")
def format_error(e) -> str:
tb = e.__traceback__
txt = ""
while tb != None :
txt = txt + f" -> {tb.tb_frame.f_code.co_name} ({tb.tb_lineno}) "
tb = tb.tb_next
return(txt + "\n" + str(e))
def progressBar(current, total=30, barLength=20, name="Progress"):
@ -104,3 +61,22 @@ def progressBar(current, total=30, barLength=20, name="Progress"):
arrow = "-" * int(percent / 100 * barLength - 1) + ">"
spaces = " " * (barLength - len(arrow))
print(name + ": [%s%s] %d %%" % (arrow, spaces, percent), end="\r")
def save_points_from_file(file):
with open(file) as f:
read = reader(f)
points_list = list(read)
for item in points_list:
compte, points = item[0], item[1]
add_to_database(compte, points, g.sql_host,g.sql_usr,g.sql_pwd,g.sql_database, save_if_fail=False)
with open(file, "w") as f:
f.write("")
def select_accounts(multiple = True):
system("clear") # clear from previous command to allow a clean choice
emails = [x[0] for x in g._cred] # list of all email adresses
emails_selected = enquiries.choose(f"quel{'s' if multiple else ''} compte{'s' if multiple else ''} ?", emails, multi=multiple)
return([x for x in g._cred if x[0] in emails_selected])

View File

@ -3,4 +3,10 @@ argparse
discord.py==1.7.3
selenium
enquiries
rich
rich
requests
pyvirtualdisplay
pillow
EasyProcess
pyotp
packaging

View File

@ -5,7 +5,6 @@ logpath = /your/path/to/loginandpass.csv
[SETTINGS]
FidelityLink = Null
embeds = False
Headless = True
@ -14,7 +13,7 @@ Headless = True
DiscordErrorEnabled = True
DiscordSuccessEnabled = True
successlink = https://discord.com/api/webhooks/[put your webhook here]
errorlink =https://discord.com/api/webhooks/[put your webhook here]
errorlink = https://discord.com/api/webhooks/[put your webhook here]
[PROXY]
@ -32,5 +31,7 @@ pwd = password
[OTHER]
avatar = https://cdn.discordapp.com/icons/793934298977009674/d8055bccef6eca4855c349e808d0d788.webp
ipv6 = False
claim_amazon = False
database_override = False
fast = False

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

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

1
version Normal file
View File

@ -0,0 +1 @@
v5.10.10