├── .github ├── scripts │ ├── cat_logs.sh │ ├── common.py │ ├── eligible_accounts.py │ └── illegal_tries.py └── workflows │ └── display_logs.yml ├── .gitignore ├── LICENSE ├── README.md ├── clean_mem.sh ├── cron.tab ├── install.sh ├── logs ├── init ├── log_1 ├── log_10 ├── log_11 ├── log_12 ├── log_13 ├── log_14 ├── log_15 ├── log_16 ├── log_17 ├── log_18 ├── log_2 ├── log_3 ├── log_4 ├── log_5 ├── log_6 ├── log_7 ├── log_8 └── log_9 ├── ms_rewards.log ├── ms_rewards_farmer.py ├── requirements.txt ├── scripts └── upgrade_browser.sh ├── ss.sh └── upload_log.sh /.github/scripts/cat_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../.. && pwd)" 3 | 4 | for file in ${PROJECT_DIR}/logs/log* 5 | do 6 | echo $file 7 | cat $file 8 | done -------------------------------------------------------------------------------- /.github/scripts/common.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | LOG_PREFIX = "log_" 5 | 6 | LOG_TO_INSTANCE = { 7 | "1": "o-ubuntu", 8 | "2": "o-opc", 9 | "3": "msr001", 10 | "4": "us2", 11 | "5": "us3", 12 | "6": "us32", 13 | "7": "us4", 14 | "8": "us42", 15 | "9": "us43", 16 | "10": "us5", 17 | "11": "us41", 18 | "12": "us51", 19 | "13": "us52", 20 | "14": "us53", 21 | "15": "us6", 22 | "16": "us61", 23 | "17": "msr_free", 24 | "18": "salt.li_free" 25 | } 26 | 27 | MACHINE_TO_ACCOUNT = { 28 | #template 29 | "": { 30 | "edge":"", 31 | "chrome":"", 32 | "firefox":"", 33 | "yandex":"", 34 | "opera":"", 35 | "vivaldi":"", 36 | "comodo_icedragon":"", 37 | "slimbrowser":"", 38 | "maxthon":"", 39 | "waterfox":"", 40 | "brave":"", 41 | "seamonkey":"", 42 | "lunascape":"", 43 | "midori":"", 44 | "ur":"", 45 | "pale_moon":"", 46 | "srware_iron":"", 47 | "slimjet":"", 48 | "avg":"", 49 | "liebao":"", 50 | "cent":"", 51 | "theworld":"", 52 | }, 53 | "macP_win1022H2": { 54 | "edge":"lysdgrmr@outlook.com", 55 | "chrome":"ktlftboh@outlook.com", 56 | "firefox":"smcinqjj@outlook.com", 57 | "yandex":"bncpiwkk@outlook.com", 58 | "opera":"glggvmgc@outlook.com", 59 | "vivaldi":"gcxdrwqd@outlook.com", 60 | "comodo_icedragon":"qcumuyjj@outlook.com", 61 | "slimbrowser":"gimfumsk@outlook.com", 62 | "maxthon":"ookknadg@outlook.com", 63 | "waterfox":"pmceuitf@outlook.com", 64 | "brave":"tpsgjuvw@outlook.com", 65 | "seamonkey":"ynhudhwm@outlook.com", 66 | "lunascape":"ztbsqsft@outlook.com", 67 | "midori":"unfdhqgm@outlook.com", 68 | "ur":"vckoyirs@outlook.com", 69 | "pale_moon":"mlfyfjgw@outlook.com", 70 | "srware_iron":"tlwesqjg@outlook.com ", 71 | "slimjet":"oxutorhw@outlook.com", 72 | "avg":"dcpnzssa@outlook.com", 73 | "liebao":"ardjjelo@outlook.com", 74 | "cent":"elftxvvs@outlook.com", 75 | "theworld":"", 76 | }, 77 | "miHyper_win1022H2": { 78 | "edge":"", 79 | "chrome":"fvevijqg@outlook.com", 80 | "firefox":"", 81 | "yandex":"huqafhdp@outlook.com", 82 | "opera":"rjkiwmjl@outlook.com", 83 | "vivaldi":"ejvkbmpr@outlook.com", 84 | "comodo_icedragon":"wdkdqndc@outlook.com", 85 | "slimbrowser":"bnhrqspr@outlook.com", 86 | "maxthon":"coprnbbt@outlook.com", 87 | "waterfox":"qnxwkvcs@outlook.com", 88 | "brave":"joothsto@outlook.com", 89 | "seamonkey":"wgdzzlnm@outlook.com", 90 | "lunascape":"dicxdycq@outlook.com", 91 | "midori":"pjysssqw@outlook.com", 92 | "ur":"vqkufecw@outlook.com", 93 | "pale_moon":"", 94 | "srware_iron":"", 95 | "slimjet":"spxbtglt@outlook.com", 96 | "avg":"lfsqfgnp@outlook.com", 97 | "liebao":"", 98 | "cent":"nipexfsj@outlook.com", 99 | "theworld":"nhywkmfn@outlook.com", 100 | }, 101 | "miHyper_win7": { 102 | "edge":"fcbsqnjg@outlook.com", 103 | "chrome":"cthinvmh@outlook.com", 104 | "firefox":"", 105 | "yandex":"jboqcenv@outlook.com", 106 | "opera":"fxfyxblj@outlook.com", 107 | "vivaldi":"wcpxwrcn@outlook.com", 108 | "comodo_icedragon":"wigpbsoy@outlook.com", 109 | "slimbrowser":"rvyujeks@outlook.com", 110 | "maxthon":"iebtfdkf@outlook.com", 111 | "waterfox":"emqovroe@outlook.com", 112 | "brave":"iejvease@outlook.com", 113 | "seamonkey":"", 114 | "lunascape":"", 115 | "midori":"", 116 | "ur":"", 117 | "pale_moon":"", 118 | "srware_iron":"", 119 | "slimjet":"", 120 | "avg":"", 121 | "liebao":"", 122 | "cent":"", 123 | "theworld":"", 124 | }, 125 | "mac_origin": { 126 | "chrome":"ymizpwly@outlook.com", 127 | "chrome2":"wotfvcat@outlook.com", 128 | "safari":"jmbltatj@outlook.com", 129 | "brave":"", 130 | }, 131 | } 132 | 133 | MACHINE_PRIORITY = { 134 | "macP_win1022H2": 1, 135 | "miHyper_win1022H2": 2, 136 | "miHyper_win7":3, 137 | "mac_origin": 4, 138 | } 139 | 140 | ACCOUNT_TO_MACHINE = {} 141 | 142 | def init_account_to_machine_for_once(): 143 | if len(ACCOUNT_TO_MACHINE) != 0: 144 | return 145 | for machine, browser_to_account in MACHINE_TO_ACCOUNT.items(): 146 | if len(machine) == 0: 147 | continue 148 | for browser, account in browser_to_account.items(): 149 | ACCOUNT_TO_MACHINE[account] = { 150 | "browser": browser, 151 | "machine": machine, 152 | } 153 | 154 | 155 | 156 | ACCOUNT_REGION = { 157 | } 158 | 159 | class LogFile: 160 | def __init__(self, name, content): 161 | self.file_name = name 162 | self.json_obj = content 163 | 164 | def get_log_location(file_name): 165 | start = len(LOG_PREFIX) 166 | file_index = file_name[start:] 167 | if file_index in LOG_TO_INSTANCE: 168 | return f'instance: {LOG_TO_INSTANCE[file_index]}' 169 | return f'log: {file_name}' 170 | 171 | def get_account_region(account): 172 | if account in ACCOUNT_REGION: 173 | return ACCOUNT_REGION[account] 174 | return "us" 175 | 176 | def get_account_machine(account): 177 | init_account_to_machine_for_once() 178 | if account not in ACCOUNT_TO_MACHINE: 179 | return "" 180 | account_info = ACCOUNT_TO_MACHINE[account] 181 | return f'[{account_info["machine"]}][{account_info["browser"]}]' 182 | 183 | def get_account_priority(account): 184 | init_account_to_machine_for_once() 185 | if account not in ACCOUNT_TO_MACHINE: 186 | return 0 187 | machine = ACCOUNT_TO_MACHINE[account]["machine"] 188 | if len(machine) == 0: 189 | print("[ERROR]", "account:", account, "has invalid 'machine' field configured in ACCOUNT_TO_MACHINE") 190 | return 0 191 | 192 | if machine not in MACHINE_PRIORITY: 193 | print("[ERROR]", "machine:", machine, "is not configured in MACHINE_PRIORITY") 194 | return 0 195 | return MACHINE_PRIORITY[machine] 196 | 197 | def read_logs_to(func): 198 | ''' 199 | call the internal func with LogFile 200 | ''' 201 | log_dir = os.path.abspath(os.path.join(os.path.abspath(__file__), "../../../logs")) 202 | files= os.listdir(log_dir) 203 | for file in files: 204 | if os.path.isdir(file) or not file.startswith(LOG_PREFIX): 205 | continue 206 | with open(log_dir+"/"+file) as input: 207 | json_obj = json.load(input) 208 | func(LogFile(file, json_obj)) -------------------------------------------------------------------------------- /.github/scripts/eligible_accounts.py: -------------------------------------------------------------------------------- 1 | from common import read_logs_to, get_log_location, get_account_region, get_account_priority, get_account_machine 2 | 3 | REGION_POINT_BAR = { 4 | "sg": 9100, 5 | "us": 13000, 6 | } 7 | 8 | priority_print = {} 9 | 10 | def append_ele_to_dict_of_list(map, key, value): 11 | to_set_list = [] 12 | if key in map: 13 | to_set_list = map[key] 14 | to_set_list.append(value) 15 | map[key] = to_set_list 16 | 17 | 18 | def get_eligible_accounts(obj): 19 | ''' 20 | :input: LogFile 21 | ''' 22 | filename = obj.file_name 23 | json_obj = obj.json_obj 24 | location = get_log_location(filename) 25 | for key, val in json_obj.items(): 26 | region = get_account_region(key) 27 | if isinstance(val["Points"], int) and val["Points"] > REGION_POINT_BAR[region]: 28 | priority = get_account_priority(key) 29 | # Region logic isn't used for now 30 | if priority == 0: 31 | append_ele_to_dict_of_list(priority_print, priority, 32 | f'[need verify] account: {key} -> points:{val["Points"]} from {location}|{region}') 33 | continue 34 | machine = get_account_machine(key) 35 | append_ele_to_dict_of_list(priority_print, priority, 36 | f'{machine} account: {key} -> points:{val["Points"]} from {location}| {region}') 37 | 38 | def print_logs_in_priority(): 39 | for priority in sorted(priority_print.keys()): 40 | logs = priority_print[priority] 41 | for log in logs: 42 | print(log) 43 | 44 | read_logs_to(get_eligible_accounts) 45 | print_logs_in_priority() 46 | -------------------------------------------------------------------------------- /.github/scripts/illegal_tries.py: -------------------------------------------------------------------------------- 1 | from common import read_logs_to, get_log_location 2 | from datetime import date, timedelta 3 | 4 | def get_illegal_tries(obj): 5 | ''' 6 | :input: LogFile 7 | ''' 8 | filename = obj.file_name 9 | json_obj = obj.json_obj 10 | today = str((date.today())) 11 | yesterday = str((date.today() - timedelta(days = 1))) 12 | location = get_log_location(filename) 13 | for key, val in json_obj.items(): 14 | check_situation = val["Last check"] 15 | if len(check_situation) != 10 or check_situation[0] != "2": 16 | print(f'abnormal operation: account: {key} -> check:{check_situation} of {filename} in {location}') 17 | continue 18 | if check_situation != yesterday and check_situation != today: 19 | print(f'outdated log: account: {key} -> last time updated:{check_situation} of {filename} in {location}') 20 | continue 21 | 22 | read_logs_to(get_illegal_tries) -------------------------------------------------------------------------------- /.github/workflows/display_logs.yml: -------------------------------------------------------------------------------- 1 | name: Display all the logs 2 | on: [push] 3 | jobs: 4 | Display-All-The-Logs: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Check out repository code 8 | uses: actions/checkout@v3 9 | - uses: actions/setup-python@v4 10 | with: 11 | python-version: '3.7' 12 | - name: Display all the logs 13 | run: | 14 | cd ${{ github.workspace }} 15 | bash .github/scripts/cat_logs.sh 16 | - name: Display illegal tries 17 | run: | 18 | cd ${{ github.workspace }} 19 | python3 .github/scripts/illegal_tries.py 20 | - name: Display eligible accounts 21 | run: | 22 | cd ${{ github.workspace }} 23 | python3 .github/scripts/eligible_accounts.py 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | *.txt 3 | .vscode 4 | chromedriver.exe 5 | env 6 | *.deb 7 | __pycache__ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Farshad Zargari 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 | 8 |
 9 | ███╗   ███╗███████╗    ███████╗ █████╗ ██████╗ ███╗   ███╗███████╗██████╗ 
10 | ████╗ ████║██╔════╝    ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝██╔══██╗
11 | ██╔████╔██║███████╗    █████╗  ███████║██████╔╝██╔████╔██║█████╗  ██████╔╝
12 | ██║╚██╔╝██║╚════██║    ██╔══╝  ██╔══██║██╔══██╗██║╚██╔╝██║██╔══╝  ██╔══██╗
13 | ██║ ╚═╝ ██║███████║    ██║     ██║  ██║██║  ██║██║ ╚═╝ ██║███████╗██║  ██║
14 | ╚═╝     ╚═╝╚══════╝    ╚═╝     ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝
15 |         built by @charlesbel upgraded by @farshadz1997      version 2.0
16 | 
17 | 18 |

19 | 20 | 21 |

22 | 23 |

👋 Welcome to the future of automation

24 |

A simple bot that uses selenium to farm Microsoft Rewards written in Python.

25 | 26 |

Installation

27 |

You can also find this repository on Gitlab.

28 |

29 |

69 |

70 | 71 |

Features

72 |

73 |

91 |

92 |

⚠️CAUTION!⚠️

93 |

94 |

Do not use headless mode, it can cause your account to be suspended from Microsoft Rewards.

95 | -------------------------------------------------------------------------------- /clean_mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pkill -9 python 3 | pkill -9 Xvfb 4 | pkill -9 chrome -------------------------------------------------------------------------------- /cron.tab: -------------------------------------------------------------------------------- 1 | 10 8 * * * /usr/bin/sh /home/saltleemsr/src/Microsoft-Rewards-bot/clean_mem.sh 2 | 11 8 * * * /usr/bin/python3 /home/saltleemsr/src/Microsoft-Rewards-bot/ms_rewards_farmer.py >> /home/saltleemsr/src/Microsoft-Rewards-bot/cron.log 3 | 0 1 * * * bash /home/saltleemsr/src/Microsoft-Rewards-bot/upload_log.sh 0 4 | 5 | sudo apt-get --only-upgrade install google-chrome-stable -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo apt-get update -y 3 | sudo apt-get install -y xvfb 4 | wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 5 | sudo apt install -y ./google-chrome-stable_current_amd64.deb 6 | sudo apt install -y chromium-chromedriver 7 | sudo apt-get -y install python3-pip 8 | sudo pip3 install -r requirements.txt 9 | # incompatible lib fix 10 | sudo pip3 uninstall --yes chardet 11 | sudo pip3 uninstall --yes urllib3 12 | sudo pip3 install --upgrade requests --no-input 13 | # sys log storage up-limit 14 | sudo journalctl --vacuum-size=100M 15 | sudo touch accounts.json -------------------------------------------------------------------------------- /logs/init: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macrosalt/Microsoft-Rewards-bot/bf851e5761f583fff48a1bef481638ae57df6c8f/logs/init -------------------------------------------------------------------------------- /logs/log_1: -------------------------------------------------------------------------------- 1 | { 2 | "gimfumsk@outlook.com": { 3 | "Last check": "Unknown error: Microsoft account notice !", 4 | "Today's points": 320, 5 | "Points": 25715, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "ookknadg@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account notice !", 13 | "Today's points": 340, 14 | "Points": 12381, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "wotfvcat@outlook.com": { 21 | "Last check": "Unknown error: Microsoft account notice !", 22 | "Today's points": 275, 23 | "Points": 15066, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "bocpsbvb@outlook.com": { 30 | "Last check": "2024-07-23", 31 | "Today's points": 330, 32 | "Points": 8718, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_10: -------------------------------------------------------------------------------- 1 | { 2 | "joothsto@outlook.com": { 3 | "Last check": "Your account has been locked !", 4 | "Today's points": 5976, 5 | "Points": 30202 6 | }, 7 | "nipexfsj@outlook.com": { 8 | "Last check": "Unknown error: Sign in to your Microsoft account !", 9 | "Today's points": 335, 10 | "Points": 19383, 11 | "Daily": false, 12 | "Punch cards": false, 13 | "More promotions": false, 14 | "PC searches": false 15 | }, 16 | "jboqcenv@outlook.com": { 17 | "Last check": "Unknown error: Sign in to your Microsoft account !", 18 | "Today's points": 365, 19 | "Points": 8867 20 | }, 21 | "rvyujeks@outlook.com": { 22 | "Last check": "Unknown error: Sign in to your Microsoft account !", 23 | "Today's points": 19260, 24 | "Points": 28127 25 | } 26 | } -------------------------------------------------------------------------------- /logs/log_11: -------------------------------------------------------------------------------- 1 | { 2 | "ymizpwly@outlook.com": { 3 | "Last check": "Unknown error: Microsoft account privacy notice !", 4 | "Today's points": 33363, 5 | "Points": 33363 6 | }, 7 | "qnxwkvcs@outlook.com": { 8 | "Last check": "Unknown error: Microsoft account privacy notice !", 9 | "Today's points": 305, 10 | "Points": 31803 11 | }, 12 | "rmslyruy@outlook.com": { 13 | "Last check": "Unknown error: Microsoft account privacy notice !", 14 | "Today's points": 350, 15 | "Points": 35107, 16 | "Daily": false, 17 | "Punch cards": false, 18 | "More promotions": false, 19 | "PC searches": false 20 | }, 21 | "lejhdeey@outlook.com": { 22 | "Last check": "Unknown error: Microsoft account privacy notice !", 23 | "Today's points": 355, 24 | "Points": 20664 25 | } 26 | } -------------------------------------------------------------------------------- /logs/log_12: -------------------------------------------------------------------------------- 1 | { 2 | "tlwesqjg@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 375, 5 | "Points": 51783, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "dicxdycq@outlook.com": { 12 | "Last check": "Your account has been locked !", 13 | "Today's points": -14720, 14 | "Points": 13362, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "cthinvmh@outlook.com": { 21 | "Last check": "Unknown error: Microsoft account privacy notice !", 22 | "Today's points": -19795, 23 | "Points": 31613, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "vhldgkyv@outlook.com": { 30 | "Last check": "2023-05-30", 31 | "Today's points": -16300, 32 | "Points": 35483, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_13: -------------------------------------------------------------------------------- 1 | { 2 | "wgdzzlnm@outlook.com": { 3 | "Last check": "Unknown error: Microsoft account privacy notice !", 4 | "Today's points": 16708, 5 | "Points": 16708 6 | }, 7 | "mthoklgd@outlook.com": { 8 | "Last check": "Unknown error: Microsoft account privacy notice !", 9 | "Today's points": 25334, 10 | "Points": 47563, 11 | "Daily": false, 12 | "Punch cards": false, 13 | "More promotions": false, 14 | "PC searches": false 15 | }, 16 | "cloaveoc@outlook.com": { 17 | "Last check": "Unknown error: Microsoft account privacy notice !", 18 | "Today's points": 23199, 19 | "Points": 23199 20 | }, 21 | "pzkxscig@outlook.com": { 22 | "Last check": "Your account has been suspended", 23 | "Today's points": "N/A", 24 | "Points": "N/A" 25 | } 26 | } -------------------------------------------------------------------------------- /logs/log_14: -------------------------------------------------------------------------------- 1 | { 2 | "fvevijqg@outlook.com": { 3 | "Last check": "2023-05-30", 4 | "Today's points": -24707, 5 | "Points": 14313, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "nhywkmfn@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account privacy notice !", 13 | "Today's points": 395, 14 | "Points": 14378, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "bnhrqspr@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": 330, 23 | "Points": 40843, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "jbfqipsb@outlook.com": { 30 | "Last check": "2023-06-13", 31 | "Today's points": 385, 32 | "Points": 39020, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_15: -------------------------------------------------------------------------------- 1 | { 2 | "dcpnzssa@outlook.com": { 3 | "Last check": "2023-05-30", 4 | "Today's points": -12989, 5 | "Points": 18420, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "ardjjelo@outlook.com": { 12 | "Last check": "2023-05-30", 13 | "Today's points": 390, 14 | "Points": 20520, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "chlsnyec@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": 330, 23 | "Points": 31409, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "titicbpv@outlook.com": { 30 | "Last check": "2023-06-13", 31 | "Today's points": 315, 32 | "Points": 8713, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_16: -------------------------------------------------------------------------------- 1 | { 2 | "coprnbbt@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 330, 5 | "Points": 27468, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "vckoyirs@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account privacy notice !", 13 | "Today's points": 860, 14 | "Points": 27723, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "smcinqjj@outlook.com": { 21 | "Last check": "Your account has been suspended", 22 | "Today's points": "N/A", 23 | "Points": "N/A" 24 | }, 25 | "bncpiwkk@outlook.com": { 26 | "Last check": "Unknown error: Microsoft account privacy notice !", 27 | "Today's points": 375, 28 | "Points": 27048, 29 | "Daily": false, 30 | "Punch cards": false, 31 | "More promotions": false, 32 | "PC searches": false 33 | } 34 | } -------------------------------------------------------------------------------- /logs/log_17: -------------------------------------------------------------------------------- 1 | { 2 | "jmbltatj@outlook.com": { 3 | "Last check": "2025-03-05", 4 | "Today's points": 24370, 5 | "Points": 24370, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "pmceuitf@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account notice !", 13 | "Today's points": -4860, 14 | "Points": 18825, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "ztbsqsft@outlook.com": { 21 | "Last check": "Unknown error: Microsoft account notice !", 22 | "Today's points": 12320, 23 | "Points": 31145, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "hotlhswh@outlook.com": { 30 | "Last check": "Unknown error: Microsoft account notice !", 31 | "Today's points": 510, 32 | "Points": 25187, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_18: -------------------------------------------------------------------------------- 1 | { 2 | "emqovroe@outlook.com": { 3 | "Last check": "2023-07-07", 4 | "Today's points": 330, 5 | "Points": 38887, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "iejvease@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account privacy notice !", 13 | "Today's points": 375, 14 | "Points": 36742, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "nyuhrcrx@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": 335, 23 | "Points": 65072, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "cjubtkgo@outlook.com": { 30 | "Last check": "2023-05-30", 31 | "Today's points": 385, 32 | "Points": 56557, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_2: -------------------------------------------------------------------------------- 1 | { 2 | "spxbtglt@outlook.com": { 3 | "Last check": "Unknown error: Microsoft account notice !", 4 | "Today's points": 365, 5 | "Points": 36898, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "elftxvvs@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account notice !", 13 | "Today's points": 410, 14 | "Points": 15238, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "wigpbsoy@outlook.com": { 21 | "Last check": "2025-06-08", 22 | "Today's points": 450, 23 | "Points": 10677, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "yisjuold@outlook.com": { 30 | "Last check": "Unknown error: Microsoft account notice !", 31 | "Today's points": 345, 32 | "Points": 11258, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_3: -------------------------------------------------------------------------------- 1 | { 2 | "gcxdrwqd@outlook.com": { 3 | "Last check": "Unknown error: Sign in to your Microsoft account !", 4 | "Today's points": 330, 5 | "Points": 21995 6 | }, 7 | "qcumuyjj@outlook.com": { 8 | "Last check": "Unknown error: Microsoft account privacy notice !", 9 | "Today's points": 416, 10 | "Points": 20545 11 | }, 12 | "wcpxwrcn@outlook.com": { 13 | "Last check": "Unknown error: Microsoft account privacy notice !", 14 | "Today's points": 280, 15 | "Points": 14092 16 | }, 17 | "iebtfdkf@outlook.com": { 18 | "Last check": "Unknown error: Microsoft account privacy notice !", 19 | "Today's points": 270, 20 | "Points": 14149, 21 | "Daily": false, 22 | "Punch cards": false, 23 | "More promotions": false, 24 | "PC searches": false 25 | } 26 | } -------------------------------------------------------------------------------- /logs/log_4: -------------------------------------------------------------------------------- 1 | { 2 | "ktlftboh@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 380, 5 | "Points": 16503, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "oxutorhw@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account privacy notice !", 13 | "Today's points": 13080, 14 | "Points": 29583, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "unfdhqgm@outlook.com": { 21 | "Last check": "Unknown error: Microsoft account privacy notice !", 22 | "Today's points": -18840, 23 | "Points": 10368, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "wgmulkec@outlook.com": { 30 | "Last check": "Your account has been suspended", 31 | "Today's points": "N/A", 32 | "Points": "N/A" 33 | } 34 | } -------------------------------------------------------------------------------- /logs/log_5: -------------------------------------------------------------------------------- 1 | { 2 | "wdkdqndc@outlook.com": { 3 | "Last check": "2023-06-01", 4 | "Today's points": 375, 5 | "Points": 19868, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "ynhudhwm@outlook.com": { 12 | "Last check": "2023-05-30", 13 | "Today's points": 370, 14 | "Points": 32843, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "huqafhdp@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": -14275, 23 | "Points": 18568, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "vmtgmjti@outlook.com": { 30 | "Last check": "Your account has been suspended", 31 | "Today's points": "N/A", 32 | "Points": "N/A" 33 | } 34 | } -------------------------------------------------------------------------------- /logs/log_6: -------------------------------------------------------------------------------- 1 | { 2 | "rjkiwmjl@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 415, 5 | "Points": 18823, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "fcbsqnjg@outlook.com": { 12 | "Last check": "2023-05-30", 13 | "Today's points": 20924, 14 | "Points": 39747, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "fxfyxblj@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": 13110, 23 | "Points": 52857, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "ygbxznxy@outlook.com": { 30 | "Last check": "Unknown error: Microsoft account privacy notice !", 31 | "Today's points": -4062, 32 | "Points": 48005, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /logs/log_7: -------------------------------------------------------------------------------- 1 | { 2 | "ejvkbmpr@outlook.com": { 3 | "Last check": "Unknown error: Microsoft account privacy notice !", 4 | "Today's points": 385, 5 | "Points": 7850, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "lfsqfgnp@outlook.com": { 12 | "Last check": "2023-05-30", 13 | "Today's points": 415, 14 | "Points": 36690, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "vuorgvuj@outlook.com": { 21 | "Last check": "2023-06-13", 22 | "Today's points": 355, 23 | "Points": 37019, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "rxqinlhb@outlook.com": { 30 | "Last check": "Your account has been suspended", 31 | "Today's points": "N/A", 32 | "Points": "N/A" 33 | } 34 | } -------------------------------------------------------------------------------- /logs/log_8: -------------------------------------------------------------------------------- 1 | { 2 | "pjysssqw@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 380, 5 | "Points": 29588, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "wfaobymr@outlook.com": { 12 | "Last check": "2023-05-30", 13 | "Today's points": 54810, 14 | "Points": 54810, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "csdmuvrk@outlook.com": { 21 | "Last check": "2023-05-30", 22 | "Today's points": -1875, 23 | "Points": 52935, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "jsgxncdc@outlook.com": { 30 | "Last check": "Your account has been suspended", 31 | "Today's points": "N/A", 32 | "Points": "N/A" 33 | } 34 | } -------------------------------------------------------------------------------- /logs/log_9: -------------------------------------------------------------------------------- 1 | { 2 | "tpsgjuvw@outlook.com": { 3 | "Last check": "2023-06-13", 4 | "Today's points": 415, 5 | "Points": 31858, 6 | "Daily": false, 7 | "Punch cards": false, 8 | "More promotions": false, 9 | "PC searches": false 10 | }, 11 | "mlfyfjgw@outlook.com": { 12 | "Last check": "Unknown error: Microsoft account privacy notice !", 13 | "Today's points": 355, 14 | "Points": 25078, 15 | "Daily": false, 16 | "Punch cards": false, 17 | "More promotions": false, 18 | "PC searches": false 19 | }, 20 | "qnxfhcwo@outlook.com": { 21 | "Last check": "2023-05-31", 22 | "Today's points": 330, 23 | "Points": 40758, 24 | "Daily": false, 25 | "Punch cards": false, 26 | "More promotions": false, 27 | "PC searches": false 28 | }, 29 | "okihqbow@outlook.com": { 30 | "Last check": "2023-05-30", 31 | "Today's points": 24317, 32 | "Points": 56175, 33 | "Daily": false, 34 | "Punch cards": false, 35 | "More promotions": false, 36 | "PC searches": false 37 | } 38 | } -------------------------------------------------------------------------------- /ms_rewards.log: -------------------------------------------------------------------------------- 1 | nohup: ignoring input 2 | sh: 1: color: not found 3 | -------------------------------------------------------------------------------- /ms_rewards_farmer.py: -------------------------------------------------------------------------------- 1 | import time 2 | import json 3 | from datetime import date, timedelta, datetime 4 | import requests 5 | import random 6 | import urllib.parse 7 | import ipapi 8 | import os 9 | from random_word import RandomWords 10 | from func_timeout import func_set_timeout, FunctionTimedOut 11 | import subprocess 12 | import platform 13 | from argparse import ArgumentParser 14 | import sys 15 | 16 | from pyvirtualdisplay import Display 17 | from selenium import webdriver 18 | from selenium.webdriver.chrome.webdriver import WebDriver 19 | from selenium.webdriver.support.ui import WebDriverWait 20 | from selenium.webdriver.support import expected_conditions as ec 21 | from selenium.webdriver.common.by import By 22 | from selenium.common.exceptions import (NoSuchElementException, TimeoutException, ElementNotInteractableException, 23 | UnexpectedAlertPresentException, NoAlertPresentException, SessionNotCreatedException) 24 | 25 | # Define user-agents 26 | PC_USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36 Edg/105.0.1343.33' 27 | MOBILE_USER_AGENT = 'Mozilla/5.0 (Linux; Android 12; SM-N9750) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Mobile Safari/537.36' 28 | 29 | POINTS_COUNTER = 0 30 | 31 | # Global variables 32 | FINISHED_ACCOUNTS = [] # added accounts when finished or those have same date as today date in LOGS at beginning. 33 | ERROR = True # A flag for when error occurred. 34 | MOBILE = True # A flag for when the account has mobile bing search, it is useful for accounts level 1 to pass mobile. 35 | CURRENT_ACCOUNT = None # save current account into this variable when farming. 36 | LOGS = {} # Dictionary of accounts to write in 'logs_accounts.txt'. 37 | FAST = False # When this variable set True then all possible delays reduced. 38 | 39 | # Define browser setup function 40 | def browserSetup(isMobile: bool, user_agent: str = PC_USER_AGENT) -> WebDriver: 41 | # Create Chrome browser 42 | from selenium.webdriver.chrome.options import Options 43 | options = Options() 44 | if ARGS.session: 45 | if not isMobile: 46 | options.add_argument(rf'--user-data-dir={os.path.join(os.getcwd()+"/Profiles/" + CURRENT_ACCOUNT, "PC")}') 47 | else: 48 | options.add_argument(rf'--user-data-dir={os.path.join(os.getcwd()+"/Profiles/" + CURRENT_ACCOUNT, "Mobile")}') 49 | options.add_argument("user-agent=" + user_agent) 50 | options.add_argument('lang=' + LANG.split("-")[0]) 51 | options.add_argument('--disable-blink-features=AutomationControlled') 52 | prefs = {"profile.default_content_setting_values.geolocation" :2, 53 | "credentials_enable_service": False, 54 | "profile.password_manager_enabled": False, 55 | "webrtc.ip_handling_policy": "disable_non_proxied_udp", 56 | "webrtc.multiple_routes_enabled": False, 57 | "webrtc.nonproxied_udp_enabled" : False} 58 | options.add_experimental_option("prefs",prefs) 59 | options.add_experimental_option("useAutomationExtension", False) 60 | options.add_experimental_option("excludeSwitches", ["enable-automation"]) 61 | if ARGS.headless: 62 | options.add_argument("--headless") 63 | options.add_argument('log-level=3') 64 | options.add_argument("--start-maximized") 65 | if platform.system() == 'Linux': 66 | options.add_argument("--no-sandbox") 67 | options.add_argument("--disable-dev-shm-usage") 68 | chrome_browser_obj = webdriver.Chrome(options=options) 69 | return chrome_browser_obj 70 | 71 | # Define login function 72 | def login(browser: WebDriver, email: str, pwd: str, isMobile: bool = False): 73 | # Close welcome tab for new sessions 74 | if ARGS.session: 75 | time.sleep(2) 76 | if len(browser.window_handles) > 1: 77 | current_window = browser.current_window_handle 78 | for handler in browser.window_handles: 79 | if handler != current_window: 80 | browser.switch_to.window(handler) 81 | time.sleep(0.5) 82 | browser.close() 83 | browser.switch_to.window(current_window) 84 | # Access to bing.com 85 | browser.get('https://login.live.com/') 86 | # Check if account is already logged in 87 | if ARGS.session: 88 | if browser.title == "We're updating our terms" or isElementExists(browser, By.ID, 'iAccrualForm'): 89 | time.sleep(2) 90 | browser.find_element(By.ID, 'iNext').click() 91 | time.sleep(5) 92 | if browser.title == 'Microsoft account | Home' or isElementExists(browser, By.ID, 'navs_container'): 93 | prGreen('[LOGIN] Account already logged in !') 94 | RewardsLogin(browser) 95 | print('[LOGIN]', 'Ensuring login on Bing...') 96 | checkBingLogin(browser, isMobile) 97 | return 98 | elif browser.title == 'Your account has been temporarily suspended': 99 | LOGS[CURRENT_ACCOUNT]['Last check'] = 'Your account has been locked !' 100 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 101 | updateLogs() 102 | cleanLogs() 103 | raise Exception(prRed('[ERROR] Your account has been locked !')) 104 | # Wait complete loading 105 | waitUntilVisible(browser, By.ID, 'loginHeader', 10) 106 | # Enter email 107 | print('[LOGIN]', 'Writing email...') 108 | browser.find_element(By.NAME, "loginfmt").send_keys(email) 109 | # Click next 110 | browser.find_element(By.ID, 'idSIButton9').click() 111 | # Wait 2 seconds 112 | time.sleep(5 if not FAST else 2) 113 | # Wait complete loading 114 | waitUntilVisible(browser, By.ID, 'loginHeader', 10) 115 | # Enter password 116 | browser.find_element(By.ID, "i0118").send_keys(pwd) 117 | # browser.execute_script("document.getElementById('i0118').value = '" + pwd + "';") 118 | print('[LOGIN]', 'Writing password...') 119 | # Click next 120 | browser.find_element(By.ID, 'idSIButton9').click() 121 | # Wait 5 seconds 122 | time.sleep(5) 123 | try: 124 | if browser.title == "We're updating our terms" or isElementExists(browser, By.ID, 'iAccrualForm'): 125 | time.sleep(2) 126 | browser.find_element(By.ID, 'iNext').click() 127 | time.sleep(5) 128 | if ARGS.session: 129 | # Click Yes to stay signed in. 130 | browser.find_element(By.ID, 'idSIButton9').click() 131 | else: 132 | # Click No. 133 | browser.find_element(By.ID, 'idBtn_Back').click() 134 | except NoSuchElementException: 135 | # Check for if account has been locked. 136 | if browser.title == "Your account has been temporarily suspended" or isElementExists(browser, By.CLASS_NAME, "serviceAbusePageContainer PageContainer"): 137 | LOGS[CURRENT_ACCOUNT]['Last check'] = 'Your account has been locked !' 138 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 139 | updateLogs() 140 | cleanLogs() 141 | raise Exception(prRed('[ERROR] Your account has been locked !')) 142 | elif browser.title == "Help us protect your account": 143 | prRed('[ERROR] Unusual activity detected !') 144 | LOGS[CURRENT_ACCOUNT]['Last check'] = 'Unusual activity detected !' 145 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 146 | updateLogs() 147 | cleanLogs() 148 | input('Press any key to close...') 149 | os._exit(0) 150 | else: 151 | unknown_err_msg = f'Unknown error: {browser.title} !' 152 | LOGS[CURRENT_ACCOUNT]['Last check'] = unknown_err_msg 153 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 154 | updateLogs() 155 | cleanLogs() 156 | raise Exception(prRed(unknown_err_msg)) 157 | # Wait 5 seconds 158 | time.sleep(5) 159 | # Click Security Check 160 | print('[LOGIN]', 'Passing security checks...') 161 | try: 162 | browser.find_element(By.ID, 'iLandingViewAction').click() 163 | except (NoSuchElementException, ElementNotInteractableException) as e: 164 | pass 165 | # Wait complete loading 166 | try: 167 | waitUntilVisible(browser, By.ID, 'KmsiCheckboxField', 10) 168 | except (TimeoutException) as e: 169 | pass 170 | # Click next 171 | try: 172 | browser.find_element(By.ID, 'idSIButton9').click() 173 | # Wait 5 seconds 174 | time.sleep(5) 175 | except (NoSuchElementException, ElementNotInteractableException) as e: 176 | pass 177 | print('[LOGIN]', 'Logged-in !') 178 | # Check Microsoft Rewards 179 | print('[LOGIN] Logging into Microsoft Rewards...') 180 | RewardsLogin(browser) 181 | # Check Login 182 | print('[LOGIN]', 'Ensuring login on Bing...') 183 | checkBingLogin(browser, isMobile) 184 | 185 | def RewardsLogin(browser: WebDriver): 186 | #Login into Rewards 187 | browser.get('https://rewards.microsoft.com/dashboard') 188 | try: 189 | time.sleep(10 if not FAST else 5) 190 | browser.find_element(By.ID, 'raf-signin-link-id').click() 191 | except: 192 | pass 193 | time.sleep(10 if not FAST else 5) 194 | # Check for ErrorMessage 195 | try: 196 | browser.find_element(By.ID, 'error').is_displayed() 197 | # Check wheter account suspended or not 198 | if browser.find_element(By.XPATH, '//*[@id="error"]/h1').get_attribute('innerHTML') == ' Uh oh, it appears your Microsoft Rewards account has been suspended.': 199 | LOGS[CURRENT_ACCOUNT]['Last check'] = 'Your account has been suspended' 200 | LOGS[CURRENT_ACCOUNT]["Today's points"] = 'N/A' 201 | LOGS[CURRENT_ACCOUNT]["Points"] = 'N/A' 202 | cleanLogs() 203 | updateLogs() 204 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 205 | raise Exception(prRed('[ERROR] Your Microsoft Rewards account has been suspended !')) 206 | # Check whether Rewards is available in your region or not 207 | elif browser.find_element(By.XPATH, '//*[@id="error"]/h1').get_attribute('innerHTML') == 'Microsoft Rewards is not available in this country or region.': 208 | prRed('[ERROR] Microsoft Rewards is not available in this country or region !') 209 | input('[ERROR] Press any key to close...') 210 | os._exit() 211 | except NoSuchElementException: 212 | pass 213 | 214 | @func_set_timeout(300) 215 | def checkBingLogin(browser: WebDriver, isMobile: bool = False): 216 | global POINTS_COUNTER 217 | #Access Bing.com 218 | browser.get('https://bing.com/') 219 | # Wait 15 seconds 220 | time.sleep(15 if not FAST else 5) 221 | # try to get points at first if account already logged in 222 | if ARGS.session: 223 | try: 224 | if not isMobile: 225 | POINTS_COUNTER = int(browser.find_element(By.ID, 'id_rc').get_attribute('innerHTML')) 226 | else: 227 | browser.find_element(By.ID, 'mHamburger').click() 228 | time.sleep(1) 229 | POINTS_COUNTER = int(browser.find_element(By.ID, 'fly_id_rc').get_attribute('innerHTML')) 230 | except: 231 | pass 232 | else: 233 | return None 234 | #Accept Cookies 235 | try: 236 | browser.find_element(By.ID, 'bnp_btn_accept').click() 237 | except: 238 | pass 239 | if isMobile: 240 | try: 241 | time.sleep(1) 242 | browser.find_element(By.ID, 'mHamburger').click() 243 | except: 244 | try: 245 | browser.find_element(By.ID, 'bnp_btn_accept').click() 246 | except: 247 | pass 248 | time.sleep(1) 249 | if isElementExists(browser, By.XPATH, '//*[@id="bnp_ttc_div"]/div[1]/div[2]/span'): 250 | browser.execute_script("""var element = document.evaluate('/html/body/div[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; 251 | element.remove();""") 252 | time.sleep(5) 253 | time.sleep(1) 254 | try: 255 | browser.find_element(By.ID, 'mHamburger').click() 256 | except: 257 | pass 258 | try: 259 | time.sleep(1) 260 | browser.find_element(By.ID, 'HBSignIn').click() 261 | except: 262 | pass 263 | try: 264 | time.sleep(2) 265 | browser.find_element(By.ID, 'iShowSkip').click() 266 | time.sleep(3) 267 | except: 268 | if str(browser.current_url).split('?')[0] == "https://account.live.com/proofs/Add": 269 | prRed('[LOGIN] Please complete the Security Check on ' + CURRENT_ACCOUNT) 270 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 271 | LOGS[CURRENT_ACCOUNT]['Last check'] = 'Requires manual check!' 272 | updateLogs() 273 | exit() 274 | #Wait 5 seconds 275 | time.sleep(5) 276 | # Refresh page 277 | browser.get('https://bing.com/') 278 | # Wait 15 seconds 279 | time.sleep(15 if not FAST else 5) 280 | #Update Counter 281 | try: 282 | if not isMobile: 283 | try: 284 | POINTS_COUNTER = int(browser.find_element(By.ID, 'id_rc').get_attribute('innerHTML')) 285 | except: 286 | browser.find_element(By.ID, 'id_s').click() 287 | time.sleep(15 if not FAST else 7) 288 | checkBingLogin(browser, isMobile) 289 | else: 290 | try: 291 | browser.find_element(By.ID, 'mHamburger').click() 292 | except: 293 | try: 294 | browser.find_element(By.ID, 'bnp_close_link').click() 295 | time.sleep(4) 296 | browser.find_element(By.ID, 'bnp_btn_accept').click() 297 | except: 298 | pass 299 | time.sleep(1) 300 | browser.find_element(By.ID, 'mHamburger').click() 301 | time.sleep(1) 302 | POINTS_COUNTER = int(browser.find_element(By.ID, 'fly_id_rc').get_attribute('innerHTML')) 303 | except: 304 | print("[WARN]", "Failure to load point counter") 305 | return 306 | checkBingLogin(browser, isMobile) 307 | 308 | def waitUntilVisible(browser: WebDriver, by_: By, selector: str, time_to_wait: int = 10): 309 | WebDriverWait(browser, time_to_wait).until(ec.visibility_of_element_located((by_, selector))) 310 | 311 | def waitUntilClickable(browser: WebDriver, by_: By, selector: str, time_to_wait: int = 10): 312 | WebDriverWait(browser, time_to_wait).until(ec.element_to_be_clickable((by_, selector))) 313 | 314 | def waitUntilQuestionRefresh(browser: WebDriver): 315 | tries = 0 316 | refreshCount = 0 317 | while True: 318 | try: 319 | browser.find_elements(By.CLASS_NAME, 'rqECredits')[0] 320 | return True 321 | except: 322 | if tries < 10: 323 | tries += 1 324 | time.sleep(0.5) 325 | else: 326 | if refreshCount < 5: 327 | browser.refresh() 328 | refreshCount += 1 329 | tries = 0 330 | time.sleep(5) 331 | else: 332 | return False 333 | 334 | def waitUntilQuizLoads(browser: WebDriver): 335 | tries = 0 336 | refreshCount = 0 337 | while True: 338 | try: 339 | browser.find_element(By.XPATH, '//*[@id="currentQuestionContainer"]') 340 | return True 341 | except: 342 | if tries < 10: 343 | tries += 1 344 | time.sleep(0.5) 345 | else: 346 | if refreshCount < 5: 347 | browser.refresh() 348 | refreshCount += 1 349 | tries = 0 350 | time.sleep(5) 351 | else: 352 | return False 353 | 354 | def findBetween(s: str, first: str, last: str) -> str: 355 | try: 356 | start = s.index(first) + len(first) 357 | end = s.index(last, start) 358 | return s[start:end] 359 | except ValueError: 360 | return "" 361 | 362 | def getCCodeLangAndOffset() -> tuple: 363 | try: 364 | nfo = ipapi.location() 365 | lang = nfo['languages'].split(',')[0] 366 | geo = nfo['country'] 367 | tz = str(round(int(nfo['utc_offset']) / 100 * 60)) 368 | return(lang, geo, tz) 369 | # Due to limits that ipapi has some times it returns error so I put US and English as default, you may change it at whatever you need. 370 | except: 371 | return('en-US', 'US', '-480') 372 | 373 | def getGoogleTrends(numberOfwords: int) -> list: 374 | search_terms = [] 375 | i = 0 376 | while len(search_terms) < numberOfwords : 377 | i += 1 378 | r = requests.get('https://trends.google.com/trends/api/dailytrends?hl=' + LANG + '&ed=' + str((date.today() - timedelta(days = i)).strftime('%Y%m%d')) + '&geo=' + GEO + '&ns=15') 379 | google_trends = json.loads(r.text[6:]) 380 | for topic in google_trends['default']['trendingSearchesDays'][0]['trendingSearches']: 381 | search_terms.append(topic['title']['query'].lower()) 382 | for related_topic in topic['relatedQueries']: 383 | search_terms.append(related_topic['query'].lower()) 384 | search_terms = list(set(search_terms)) 385 | del search_terms[numberOfwords:(len(search_terms)+1)] 386 | return search_terms 387 | 388 | def getRelatedTerms(word: str) -> list: 389 | try: 390 | r = requests.get('https://api.bing.com/osjson.aspx?query=' + word, headers = {'User-agent': PC_USER_AGENT}) 391 | return r.json()[1] 392 | except: 393 | return [] 394 | 395 | def resetTabs(browser: WebDriver): 396 | try: 397 | curr = browser.current_window_handle 398 | 399 | for handle in browser.window_handles: 400 | if handle != curr: 401 | browser.switch_to.window(handle) 402 | time.sleep(0.5) 403 | browser.close() 404 | time.sleep(0.5) 405 | 406 | browser.switch_to.window(curr) 407 | time.sleep(0.5) 408 | browser.get('https://rewards.microsoft.com/') 409 | except: 410 | browser.get('https://rewards.microsoft.com/') 411 | 412 | def getAnswerCode(key: str, string: str) -> str: 413 | t = 0 414 | for i in range(len(string)): 415 | t += ord(string[i]) 416 | t += int(key[-2:], 16) 417 | return str(t) 418 | 419 | def bingSearches(browser: WebDriver, numberOfSearches: int, isMobile: bool = False): 420 | global POINTS_COUNTER 421 | i = 0 422 | R = RandomWords() 423 | search_terms = R.get_random_words(limit = numberOfSearches) 424 | if search_terms == None: 425 | search_terms = getGoogleTrends(numberOfSearches) 426 | for word in search_terms: 427 | i += 1 428 | print('[BING]', str(i) + "/" + str(numberOfSearches)) 429 | points = bingSearch(browser, word, isMobile) 430 | if points <= POINTS_COUNTER : 431 | relatedTerms = getRelatedTerms(word) 432 | for term in relatedTerms : 433 | points = bingSearch(browser, term, isMobile) 434 | if points >= POINTS_COUNTER: 435 | break 436 | if points > 0: 437 | POINTS_COUNTER = points 438 | else: 439 | break 440 | 441 | def bingSearch(browser: WebDriver, word: str, isMobile: bool): 442 | try: 443 | if not isMobile: 444 | browser.find_element(By.ID, 'sb_form_q').clear() 445 | time.sleep(1) 446 | else: 447 | browser.get('https://bing.com') 448 | except: 449 | browser.get('https://bing.com') 450 | time.sleep(2) 451 | searchbar = browser.find_element(By.ID, 'sb_form_q') 452 | if FAST: 453 | searchbar.send_keys(word) 454 | time.sleep(1) 455 | else: 456 | for char in word: 457 | searchbar.send_keys(char) 458 | time.sleep(0.33) 459 | searchbar.submit() 460 | time.sleep(random.randint(12, 24) if not FAST else random.randint(6, 9)) 461 | points = 0 462 | try: 463 | if not isMobile: 464 | points = int(browser.find_element(By.ID, 'id_rc').get_attribute('innerHTML')) 465 | else: 466 | try : 467 | browser.find_element(By.ID, 'mHamburger').click() 468 | except UnexpectedAlertPresentException: 469 | try : 470 | browser.switch_to.alert.accept() 471 | time.sleep(1) 472 | browser.find_element(By.ID, 'mHamburger').click() 473 | except NoAlertPresentException : 474 | pass 475 | time.sleep(1) 476 | points = int(browser.find_element(By.ID, 'fly_id_rc').get_attribute('innerHTML')) 477 | except: 478 | pass 479 | return points 480 | 481 | def completePromotionalItems(browser: WebDriver): 482 | try: 483 | item = getDashboardData(browser)["promotionalItem"] 484 | if (item["pointProgressMax"] == 100 or item["pointProgressMax"] == 200) and item["complete"] == False and item["destinationUrl"] == "https://rewards.microsoft.com/": 485 | browser.find_element(By.XPATH, '//*[@id="promo-item"]/section/div/div/div/a').click() 486 | time.sleep(1) 487 | browser.switch_to.window(window_name = browser.window_handles[1]) 488 | time.sleep(8) 489 | browser.close() 490 | time.sleep(2) 491 | browser.switch_to.window(window_name = browser.window_handles[0]) 492 | time.sleep(2) 493 | except: 494 | pass 495 | 496 | def completeDailySetSearch(browser: WebDriver, cardNumber: int): 497 | time.sleep(5) 498 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-daily-set-section/div/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-daily-set-item-content/div/a/div/span').click() 499 | time.sleep(1) 500 | browser.switch_to.window(window_name = browser.window_handles[1]) 501 | time.sleep(random.randint(13, 17) if not FAST else random.randint(6, 9)) 502 | browser.close() 503 | time.sleep(2) 504 | browser.switch_to.window(window_name = browser.window_handles[0]) 505 | time.sleep(2) 506 | 507 | def completeDailySetSurvey(browser: WebDriver, cardNumber: int): 508 | time.sleep(5) 509 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-daily-set-section/div/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-daily-set-item-content/div/a/div/span').click() 510 | time.sleep(1) 511 | browser.switch_to.window(window_name = browser.window_handles[1]) 512 | time.sleep(8 if not FAST else 5) 513 | # Accept cookie popup 514 | if isElementExists(browser, By.ID, 'bnp_container'): 515 | browser.find_element(By.ID, 'bnp_btn_accept').click() 516 | time.sleep(2) 517 | # Click on later on Bing wallpaper app popup 518 | if isElementExists(browser, By.ID, 'b_notificationContainer_bop'): 519 | browser.find_element(By.ID, 'bnp_hfly_cta2').click() 520 | time.sleep(2) 521 | browser.find_element(By.ID, "btoption" + str(random.randint(0, 1))).click() 522 | time.sleep(random.randint(10, 15) if not FAST else 7) 523 | browser.close() 524 | time.sleep(2) 525 | browser.switch_to.window(window_name = browser.window_handles[0]) 526 | time.sleep(2) 527 | 528 | def completeDailySetQuiz(browser: WebDriver, cardNumber: int): 529 | time.sleep(5) 530 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-daily-set-section[1]/div/mee-card-group[1]/div[1]/mee-card[{str(cardNumber)}]/div[1]/card-content[1]/mee-rewards-daily-set-item-content[1]/div[1]/a[1]/div[3]/span[1]').click() 531 | time.sleep(3) 532 | browser.switch_to.window(window_name = browser.window_handles[1]) 533 | time.sleep(12 if not FAST else random.randint(5, 8)) 534 | if not waitUntilQuizLoads(browser): 535 | resetTabs(browser) 536 | return 537 | # Accept cookie popup 538 | if isElementExists(browser, By.ID, 'bnp_container'): 539 | browser.find_element(By.ID, 'bnp_btn_accept').click() 540 | time.sleep(2) 541 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 542 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]/div/div[1]', 10) 543 | time.sleep(3) 544 | numberOfQuestions = browser.execute_script("return _w.rewardsQuizRenderInfo.maxQuestions") 545 | numberOfOptions = browser.execute_script("return _w.rewardsQuizRenderInfo.numberOfOptions") 546 | for question in range(numberOfQuestions): 547 | if numberOfOptions == 8: 548 | answers = [] 549 | for i in range(8): 550 | if browser.find_element(By.ID, "rqAnswerOption" + str(i)).get_attribute("iscorrectoption").lower() == "true": 551 | answers.append("rqAnswerOption" + str(i)) 552 | for answer in answers: 553 | # Click on later on Bing wallpaper app popup 554 | if isElementExists(browser, By.ID, 'b_notificationContainer_bop'): 555 | browser.find_element(By.ID, 'bnp_hfly_cta2').click() 556 | time.sleep(2) 557 | browser.find_element(By.ID, answer).click() 558 | time.sleep(5) 559 | if not waitUntilQuestionRefresh(browser): 560 | return 561 | time.sleep(5) 562 | elif numberOfOptions == 4: 563 | correctOption = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 564 | for i in range(4): 565 | if browser.find_element(By.ID, "rqAnswerOption" + str(i)).get_attribute("data-option") == correctOption: 566 | # Click on later on Bing wallpaper app popup 567 | if isElementExists(browser, By.ID, 'b_notificationContainer_bop'): 568 | browser.find_element(By.ID, 'bnp_hfly_cta2').click() 569 | time.sleep(2) 570 | browser.find_element(By.ID, "rqAnswerOption" + str(i)).click() 571 | time.sleep(5) 572 | if not waitUntilQuestionRefresh(browser): 573 | return 574 | break 575 | time.sleep(5) 576 | time.sleep(5) 577 | browser.close() 578 | time.sleep(2) 579 | browser.switch_to.window(window_name = browser.window_handles[0]) 580 | time.sleep(2) 581 | 582 | def completeDailySetVariableActivity(browser: WebDriver, cardNumber: int): 583 | time.sleep(2) 584 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-daily-set-section/div/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-daily-set-item-content/div/a/div/span').click() 585 | time.sleep(1) 586 | browser.switch_to.window(window_name = browser.window_handles[1]) 587 | time.sleep(8) 588 | # Accept cookie popup 589 | if isElementExists(browser, By.ID, 'bnp_container'): 590 | browser.find_element(By.ID, 'bnp_btn_accept').click() 591 | time.sleep(2) 592 | try : 593 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 594 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]/div/div[1]', 3) 595 | except (NoSuchElementException, TimeoutException): 596 | try: 597 | counter = str(browser.find_element(By.XPATH, '//*[@id="QuestionPane0"]/div[2]').get_attribute('innerHTML'))[:-1][1:] 598 | numberOfQuestions = max([int(s) for s in counter.split() if s.isdigit()]) 599 | for question in range(numberOfQuestions): 600 | # Click on later on Bing wallpaper app popup 601 | if isElementExists(browser, By.ID, 'b_notificationContainer_bop'): 602 | browser.find_element(By.ID, 'bnp_hfly_cta2').click() 603 | time.sleep(2) 604 | 605 | browser.execute_script(f'document.evaluate("//*[@id=\'QuestionPane{str(question)}\']/div[1]/div[2]/a[{str(random.randint(1, 3))}]/div", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click()') 606 | time.sleep(8) 607 | time.sleep(5) 608 | browser.close() 609 | time.sleep(2) 610 | browser.switch_to.window(window_name=browser.window_handles[0]) 611 | time.sleep(2) 612 | return 613 | except NoSuchElementException: 614 | time.sleep(random.randint(5, 9)) 615 | browser.close() 616 | time.sleep(2) 617 | browser.switch_to.window(window_name = browser.window_handles[0]) 618 | time.sleep(2) 619 | return 620 | time.sleep(3) 621 | correctAnswer = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 622 | if browser.find_element(By.ID, "rqAnswerOption0").get_attribute("data-option") == correctAnswer: 623 | browser.find_element(By.ID, "rqAnswerOption0").click() 624 | else : 625 | browser.find_element(By.ID, "rqAnswerOption1").click() 626 | time.sleep(10) 627 | browser.close() 628 | time.sleep(2) 629 | browser.switch_to.window(window_name = browser.window_handles[0]) 630 | time.sleep(2) 631 | 632 | def completeDailySetThisOrThat(browser: WebDriver, cardNumber: int): 633 | time.sleep(2) 634 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-daily-set-section/div/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-daily-set-item-content/div/a/div/span').click() 635 | time.sleep(1) 636 | browser.switch_to.window(window_name=browser.window_handles[1]) 637 | time.sleep(15 if not FAST else random.randint(5, 8)) 638 | # Accept cookie popup 639 | if isElementExists(browser, By.ID, 'bnp_container'): 640 | browser.find_element(By.ID, 'bnp_btn_accept').click() 641 | time.sleep(2) 642 | if not waitUntilQuizLoads(browser): 643 | resetTabs(browser) 644 | return 645 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 646 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]/div/div[1]', 10) 647 | time.sleep(5) 648 | for question in range(10): 649 | # Click on later on Bing wallpaper app popup 650 | if isElementExists(browser, By.ID, 'b_notificationContainer_bop'): 651 | browser.find_element(By.ID, 'bnp_hfly_cta2').click() 652 | time.sleep(2) 653 | 654 | answerEncodeKey = browser.execute_script("return _G.IG") 655 | 656 | answer1 = browser.find_element(By.ID, "rqAnswerOption0") 657 | answer1Title = answer1.get_attribute('data-option') 658 | answer1Code = getAnswerCode(answerEncodeKey, answer1Title) 659 | 660 | answer2 = browser.find_element(By.ID, "rqAnswerOption1") 661 | answer2Title = answer2.get_attribute('data-option') 662 | answer2Code = getAnswerCode(answerEncodeKey, answer2Title) 663 | 664 | correctAnswerCode = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 665 | 666 | if (answer1Code == correctAnswerCode): 667 | answer1.click() 668 | time.sleep(15 if not FAST else 7) 669 | elif (answer2Code == correctAnswerCode): 670 | answer2.click() 671 | time.sleep(15 if not FAST else 7) 672 | 673 | time.sleep(5) 674 | browser.close() 675 | time.sleep(2) 676 | browser.switch_to.window(window_name=browser.window_handles[0]) 677 | time.sleep(2) 678 | 679 | def getDashboardData(browser: WebDriver) -> dict: 680 | dashboard = findBetween(browser.find_element(By.XPATH, '/html/body').get_attribute('innerHTML'), "var dashboard = ", ";\n appDataModule.constant(\"prefetchedDashboard\", dashboard);") 681 | dashboard = json.loads(dashboard) 682 | return dashboard 683 | 684 | def completeDailySet(browser: WebDriver): 685 | d = getDashboardData(browser)['dailySetPromotions'] 686 | todayDate = datetime.today().strftime('%m/%d/%Y') 687 | todayPack = [] 688 | for date, data in d.items(): 689 | if date == todayDate: 690 | todayPack = data 691 | for activity in todayPack: 692 | try: 693 | if activity['complete'] == False: 694 | cardNumber = int(activity['offerId'][-1:]) 695 | if activity['promotionType'] == "urlreward": 696 | print('[DAILY SET]', 'Completing search of card ' + str(cardNumber)) 697 | completeDailySetSearch(browser, cardNumber) 698 | if activity['promotionType'] == "quiz": 699 | if activity['pointProgressMax'] == 50 and activity['pointProgress'] == 0: 700 | print('[DAILY SET]', 'Completing This or That of card ' + str(cardNumber)) 701 | completeDailySetThisOrThat(browser, cardNumber) 702 | elif (activity['pointProgressMax'] == 40 or activity['pointProgressMax'] == 30) and activity['pointProgress'] == 0: 703 | print('[DAILY SET]', 'Completing quiz of card ' + str(cardNumber)) 704 | completeDailySetQuiz(browser, cardNumber) 705 | elif activity['pointProgressMax'] == 10 and activity['pointProgress'] == 0: 706 | searchUrl = urllib.parse.unquote(urllib.parse.parse_qs(urllib.parse.urlparse(activity['destinationUrl']).query)['ru'][0]) 707 | searchUrlQueries = urllib.parse.parse_qs(urllib.parse.urlparse(searchUrl).query) 708 | filters = {} 709 | for filter in searchUrlQueries['filters'][0].split(" "): 710 | filter = filter.split(':', 1) 711 | filters[filter[0]] = filter[1] 712 | if "PollScenarioId" in filters: 713 | print('[DAILY SET]', 'Completing poll of card ' + str(cardNumber)) 714 | completeDailySetSurvey(browser, cardNumber) 715 | else: 716 | print('[DAILY SET]', 'Completing quiz of card ' + str(cardNumber)) 717 | completeDailySetVariableActivity(browser, cardNumber) 718 | except: 719 | resetTabs(browser) 720 | 721 | def getAccountPoints(browser: WebDriver) -> int: 722 | return getDashboardData(browser)['userStatus']['availablePoints'] 723 | 724 | def completePunchCard(browser: WebDriver, url: str, childPromotions: dict): 725 | browser.get(url) 726 | for child in childPromotions: 727 | if child['complete'] == False: 728 | if child['promotionType'] == "urlreward": 729 | browser.execute_script("document.getElementsByClassName('offer-cta')[0].click()") 730 | time.sleep(1) 731 | browser.switch_to.window(window_name = browser.window_handles[1]) 732 | time.sleep(random.randint(13, 17)) 733 | browser.close() 734 | time.sleep(2) 735 | browser.switch_to.window(window_name = browser.window_handles[0]) 736 | time.sleep(2) 737 | if child['promotionType'] == "quiz" and child['pointProgressMax'] >= 50 : 738 | browser.find_element(By.XPATH, '//*[@id="rewards-dashboard-punchcard-details"]/div[2]/div[2]/div[7]/div[3]/div[1]/a').click() 739 | time.sleep(1) 740 | browser.switch_to.window(window_name = browser.window_handles[1]) 741 | time.sleep(15) 742 | try: 743 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 744 | except: 745 | pass 746 | time.sleep(5) 747 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]', 10) 748 | numberOfQuestions = browser.execute_script("return _w.rewardsQuizRenderInfo.maxQuestions") 749 | AnswerdQuestions = browser.execute_script("return _w.rewardsQuizRenderInfo.CorrectlyAnsweredQuestionCount") 750 | numberOfQuestions -= AnswerdQuestions 751 | for question in range(numberOfQuestions): 752 | answer = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 753 | browser.find_element(By.XPATH, f'//input[@value="{answer}"]').click() 754 | time.sleep(15) 755 | time.sleep(5) 756 | browser.close() 757 | time.sleep(2) 758 | browser.switch_to.window(window_name=browser.window_handles[0]) 759 | time.sleep(2) 760 | browser.refresh() 761 | break 762 | elif child['promotionType'] == "quiz" and child['pointProgressMax'] < 50: 763 | browser.execute_script("document.getElementsByClassName('offer-cta')[0].click()") 764 | time.sleep(1) 765 | browser.switch_to.window(window_name = browser.window_handles[1]) 766 | time.sleep(8) 767 | counter = str(browser.find_element(By.XPATH, '//*[@id="QuestionPane0"]/div[2]').get_attribute('innerHTML'))[:-1][1:] 768 | numberOfQuestions = max([int(s) for s in counter.split() if s.isdigit()]) 769 | for question in range(numberOfQuestions): 770 | browser.execute_script('document.evaluate("//*[@id=\'QuestionPane' + str(question) + '\']/div[1]/div[2]/a[' + str(random.randint(1, 3)) + ']/div", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click()') 771 | time.sleep(10) 772 | time.sleep(5) 773 | browser.close() 774 | time.sleep(2) 775 | browser.switch_to.window(window_name = browser.window_handles[0]) 776 | time.sleep(2) 777 | browser.refresh() 778 | break 779 | 780 | def completePunchCards(browser: WebDriver): 781 | punchCards = getDashboardData(browser)['punchCards'] 782 | for punchCard in punchCards: 783 | try: 784 | if punchCard['parentPromotion'] != None and punchCard['childPromotions'] != None and punchCard['parentPromotion']['complete'] == False and punchCard['parentPromotion']['pointProgressMax'] != 0: 785 | url = punchCard['parentPromotion']['attributes']['destination'] 786 | if browser.current_url.startswith('https://rewards.'): 787 | path = url.replace('https://rewards.microsoft.com', '') 788 | new_url = 'https://rewards.microsoft.com/dashboard/' 789 | userCode = path[11:15] 790 | dest = new_url + userCode + path.split(userCode)[1] 791 | else: 792 | path = url.replace('https://account.microsoft.com/rewards/dashboard/','') 793 | new_url = 'https://account.microsoft.com/rewards/dashboard/' 794 | userCode = path[:4] 795 | dest = new_url + userCode + path.split(userCode)[1] 796 | completePunchCard(browser, dest, punchCard['childPromotions']) 797 | except: 798 | resetTabs(browser) 799 | time.sleep(2) 800 | browser.get('https://rewards.microsoft.com/dashboard/') 801 | time.sleep(2) 802 | 803 | def completeMorePromotionSearch(browser: WebDriver, cardNumber: int): 804 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-more-activities-card/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-more-activities-card-item/div/a/div/span').click() 805 | time.sleep(1) 806 | browser.switch_to.window(window_name = browser.window_handles[1]) 807 | time.sleep(random.randint(13, 17) if not FAST else random.randint(5, 8)) 808 | browser.close() 809 | time.sleep(2) 810 | browser.switch_to.window(window_name = browser.window_handles[0]) 811 | time.sleep(2) 812 | 813 | def completeMorePromotionQuiz(browser: WebDriver, cardNumber: int): 814 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-more-activities-card/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-more-activities-card-item/div/a/div/span').click() 815 | time.sleep(1) 816 | browser.switch_to.window(window_name=browser.window_handles[1]) 817 | time.sleep(8 if not FAST else 5) 818 | if not waitUntilQuizLoads(browser): 819 | resetTabs(browser) 820 | return 821 | CurrentQuestionNumber = browser.execute_script("return _w.rewardsQuizRenderInfo.currentQuestionNumber") 822 | if CurrentQuestionNumber == 1 and isElementExists(browser, By.XPATH, '//*[@id="rqStartQuiz"]'): 823 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 824 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]/div/div[1]', 10) 825 | time.sleep(3) 826 | numberOfQuestions = browser.execute_script("return _w.rewardsQuizRenderInfo.maxQuestions") 827 | Questions = numberOfQuestions - CurrentQuestionNumber + 1 828 | numberOfOptions = browser.execute_script("return _w.rewardsQuizRenderInfo.numberOfOptions") 829 | for question in range(Questions): 830 | if numberOfOptions == 8: 831 | answers = [] 832 | for i in range(8): 833 | if browser.find_element(By.ID, "rqAnswerOption" + str(i)).get_attribute("iscorrectoption").lower() == "true": 834 | answers.append("rqAnswerOption" + str(i)) 835 | for answer in answers: 836 | browser.find_element(By.ID, answer).click() 837 | time.sleep(5) 838 | if not waitUntilQuestionRefresh(browser): 839 | return 840 | time.sleep(5) 841 | elif numberOfOptions == 4: 842 | correctOption = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 843 | for i in range(4): 844 | if browser.find_element(By.ID, "rqAnswerOption" + str(i)).get_attribute("data-option") == correctOption: 845 | browser.find_element(By.ID, "rqAnswerOption" + str(i)).click() 846 | time.sleep(5) 847 | if not waitUntilQuestionRefresh(browser): 848 | return 849 | break 850 | time.sleep(5) 851 | time.sleep(5) 852 | browser.close() 853 | time.sleep(2) 854 | browser.switch_to.window(window_name=browser.window_handles[0]) 855 | time.sleep(2) 856 | 857 | def completeMorePromotionABC(browser: WebDriver, cardNumber: int): 858 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-more-activities-card/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-more-activities-card-item/div/a/div/span').click() 859 | time.sleep(1) 860 | browser.switch_to.window(window_name=browser.window_handles[1]) 861 | time.sleep(8 if not FAST else 5) 862 | counter = str(browser.find_element(By.XPATH, '//*[@id="QuestionPane0"]/div[2]').get_attribute('innerHTML'))[:-1][1:] 863 | numberOfQuestions = max([int(s) for s in counter.split() if s.isdigit()]) 864 | for question in range(numberOfQuestions): 865 | browser.execute_script(f'document.evaluate("//*[@id=\'QuestionPane{str(question)}\']/div[1]/div[2]/a[{str(random.randint(1, 3))}]/div", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click()') 866 | time.sleep(8 if not FAST else 5) 867 | time.sleep(5) 868 | browser.close() 869 | time.sleep(2) 870 | browser.switch_to.window(window_name=browser.window_handles[0]) 871 | time.sleep(2) 872 | 873 | def completeMorePromotionThisOrThat(browser: WebDriver, cardNumber: int): 874 | browser.find_element(By.XPATH, f'//*[@id="app-host"]/ui-view/mee-rewards-dashboard/main/div/mee-rewards-more-activities-card/mee-card-group/div/mee-card[{str(cardNumber)}]/div/card-content/mee-rewards-more-activities-card-item/div/a/div/span').click() 875 | time.sleep(1) 876 | browser.switch_to.window(window_name=browser.window_handles[1]) 877 | time.sleep(8 if not FAST else 5) 878 | if not waitUntilQuizLoads(browser): 879 | resetTabs(browser) 880 | return 881 | CrrentQuestionNumber = browser.execute_script("return _w.rewardsQuizRenderInfo.currentQuestionNumber") 882 | NumberOfQuestionsLeft = 10 - CrrentQuestionNumber + 1 883 | if CrrentQuestionNumber == 1 and isElementExists(browser, By.XPATH, '//*[@id="rqStartQuiz"]'): 884 | browser.find_element(By.XPATH, '//*[@id="rqStartQuiz"]').click() 885 | waitUntilVisible(browser, By.XPATH, '//*[@id="currentQuestionContainer"]/div/div[1]', 10) 886 | time.sleep(3) 887 | for question in range(NumberOfQuestionsLeft): 888 | answerEncodeKey = browser.execute_script("return _G.IG") 889 | 890 | answer1 = browser.find_element(By.ID, "rqAnswerOption0") 891 | answer1Title = answer1.get_attribute('data-option') 892 | answer1Code = getAnswerCode(answerEncodeKey, answer1Title) 893 | 894 | answer2 = browser.find_element(By.ID, "rqAnswerOption1") 895 | answer2Title = answer2.get_attribute('data-option') 896 | answer2Code = getAnswerCode(answerEncodeKey, answer2Title) 897 | 898 | correctAnswerCode = browser.execute_script("return _w.rewardsQuizRenderInfo.correctAnswer") 899 | 900 | if (answer1Code == correctAnswerCode): 901 | answer1.click() 902 | time.sleep(8 if not FAST else 5) 903 | elif (answer2Code == correctAnswerCode): 904 | answer2.click() 905 | time.sleep(8 if not FAST else 5) 906 | 907 | time.sleep(5) 908 | browser.close() 909 | time.sleep(2) 910 | browser.switch_to.window(window_name=browser.window_handles[0]) 911 | time.sleep(2) 912 | 913 | def completeMorePromotions(browser: WebDriver): 914 | morePromotions = getDashboardData(browser)['morePromotions'] 915 | i = 0 916 | for promotion in morePromotions: 917 | try: 918 | i += 1 919 | if promotion['complete'] == False and promotion['pointProgressMax'] != 0: 920 | if promotion['promotionType'] == "urlreward": 921 | completeMorePromotionSearch(browser, i) 922 | elif promotion['promotionType'] == "quiz": 923 | if promotion['pointProgressMax'] == 10: 924 | completeMorePromotionABC(browser, i) 925 | elif promotion['pointProgressMax'] == 30 or promotion['pointProgressMax'] == 40: 926 | completeMorePromotionQuiz(browser, i) 927 | elif promotion['pointProgressMax'] == 50: 928 | completeMorePromotionThisOrThat(browser, i) 929 | else: 930 | if promotion['pointProgressMax'] == 100 or promotion['pointProgressMax'] == 200: 931 | completeMorePromotionSearch(browser, i) 932 | if promotion['complete'] == False and promotion['pointProgressMax'] == 100 and promotion['promotionType'] == "" \ 933 | and promotion['destinationUrl'] == "https://rewards.microsoft.com": 934 | completeMorePromotionSearch(browser, i) 935 | except: 936 | resetTabs(browser) 937 | 938 | def getRemainingSearches(browser: WebDriver): 939 | dashboard = getDashboardData(browser) 940 | searchPoints = 1 941 | counters = dashboard['userStatus']['counters'] 942 | if not 'pcSearch' in counters: 943 | return 0, 0 944 | progressDesktop = counters['pcSearch'][0]['pointProgress'] + counters['pcSearch'][1]['pointProgress'] 945 | targetDesktop = counters['pcSearch'][0]['pointProgressMax'] + counters['pcSearch'][1]['pointProgressMax'] 946 | if targetDesktop == 33 : 947 | #Level 1 EU 948 | searchPoints = 3 949 | elif targetDesktop == 55 : 950 | #Level 1 US 951 | searchPoints = 5 952 | elif targetDesktop == 102 : 953 | #Level 2 EU 954 | searchPoints = 3 955 | elif targetDesktop >= 170 : 956 | #Level 2 US 957 | searchPoints = 5 958 | remainingDesktop = int((targetDesktop - progressDesktop) / searchPoints) 959 | remainingMobile = 0 960 | if dashboard['userStatus']['levelInfo']['activeLevel'] != "Level1": 961 | progressMobile = counters['mobileSearch'][0]['pointProgress'] 962 | targetMobile = counters['mobileSearch'][0]['pointProgressMax'] 963 | remainingMobile = int((targetMobile - progressMobile) / searchPoints) 964 | return remainingDesktop, remainingMobile 965 | 966 | def isElementExists(browser: WebDriver, _by: By, element: str) -> bool: 967 | '''Returns True if given element exists else False''' 968 | try: 969 | browser.find_element(_by, element) 970 | except NoSuchElementException: 971 | return False 972 | return True 973 | 974 | def validateTime(time: str): 975 | ''' 976 | check the time format and return the time if it is valid, otherwise return None 977 | ''' 978 | try: 979 | t = datetime.strptime(time, "%H:%M").strftime("%H:%M") 980 | except ValueError: 981 | return None 982 | else: 983 | return t 984 | 985 | def argumentParser(): 986 | ''' 987 | getting args from command line (--everyday [time:(HH:MM)], --session, --headless) 988 | ''' 989 | parser = ArgumentParser(description="Microsoft Rewards Farmer V2.1", 990 | allow_abbrev=False, 991 | usage="You may use execute the program with the default config or use arguments to configure available options.") 992 | parser.add_argument('--everyday', 993 | metavar=None, 994 | help='[Optional] This argument takes an input as time in 24h format (HH:MM) to execute the program at the given time everyday.', 995 | type=str, 996 | required=False) 997 | parser.add_argument('--headless', 998 | help='[Optional] Enable headless browser.', 999 | action = 'store_true', 1000 | required=False) 1001 | parser.add_argument('--session', 1002 | help='[Optional] Creates session for each account and use it.', 1003 | action='store_true', 1004 | required=False) 1005 | parser.add_argument('--error', 1006 | help='[Optional] Display errors when app fails.', 1007 | action='store_true', 1008 | required=False) 1009 | parser.add_argument('--fast', 1010 | help="[Optional] Reduce delays where ever it's possible to make script faster.", 1011 | action='store_true', 1012 | required=False) 1013 | args = parser.parse_args() 1014 | if args.everyday: 1015 | if isinstance(validateTime(args.everyday), str): 1016 | args.everyday = validateTime(args.everyday) 1017 | else: 1018 | parser.error(f'"{args.everyday}" is not valid. Please use (HH:MM) format.') 1019 | if args.fast: 1020 | global FAST 1021 | FAST = True 1022 | if len(sys.argv) > 1: 1023 | for arg in vars(args): 1024 | prBlue(f"[INFO] {arg} : {getattr(args, arg)}") 1025 | return args 1026 | 1027 | def logs(): 1028 | ''' 1029 | Read logs and check whether account farmed or not 1030 | ''' 1031 | global LOGS 1032 | shared_items =[] 1033 | try: 1034 | # Read datas on 'logs_accounts.txt' 1035 | LOGS = json.load(open(f"Logs_{filename}.txt", "r")) 1036 | # sync accounts and logs file for new accounts or remove accounts from logs. 1037 | for user in ACCOUNTS: 1038 | shared_items.append(user['username']) 1039 | if not user['username'] in LOGS.keys(): 1040 | LOGS[user["username"]] = {"Last check": "", 1041 | "Today's points": 0, 1042 | "Points": 0} 1043 | if shared_items != LOGS.keys(): 1044 | diff = LOGS.keys() - shared_items 1045 | for accs in list(diff): 1046 | del LOGS[accs] 1047 | 1048 | # check that if any of accounts has farmed today or not. 1049 | for account in LOGS.keys(): 1050 | if LOGS[account]["Last check"] == str(date.today()) and list(LOGS[account].keys()) == ['Last check', "Today's points", 'Points']: 1051 | FINISHED_ACCOUNTS.append(account) 1052 | elif LOGS[account]['Last check'] == 'Your account has been suspended': 1053 | FINISHED_ACCOUNTS.append(account) 1054 | elif LOGS[account]['Last check'] == str(date.today()) and list(LOGS[account].keys()) == ['Last check', "Today's points", 'Points', 1055 | 'Daily', 'Punch cards', 'More promotions', 'PC searches']: 1056 | continue 1057 | else: 1058 | LOGS[account]['Daily'] = False 1059 | LOGS[account]['Punch cards'] = False 1060 | LOGS[account]['More promotions'] = False 1061 | LOGS[account]['PC searches'] = False 1062 | updateLogs() 1063 | prGreen('\n[LOGS] Logs loaded successfully.\n') 1064 | except FileNotFoundError: 1065 | prRed(f'\n[LOGS] "Logs_{filename}.txt" file not found.') 1066 | LOGS = {} 1067 | for account in ACCOUNTS: 1068 | LOGS[account["username"]] = {"Last check": "", 1069 | "Today's points": 0, 1070 | "Points": 0, 1071 | "Daily": False, 1072 | "Punch cards": False, 1073 | "More promotions": False, 1074 | "PC searches": False} 1075 | updateLogs() 1076 | prGreen(f'[LOGS] "Logs_{filename}.txt" created.\n') 1077 | 1078 | def updateLogs(): 1079 | global LOGS 1080 | with open(f'Logs_{filename}.txt', 'w') as file: 1081 | file.write(json.dumps(LOGS, indent = 4)) 1082 | 1083 | def cleanLogs(): 1084 | del LOGS[CURRENT_ACCOUNT]["Daily"] 1085 | del LOGS[CURRENT_ACCOUNT]["Punch cards"] 1086 | del LOGS[CURRENT_ACCOUNT]["More promotions"] 1087 | del LOGS[CURRENT_ACCOUNT]["PC searches"] 1088 | 1089 | def checkInternetConnection(): 1090 | system = platform.system() 1091 | while True: 1092 | try: 1093 | if system == "Windows": 1094 | subprocess.check_output(["ping", "-n", "1", "8.8.8.8"], timeout=5) 1095 | elif system == "Linux": 1096 | subprocess.check_output(["ping", "-c", "1", "8.8.8.8"], timeout=5) 1097 | return 1098 | except (subprocess.CalledProcessError, subprocess.TimeoutExpired): 1099 | prRed("[ERROR] No internet connection.") 1100 | time.sleep(1) 1101 | 1102 | def prRed(prt): 1103 | print(f"\033[91m{prt}\033[00m") 1104 | def prGreen(prt): 1105 | print(f"\033[92m{prt}\033[00m") 1106 | def prYellow(prt): 1107 | print(f"\033[93m{prt}\033[00m") 1108 | def prBlue(prt): 1109 | print(f"\033[94m{prt}\033[00m") 1110 | def prPurple(prt): 1111 | print(f"\033[95m{prt}\033[00m") 1112 | 1113 | def logo(): 1114 | prRed("") 1115 | prPurple(" by @Charlesbel upgraded by @Farshadz1997 version 2.1\n") 1116 | 1117 | try: 1118 | account_path = os.path.dirname(os.path.abspath(__file__)) + '/accounts.json' 1119 | filename, ext = os.path.splitext(os.path.basename(account_path)) 1120 | ACCOUNTS = json.load(open(account_path, "r")) 1121 | except FileNotFoundError: 1122 | with open(account_path, 'w') as f: 1123 | f.write(json.dumps([{ 1124 | "username": "Your Email", 1125 | "password": "Your Password" 1126 | }], indent=4)) 1127 | prPurple(f""" 1128 | [ACCOUNT] Accounts credential file "{filename}{ext}" created. 1129 | [ACCOUNT] Edit with your credentials and save, then press any key to continue... 1130 | """) 1131 | input() 1132 | ACCOUNTS = json.load(open(account_path, "r")) 1133 | 1134 | def farmer(): 1135 | ''' 1136 | fuction that runs other functions to farm. 1137 | ''' 1138 | global ERROR, MOBILE, CURRENT_ACCOUNT 1139 | try: 1140 | for account in ACCOUNTS: 1141 | CURRENT_ACCOUNT = account['username'] 1142 | if CURRENT_ACCOUNT in FINISHED_ACCOUNTS: 1143 | continue 1144 | if LOGS[CURRENT_ACCOUNT]["Last check"] != str(date.today()): 1145 | LOGS[CURRENT_ACCOUNT]["Last check"] = str(date.today()) 1146 | updateLogs() 1147 | prYellow('********************' + CURRENT_ACCOUNT + '********************') 1148 | if not LOGS[CURRENT_ACCOUNT]['PC searches']: 1149 | browser = browserSetup(False, PC_USER_AGENT) 1150 | print('[LOGIN]', 'Logging-in...') 1151 | login(browser, account['username'], account['password']) 1152 | prGreen('[LOGIN] Logged-in successfully !') 1153 | startingPoints = POINTS_COUNTER 1154 | prGreen('[POINTS] You have ' + str(POINTS_COUNTER) + ' points on your account !') 1155 | browser.get('https://rewards.microsoft.com/dashboard') 1156 | if not LOGS[CURRENT_ACCOUNT]['Daily']: 1157 | print('[DAILY SET]', 'Trying to complete the Daily Set...') 1158 | completeDailySet(browser) 1159 | LOGS[CURRENT_ACCOUNT]['Daily'] = True 1160 | updateLogs() 1161 | prGreen('[DAILY SET] Completed the Daily Set successfully !') 1162 | if not LOGS[CURRENT_ACCOUNT]['Punch cards']: 1163 | print('[PUNCH CARDS]', 'Trying to complete the Punch Cards...') 1164 | completePunchCards(browser) 1165 | LOGS[CURRENT_ACCOUNT]['Punch cards'] = True 1166 | updateLogs() 1167 | prGreen('[PUNCH CARDS] Completed the Punch Cards successfully !') 1168 | if not LOGS[CURRENT_ACCOUNT]['More promotions']: 1169 | print('[MORE PROMO]', 'Trying to complete More Promotions...') 1170 | completeMorePromotions(browser) 1171 | LOGS[CURRENT_ACCOUNT]['More promotions'] = True 1172 | updateLogs() 1173 | prGreen('[MORE PROMO] Completed More Promotions successfully !') 1174 | remainingSearches, remainingSearchesM = getRemainingSearches(browser) 1175 | MOBILE = True if remainingSearchesM != 0 else False 1176 | if remainingSearches != 0: 1177 | print('[BING]', 'Starting Desktop and Edge Bing searches...') 1178 | bingSearches(browser, remainingSearches) 1179 | prGreen('[BING] Finished Desktop and Edge Bing searches !') 1180 | LOGS[CURRENT_ACCOUNT]['PC searches'] = True 1181 | updateLogs() 1182 | ERROR = False 1183 | browser.quit() 1184 | 1185 | if MOBILE: 1186 | browser = browserSetup(True, account.get('mobile_user_agent', MOBILE_USER_AGENT)) 1187 | print('[LOGIN]', 'Logging-in...') 1188 | login(browser, account['username'], account['password'], True) 1189 | prGreen('[LOGIN] Logged-in successfully !') 1190 | if LOGS[account['username']]['PC searches'] and ERROR: 1191 | startingPoints = POINTS_COUNTER 1192 | browser.get('https://rewards.microsoft.com/dashboard') 1193 | remainingSearches, remainingSearchesM = getRemainingSearches(browser) 1194 | if remainingSearchesM != 0: 1195 | print('[BING]', 'Starting Mobile Bing searches...') 1196 | bingSearches(browser, remainingSearchesM, True) 1197 | prGreen('[BING] Finished Mobile Bing searches !') 1198 | browser.quit() 1199 | 1200 | New_points = POINTS_COUNTER - startingPoints 1201 | prGreen('[POINTS] You have earned ' + str(New_points) + ' points today !') 1202 | prGreen('[POINTS] You are now at ' + str(POINTS_COUNTER) + ' points !\n') 1203 | 1204 | FINISHED_ACCOUNTS.append(CURRENT_ACCOUNT) 1205 | LOGS[CURRENT_ACCOUNT]["Today's points"] = New_points 1206 | LOGS[CURRENT_ACCOUNT]["Points"] = POINTS_COUNTER 1207 | cleanLogs() 1208 | updateLogs() 1209 | 1210 | except FunctionTimedOut: 1211 | prRed('[ERROR] Time out raised.\n') 1212 | ERROR = True 1213 | browser.quit() 1214 | farmer() 1215 | except SessionNotCreatedException: 1216 | prBlue('[Driver] Session not created.') 1217 | prBlue('[Driver] Please download correct version of webdriver form link below:') 1218 | prBlue('[Driver] https://chromedriver.chromium.org/downloads') 1219 | input('Press any key to close...') 1220 | exit() 1221 | except KeyboardInterrupt: 1222 | ERROR = True 1223 | browser.quit() 1224 | input('\n\033[94m[INFO] Farmer paused. Press enter to continue...\033[00m\n') 1225 | farmer() 1226 | except Exception as e: 1227 | print(e, '\n') if ARGS.error else print('\n') 1228 | ERROR = True 1229 | browser.quit() 1230 | checkInternetConnection() 1231 | farmer() 1232 | else: 1233 | FINISHED_ACCOUNTS.clear() 1234 | 1235 | def main(): 1236 | display = Display(visible=0, size=(900, 800)) 1237 | display.start() 1238 | 1239 | global LANG, GEO, TZ, ARGS 1240 | # show colors in terminal 1241 | os.system('color') 1242 | logo() 1243 | # Get the arguments from the command line 1244 | ARGS = argumentParser() 1245 | LANG, GEO, TZ = getCCodeLangAndOffset() 1246 | # set time to launch the program if everyday is not set 1247 | # if not ARGS.everyday: 1248 | # answer = input('''If you want to run the program at a specific time, type your desired time in 24h format (HH:MM) else press Enter 1249 | # (\033[93manything other than time causes the script to start immediately\033[00m): ''') 1250 | # run_on = validate_time(answer) 1251 | # else: 1252 | # run_on = ARGS.everyday 1253 | run_on = None 1254 | if run_on is not None: 1255 | while True: 1256 | if datetime.now().strftime("%H:%M") == run_on: 1257 | start = time.time() 1258 | logs() 1259 | farmer() 1260 | if ARGS.everyday is None: 1261 | break 1262 | time.sleep(30) 1263 | else: 1264 | start = time.time() 1265 | logs() 1266 | farmer() 1267 | end = time.time() 1268 | delta = end - start 1269 | hour, remain = divmod(delta, 3600) 1270 | min, sec = divmod(remain, 60) 1271 | print(f"The farmer takes : {hour:02.0f}:{min:02.0f}:{sec:02.0f}") 1272 | # input('Press any key to close the program...') 1273 | display.stop() 1274 | 1275 | if __name__ == '__main__': 1276 | main() 1277 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyyaml 2 | pyvirtualdisplay 3 | certifi 4 | chardet 5 | idna 6 | requests 7 | selenium 8 | urllib3 9 | ipapi 10 | func_timeout 11 | random-word==1.0.7 12 | pyyaml 13 | -------------------------------------------------------------------------------- /scripts/upgrade_browser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo apt-get update -y 3 | sudo apt install -y google-chrome-stable 4 | sudo apt install -y chromium-chromedriver -------------------------------------------------------------------------------- /ss.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo apt-get update -y 3 | sudo apt install -y shadowsocks-libev 4 | sudo vim /etc/shadowsocks-libev/config.json -------------------------------------------------------------------------------- /upload_log.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 | LOG_NAME="${PROJECT_DIR}/logs/log_"$*"" 4 | 5 | # push log 6 | cd ${PROJECT_DIR} 7 | git pull 8 | cp ~/Logs_accounts.txt ${LOG_NAME}; 9 | git add ${LOG_NAME} 10 | git commit -m "[log]"$*"" 11 | git push 12 | 13 | # update browser, driver version 14 | /bin/bash scripts/upgrade_browser.sh > browser.txt 15 | 16 | # clean large size log 17 | logfile=cron.log 18 | filesize=$(stat -c %s "$logfile") 19 | 20 | if [ "$filesize" -gt $((200 * 1024 * 1024)) ]; then 21 | echo "Log file is larger than 200MB, deleting..." 22 | rm "$logfile" 23 | fi --------------------------------------------------------------------------------