yt2tg-mp3.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/home/sasha/Coding/youtube2tg-mp3/env/bin/python
  2. import logging
  3. import readline
  4. import time
  5. from typing import List
  6. import validators
  7. import os
  8. from sys import exit
  9. from feed import CheckFeed
  10. from args import ArgParser
  11. from download import get_info_yt_video, get_mp3_from_yt, Video
  12. from mp3tag import modified_id3
  13. from agent import send_audio
  14. from config import YT_CHANNEL_ID, VIDEO_ITEMS_QUANTITY
  15. arg_parser = ArgParser()
  16. logging.basicConfig(
  17. format='%(asctime)s %(message)s',
  18. datefmt='%Y-%m-%d %H:%M:%S',
  19. level=logging.INFO)
  20. #TODO make TUI with ncurses
  21. #TODO make python module
  22. yt_feed = CheckFeed(YT_CHANNEL_ID, VIDEO_ITEMS_QUANTITY)
  23. def print_video_list(reread: bool = False):
  24. if reread: yt_feed.read()
  25. videos = yt_feed.videos
  26. os.system('cls' if os.name == 'nt' else 'clear')
  27. if videos:
  28. print(f'The list of titles of new items in youtube channel "{yt_feed.title}":')
  29. for i, v in enumerate(videos):
  30. is_live = "[live]" if v.is_live else ""
  31. print(f"=== {i + 1}.{is_live} {v.title} ({v.id})")
  32. else:
  33. print(f"Something went wrong. The channel {yt_feed.title} has no videos")
  34. def get_menu_choose_video():
  35. while True:
  36. select_text = "Insert num of video to convert or type command exit/link/list: "
  37. select = input(select_text)
  38. if select == "exit":
  39. logging.info("Terminate the script")
  40. exit()
  41. elif select == "list":
  42. print_video_list(reread=True)
  43. elif select == "link":
  44. while True:
  45. link = input("Insert the valid link to youtube video: ")
  46. print('Not valid')
  47. if validators.url(link):
  48. print('Not valid')
  49. break
  50. # TODO check link and video
  51. video = get_info_yt_video(link)
  52. print(f"Video title is: {video.title}")
  53. return video
  54. else:
  55. num_of_items = len(yt_feed.videos)
  56. try:
  57. video_index = int(select) - 1
  58. if 0 <= video_index < num_of_items:
  59. video = yt_feed.videos[video_index]
  60. return video
  61. else:
  62. print(f"Number is not in range (1, {num_of_items}). Try again")
  63. except ValueError:
  64. print("Error. Not valid command")
  65. # TODO refactor
  66. def get_tags_for_video() -> List[str]:
  67. while True:
  68. answer = input("Type the tags for mp3 file. Format: artist|title: ")
  69. tags = answer.split("|")
  70. if len(tags) == 2:
  71. print(f"----Artist: {tags[0]}\n----Title: {tags[1]}")
  72. if input("Is it right? y/n: ").lower() != "n":
  73. return tags
  74. else:
  75. logging.warning("This is not right string")
  76. def check_is_stream(video: Video) -> None:
  77. while True:
  78. if get_info_yt_video(video.link).is_live:
  79. logging.warning('This stream is on. Waiting for end')
  80. time.sleep(30 * 60)
  81. else:
  82. break
  83. def download_and_send(video: Video, tags: List[str]):
  84. logging.info("Start Downloading")
  85. try:
  86. get_mp3_from_yt(video)
  87. except Exception:
  88. raise RuntimeError("Something bad happened")
  89. else:
  90. files = [f for f in os.listdir() if f.endswith(".mp3") and f.startswith(video.title[:9])]
  91. # files = [f for f in os.listdir() if f.endswith(".mp3")]
  92. if len(files) == 1:
  93. file_name = files[0]
  94. else:
  95. raise RuntimeError("Something bad happened")
  96. print(f"Video title is: {video.title}")
  97. modified_id3(file_name, tags[0], tags[1])
  98. logging.info(f"----DONE!\n----File name: {file_name}")
  99. time.sleep(5)
  100. if arg_parser.args.download:
  101. return
  102. send_audio(file_name, tags[0], tags[1])
  103. logging.info("Uploading completed")
  104. if os.path.isfile(file_name):
  105. os.remove(file_name)
  106. logging.info(f"file {file_name} was removed")
  107. else:
  108. logging.warning("File doesn't exists! Remove all mp3 files in folder")
  109. dir_name = os.getcwd()
  110. files = os.listdir(dir_name)
  111. for file in files:
  112. if file.endswith(".mp3"):
  113. os.remove(os.path.join(dir_name, file))
  114. def main():
  115. link = arg_parser.args.link
  116. if not link:
  117. print_video_list()
  118. video = get_menu_choose_video()
  119. else:
  120. video = get_info_yt_video(link)
  121. print(f"Video title is: {video.title}")
  122. arg_parser.args.link = None
  123. tags = get_tags_for_video()
  124. check_is_stream(video)
  125. download_and_send(video, tags)
  126. if __name__ == "__main__":
  127. try:
  128. main()
  129. except KeyboardInterrupt:
  130. print('\n=========== Exit ===============')