From a6f845e6b77cdc0d46cfc58caaa10e94311fb8c1 Mon Sep 17 00:00:00 2001 From: Timofei Date: Sun, 4 Oct 2020 00:31:44 +0500 Subject: [PATCH 1/3] fix region blocking --- api.py | 49 ++++++++++++++++++++++++++++++++----------------- auth.py | 15 +++++++++------ main.py | 7 ++++--- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/api.py b/api.py index 796383c..c167a57 100644 --- a/api.py +++ b/api.py @@ -5,35 +5,50 @@ class Tele2Api: session: ClientSession access_token: str - def __init__(self, phone_number: str, access_token: str = ''): - base_api = f'https://msk.tele2.ru/api/subscribers/{phone_number}' + def __init__(self, phone_number: str, region_url: str = '', + access_token: str = ''): + base_api = f'https://{region_url}/api/subscribers/{phone_number}' + self.region_query_api = 'https://tele2.ru/' self.market_api = f'{base_api}/exchange/lots/created' self.rests_api = f'{base_api}/rests' self.profile_api = f'{base_api}/profile' - self.sms_post_url = f'https://msk.tele2.ru/api/validation/number/{phone_number}' - self.auth_post_url = 'https://my.tele2.ru/auth/realms/tele2-b2c/protocol/openid-connect/token' + self.sms_post_url = 'https://{}/api/validation/number/{}' + self.auth_post_url = 'https://{}/auth/realms/tele2-b2c/protocol/openid-connect/token' self.access_token = access_token async def __aenter__(self): - self.session = ClientSession(headers={ - 'Authorization': f'Bearer {self.access_token}' - }) + headers = {} + if self.access_token: + headers['Authorization'] = f'Bearer {self.access_token}' + self.session = ClientSession(headers=headers) return self async def __aexit__(self, *args): await self.session.close() - async def send_sms_code(self): - await self.session.post(self.sms_post_url, json={'sender': 'Tele2'}) + async def send_sms_code(self, phone_number: str, region_url: str): + await self.session.post( + self.sms_post_url.format(region_url, phone_number), + json={'sender': 'Tele2'}) - async def get_access_token(self, phone_number: str, sms_code: str): - response = await self.session.post(self.auth_post_url, data={ - 'client_id': 'digital-suite-web-app', - 'grant_type': 'password', - 'username': phone_number, - 'password': sms_code, - 'password_type': 'sms_code' - }) + async def determine_region(self): + resp = await self.session.get(self.region_query_api, + allow_redirects=False) + full_region_url = resp.headers['Location'] + region_url = full_region_url.split('/')[2] + self.region_url = region_url + return region_url + + async def get_access_token(self, phone_number: str, sms_code: str, + region_url: str): + response = await self.session.post( + self.auth_post_url.format(region_url), data={ + 'client_id': 'digital-suite-web-app', + 'grant_type': 'password', + 'username': phone_number, + 'password': sms_code, + 'password_type': 'sms_code' + }) return (await response.json())['access_token'] async def check_auth_code(self): diff --git a/auth.py b/auth.py index a4dbb7f..c849e11 100644 --- a/auth.py +++ b/auth.py @@ -40,23 +40,25 @@ def get_phone_number(): return phone_number -async def get_access_token(api: Tele2Api, phone_number: str): - await api.send_sms_code() +async def get_access_token(api: Tele2Api, phone_number: str, region_url: str): + await api.send_sms_code(phone_number, region_url) while True: try: sms_code = input(Fore.LIGHTCYAN_EX + 'SMS code: ') - access_token = await api.get_access_token(phone_number, sms_code) + access_token = await api.get_access_token(phone_number, sms_code, + region_url) return access_token except KeyError: print(Fore.RED + 'Invalid SMS-сode. Try again') -def save_config(phone_number: str, access_token: str): +def save_config(phone_number: str, access_token: str, region_url: str): print(Fore.GREEN + 'Successful auth!') with open('config.json', 'w') as f: json.dump({ 'number': phone_number, 'token': access_token, + 'region_url': region_url, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }, f, indent=2) print(Fore.YELLOW + 'Token saved to ' + Fore.BLUE + 'config.json') @@ -66,8 +68,9 @@ async def main(): colorama_init(autoreset=True) phone_number = get_phone_number() async with Tele2Api(phone_number) as api: - access_token = await get_access_token(api, phone_number) - save_config(phone_number, access_token) + region_url = await api.determine_region() + access_token = await get_access_token(api, phone_number, region_url) + save_config(phone_number, access_token, region_url) if __name__ == '__main__': diff --git a/main.py b/main.py index e2fbb76..5c2d0e2 100644 --- a/main.py +++ b/main.py @@ -14,8 +14,9 @@ def load_config(): obj = json.load(f) phone_number = obj['number'] access_token = obj['token'] + region_url = obj['region_url'] date = obj['date'] - return access_token, date, phone_number + return access_token, date, phone_number, region_url async def check_auth(api: Tele2Api): @@ -207,8 +208,8 @@ async def menu_again_action(api, deleted_lots): async def main(): - access_token, date, phone_number = load_config() - async with Tele2Api(phone_number, access_token) as api: + access_token, date, phone_number, region_url = load_config() + async with Tele2Api(phone_number, region_url, access_token) as api: colorama_init(autoreset=True) await check_auth(api) print_token_time(date) From 38abecb4db62a5483b4dbc23cc0c7868f17585d6 Mon Sep 17 00:00:00 2001 From: Timofei Date: Sun, 4 Oct 2020 00:34:26 +0500 Subject: [PATCH 2/3] fix region blocking --- README.md | 61 ++++++++++++++++++++----------------------------------- api.py | 49 ++++++++++++++++---------------------------- auth.py | 15 ++++++-------- main.py | 7 +++---- 4 files changed, 48 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index cafb688..7bfd1a7 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,40 @@ # Tele2 Profit -Console application that allows you to quickly sell your Tele2 data on their **Market** - +Simple console app that allows you to quickly sell your Tele2 data. ## Features * Quick market listing of your Tele2 data * Bumping up lots that haven't been sold -* Asyncronous queries to _Tele2 API_ allow to perform multiple actions simultaneously - ## Demo -![imgur demo gif](https://i.imgur.com/xKTTRDS.gif) - +![Imgur demo gif](https://i.imgur.com/xKTTRDS.gif) ## Installation -#### Steps: 1. Clone repository 2. Setup virtual environment (optional) 2.1. Create **venv** with `python -m venv venv` - 2.2. Activate by running this comand (just paste it after previous and hit enter) `venv\Scripts\activate` -3. Install dependencies with `pip install -r requirements.txt` -4. You are good to go! - -#### Command list (Windows): -* `git clone https://github.com/raritetmolodoy/tele2-profit.git` -* `cd tele2-profit` -* `python -m venv venv` -* `venv\Scripts\activate` -* `pip install -r requirements.txt` - + 2.2. Activate by running `venv\Scripts\activate` ## Usage -1. Login with running `python auth.py`. Access token works 4 hours, then it needs to be updated. -**note: access-token saves on your PC _only_, in `./config.json` file** -2. Run `python main.py` and select action. - -### FYI: Current Tele2 market lot rules - -#### Gigabytes -* Minimum GB amount - **1 GB** -* Minimum GB price - **15 rub/GB**, maximum - **50 rub/GB** - -#### Minutes -* Minimum minute amount - **50 min** -* Minimum minute price - **0.8 rub/min**, maximum - **2 rub/min** +1. Login with `auth.py`. +**note: access-token saves on your PC _only_ in `./config.json` file** +2. Run `main.py` and select action. + +### Current Tele2 market lot rules: +##### Gigabytes: +* `Minimum GB amount - 1 GB` +* `Minimum GB price - 15 rub/GB, maximum - 50 rub/GB` +##### Minutes: +* `Minimum minute amount - 50 min` +* `Minimum minute price - 0.8 rub/min, maximum - 2 rub/min` ### Listing lots -**Preparing lots is done with this syntax: ` `** -For example: `60 80` - 60 minutes (or gb) will be listed for 80 rub. - -**Standard syntax can be shortened to just ``** -For example: `68` - 68 minutes (or gb) will be listed with **minimum** possible price *(in this case - 55 rub if minutes, 1020 rub if gb)*. -When done leave input field empty (just hit enter) and you will jump to the next part. - +Preparing lots is done with this syntax: +` `, for example: `60 80` - 60 minutes (or gb) +will be listed for 80 rub. +You can shortcut it by just ``, +for example `68` - 68 minutes (or gb) will be listed with **minimum** +possible price *(in this case 55 rub if minutes, 1020 rub if gb)*. ## TODO -* Use refresh token to support longer auth persistence (currently 4 hours) +* Use refresh token to support longer auth persistence (currently 240 min.) + diff --git a/api.py b/api.py index c167a57..796383c 100644 --- a/api.py +++ b/api.py @@ -5,50 +5,35 @@ class Tele2Api: session: ClientSession access_token: str - def __init__(self, phone_number: str, region_url: str = '', - access_token: str = ''): - base_api = f'https://{region_url}/api/subscribers/{phone_number}' - self.region_query_api = 'https://tele2.ru/' + def __init__(self, phone_number: str, access_token: str = ''): + base_api = f'https://msk.tele2.ru/api/subscribers/{phone_number}' self.market_api = f'{base_api}/exchange/lots/created' self.rests_api = f'{base_api}/rests' self.profile_api = f'{base_api}/profile' - self.sms_post_url = 'https://{}/api/validation/number/{}' - self.auth_post_url = 'https://{}/auth/realms/tele2-b2c/protocol/openid-connect/token' + self.sms_post_url = f'https://msk.tele2.ru/api/validation/number/{phone_number}' + self.auth_post_url = 'https://my.tele2.ru/auth/realms/tele2-b2c/protocol/openid-connect/token' self.access_token = access_token async def __aenter__(self): - headers = {} - if self.access_token: - headers['Authorization'] = f'Bearer {self.access_token}' - self.session = ClientSession(headers=headers) + self.session = ClientSession(headers={ + 'Authorization': f'Bearer {self.access_token}' + }) return self async def __aexit__(self, *args): await self.session.close() - async def send_sms_code(self, phone_number: str, region_url: str): - await self.session.post( - self.sms_post_url.format(region_url, phone_number), - json={'sender': 'Tele2'}) - - async def determine_region(self): - resp = await self.session.get(self.region_query_api, - allow_redirects=False) - full_region_url = resp.headers['Location'] - region_url = full_region_url.split('/')[2] - self.region_url = region_url - return region_url + async def send_sms_code(self): + await self.session.post(self.sms_post_url, json={'sender': 'Tele2'}) - async def get_access_token(self, phone_number: str, sms_code: str, - region_url: str): - response = await self.session.post( - self.auth_post_url.format(region_url), data={ - 'client_id': 'digital-suite-web-app', - 'grant_type': 'password', - 'username': phone_number, - 'password': sms_code, - 'password_type': 'sms_code' - }) + async def get_access_token(self, phone_number: str, sms_code: str): + response = await self.session.post(self.auth_post_url, data={ + 'client_id': 'digital-suite-web-app', + 'grant_type': 'password', + 'username': phone_number, + 'password': sms_code, + 'password_type': 'sms_code' + }) return (await response.json())['access_token'] async def check_auth_code(self): diff --git a/auth.py b/auth.py index c849e11..a4dbb7f 100644 --- a/auth.py +++ b/auth.py @@ -40,25 +40,23 @@ def get_phone_number(): return phone_number -async def get_access_token(api: Tele2Api, phone_number: str, region_url: str): - await api.send_sms_code(phone_number, region_url) +async def get_access_token(api: Tele2Api, phone_number: str): + await api.send_sms_code() while True: try: sms_code = input(Fore.LIGHTCYAN_EX + 'SMS code: ') - access_token = await api.get_access_token(phone_number, sms_code, - region_url) + access_token = await api.get_access_token(phone_number, sms_code) return access_token except KeyError: print(Fore.RED + 'Invalid SMS-сode. Try again') -def save_config(phone_number: str, access_token: str, region_url: str): +def save_config(phone_number: str, access_token: str): print(Fore.GREEN + 'Successful auth!') with open('config.json', 'w') as f: json.dump({ 'number': phone_number, 'token': access_token, - 'region_url': region_url, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }, f, indent=2) print(Fore.YELLOW + 'Token saved to ' + Fore.BLUE + 'config.json') @@ -68,9 +66,8 @@ async def main(): colorama_init(autoreset=True) phone_number = get_phone_number() async with Tele2Api(phone_number) as api: - region_url = await api.determine_region() - access_token = await get_access_token(api, phone_number, region_url) - save_config(phone_number, access_token, region_url) + access_token = await get_access_token(api, phone_number) + save_config(phone_number, access_token) if __name__ == '__main__': diff --git a/main.py b/main.py index 5c2d0e2..e2fbb76 100644 --- a/main.py +++ b/main.py @@ -14,9 +14,8 @@ def load_config(): obj = json.load(f) phone_number = obj['number'] access_token = obj['token'] - region_url = obj['region_url'] date = obj['date'] - return access_token, date, phone_number, region_url + return access_token, date, phone_number async def check_auth(api: Tele2Api): @@ -208,8 +207,8 @@ async def menu_again_action(api, deleted_lots): async def main(): - access_token, date, phone_number, region_url = load_config() - async with Tele2Api(phone_number, region_url, access_token) as api: + access_token, date, phone_number = load_config() + async with Tele2Api(phone_number, access_token) as api: colorama_init(autoreset=True) await check_auth(api) print_token_time(date) From e00f46557e45e0287be075e9d7d3292c978964aa Mon Sep 17 00:00:00 2001 From: Timofei Date: Sun, 4 Oct 2020 00:41:36 +0500 Subject: [PATCH 3/3] fix region blocking --- README.md | 61 +++++++++++++++++++++++++++++++++++-------------------- api.py | 49 ++++++++++++++++++++++++++++---------------- auth.py | 15 ++++++++------ main.py | 7 ++++--- 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 7bfd1a7..cafb688 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,57 @@ # Tele2 Profit -Simple console app that allows you to quickly sell your Tele2 data. +Console application that allows you to quickly sell your Tele2 data on their **Market** + ## Features * Quick market listing of your Tele2 data * Bumping up lots that haven't been sold +* Asyncronous queries to _Tele2 API_ allow to perform multiple actions simultaneously + ## Demo -![Imgur demo gif](https://i.imgur.com/xKTTRDS.gif) +![imgur demo gif](https://i.imgur.com/xKTTRDS.gif) + ## Installation +#### Steps: 1. Clone repository 2. Setup virtual environment (optional) 2.1. Create **venv** with `python -m venv venv` - 2.2. Activate by running `venv\Scripts\activate` + 2.2. Activate by running this comand (just paste it after previous and hit enter) `venv\Scripts\activate` +3. Install dependencies with `pip install -r requirements.txt` +4. You are good to go! + +#### Command list (Windows): +* `git clone https://github.com/raritetmolodoy/tele2-profit.git` +* `cd tele2-profit` +* `python -m venv venv` +* `venv\Scripts\activate` +* `pip install -r requirements.txt` + ## Usage -1. Login with `auth.py`. -**note: access-token saves on your PC _only_ in `./config.json` file** -2. Run `main.py` and select action. - -### Current Tele2 market lot rules: -##### Gigabytes: -* `Minimum GB amount - 1 GB` -* `Minimum GB price - 15 rub/GB, maximum - 50 rub/GB` -##### Minutes: -* `Minimum minute amount - 50 min` -* `Minimum minute price - 0.8 rub/min, maximum - 2 rub/min` +1. Login with running `python auth.py`. Access token works 4 hours, then it needs to be updated. +**note: access-token saves on your PC _only_, in `./config.json` file** +2. Run `python main.py` and select action. + +### FYI: Current Tele2 market lot rules + +#### Gigabytes +* Minimum GB amount - **1 GB** +* Minimum GB price - **15 rub/GB**, maximum - **50 rub/GB** + +#### Minutes +* Minimum minute amount - **50 min** +* Minimum minute price - **0.8 rub/min**, maximum - **2 rub/min** ### Listing lots -Preparing lots is done with this syntax: -` `, for example: `60 80` - 60 minutes (or gb) -will be listed for 80 rub. -You can shortcut it by just ``, -for example `68` - 68 minutes (or gb) will be listed with **minimum** -possible price *(in this case 55 rub if minutes, 1020 rub if gb)*. +**Preparing lots is done with this syntax: ` `** +For example: `60 80` - 60 minutes (or gb) will be listed for 80 rub. -## TODO -* Use refresh token to support longer auth persistence (currently 240 min.) +**Standard syntax can be shortened to just ``** +For example: `68` - 68 minutes (or gb) will be listed with **minimum** possible price *(in this case - 55 rub if minutes, 1020 rub if gb)*. +When done leave input field empty (just hit enter) and you will jump to the next part. + +## TODO +* Use refresh token to support longer auth persistence (currently 4 hours) diff --git a/api.py b/api.py index 796383c..c167a57 100644 --- a/api.py +++ b/api.py @@ -5,35 +5,50 @@ class Tele2Api: session: ClientSession access_token: str - def __init__(self, phone_number: str, access_token: str = ''): - base_api = f'https://msk.tele2.ru/api/subscribers/{phone_number}' + def __init__(self, phone_number: str, region_url: str = '', + access_token: str = ''): + base_api = f'https://{region_url}/api/subscribers/{phone_number}' + self.region_query_api = 'https://tele2.ru/' self.market_api = f'{base_api}/exchange/lots/created' self.rests_api = f'{base_api}/rests' self.profile_api = f'{base_api}/profile' - self.sms_post_url = f'https://msk.tele2.ru/api/validation/number/{phone_number}' - self.auth_post_url = 'https://my.tele2.ru/auth/realms/tele2-b2c/protocol/openid-connect/token' + self.sms_post_url = 'https://{}/api/validation/number/{}' + self.auth_post_url = 'https://{}/auth/realms/tele2-b2c/protocol/openid-connect/token' self.access_token = access_token async def __aenter__(self): - self.session = ClientSession(headers={ - 'Authorization': f'Bearer {self.access_token}' - }) + headers = {} + if self.access_token: + headers['Authorization'] = f'Bearer {self.access_token}' + self.session = ClientSession(headers=headers) return self async def __aexit__(self, *args): await self.session.close() - async def send_sms_code(self): - await self.session.post(self.sms_post_url, json={'sender': 'Tele2'}) + async def send_sms_code(self, phone_number: str, region_url: str): + await self.session.post( + self.sms_post_url.format(region_url, phone_number), + json={'sender': 'Tele2'}) - async def get_access_token(self, phone_number: str, sms_code: str): - response = await self.session.post(self.auth_post_url, data={ - 'client_id': 'digital-suite-web-app', - 'grant_type': 'password', - 'username': phone_number, - 'password': sms_code, - 'password_type': 'sms_code' - }) + async def determine_region(self): + resp = await self.session.get(self.region_query_api, + allow_redirects=False) + full_region_url = resp.headers['Location'] + region_url = full_region_url.split('/')[2] + self.region_url = region_url + return region_url + + async def get_access_token(self, phone_number: str, sms_code: str, + region_url: str): + response = await self.session.post( + self.auth_post_url.format(region_url), data={ + 'client_id': 'digital-suite-web-app', + 'grant_type': 'password', + 'username': phone_number, + 'password': sms_code, + 'password_type': 'sms_code' + }) return (await response.json())['access_token'] async def check_auth_code(self): diff --git a/auth.py b/auth.py index a4dbb7f..c849e11 100644 --- a/auth.py +++ b/auth.py @@ -40,23 +40,25 @@ def get_phone_number(): return phone_number -async def get_access_token(api: Tele2Api, phone_number: str): - await api.send_sms_code() +async def get_access_token(api: Tele2Api, phone_number: str, region_url: str): + await api.send_sms_code(phone_number, region_url) while True: try: sms_code = input(Fore.LIGHTCYAN_EX + 'SMS code: ') - access_token = await api.get_access_token(phone_number, sms_code) + access_token = await api.get_access_token(phone_number, sms_code, + region_url) return access_token except KeyError: print(Fore.RED + 'Invalid SMS-сode. Try again') -def save_config(phone_number: str, access_token: str): +def save_config(phone_number: str, access_token: str, region_url: str): print(Fore.GREEN + 'Successful auth!') with open('config.json', 'w') as f: json.dump({ 'number': phone_number, 'token': access_token, + 'region_url': region_url, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }, f, indent=2) print(Fore.YELLOW + 'Token saved to ' + Fore.BLUE + 'config.json') @@ -66,8 +68,9 @@ async def main(): colorama_init(autoreset=True) phone_number = get_phone_number() async with Tele2Api(phone_number) as api: - access_token = await get_access_token(api, phone_number) - save_config(phone_number, access_token) + region_url = await api.determine_region() + access_token = await get_access_token(api, phone_number, region_url) + save_config(phone_number, access_token, region_url) if __name__ == '__main__': diff --git a/main.py b/main.py index e2fbb76..5c2d0e2 100644 --- a/main.py +++ b/main.py @@ -14,8 +14,9 @@ def load_config(): obj = json.load(f) phone_number = obj['number'] access_token = obj['token'] + region_url = obj['region_url'] date = obj['date'] - return access_token, date, phone_number + return access_token, date, phone_number, region_url async def check_auth(api: Tele2Api): @@ -207,8 +208,8 @@ async def menu_again_action(api, deleted_lots): async def main(): - access_token, date, phone_number = load_config() - async with Tele2Api(phone_number, access_token) as api: + access_token, date, phone_number, region_url = load_config() + async with Tele2Api(phone_number, region_url, access_token) as api: colorama_init(autoreset=True) await check_auth(api) print_token_time(date)