A Tool to download a entire Chat from Telegram to have a handy backup.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

151 行
4.3KB

  1. #!/usr/bin/env python3
  2. import configparser
  3. import os
  4. import sys
  5. from datetime import timedelta
  6. from telethon import TelegramClient, events
  7. from telethon.tl.types import User, Channel
  8. def strip(str):
  9. return ''.join(e for e in str if e.isalnum())
  10. def isBot(dialog):
  11. if not isinstance(d.entity, User):
  12. return False
  13. return d.entity.bot
  14. def isChannel(dialog):
  15. return isinstance(dialog, Channel)
  16. def printDialog(id, d):
  17. #print(d)
  18. # print (d.id, " ", d.name," ", d.pinned)
  19. print('{0:2d} | {1:14d} | {2:30} | {3:1}'.format(id, d.id, d.name, d.pinned))
  20. def saveMessage(message, file, dlid, ownid):
  21. out = None
  22. if message.message:
  23. # print(message)
  24. file.write(' <message>\n <date>')
  25. file.write(message.date.strftime("%s"))
  26. file.write('</date>\n <msg>')
  27. file.write(message.message)
  28. file.write('</msg>\n <me>')
  29. file.write(str(int(ownid == message.from_id)))
  30. file.write('</me>\n')
  31. # dl and write media if exist
  32. if message.media != None:
  33. file.write(' <media>')
  34. file.write(str(dlid))
  35. file.write('</media>\n')
  36. out = message
  37. file.write(' </message>\n')
  38. return out
  39. def createFolder(path):
  40. if not os.path.exists(path):
  41. os.makedirs(path)
  42. class DelayedDownload:
  43. """A class to store the data, for other methods to download media later"""
  44. message = None
  45. id = 1
  46. def __init__(self, _id, msg):
  47. self.id = _id
  48. self.message = msg
  49. def downloadChat(dialog, filename, downloadmedia):
  50. print ("selected: ", dialog.name, 'retriving chat!')
  51. chat = client.get_messages(dialog, limit=2000000)
  52. print("retrived ", len(chat), " Messages.")
  53. toDL = [] # list of DelayedDownload
  54. createFolder('out/')
  55. while True:
  56. try:
  57. fout = open('out/' + filename + '.xml', 'x')
  58. break
  59. except FileExistsError:
  60. get = input('Override out/' + filename + '.xml [y/n]?')
  61. if get == 'y' or get == 'Y':
  62. # delete
  63. os.remove('out/' + filename + '.xml')
  64. elif get == 'n' or get == 'N':
  65. # exit
  66. print ("Bye.")
  67. exit(2)
  68. fout.write('<chat>\n')
  69. for c in chat:
  70. dl = saveMessage(c, fout, len(toDL), me.id)
  71. if dl != None:
  72. if dl.media != None:
  73. # here is something to download later
  74. toDL.append(DelayedDownload(len(toDL), c))
  75. fout.write('</chat>\n')
  76. fout.close()
  77. if(downloadmedia):
  78. createFolder('out/media/')
  79. print('Chat structure stored. Downloading Media - this may take a while!')
  80. for dl in toDL:
  81. print ('.', end='')
  82. client.download_media(dl.message, "out/media/" + str(dl.id))
  83. print('\n', len(toDL), " Media Files Downloaded.")
  84. # ==================================
  85. # MAIN program
  86. # read config
  87. try:
  88. config = configparser.ConfigParser()
  89. config.read('config.ini')
  90. api_id = int(config.get('Main', 'api_id'))
  91. api_hash = config.get('Main', 'api_hash')
  92. workers = int(config.get('Main', 'workers'))
  93. session_name = config.get('Main', 'user')
  94. except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
  95. print('invalid config.ini')
  96. exit(3)
  97. # create connection
  98. client = TelegramClient(session_name, api_id, api_hash, update_workers=workers, spawn_read_thread=True)
  99. client.start()
  100. me = client.get_me()
  101. # get dialogs
  102. dialogs = client.get_dialogs(limit=100)
  103. print ("chats loaded. (", len(dialogs), ")")
  104. # print chats
  105. id = 0
  106. # table header
  107. print (
  108. 'ID | Internal ID | Username | pinned\n———+————————————————+————————————————————————————————+———————')
  109. # content
  110. for d in dialogs:
  111. printDialog(id, d)
  112. id = id + 1
  113. get = input("Please Enter Chat ID or all: ")
  114. if get == 'all':
  115. for d in dialogs:
  116. if not isBot(d) and d.entity.id != me.id and not isChannel(d):
  117. downloadChat(d, strip(d.name), False)
  118. elif int(get) < 0 or int(get) >= id:
  119. print ("Unknown Chat ID!")
  120. exit(1)
  121. else:
  122. downloadChat(dialogs[int(get)], 'chat', True)
  123. print ('End.')