Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

81 строка
2.2 KiB

  1. #!/usr/bin/env python3
  2. import asyncio
  3. import base64
  4. import datetime
  5. import functools
  6. import json
  7. import os
  8. import re
  9. import sys
  10. import telethon
  11. try:
  12. import tqdm
  13. except ImportError:
  14. tqdm = None
  15. API_ID = os.environ['TELEGRAM_API_ID']
  16. API_HASH = os.environ['TELEGRAM_API_HASH']
  17. BOT_TOKEN = os.environ['TELEGRAM_BOT_TOKEN']
  18. URL_PATTERN = re.compile(r'^https?://t\.me/(?:s/)?(?P<channel>[^/]+)/(?P<message>\d+)$')
  19. def stuff_to_json(o):
  20. if isinstance(o, datetime.datetime):
  21. return o.isoformat()
  22. if isinstance(o, bytes):
  23. return f'binary data: {base64.b64encode(o).decode("ascii")}'
  24. raise TypeError(f'Object of type {type(o)} is not JSON serializable')
  25. def download_callback(current, total, bar = None):
  26. if bar is None:
  27. return
  28. bar.total = total #FIXME: Accesses undocumented attribute of tqdm
  29. bar.update(current - bar.n) #FIXME: https://github.com/tqdm/tqdm/issues/1264
  30. async def main():
  31. # Parse URLs
  32. targets = []
  33. for url in sys.argv[1:]:
  34. m = URL_PATTERN.match(url)
  35. if not m:
  36. print(f'Error: {url} is not a recognised Telegram URL', file = sys.stderr)
  37. sys.exit(1)
  38. targets.append((m['channel'], int(m['message'])))
  39. if not targets:
  40. print(f'Usage: telegram-dl.py URL [URL...]', file = sys.stderr)
  41. sys.exit(1)
  42. channelName = targets[0][0]
  43. if not all(x[0] == channelName for x in targets[1:]):
  44. print(f'Error: all URLs must be of the same channel', file = sys.stderr)
  45. sys.exit(1)
  46. ids = [x[1] for x in targets]
  47. # Let's go...
  48. client = telethon.TelegramClient('.telegram-dl', API_ID, API_HASH)
  49. print('Connecting', file = sys.stderr)
  50. await client.start(bot_token = BOT_TOKEN)
  51. print('Fetching messages', file = sys.stderr)
  52. messages = await client.get_messages(channelName, ids = ids)
  53. for message in messages:
  54. if not message:
  55. continue
  56. print(f'Processing message {message.id}', file = sys.stderr)
  57. with open(f'{channelName}_{message.id}.json', 'x') as fp:
  58. json.dump(message.to_dict(), fp, default = stuff_to_json)
  59. if message.media and tqdm:
  60. bar = tqdm.tqdm(unit = 'iB', unit_divisor = 1024, unit_scale = True)
  61. else:
  62. bar = None
  63. try:
  64. await client.download_media(message, progress_callback = functools.partial(download_callback, bar = bar))
  65. finally:
  66. if bar is not None:
  67. bar.close()
  68. asyncio.run(main())