47 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
18 changed files with 909 additions and 733 deletions

3
.gitignore vendored
View File

@ -1,7 +1,6 @@
/old /old
geckodriver.log geckodriver.log
.vscode/ .vscode/
update.sh
/Git /Git
page.html page.html
screenshot.png screenshot.png
@ -11,3 +10,5 @@ data
/user_data /user_data
install.sh install.sh
nohup.out 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,11 +4,11 @@ ENV DEBIAN_FRONTEND noninteractive
ENV GECKODRIVER_VER v0.31.0 ENV GECKODRIVER_VER v0.31.0
ENV FIREFOX_VER 87.0 ENV FIREFOX_VER 87.0
WORKDIR /app WORKDIR /app
RUN set -x \ RUN set -x \
&& apt update \ && apt update \
&& apt upgrade -y \ && apt upgrade -y \
&& apt install -y \ && apt install -y \
tzdata \
wfrench \ wfrench \
git \ git \
libx11-xcb1 \ libx11-xcb1 \
@ -19,6 +19,7 @@ RUN set -x \
nano \ nano \
tigervnc-standalone-server \ tigervnc-standalone-server \
&& git clone https://github.com/piair338/MsRewards \ && git clone https://github.com/piair338/MsRewards \
&& ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime \
&& pip install -r MsRewards/requirements.txt \ && 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 \ && 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-* \ && tar -jxf firefox-* \
@ -31,6 +32,7 @@ RUN set -x \
&& mv geckodriver /usr/bin/ && mv geckodriver /usr/bin/
ENV TZ="Europe/Paris"
WORKDIR /app/MsRewards WORKDIR /app/MsRewards
CMD python main.py CMD python main.py

View File

@ -1,46 +1,50 @@
# MsReward # MsReward
A Microsoft reward automator, designed to work headless on any server. A Microsoft reward automator, designed to work headless on any x64 server.
Using a discord webhook or SQL to log points everyday. Using a discord webhook or SQL to log points everyday.
Using Selenium and geckodriver. 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) ### Using docker (Recommended)
to use docker, run 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 . git clone https://github.com/piair338/MsRewards
#copy the build id
sudo docker run -ti --name MsRewards [build id]
``` ```
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 ### **not** using docker (not recommended)
**This is only a recommandation and shouldn't be used !**
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 :
``` ```
sudo apt-get install xdg-utils libdbus-glib-1-2 bzip2 wfrench tigervnc-standalone-server -y 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 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 tar -xjf firefox-91.9.1esr.tar.bz2
sudo mv firefox /opt/ sudo mv firefox /opt/
sudo ln -s /opt/firefox/firefox /usr/bin/firefox 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 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 tar zxf geckodriver-v0.31.0-linux64.tar.gz
sudo mv geckodriver /usr/bin/ sudo mv geckodriver /usr/bin/
@ -48,3 +52,41 @@ sudo mv geckodriver /usr/bin/
rm geckodriver-v0.31.0-linux64.tar.gz rm geckodriver-v0.31.0-linux64.tar.gz
rm firefox-91.9.1esr.tar.bz2 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
```

675
V5.py

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,16 @@ parser.add_argument(
help="Choose a file", help="Choose a file",
type=argparse.FileType('r') type=argparse.FileType('r')
) )
parser.add_argument(
"-m",
"--manual",
help="add point manually do database",
dest="manual",
action="store_true"
)
args = parser.parse_args() args = parser.parse_args()
MANUAL = args.manual
config_path = "./user_data/config.cfg" config_path = "./user_data/config.cfg"
config = configparser.ConfigParser() config = configparser.ConfigParser()
@ -47,10 +54,10 @@ def ban_account(name: str, pts = 0):
def update_pts(name: str, pts = 0): def update_pts(name: str, pts = 0):
pass pass
if not MANUAL :
print("ajouter un compte : 1\nban un compte : 2") print("ajouter un compte : 1\nban un compte : 2")
i = input() i = input()
if i == "1": if i == "1":
if args.file : if args.file :
l =[x.split(",")[0].split("@")[0] for x in args.file.readlines()] l =[x.split(",")[0].split("@")[0] for x in args.file.readlines()]
endroit = input("ou est le bot ? ") endroit = input("ou est le bot ? ")
@ -62,11 +69,24 @@ if i == "1":
endroit = input("ou est le bot ? ") endroit = input("ou est le bot ? ")
proprio = input("qui est le proprio ? ") proprio = input("qui est le proprio ? ")
add_account(name, endroit, proprio) add_account(name, endroit, proprio)
elif i == '2': elif i == '2':
name = input("quel est le compte qui a été ban ? ") name = input("quel est le compte qui a été ban ? ")
pts = input("il avait combien de points ? ") pts = input("il avait combien de points ? ")
ban_account(name, pts) ban_account(name, pts)
mydb.commit() mydb.commit()
mycursor.close() mycursor.close()
mydb.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)

71
main.py
View File

@ -1,8 +1,11 @@
#/usr/bin/python3.10 #/usr/bin/python3.10
from packaging.version import parse as parse_version
import configparser import configparser
import os import os
import shutil import shutil
import requests
import sys
config = configparser.ConfigParser() config = configparser.ConfigParser()
@ -16,8 +19,6 @@ except :
config.read(config_path) config.read(config_path)
def confirm(texte, default = False): def confirm(texte, default = False):
if default : if default :
txt = '[Y/n]' txt = '[Y/n]'
@ -33,7 +34,7 @@ def confirm(texte, default = False):
return False return False
return default return default
lang = "fr" lang = "en"
text = {"fr" : { text = {"fr" : {
"compte" : "entrer l'adresse mail du compte ", "compte" : "entrer l'adresse mail du compte ",
@ -41,12 +42,12 @@ text = {"fr" : {
"next" : "voulez vous ajouter un compte ? ", "next" : "voulez vous ajouter un compte ? ",
"finc" : "comptes en cours d'ajout ", "finc" : "comptes en cours d'ajout ",
"ajout" : "comptes 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 ", "lien" : "entrez le lien ",
"discorde" : "voulez vous envoyer les erreurs sur discord ? ", "discorde" : "voulez vous envoyer les erreurs sur discord ? ",
"w1" : "entrez le lien du WebHook pour envoyer les points ", "w1" : "entrez le lien du WebHook pour envoyer les points ",
"w2" : "entrez le lien du WebHook pour envoyer les erreurs ", "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 ", "msqll" : "entrez le lien de la base de donnée ",
"msqlu" : "entrez l'utilisateur 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 ", "msqlp" : "entrez le mot de passe de la base de donnée ",
@ -54,6 +55,24 @@ text = {"fr" : {
"proxye" : "voulez vous utiliser un proxy ", "proxye" : "voulez vous utiliser un proxy ",
"proxyl" : "entrez le lien du proxy ", "proxyl" : "entrez le lien du proxy ",
"proxyp" : "entrez le port 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 "
} }
} }
@ -83,8 +102,6 @@ def setup_comptes():
f.write("\n") f.write("\n")
f.close() f.close()
print(t["ajout"]) print(t["ajout"])
#modifie le fichier de configuration
edit_config_txt("logpath",f'{os.getcwd()}/user_data/login.csv') edit_config_txt("logpath",f'{os.getcwd()}/user_data/login.csv')
@ -93,7 +110,7 @@ def edit_config_txt(ligne, contenu):
txt = f.readlines() txt = f.readlines()
f.close() f.close()
if txt.count(txt) >1: 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)) : for i in range(len(txt)) :
name = txt[i].split(" = ")[0] name = txt[i].split(" = ")[0]
@ -107,16 +124,11 @@ def edit_config_txt(ligne, contenu):
def setup_settings(): def setup_settings():
general()
discord() discord()
proxy() proxy()
sql() sql()
amazon()
def general():
if confirm(t["fidelity"]):
lien = input(t["lien"])
edit_config_txt('FidelityLink',lien)
def discord(): def discord():
@ -144,6 +156,7 @@ def sql() :
pwd = input(t["msqlp"]) pwd = input(t["msqlp"])
edit_config_txt("pwd",pwd) edit_config_txt("pwd",pwd)
def proxy() : def proxy() :
enabled = confirm(t["proxye"], default = False) enabled = confirm(t["proxye"], default = False)
if enabled : if enabled :
@ -153,13 +166,33 @@ def proxy() :
port = input(t["proxyp"]) port = input(t["proxyp"])
edit_config_txt("port",port) 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"] LogPath = config["PATH"]["logpath"]
if LogPath == "/your/path/to/loginandpass.csv" : if LogPath == "/your/path/to/loginandpass.csv" :
setup() setup()
else : else :
os.system("python3 V5.py") args = " ".join(sys.argv[1::])
args = check_update(args)
os.system("python3 V5.py " + args)

View File

@ -1,69 +0,0 @@
from easyprocess import EasyProcess
from pyvirtualdisplay import Display
from modules.config import *
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
def setup_proxy(ip, port, options, 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 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/110.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/605.1.15 (KHTML, like Gecko)"
"CriOS/103.0.5060.63 Mobile/15E148 Safari/604.1"
)
options = Options()
options.set_preference('intl.accept_languages', 'fr-FR, fr')
if proxy_enabled :
setup_proxy(proxy_address,proxy_port, 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 select_accounts(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
emails_selected = enquiries.choose(f"quel{'s' if multiple else ''} compte{'s' if multiple else ''} ?", emails, multi=multiple)
return([x for x in Credentials if x[0] in emails_selected])
with Display(backend="xvnc", size=(2000, 1000), rfbport=5904) as disp:
_mail, _password = select_accounts(False)[0]
driver = firefox_driver()
print(f"connect via VNC to port 5904. \nID: {_mail}\npwd : {_password}")
i = input('stop ? ')
driver.close()

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,18 +1,7 @@
#!/usr/bin/python3.10 #!/usr/bin/python3.10
import configparser from modules.driver_tools import *
from csv import reader from modules.imports import *
from os import sys, system, path import modules.globals as g
from sys import platform
import argparse
from discord import ( # Importing discord.Webhook and discord.RequestsWebhookAdapter
RequestsWebhookAdapter,
Webhook,
Colour,
)
from time import time
from random import shuffle
""" """
Setup for option, like --override or --fulllog Setup for option, like --override or --fulllog
""" """
@ -50,19 +39,12 @@ parser.add_argument(
help="enable full logging in discord", help="enable full logging in discord",
action="store_true", 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( parser.add_argument(
"-c", "-c",
"--config", "--config",
help="Choose a specific config file", help="Choose a specific config file",
type=argparse.FileType('r') default=""
) )
parser.add_argument( parser.add_argument(
@ -81,87 +63,117 @@ parser.add_argument(
default="None" 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() args = parser.parse_args()
CUSTOM_START = args.override g.custom_start = args.override
UNBAN = args.unban g.unban = args.unban
LOG = args.log g.log = args.log
FULL_LOG = args.fulllog g.full_log = args.fulllog
FAST = args.fast g.dev = args.dev
if CUSTOM_START :
LOG = True
VNC_ENABLED = args.vnc != "None"
VNC_PORT = args.vnc
POINTS_FILE = args.points_file
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 # global variables used later in the code
LINUX_HOST = platform == "linux" # if the computer running this program is Linux, it allow more things g.islinux = platform == "linux" # if the computer running this program is Linux, it allow more things
START_TIME = time() g.start_time = time()
if LINUX_HOST:
import enquiries
else:
system("") # enable colors in windows cmd
#reading configuration #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 = 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 # path configurations
MotPath = config["PATH"]["motpath"] g.mot_path = config["PATH"]["motpath"]
CREDENTIALS_PATH = config["PATH"]["logpath"] g.credential_path = config["PATH"]["logpath"]
# discord configuration # discord configuration
DISCORD_SUCCESS_LINK = config["DISCORD"]["successlink"] g.discord_success_link = config["DISCORD"]["successlink"]
DISCORD_ERROR_LINK = config["DISCORD"]["errorlink"] g.discord_error_link = config["DISCORD"]["errorlink"]
DISCORD_ENABLED_ERROR = config["DISCORD"]["DiscordErrorEnabled"] == "True" g.discord_enabled_error = config["DISCORD"]["DiscordErrorEnabled"] == "True"
DISCORD_ENABLED_SUCCESS = config["DISCORD"]["DiscordSuccessEnabled"]== "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 DISCORD_ENABLED_ERROR: if g.discord_enabled_error:
webhookFailure = Webhook.from_url(DISCORD_ERROR_LINK, adapter=RequestsWebhookAdapter()) webhookFailure = Webhook.from_url(g.discord_error_link, adapter=RequestsWebhookAdapter())
if DISCORD_ENABLED_SUCCESS: if g.discord_enabled_success:
webhookSuccess = Webhook.from_url(DISCORD_SUCCESS_LINK, adapter=RequestsWebhookAdapter()) webhookSuccess = Webhook.from_url(g.discord_success_link, adapter=RequestsWebhookAdapter())
# base settings # base settings
FidelityLink = config["SETTINGS"]["FidelityLink"] g.fidelity_link = config["SETTINGS"]["FidelityLink"]
DISCORD_EMBED = config["SETTINGS"]["embeds"] == "True" #print new point value in an embed g.discord_embed = config["SETTINGS"]["embeds"] == "True" #print new point value in an embed
Headless = config["SETTINGS"]["headless"] == "True" g.headless = config["SETTINGS"]["headless"] == "True"
# proxy settings # proxy settings
proxy_enabled = config["PROXY"]["proxy_enabled"] == "True" g.proxy_enabled = config["PROXY"]["proxy_enabled"] == "True"
proxy_address = config["PROXY"]["url"] g.proxy_address = config["PROXY"]["url"]
proxy_port = config["PROXY"]["port"] g.proxy_port = config["PROXY"]["port"]
# MySQL settings # MySQL settings
sql_enabled = config["SQL"]["sql_enabled"] == "True" g.sql_enabled = config["SQL"]["sql_enabled"] == "True"
sql_usr = config["SQL"]["usr"] g.sql_usr = config["SQL"]["usr"]
sql_pwd = config["SQL"]["pwd"] g.sql_pwd = config["SQL"]["pwd"]
sql_host = config["SQL"]["host"] g.sql_host = config["SQL"]["host"]
sql_database = config["SQL"]["database"] g.sql_database = config["SQL"]["database"]
# Other settings
IPV6_CHECKED = config["OTHER"]["ipv6"]
g = open(MotPath, "r", encoding="utf-8") try :
lines = g.readlines() 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 : if len(lines) < 3 :
Liste_de_mot = list(lines[0].split(",")) Liste_de_mot = list(lines[0].split(","))
else : else :
Liste_de_mot = [x.replace('\n', "") for x in lines] 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) reader = reader(f)
Credentials = list(reader) Credentials = list(reader)
shuffle(Credentials) shuffle(Credentials)
g._cred = Credentials
if g.proxy_enabled :
setup_proxy(g.proxy_address,g.proxy_port)

View File

@ -1,22 +1,19 @@
from modules.imports import * from modules.imports import *
from modules.config import * from modules.config import *
from modules.tools import *
import modules.globals as g
def setup_proxy(ip, port, options, socks=False) : def setup_proxy(ip: str, port: str) -> None:
PROXY = f"{ip}:{port}" 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'] = { webdriver.DesiredCapabilities.FIREFOX['proxy'] = {
"httpProxy": PROXY, "httpProxy": PROXY,
"sslProxy": PROXY, "sslProxy": PROXY,
"proxyType": "MANUAL", "proxyType": "MANUAL",
} }
#Deal with rgpd popup as well as some random popup like 'are you satisfied' one
#Deal with RGPD popup as well as some random popup like 'are you satisfied' one
def rgpd_popup(driver) -> None: def rgpd_popup(driver) -> None:
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] : for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] :
try: try:
@ -24,13 +21,27 @@ def rgpd_popup(driver) -> None:
except: except:
pass pass
# save webdriver cookies # save webdriver cookies
def save_cookies(driver, _mail): def save_cookies(driver) -> None:
pickle.dump(driver.get_cookies(), open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{_mail}.pkl", "wb")) 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 # load cookies previously saved to the driver
def load_cookies(driver, _mail): def load_cookies(driver) -> None:
cookies = pickle.load(open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{_mail}.pkl", "rb")) 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: for cookie in cookies:
driver.add_cookie(cookie) driver.add_cookie(cookie)
@ -38,12 +49,9 @@ def load_cookies(driver, _mail):
send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random time between each press to simulate human action. send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random time between each press to simulate human action.
keys can be an string, but also selenium keys keys can be an string, but also selenium keys
""" """
def send_keys_wait(element, keys): def send_keys_wait(element, keys: str) -> None:
for i in keys: for i in keys:
element.send_keys(i) element.send_keys(i)
if FAST :
pass
else :
sleep(uniform(0.1, 0.3)) sleep(uniform(0.1, 0.3))
@ -52,6 +60,8 @@ def send_keys_wait(element, keys):
def wait_until_visible(search_by: str, identifier: str, timeout = 20, browser = None) -> None: def wait_until_visible(search_by: str, identifier: str, timeout = 20, browser = None) -> None:
try : try :
WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((search_by,identifier)), "element not found") WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((search_by,identifier)), "element not found")
return(True)
except TimeoutException as e: except TimeoutException as e:
print(f"element not found after {timeout}s") printf(f"element {identifier} not found after {timeout}s")
return(False)

View File

@ -3,3 +3,6 @@ class Banned(Exception):
class NotBanned(Exception): class NotBanned(Exception):
pass 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

View File

@ -1,24 +1,33 @@
import argparse
import asyncio import asyncio
import csv import configparser
from os import sys, system, path 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 random import choice, randint, shuffle, uniform
from re import findall, search from re import findall, search
from sys import platform from sys import platform
from time import sleep from time import sleep, time
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 selenium.common.exceptions import WebDriverException, TimeoutException, NoSuchElementException, ElementClickInterceptedException
from discord import Colour, Embed, File, RequestsWebhookAdapter, Webhook
from pyotp import TOTP from pyotp import TOTP
from pyvirtualdisplay import Display from pyvirtualdisplay import Display
from pyvirtualdisplay.smartdisplay import SmartDisplay from pyvirtualdisplay.smartdisplay import SmartDisplay
import pickle from requests import get
from datetime import timedelta, datetime from selenium import webdriver
from discord import Embed, Colour, File 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,18 +1,22 @@
from modules.imports import * from modules.imports import *
from modules.config import * from modules.config import *
from modules.db import *
import modules.globals as g
# add the time arround the text given in [text]& # add the time arround the text given in [text]&
def Timer(text: str, mail: str) -> str: def Timer(text: str) -> str:
return(f"[{mail} - {datetime.today().strftime('%d-%m-%Y')} - {timedelta(seconds = round(float(time() - START_TIME)))}] " + str(text)) 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 # replace the function print, with more options
# [txt] : string, [driver] : selenium webdriver # [txt] : string, [driver] : selenium webdriver
def printf2(txt, mail, LOG = LOG): def printf(txt):
print(Timer(txt, mail)) 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 # check if the user is using IPV4 using ipify.org
# [driver] : selenium webdriver # [driver] : selenium webdriver
@ -26,12 +30,9 @@ def check_ipv4(driver):
return False return False
def custom_sleep(temps): def custom_sleep(temps):
try : try :
if FAST and temps > 50: if g.log : #only print sleep when user see it
sleep(temps/10)
elif LOG: #only print sleep when user see it
points = ["", "", "", "", "", "", "", ""] points = ["", "", "", "", "", "", "", ""]
passe = 0 passe = 0
for i in range(int(temps)): for i in range(int(temps)):
@ -64,20 +65,18 @@ def progressBar(current, total=30, barLength=20, name="Progress"):
def save_points_from_file(file): def save_points_from_file(file):
with open(file) as f: with open(file) as f:
reader = csv.reader(f) read = reader(f)
points_list = list(reader) points_list = list(read)
for item in points_list: for item in points_list:
compte, points = item[0], item[1] compte, points = item[0], item[1]
add_to_database(compte, points, sql_host,sql_usr,sql_pwd,sql_database, save_if_fail=False) 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: with open(file, "w") as f:
f.write("") f.write("")
def select_accounts(multiple = True): def select_accounts(multiple = True):
system("clear") # clear from previous command to allow a clean choice system("clear") # clear from previous command to allow a clean choice
emails = [x[0] for x in Credentials] # list of all email adresses 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) emails_selected = enquiries.choose(f"quel{'s' if multiple else ''} compte{'s' if multiple else ''} ?", emails, multi=multiple)
return([x for x in Credentials if x[0] in emails_selected]) return([x for x in g._cred if x[0] in emails_selected])

View File

@ -9,3 +9,4 @@ pyvirtualdisplay
pillow pillow
EasyProcess EasyProcess
pyotp pyotp
packaging

View File

@ -5,7 +5,6 @@ logpath = /your/path/to/loginandpass.csv
[SETTINGS] [SETTINGS]
FidelityLink = Null
embeds = False embeds = False
Headless = True Headless = True
@ -32,4 +31,7 @@ pwd = password
[OTHER] [OTHER]
avatar = https://cdn.discordapp.com/icons/793934298977009674/d8055bccef6eca4855c349e808d0d788.webp
ipv6 = False ipv6 = False
database_override = False
fast = False

1
version Normal file
View File

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