Skip to content

Commit

Permalink
Updating all files to tgback2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
NotStatilko committed Nov 2, 2019
1 parent 0fbd3db commit 1d17512
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 92 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,5 @@ venv.bak/

# tgback
.tgback
.dtgback
.session
Binary file modified TelegramBackup.exe
Binary file not shown.
115 changes: 95 additions & 20 deletions TelegramBackup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,34 @@

import os.path

from asyncio import run as asyncio_run
from base64 import b64encode
from NonCipher import NonCipher
from os import system as os_system_
from asyncio import run as asyncio_run
from telethon.errors import FloodWaitError

from tgback import (
TelegramAccount, check_app, restore
from tgback_utils import (
TelegramAccount, restore, make_session
)


def clear_terminal():
os_system_('cls || clear')
print('\n' * 100)
print('\n' * 50)


async def main():
try:
clear_terminal()
while True:
print(''' - TelegramBackup 1.1 -\n\n'''
print(''' - TelegramBackup 2.0 -\n\n'''
'''> 1) Backup Telegram account\n'''
'''>> 2) Change phone number\n'''
'''>>> 3) Decrypt .tgback backup\n'''
'''>>>> 4) Exit from TelegramBackup'''
'''\n\n% Press Ctrl+C in any mode for returning to this page'''
)
selected_section = input('\n@ Input: ')
if selected_section in list('1234'):
if selected_section in list('1234') + ['what\'s new?']:
break
clear_terminal()

Expand All @@ -38,8 +40,7 @@ async def main():
clear_terminal()
api_hash = input('>> API Hash: ')
clear_terminal()
phone = input('>>> Phone Number: ')

phone = input('>>> Phone number: ')
try:
clear_terminal()
print('@ Checking for correctness...')
Expand All @@ -55,7 +56,7 @@ async def main():
code = input('> Confirmation Code: ')
password = input('>> Your Telegram password: ')
clear_terminal()

print('@ Trying to login...')
try:
await account.login(password,code)
Expand All @@ -68,20 +69,86 @@ async def main():
print('@ Backup password generating, please wait...')

file = account.backup(tgback_password, tgback_filename)
clear_terminal()

account.remove_session()
input('@ Successfully backuped and encrypted! ({0})'.format(file))
await main()

except (KeyboardInterrupt, EOFError):
await main()
except:
input('\n@: ! Invalid password or code. Try again.')

except FloodWaitError as e:
clear_terminal()
input('''@: ! Telegram servers return FloodWaitError. '''
'''Please wait {0} seconds '''.format(e.seconds))
await main()
except:
input('''\n\n@: ! App Invalid! Copy and paste from the '''
'''site my.telegram.org. Help: bit.ly/tgback'''
clear_terminal()
input('''@: ! App Invalid! Copy and paste from the '''
'''site my.telegram.org. Help: bit.ly/tgback '''
)
finally:
account.remove_session()

elif selected_section == '2':
input('@ Work in Progress. Check out bit.ly/tgback for updates.')
await main()
clear_terminal()
path_to_tgback = input('> Path to .tgback file: ')
if not os.path.exists(path_to_tgback):
input('@: ! Can\'t open .tgback file. Check your path. ')
await main()
else:
tgback_password = input('>> Password to .tgback file: ')
clear_terminal()
print('@ Backup password generating, please wait...')
try:
restored = restore(path_to_tgback, tgback_password)
restored_backup = restored[0]
primary_hash, hash_of_input_data = restored[1]
except:
clear_terminal()
input('\n@: ! Incorrect Password. ')
await main()
else:
clear_terminal()
make_session(restored_backup)
account = TelegramAccount(*restored_backup[1], restored_backup[0])
await account.connect()
while True:
clear_terminal()
new_phone = input('> Enter your new phone number: ')
try:
code_hash = await account.request_change_phone_code(new_phone)
except:
input('\n@: ! Number is invalid or already in use. ')
else: break

while True:
clear_terminal()
print('>> Confirmation code has been sent to ' + new_phone)
code = input('@ >> Code: ')

try:
await account.change_phone(code, code_hash, new_phone)
except:
input('\n@: ! Invalid code. Try again or hit Ctrl+C. ')
else: break

clear_terminal()
account.remove_session()

new_backup = (new_phone, restored_backup[1], restored_backup[2])
nc = NonCipher(primary_hash=primary_hash, hash_of_input_data=hash_of_input_data)
nc.init()

with open(path_to_tgback,'wb') as f:
f.write(b64encode(nc.encrypt(repr(new_backup)).encode()))

input('''@: Your phone has been successfully changed! '''
'''Now you can login to your Telegram account with phone ''' + new_phone + ' ! ')
await main()

elif selected_section == '3':
path_to_backup = input('> Direct path to .tgback file: ')
Expand All @@ -93,20 +160,28 @@ async def main():

name = os.path.split(path_to_backup)[1].split('.tgback')[0]

restored = restore(path_to_backup, tgback_password)
if len(restored) == 1 or not check_app(restored[0], restored[1]):
input('\n@: ! Incorrect Password. Please, try again.')
try:
restored = restore(path_to_backup, tgback_password)
clear_terminal()
except:
input('\n@: ! Incorrect Password. ')
await main()
else:
with open(name + '.dtgback','w') as f:
f.write(' '.join(restored))
with open(name + '.dtgback','wb') as f:
f.write(repr(restored).encode())

input('@ Successfully decrypted! ({0})'.format(name + '.dtgback'))
await main()
else:
input('\n@: ! Can\'t open .tgback file. Please check your path.')

elif selected_section == '4':
exit()


elif selected_section == 'what\'s new?':
input('@: # New mode and first stable version! bit.ly/tgback. NonSense. ')
await main()

except (KeyboardInterrupt, EOFError):
await main()

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Telethon==1.9.0

NonCipher==5.1
Binary file added template.tsession
Binary file not shown.
72 changes: 0 additions & 72 deletions tgback.py

This file was deleted.

110 changes: 110 additions & 0 deletions tgback_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from sqlite3 import connect as sqlite3_connect
from base64 import b64encode, b64decode
from hashlib import md5, sha512
from shutil import copyfile
from ast import literal_eval
from time import time

from telethon import TelegramClient
from telethon.errors import PhoneNumberInvalidError, SessionPasswordNeededError
from telethon.tl.functions.account import ChangePhoneRequest, SendChangePhoneCodeRequest
from telethon.tl.types import CodeSettings
from telethon.sessions.abstract import Session

from NonCipher import NonCipher, get_hash_of


class TelegramAccount:
def __init__(self, api_id: int, api_hash: str, phone_number: str):
self._api_id = api_id
self._api_hash = api_hash
self._phone_number = phone_number
self._session_filename = 'tgback_' + md5(str(api_id).encode()).hexdigest() + '.session'
self._TelegramClient = TelegramClient(
self._session_filename,
self._api_id, self._api_hash
)
async def connect(self):
await self._TelegramClient.connect()

def remove_session(self):
try:
self._TelegramClient.session._conn.commit()
self._TelegramClient.session.close()
self._TelegramClient.session.delete()
except:
return False
return True

async def request_code(self):
await self._TelegramClient.send_code_request(self._phone_number)

async def login(self, password: str=None, code: int=None):
if not await self._TelegramClient.is_user_authorized():
try:
await self._TelegramClient.sign_in(self._phone_number, code)
except SessionPasswordNeededError:
await self._TelegramClient.sign_in(password=password)

async def request_change_phone_code(self, new_number: str):
request = change_phone_request = await self._TelegramClient(SendChangePhoneCodeRequest(
phone_number = new_number,
settings = CodeSettings(allow_flashcall=True, current_number=True)
))
return request.phone_code_hash

async def change_phone(self, code: str, code_hash: str, new_number: str):
await self._TelegramClient(ChangePhoneRequest(
phone_number=new_number, phone_code=code,
phone_code_hash=code_hash
))

def backup(self, password: str , filename: str=None):
nc = NonCipher(password, sha512(password.encode()).hexdigest(), 5_000_000)
nc.init()

filename = (filename if filename else str(int(time()))) + '.tgback'

session_db = sqlite3_connect(self._session_filename)
session_cursor = session_db.cursor()

metadata = session_cursor.execute('SELECT * FROM sessions')
metadata = metadata.fetchall()
session_db.close()

to_backup = (self._phone_number,
(self._api_id, self._api_hash), metadata[0]
)
backup = b64encode(nc.encrypt(repr(to_backup)).encode())

with open(filename,'wb') as f:
f.write(backup)

return filename


def restore(tgback_file_path: str, password: str):
nc = NonCipher(password, sha512(password.encode()).hexdigest(), 5_000_000)
nc.init()

with open(tgback_file_path,'rb') as f:
restored = nc.decrypt(b64decode(f.read()))
return (literal_eval(restored.decode()), (nc._primary_hash, nc._hash_of_input_data))


def make_session(restored_backup: tuple):
session_filename = 'tgback_' + md5(
str(restored_backup[1][0]).encode()
).hexdigest() + '.session'

copyfile('template.tsession', session_filename)

session_db = sqlite3_connect(session_filename)
session_cursor = session_db.cursor()

session_cursor.execute(
'INSERT INTO sessions VALUES (?,?,?,?,?)',
restored_backup[2]
)
session_db.commit()
session_db.close()

0 comments on commit 1d17512

Please sign in to comment.