Skip to content

Commit

Permalink
Fixed import errors
Browse files Browse the repository at this point in the history
  • Loading branch information
rohittp0 committed Feb 9, 2021
1 parent 4ba9120 commit 047d875
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 0 deletions.
1 change: 1 addition & 0 deletions gramup/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# init file for the program.
124 changes: 124 additions & 0 deletions gramup/backup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# This is a utility to use Telegram's unlimited storage for backup.
# Copyright (C) 2021 Rohit T P
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see https://www.gnu.org/licenses/

from datetime import datetime
from os.path import relpath
from pathlib import Path
import speedtest
import time
try :
import utils
except :
from .utils import *

def getUploadedFiles(tg,chat_id) :
last_id = 0
files = set([])

while True :
messages = tg.call_method(
"getChatHistory",
{
"chat_id": chat_id,
"offset": 0,
"limit": 100,
"only_local": False,
"from_message_id": last_id
}
)

messages.wait()
if len(messages.update["messages"]) == 0 : break
for message in messages.update["messages"] :
if "document" in message["content"] and message["content"]["document"]["document"]["local"]["can_be_downloaded"] :
files.add(message["content"]["document"]["document"]["local"]["path"])
last_id = message["id"]

return files

def sendFile(tg,chat_id,file_path,parent_folder="/") :
param= {
'chat_id': chat_id,
'input_message_content': {
'@type':'inputMessageDocument',
'document': {
'@type':'inputFileLocal',
'path': file_path
},
'caption' : {
'@type': 'formattedText',
'text': str(relpath(file_path,parent_folder))
},
'disable_content_type_detection': True
},
'@extra': {
'path': file_path
}
}
return tg.call_method("sendMessage",param)

def showResults(done,failed,errors) :
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print(f"Total files to upload {done+failed}")
print(f"{done} files uploaded")
print(f"{failed} files failed to upload")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

if failed > 0 and input("Do you wan't to see the error log (y/N) ? : ").lower() == "y" :
print(errors)

print("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")
print("Press crtl+c once you recive all files\n\n")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")

return None

def backup(tg,chat_id,back_up_folders):
print("\nGetting list of uploaded files")
old_files = getUploadedFiles(tg,chat_id)

new_files = []
print("Getting list of files to upload")

for folder in back_up_folders :
new_files.extend(utils.getNewFiles(folder,old_files))

if len(new_files) == 0 : return showResults(0,0,"")

print("Measuring internet speed")
total_files = len(new_files)
net_speed = speedtest.Speedtest().upload()/8
(done,failed,errors) = (0,0,"")

utils.printProgressBar(0,total_files, autosize = True)
tg.send_message(chat_id=chat_id,text=f"Backup started on {datetime.today().strftime('%Y-%m-%d %I:%M %p')}")
tg.send_message(chat_id=chat_id,text=f"\nBacking up {total_files} files @ {net_speed/1000000} MBps.");

for (new_file,folder) in new_files :
task = sendFile(tg,chat_id,new_file,folder)
task.wait();
if(task.error_info == None ) :
time.sleep(task.update["content"]["document"]["document"]["size"]/net_speed)
done += 1
else :
failed += 1
errors += str(task.error_info) + "\n\n"
utils.printProgressBar(done+failed, total_files, prefix = 'Uploading:', suffix = 'Complete', autosize = True)

tg.send_message(chat_id=chat_id, text=f"Backup ended on {datetime.today().strftime('%Y-%m-%d %I:%M %p')}");

showResults(done,failed,errors)
tg.idle()
26 changes: 26 additions & 0 deletions gramup/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This is a utility to use Telegram's unlimited storage for backup.
# Copyright (C) 2021 Rohit T P
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see https://www.gnu.org/licenses/

from os.path import expanduser,join

API_ID="2754829"
API_HASH="57853ffaed0830f9c16b3a3bd44f17f7"
DATABASE_ENCRYPTION_KEY="MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daSan9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTwEfzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3nSlv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB"
FILES_DIR=join(expanduser("~"),".gramup/messages/")
MESGS_DIR=join(expanduser("~"),".gramup/messages/files")
DATA_FILE=join(expanduser("~"),".gramup/saved")
RE_FOLDER=join(expanduser("~"),"Restored/")

99 changes: 99 additions & 0 deletions gramup/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# This is a utility to use Telegram's unlimited storage for backup.
# Copyright (C) 2021 Rohit T P
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see https://www.gnu.org/licenses/

import pickle
import os
from telegram.client import Telegram
from telegram.client import AuthorizationState
try:
import constants
except:
from .constants import *

def loadData():
try:
with open(constants.DATA_FILE, "rb") as dbfile:
db = pickle.load(dbfile)
return (db["phone_number"],db["chat_id"],db["back_up_folders"])

except Exception as e :
ph_no = input("Enter your phone number with country code: ")
bup_folders = set(input("Enter path to folders to be backedup ( seperated by ',' ): ").split(","))
chat_id = input("Enter the chat ID to be used for backup (leave blank if you are unsure): ")

if not chat_id.isnumeric() : chat_id = None

os.makedirs(os.path.dirname(constants.DATA_FILE), exist_ok=True)
os.makedirs(os.path.dirname(constants.FILES_DIR), exist_ok=True)

with open(constants.DATA_FILE, "wb") as dbfile:
data = { "phone_number": phone_number, "chat_id": chat_id, "back_up_folders": bup_folders }
pickle.dump(data, dbfile)

return (ph_no,chat_id,bup_folders)

def login(call_back):

(ph_no,chat_id,bup_folders) = loadData()

tg = Telegram(
api_id=constants.API_ID,
api_hash=constants.API_HASH,
files_directory=constants.FILES_DIR,
database_encryption_key=constants.DATABASE_ENCRYPTION_KEY,
tdlib_verbosity=0,
phone=ph_no
)

tg.call_method(
'setOption',
{
'name': 'prefer_ipv6',
'value': {'@type': 'optionValueBoolean', 'value': False},
},
)

tg.login()
tg.get_chats().wait()

if chat_id == None :
def messageHandler(update) :
message_content = update['message']['content'].get('text', {})
message_text = message_content.get('text', '').lower()

if message_text == 'use_this_chat':
with open(constants.DATA_FILE, "wb") as dbfile:
pickle.dump(
{
"phone_number": ph_no,
"chat_id": update['message']['chat_id'],
"back_up_folders": bup_folders
},
dbfile
)

tg.send_message(
chat_id=chat_id,
text='Chat selected for backup. \nIf this was not the first time then restart app.'
)

call_back(tg,chat_id,bup_folders)
tg.add_message_handler(messageHandler)
print("Send 'use_this_chat' to the chat you wan't to use for backup (case insensitive)")
tg.idle() # blocking waiting for CTRL+C

call_back(tg,chat_id,bup_folders)

41 changes: 41 additions & 0 deletions gramup/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This is a utility to use Telegram's unlimited storage for backup.
# Copyright (C) 2021 Rohit T P
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see https://www.gnu.org/licenses/

try:
from login import login
from backup import backup
from restore import restore
except :
from .login import login
from .backup import backup
from .restore import restore

def clientReady(tg,chat_id,bup_folders) :
choise = input("Backup (b) or Restore (r) ? : ")

if choise == "b" :
backup(tg,chat_id,bup_folders)
elif choise == "r" :
restore(tg,chat_id)

print("Invalid option")

def main() :
login(clientReady)

if __name__ == "__main__" :
main()

100 changes: 100 additions & 0 deletions gramup/restore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# This is a utility to use Telegram's unlimited storage for backup.
# Copyright (C) 2021 Rohit T P
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see https://www.gnu.org/licenses/

from shutil import copyfile,rmtree
from os.path import join,dirname
from os import makedirs
try :
from constants import RE_FOLDER,MESGS_DIR
from utils import printProgressBar
except :
from .constants import RE_FOLDER,MESGS_DIR
from .utils import printProgressBar

def getUploadedFiles(tg,chat_id) :
last_id = 0
files = []

while True :
messages = tg.call_method(
"getChatHistory",
{
"chat_id": chat_id,
"offset": 0,
"limit": 100,
"only_local": False,
"from_message_id": last_id
}
)

messages.wait()
if len(messages.update["messages"]) == 0 : break
for message in messages.update["messages"] :
print(f"{message}\n\n")
if "document" in message["content"] and message["content"]["document"]["document"]["local"]["can_be_downloaded"] :
files.append((message["content"]["document"]["document"]["id"],message["content"]["caption"]["text"]))
last_id = message["id"]

return files

def downloadFiles(tg,files) :
(restored,failed,total) = (0,0,len(files))
errors = ""

if total <= 0 : return (restored,failed,errors)

printProgressBar(0,total, autosize = True)

for (file_id,path) in files :
task = tg.call_method("downloadFile",
{
"file_id": file_id,
"priority": 32,
"offset": 0,
"limit": 0,
"synchronous": True
}
)
task.wait()
if not path : path = str(file_id)
if task.error_info == None :
makedirs(dirname(join(RE_FOLDER,path)), exist_ok=True)
copyfile(task.update["local"]["path"],join(RE_FOLDER,path))
restored += 1
else :
errors += str(task.error_info) + "\n"
failed += 1
printProgressBar(restored+failed, total, prefix = 'Restoring:', suffix = 'Complete', autosize = True)

return (restored,failed,errors)

def restore(tg,chat_id) :
print("\nGetting file list")
files = getUploadedFiles(tg,chat_id)

print(f"Restoring {len(files)} files\n")
(restored,failed,errors) = downloadFiles(tg,files)

print("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
print(f"{restored} files restored to ~/Restored")
print(f"{failed} failed \n")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")

rmtree(MESGS_DIR)

if failed > 0 and input("Do you wan't to see the error log (y/N) ? : ").lower() == "y" :
print(errors)

Loading

0 comments on commit 047d875

Please sign in to comment.