forked from alfem/telegram-downloader-bot
-
Notifications
You must be signed in to change notification settings - Fork 1
/
telethon-download.py
128 lines (95 loc) · 4.06 KB
/
telethon-download.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import asyncio
import logging
import os
from telethon import TelegramClient, errors, types, sync
from telethonSession import getSession, saveSession, saveProgress, getProgress
from typing import Union
loop = asyncio.get_event_loop()
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
def dl_progr(current, total):
global pbar
global prev_curr
units = ['B', 'KB', 'MB', 'GB', 'TB']
unit_index = 0
while total >= 1024 and unit_index < len(units) - 1:
current /= 1024
total /= 1024
unit_index += 1
print(
f'Downloaded {current:.2f} {units[unit_index]} out of {total:.2f} {units[unit_index]}', end='\r')
def get_file_name(message: types.Message) -> Union[str, None]:
filename = None
if isinstance(message.media, types.MessageMediaDocument):
for attr in message.media.document.attributes:
if isinstance(attr, types.DocumentAttributeFilename):
filename = attr.file_name
break
return filename
def get_dl_dir(message: types.Message, base_dir: str) -> str:
msg_date = message.date.strftime('%Y%m%d')
dldir = os.path.join(base_dir, msg_date)
os.makedirs(dldir, mode=0o777, exist_ok=True)
return dldir
async def download_media(client, msg: types.Message, directory: str) -> Union[str, None]:
dldir = get_dl_dir(msg, directory)
filename = get_file_name(msg)
if filename and os.path.exists(os.path.join(dldir, filename)):
logger.info(f'Already downloaded: "{filename}"')
return None
logger.info(f'Downloading "{filename or "N/A"}"')
# downloaded = await fast_download(client, msg, download_folder=dldir)
downloaded = await msg.download_media(file=dldir, progress_callback=dl_progr)
# client.iter_download
logger.info(f'Finished download of "{downloaded}"')
return downloaded
async def main():
global session_path
from dotenv import load_dotenv
if not load_dotenv():
logger.info('No .env file found')
# Your API ID and hash
app_id = os.getenv("TELEGRAM_APP_ID")
app_hash = os.getenv("TELEGRAM_APP_HASH")
invite_link = os.getenv("TELEGRAM_CHANNEL_INVITE_LINK")
download_dir = os.getenv("TELEGRAM_DOWNLOAD_DIR")
limit = int(os.getenv("DOWNLOAD_LIMIT", 10))
session_path = os.getenv("TELEGRAM_DAEMON_SESSION_PATH", "./")
if not app_id or not app_hash or not invite_link or not download_dir:
logger.fatal('Missing environment variables')
return
# Creating the client and connecting
async with TelegramClient(getSession(session_path), api_id=app_id, api_hash=app_hash, receive_updates=False) as client:
saveSession(client.session, session_path)
await client.start()
private_info = await client.get_input_entity(invite_link)
logger.debug(private_info.stringify())
channel = await client.get_entity(private_info.channel_id)
logger.debug(channel.stringify())
try:
async with client.takeout() as takeout:
newer_than_id = int(getProgress(session_path) or 0)
async for message in takeout.iter_messages(
channel,
wait_time=0,
limit=limit,
reverse=True, # from old to new
# filter=types.InputMessagesFilterDocument,
offset_id=newer_than_id
):
logger.debug(message.stringify())
if message.media:
await download_media(takeout, message, directory=download_dir)
# Save the last message id to continue from there if the script is restarted
saveProgress(message.id, session_path)
except errors.TakeoutInitDelayError as e:
print('Must wait', e.seconds, 'before takeout')
return
finally:
await client.disconnect()
if __name__ == '__main__':
# asyncio.run(main())
loop.run_until_complete(main())