Skip to content
This repository was archived by the owner on Feb 26, 2026. It is now read-only.

Commit 9682ccd

Browse files
author
Anthony Jiang
authored
Merge pull request #5 from ashanrath/feature_telegram
Thank you for your contribution. Telegram Functionality
2 parents 3162e63 + 70b93c5 commit 9682ccd

File tree

8 files changed

+205
-12
lines changed

8 files changed

+205
-12
lines changed

README-Telegram.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Configuring Telegram updates for MS Reward Bot
2+
3+
To enable Telegram updates, you must
4+
5+
1. Check/create your Telegram API key and Chat ID. There are multiple ways to do this. One option is via the get_id_bot: https://telegram.me/get_id_bot
6+
2. Open `ms_rewards_telegram_bot.json` and add in your API key and chat ID:
7+
```json
8+
[
9+
{
10+
"telegram_apikey": "0123456789:AAAAbbCCCCCCCdddd-eeeeeeeeeeeeeeeee",
11+
"telegram_chatid": "-0123456789012"
12+
}
13+
]
14+
```
15+
3. Save the file.
16+
4. Update [runbot.bat]/[runbot.sh] and add the `--telegram` flag.
17+
18+
Telegram updates should be sent after searches are complete and shown as:
19+
```
20+
Update for {email}
21+
☒ PC 90/90 ☒ Punch Card 100/100
22+
☒ Mob 60/60 ☒ Quiz 170/170
23+
Total Points: XX,XXX
24+
```
25+
26+
27+
# Optional - Include redemption value of current points
28+
29+
The telegram update can also be used to show the value of any redemption options available with the current point balance.
30+
31+
1. Go to https://rewards.microsoft.com/redeem/shop and confirm the details of any item that you wish to track for.
32+
2. Open `ms_rewards_redeem_options.json.example` and add in the details of any item to be tracked.
33+
```
34+
[
35+
{
36+
"type": "Xbox Live",
37+
"short_desc": "XBL",
38+
"currency": "$",
39+
"value": "5",
40+
"price": "4750"
41+
},
42+
{
43+
"type": "Other Gift Voucher",
44+
"short_desc": "GV",
45+
"currency": "$",
46+
"value": "5",
47+
"price": "6750"
48+
}
49+
]
50+
```
51+
3. Save the file.
52+
53+
54+
Telegram updates should now include the redemption value the current point balance.
55+
56+
```
57+
Update for {email}
58+
☒ PC 90/90 ☒ Punch Card 100/100
59+
☒ Mob 60/60 ☒ Quiz 170/170
60+
Total Points: 10,848 ($10 XBL, $5 GV)
61+
```
62+

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ This program will automatically complete search requests and quizzes on Microsof
1717
- Logs errors and info by default, can log executed commands and search terms by changing the log level to DEBUG
1818
- Tested and confirmed working for U.K. (more to come!)
1919

20-
- Python [3.9](https://www.python.org/downloads/)
21-
- Requests 2.25.1
22-
- Selenium 3.141.0
23-
- pyotp 2.6.0
24-
- Chrome Browser (Up-to-date)
20+
- Python [3.9](https://www.python.org/downloads/)
21+
- Requests 2.25.1
22+
- Selenium 3.141.0
23+
- pyotp 2.6.0
24+
- python-telegram-bot 13.7
25+
- Chrome Browser (Up-to-date)
2526

2627
## Use
2728

@@ -38,6 +39,7 @@ This program will automatically complete search requests and quizzes on Microsof
3839
- `--pc` is for pc search
3940
- `--quiz` is for quiz search
4041
- `-a` or `--all` is short for mobile, pc, and quiz search
42+
- `--telegram` is to enable telegram updates. Please follow please follow [README-Telegram](README-Telegram.md).
4143
- Script by default will execute mobile, pc, edge, searches, and complete quizzes for all accounts (can change this setting in the .py file)
4244
- Script by default will run in interactive mode
4345
- If python environment variable is not set, enter `/path/to/python/executable ms_rewards.py`

helper/telegram.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import json
2+
import telegram
3+
from telegram.ext import Updater
4+
from telegram.utils.helpers import escape_markdown
5+
from helper.logger import *
6+
import math
7+
8+
def get_telegram_info():
9+
try:
10+
with open('ms_rewards_telegram_bot.json', 'r') as f:
11+
return json.load(f)
12+
except FileNotFoundError as e:
13+
logging.exception(msg=f'Telegram updates are enabled, but ms_rewards_telegram_bot.json not found.', exc_info=False)
14+
except Exception as e:
15+
logging.exception(msg=f'Telegram updates are enabled, but failed: {e}.')
16+
17+
def get_redeem_options():
18+
with open('ms_rewards_redeem_options.json', 'r') as f:
19+
return json.load(f)
20+
21+
def markdown_escape(message_text):
22+
#Remove special characters when passing exceptions to telegram.
23+
escaped_markdown = escape_markdown(message_text, version=2)
24+
return escaped_markdown
25+
26+
def telegram_update(message_text):
27+
try:
28+
telegram_chats = get_telegram_info()
29+
for chat in telegram_chats:
30+
telegram_apikey = chat["telegram_apikey"]
31+
telegram_chatid = chat["telegram_chatid"]
32+
bot = telegram.Bot(token=telegram_apikey)
33+
bot.send_message(chat_id=telegram_chatid, text=(message_text), parse_mode="MarkdownV2")
34+
except TypeError:
35+
logging.exception(msg=f'Telegram updates are enabled, but failed to process ms_rewards_telegram_bot.json.', exc_info=False)
36+
except FileNotFoundError:
37+
logging.exception(msg=f'Telegram updates are enabled, but ms_rewards_telegram_bot.json not found.', exc_info=False)
38+
except Exception as e:
39+
logging.exception(msg=f'Telegram updates are enabled but failed to send.', exc_info=True)
40+
41+
def flag_checkbox(done_flag):
42+
if done_flag:
43+
return '☒'
44+
else:
45+
return '☐'
46+
47+
def points_credit_value(points):
48+
try:
49+
redeem_options = get_redeem_options()
50+
message_list = []
51+
for option in redeem_options:
52+
available_value = str(math.floor(int(points)/int(option["price"]))*int(option["value"]))
53+
message_list.append(f'{option["currency"]}{available_value} {option["short_desc"]}')
54+
55+
return '('+', '.join(message_list)+')'
56+
except FileNotFoundError as e:
57+
logging.info(msg=f'Skipped redemption value check, ms_rewards_redeem_options.json not found.', exc_info=False)
58+
return ''
59+
pass
60+
except Exception as e:
61+
logging.info(msg=f'Skipped redemption value check, failed to process file.', exc_info=False)
62+
return ''
63+
pass
64+
65+
def telegram_update_post_search(email,summary):
66+
email = markdown_escape(email)
67+
pc_flag=flag_checkbox(summary.pc_search_done)
68+
pc_c=summary.pc_search_progress
69+
pc_m=summary.pc_search_max
70+
mo_flag=flag_checkbox(summary.mob_search_done)
71+
mo_c=summary.mobile_search_progress
72+
mo_m=summary.mobile_search_max
73+
pu_flag=flag_checkbox(summary.punch_card_done)
74+
pu_c=summary.punch_card_progress
75+
pu_m=summary.punch_card_max
76+
qz_flag=flag_checkbox(summary.quiz_done)
77+
qz_c=summary.quiz_progress
78+
qz_m=summary.quiz_max
79+
points_credit_value_list=markdown_escape(points_credit_value(summary.available_points))
80+
81+
telegram_message = (
82+
f'Update for {email}\n' \
83+
f'```\n' \
84+
f' {pc_flag} PC {pc_c}/{pc_m} {pu_flag} Punch Card {pu_c}/{pu_m}\n' \
85+
f' {mo_flag} Mob {mo_c}/{mo_m} {qz_flag} Quiz {qz_c}/{qz_m}\n' \
86+
f'```' \
87+
f'Total Points: {summary.available_points:,} {points_credit_value_list}' \
88+
)
89+
telegram_update(telegram_message)

ms_rewards.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from selenium.common.exceptions import WebDriverException
99
from helper.logger import *
1010
from helper.driver import update_driver
11-
11+
from helper.telegram import *
1212

1313
msr_version = 'v2.1.0'
1414

@@ -70,6 +70,12 @@ def parse_args():
7070
dest='exit_on_finish',
7171
default=False,
7272
help=f'Script will exit when finishes, otherwise will remain open and wait for user to press enter to end.')
73+
arg_parser.add_argument(
74+
'--telegram',
75+
action='store_true',
76+
dest='telegram_message',
77+
default=False,
78+
help=f'Activates telegram updates upon completion of searhes.')
7379
_parser = arg_parser.parse_args()
7480
if _parser.all_mode:
7581
_parser.mobile_mode = True
@@ -81,8 +87,7 @@ def parse_args():
8187
def get_login_info():
8288
with open('ms_rewards_login_dict.json', 'r') as f:
8389
return json.load(f)
84-
85-
90+
8691
if __name__ == '__main__':
8792
check_python_version()
8893
if os.path.exists("drivers/chromedriver.exe"):
@@ -99,6 +104,7 @@ def get_login_info():
99104
logging.info(msg=f'Bot version: {msr_version}')
100105

101106
login_cred = get_login_info()
107+
102108
logging.info(msg=f'logins retrieved, {len(login_cred)} account(s):')
103109
for cred in login_cred:
104110
logging.info(msg=f'{cred["email"]}')
@@ -110,8 +116,10 @@ def get_login_info():
110116
logging.info(
111117
msg='--------------------------------------------------')
112118
logging.info(msg=f'Current account: {msr.email}')
119+
113120
msr.work(flag_pc=parser.pc_mode, flag_mob=parser.mobile_mode,
114-
flag_quiz=parser.quiz_mode)
121+
flag_quiz=parser.quiz_mode, flag_telegram=parser.telegram_message)
122+
115123

116124
except Exception:
117125
logging.exception('An error has occurred.', exc_info=True)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"type": "Xbox Live",
4+
"short_desc": "XBL",
5+
"currency": "$",
6+
"value": "5",
7+
"price": "4750"
8+
},
9+
{
10+
"type": "Other Gift Voucher",
11+
"short_desc": "GV",
12+
"currency": "$",
13+
"value": "5",
14+
"price": "6750"
15+
}
16+
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"telegram_apikey": "0123456789:AAAAbbCCCCCCCdddd-eeeeeeeeeeeeeeeee",
4+
"telegram_chatid": "-0123456789012"
5+
}
6+
]

msreward/msr.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from msreward.worker import MSRWorker
55
from helper.browser import Browser
66

7+
from helper.telegram import *
8+
79
# URLs
810
DASHBOARD_URL = 'https://account.microsoft.com/rewards/dashboard'
911

@@ -40,17 +42,24 @@ def _quit_browser(self) -> None:
4042
if self.browser:
4143
self.browser.quit()
4244

43-
def work(self, flag_pc: bool, flag_mob: bool, flag_quiz: bool) -> None:
45+
def work(self, flag_pc: bool, flag_mob: bool, flag_quiz: bool, flag_telegram: bool) -> None:
4446
ua = PC_USER_AGENT if flag_pc or flag_quiz else MOBILE_USER_AGENT
4547
if not self._start_browser(ua, log_in=True):
4648
logging.info('Fail to initiate.')
4749
return
4850

49-
summary = self.account.get_summary(log=True)
51+
summary = self.account.get_summary(log=True)
52+
5053
if summary.all_done:
5154
logging.info(msg=f'{"Already done":-^33}')
55+
if flag_telegram:
56+
telegram_update_post_search(self.account.email,summary)
5257
else:
5358
self._work(flag_pc, flag_mob, flag_quiz)
59+
if flag_telegram:
60+
summary = self.account.get_summary(log=False)
61+
telegram_update_post_search(self.account.email,summary)
62+
5463
self._quit_browser()
5564

5665
def _work(self, flag_pc: bool, flag_mob: bool, flag_quiz: bool) -> None:

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
selenium==3.141.0
22
requests==2.25.1
3-
pyotp==2.6.0
3+
pyotp==2.6.0
4+
python-telegram-bot==13.7

0 commit comments

Comments
 (0)