helpers.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import time
  2. import subprocess
  3. import os
  4. import shutil
  5. import json
  6. import shlex
  7. try:
  8. import pil
  9. import helpers
  10. import logger
  11. from constants import Constants
  12. except ImportError:
  13. from . import pil
  14. from . import helpers
  15. from . import logger
  16. from .constants import Constants
  17. def strdatetime():
  18. return time.strftime('%m-%d-%Y %I:%M:%S %p')
  19. def strtime():
  20. return time.strftime('%I:%M:%S %p')
  21. def strdate():
  22. return time.strftime('%m-%d-%Y')
  23. def strepochtime():
  24. return str(int(time.time()))
  25. def strdatetime_compat(epochtime):
  26. return time.strftime('%m%d%Y_{:s}'.format(epochtime))
  27. def command_exists(command):
  28. try:
  29. fnull = open(os.devnull, 'w')
  30. subprocess.call([command], stdout=fnull, stderr=subprocess.STDOUT)
  31. return True
  32. except OSError as e:
  33. return False
  34. def run_command(command):
  35. try:
  36. fnull = open(os.devnull, 'w')
  37. subprocess.Popen(shlex.split(command), stdout=fnull, stderr=subprocess.STDOUT)
  38. return False
  39. except Exception as e:
  40. return str(e)
  41. def bool_str_parse(bool_str):
  42. if bool_str.lower() in ["true", "yes", "y", "1"]:
  43. return True
  44. elif bool_str.lower() in ["false", "no", "n", "0"]:
  45. return False
  46. else:
  47. return "Invalid"
  48. def check_if_guesting():
  49. try:
  50. broadcast_guest = pil.livestream_obj.get('cobroadcasters', {})[0].get('username')
  51. except Exception:
  52. broadcast_guest = None
  53. print(broadcast_guest)
  54. if broadcast_guest and not pil.has_guest:
  55. logger.binfo('The livestream owner has started guesting "{}".'.format(broadcast_guest))
  56. pil.has_guest = broadcast_guest
  57. if not broadcast_guest and pil.has_guest:
  58. logger.binfo('The livestream owner has stopped guesting "{}".'.format(broadcast_guest))
  59. pil.has_guest = None
  60. def generate_json_segments():
  61. while not pil.broadcast_downloader.is_aborted:
  62. pil.livestream_obj['delay'] = (int(pil.epochtime) - pil.livestream_obj['published_time'])
  63. if 'initial_buffered_duration' not in pil.livestream_obj and pil.broadcast_downloader.initial_buffered_duration:
  64. pil.livestream_obj['initial_buffered_duration'] = pil.broadcast_downloader.initial_buffered_duration
  65. pil.livestream_obj['segments'] = pil.broadcast_downloader.segment_meta
  66. try:
  67. with open(pil.live_folder_path + ".json", 'w') as json_file:
  68. json.dump(pil.livestream_obj, json_file, indent=2)
  69. if not pil.broadcast_downloader.stream_id:
  70. pil.broadcast_downloader.stream_id = pil.livestream_obj['id']
  71. #check_if_guesting()
  72. time.sleep(2.5)
  73. except Exception as e:
  74. logger.warn(str(e))
  75. def clean_download_dir():
  76. dir_delcount = 0
  77. file_delcount = 0
  78. error_count = 0
  79. lock_count = 0
  80. try:
  81. logger.info('Cleaning up temporary files and folders.')
  82. if Constants.PYTHON_VER[0] == "2":
  83. directories = (os.walk(pil.dl_path).next()[1])
  84. files = (os.walk(pil.dl_path).next()[2])
  85. else:
  86. directories = (os.walk(pil.dl_path).__next__()[1])
  87. files = (os.walk(pil.dl_path).__next__()[2])
  88. for directory in directories:
  89. if directory.endswith('_downloads'):
  90. if not any(filename.endswith('.lock') for filename in
  91. os.listdir(os.path.join(pil.dl_path, directory))):
  92. try:
  93. shutil.rmtree(os.path.join(pil.dl_path, directory))
  94. dir_delcount += 1
  95. except Exception as e:
  96. logger.error("Could not remove folder: {:s}".format(str(e)))
  97. error_count += 1
  98. else:
  99. lock_count += 1
  100. logger.separator()
  101. for file in files:
  102. if file.endswith('_downloads.json'):
  103. if not any(filename.endswith('.lock') for filename in
  104. os.listdir(os.path.join(pil.dl_path))):
  105. try:
  106. os.remove(os.path.join(pil.dl_path, file))
  107. file_delcount += 1
  108. except Exception as e:
  109. logger.error("Could not remove file: {:s}".format(str(e)))
  110. error_count += 1
  111. else:
  112. lock_count += 1
  113. if dir_delcount == 0 and file_delcount == 0 and error_count == 0 and lock_count == 0:
  114. logger.info('The cleanup has finished. No items were removed.')
  115. logger.separator()
  116. return
  117. logger.info('The cleanup has finished.')
  118. logger.info('Folders removed: {:d}'.format(dir_delcount))
  119. logger.info('Files removed: {:d}'.format(file_delcount))
  120. logger.info('Locked items: {:d}'.format(lock_count))
  121. logger.info('Errors: {:d}'.format(error_count))
  122. logger.separator()
  123. except KeyboardInterrupt as e:
  124. logger.separator()
  125. logger.warn("The cleanup has been aborted.")
  126. if dir_delcount == 0 and file_delcount == 0 and error_count == 0 and lock_count == 0:
  127. logger.info('No items were removed.')
  128. logger.separator()
  129. return
  130. logger.info('Folders removed: {:d}'.format(dir_delcount))
  131. logger.info('Files removed: {:d}'.format(file_delcount))
  132. logger.info('Locked items : {:d}'.format(lock_count))
  133. logger.info('Errors: {:d}'.format(error_count))
  134. logger.separator()
  135. def show_info():
  136. cookie_files = []
  137. cookie_from_config = ''
  138. try:
  139. for file in os.listdir(os.getcwd()):
  140. if file.endswith(".json"):
  141. with open(file) as data_file:
  142. try:
  143. json_data = json.load(data_file)
  144. if json_data.get('created_ts'):
  145. cookie_files.append(file)
  146. except Exception as e:
  147. pass
  148. if pil.ig_user == file.replace(".json", ''):
  149. cookie_from_config = file
  150. except Exception as e:
  151. logger.warn("Could not check for cookie files: {:s}".format(str(e)))
  152. logger.whiteline()
  153. logger.info("To see all the available arguments, use the -h argument.")
  154. logger.whiteline()
  155. logger.info("PyInstaLive version: {:s}".format(Constants.SCRIPT_VER))
  156. logger.info("Python version: {:s}".format(Constants.PYTHON_VER))
  157. if not command_exists("ffmpeg"):
  158. logger.error("FFmpeg framework: Not found")
  159. else:
  160. logger.info("FFmpeg framework: Available")
  161. if len(cookie_from_config) > 0:
  162. logger.info("Cookie files: {:s} ({:s} matches config user)".format(str(len(cookie_files)),
  163. cookie_from_config))
  164. elif len(cookie_files) > 0:
  165. logger.info("Cookie files: {:s}".format(str(len(cookie_files))))
  166. else:
  167. logger.warn("Cookie files: None found")
  168. logger.info("CLI supports color: {:s}".format("No" if not logger.supports_color() else "Yes"))
  169. logger.info(
  170. "Command to run at start: {:s}".format("None" if not pil.run_at_start else pil.run_at_start))
  171. logger.info(
  172. "Command to run at finish: {:s}".format("None" if not pil.run_at_finish else pil.run_at_finish))
  173. if os.path.exists(pil.config_path):
  174. logger.info("Config file contents:")
  175. logger.whiteline()
  176. with open(pil.config_path) as f:
  177. for line in f:
  178. logger.plain(" {:s}".format(line.rstrip()))
  179. else:
  180. logger.error("Config file: Not found")
  181. logger.whiteline()
  182. logger.info("End of PyInstaLive information screen.")
  183. logger.separator()
  184. def new_config():
  185. try:
  186. if os.path.exists(pil.config_path):
  187. logger.info("A configuration file is already present:")
  188. logger.whiteline()
  189. with open(pil.config_path) as f:
  190. for line in f:
  191. logger.plain(" {:s}".format(line.rstrip()))
  192. logger.whiteline()
  193. logger.info("To create a default config file, delete 'pyinstalive.ini' and run this script again.")
  194. logger.separator()
  195. else:
  196. try:
  197. logger.warn("Could not find configuration file, creating a default one.")
  198. config_file = open(pil.config_path, "w")
  199. config_file.write(Constants.CONFIG_TEMPLATE.format(os.getcwd()).strip())
  200. config_file.close()
  201. logger.warn("Edit the created 'pyinstalive.ini' file and run this script again.")
  202. logger.separator()
  203. return
  204. except Exception as e:
  205. logger.error("Could not create default config file: {:s}".format(str(e)))
  206. logger.warn("You must manually create and edit it with the following template: ")
  207. logger.whiteline()
  208. for line in Constants.CONFIG_TEMPLATE.strip().splitlines():
  209. logger.plain(" {:s}".format(line.rstrip()))
  210. logger.whiteline()
  211. logger.warn("Save it as 'pyinstalive.ini' and run this script again.")
  212. logger.separator()
  213. except Exception as e:
  214. logger.error("An error occurred: {:s}".format(str(e)))
  215. logger.warn(
  216. "If you don't have a configuration file, manually create and edit one with the following template:")
  217. logger.whiteline()
  218. logger.plain(Constants.CONFIG_TEMPLATE)
  219. logger.whiteline()
  220. logger.warn("Save it as 'pyinstalive.ini' and run this script again.")
  221. logger.separator()
  222. def create_lock_user():
  223. try:
  224. if not os.path.isfile(os.path.join(pil.dl_path, pil.dl_user + '.lock')):
  225. if pil.use_locks:
  226. open(os.path.join(pil.dl_path, pil.dl_user + '.lock'), 'a').close()
  227. return True
  228. else:
  229. return False
  230. except Exception as e:
  231. logger.warn("Lock file could not be created. Be careful when running multiple downloads concurrently!")
  232. return True
  233. def create_lock_folder():
  234. try:
  235. if not os.path.isfile(os.path.join(pil.live_folder_path, 'folder.lock')):
  236. if pil.use_locks:
  237. open(os.path.join(pil.live_folder_path, 'folder.lock'), 'a').close()
  238. return True
  239. else:
  240. return False
  241. except Exception as e:
  242. logger.warn("Lock file could not be created. Be careful when running multiple downloads concurrently!")
  243. return True
  244. def remove_lock():
  245. try:
  246. os.remove(os.path.join(pil.dl_path, pil.dl_user + '.lock'))
  247. os.remove(os.path.join(pil.live_folder_path, 'folder.lock'))
  248. except Exception:
  249. pass
  250. def check_lock_file():
  251. return os.path.isfile(os.path.join(pil.dl_path, pil.dl_user + '.lock'))