playlistalo.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #!/usr/bin/env python3
  2. #Playlistalo - simpatico script che legge le cartelle e genera la playlist
  3. import youtube_dl
  4. import shutil
  5. import sys
  6. import re
  7. import os
  8. import validators
  9. from glob import glob
  10. import json
  11. import time
  12. import subprocess
  13. import random
  14. scriptpath = os.path.dirname(os.path.realpath(__file__))
  15. def add(url, user = "-unknown-", sortrandom = False):
  16. print ('--- Inizio ---')
  17. init()
  18. ydl_opts = {
  19. 'format': 'bestaudio[ext=m4a]',
  20. 'outtmpl': 'cache/%(id)s.m4a',
  21. 'noplaylist': True,
  22. }
  23. url = url.strip()
  24. print (url)
  25. print (user)
  26. if not validators.url(url):
  27. print ('--- URL malformato ---')
  28. return ("Err: url non valido")
  29. with youtube_dl.YoutubeDL(ydl_opts) as ydl:
  30. try:
  31. meta = ydl.extract_info(url, download = False)
  32. except youtube_dl.DownloadError as detail:
  33. print ('--- Errore video non disponibile ---')
  34. print(str(detail))
  35. return ("Err: " + str(detail))
  36. id = meta.get('id').strip()
  37. title = __normalizetext(meta.get('title'))
  38. print ('id : %s' %(id))
  39. print ('title : %s' %(title))
  40. #scrivo il json
  41. with open(os.path.join("cache", id + ".json"), 'w') as outfile:
  42. json.dump(meta, outfile, indent=4)
  43. #ho letto le info, ora controllo se il file esiste altrimenti lo scarico
  44. #miglioria: controllare se upload_date e' uguale a quella del json gia' esistente
  45. filetemp = os.path.join("cache", id + ".m4a")
  46. if not glob(filetemp):
  47. print ('--- Scarico ---')
  48. ydl.download([url]) #non ho capito perche' ma senza [] fa un carattere per volta
  49. #se il file esiste gia' in playlist salto (potrebbe esserci, anche rinominato)
  50. if glob(scriptpath + "/playlist/**/*|" + id + ".*"):
  51. print ('--- File già presente ---')
  52. return ("Err: %s [%s] già presente" %(title, id))
  53. print ('--- Scarico ---')
  54. if not os.path.exists("playlist/" + user):
  55. os.makedirs("playlist/" + user) #qui compone il nome del file
  56. if sortrandom:
  57. fileout = str(random.randrange(10**6)).zfill(14) + "|" + title + "|" + id + ".m4a"
  58. else:
  59. fileout = time.strftime("%Y%m%d%H%M%S") + "|" + title + "|" + id + ".m4a"
  60. print (fileout)
  61. fileout = os.path.join("playlist/" + user, fileout)
  62. if not os.path.isfile(filetemp):
  63. return("Err: file non scaricato")
  64. #copia il file nella cartella playlist
  65. #shutil.copy(filetemp, fileout)
  66. print ('--- Converto ---')
  67. subprocess.call([scriptpath + "/trimaudio.sh", filetemp, fileout])
  68. if not os.path.isfile(fileout):
  69. return("Err: file non convertito")
  70. #cerca la posizione del pezzo appena inserito
  71. pos = getposition(fileout)
  72. print ('--- Fine ---')
  73. print ("")
  74. return ("OK: %s [%s] aggiunto alla playlist in posizione %s" %(title, id, pos))
  75. def __normalizetext(s):
  76. if s is None:
  77. return None
  78. else:
  79. s = re.sub(r'[\\|/|:|*|?|"|<|>|\|]',r'',s)
  80. s = " ".join(s.split())
  81. return s
  82. def init():
  83. if not os.path.exists("playlist"):
  84. os.makedirs("playlist")
  85. if not os.path.exists("cache"):
  86. os.makedirs("cache")
  87. if not os.path.exists("fallback"):
  88. os.makedirs("fallback")
  89. if not os.path.exists("archive"):
  90. os.makedirs("archive")
  91. def list():
  92. pl = []
  93. pl2 = []
  94. for udir in sorted(glob(scriptpath + "/playlist/*/")):
  95. #print (udir)
  96. user = os.path.basename(os.path.dirname(udir))
  97. #cerca il file last
  98. last = ""
  99. if os.path.exists(udir + "/last"):
  100. f = open(udir + "/last", "r")
  101. last = f.readline().rstrip()
  102. else:
  103. last = os.path.basename(sorted(glob(udir + "/*.m4a"))[0]).split("|")[0]
  104. #print ("LAST: " + last)
  105. #leggi i file nella cartella
  106. files = sorted(glob(udir + "/*.m4a"))
  107. seq = 0
  108. for file in files:
  109. bn = os.path.splitext(os.path.basename(file))[0]
  110. #print ("BASENAME: " + bn)
  111. seq = seq + 1
  112. dat = bn.split("|")[0]
  113. nam = bn.split("|")[1]
  114. cod = bn.split("|")[2]
  115. key = "-".join([str(seq).zfill(5), last, dat])
  116. #print ("KEY: " + key)
  117. plsong = [key, file.replace(scriptpath + "/", "") , user, nam, cod] #, file
  118. pl.append(plsong)
  119. pl.sort()
  120. #rimuove la prima colonna, che serve solo per l'ordinamento
  121. pl2 = [x[1:] for x in pl]
  122. #print (pl)
  123. #print ('\n'.join([", ".join(x) for x in pl]))
  124. #print ('\n'.join([x[0] for x in pl]))
  125. return pl2
  126. def listfallback():
  127. pl = []
  128. pl2 = []
  129. #leggi i file nella cartella
  130. files = sorted(glob(scriptpath + "/fallback/*.m4a"))
  131. seq = 0
  132. for file in files:
  133. bn = os.path.splitext(os.path.basename(file))[0]
  134. seq = seq + 1
  135. dat = bn.split("|")[0]
  136. nam = bn.split("|")[1]
  137. cod = bn.split("|")[2]
  138. key = "-".join([str(seq).zfill(5), dat])
  139. plsong = [key, file.replace(scriptpath + "/", "") , "fallback", nam, cod] #, file
  140. pl.append(plsong)
  141. pl.sort()
  142. #rimuove la prima colonna, che serve solo per l'ordinamento
  143. pl2 = [x[1:] for x in pl]
  144. return pl2
  145. def playsingle():
  146. pl = list()
  147. #print ('\n'.join([x[0] for x in pl]))
  148. if pl:
  149. firstsong = scriptpath + "/" + pl[0][0]
  150. print (firstsong)
  151. #qui fa play
  152. subprocess.call(["mplayer", "-nolirc", "-msglevel", "all=0:statusline=5", firstsong])
  153. #alla fine consuma
  154. os.rename(firstsong, scriptpath + "/archive/" + os.path.basename(firstsong))
  155. #se non ci sono + file cancella la cartella
  156. if not glob(os.path.dirname(firstsong) + "/*.m4a"):
  157. shutil.rmtree(os.path.dirname(firstsong))
  158. else:
  159. with open(os.path.dirname(firstsong) + "/last", "w") as f:
  160. f.write(time.strftime("%Y%m%d%H%M%S"))
  161. else:
  162. #usa il fallback
  163. #eventualmente aggiungere file di avviso con istruzioni veloci
  164. plf = listfallback()
  165. #print ('\n'.join([x[0] for x in plf]))
  166. if plf:
  167. firstsong = plf[0][0]
  168. print (firstsong)
  169. #qui fa play
  170. subprocess.call(["mplayer", "-nolirc", "-msglevel", "all=0:statusline=5", firstsong])
  171. #alla fine consuma
  172. fname = time.strftime("%Y%m%d%H%M%S") + "|" + "|".join(os.path.basename(firstsong).split("|")[1:])
  173. fname = os.path.dirname(firstsong) + "/" + fname
  174. os.rename(firstsong, fname)
  175. def playloop():
  176. while True:
  177. playsingle()
  178. def clean():
  179. #cancella tutto dalla playlist
  180. shutil.rmtree("playlist")
  181. os.makedirs("playlist")
  182. def shuffleusers():
  183. #scrivere un numero casuale dentro a tutti i file last
  184. for udir in sorted(glob("playlist/*/")):
  185. #print (udir)
  186. with open(udir + "/last", "w") as f:
  187. f.write(str(random.randrange(10**6)).zfill(14))
  188. def shufflefallback():
  189. #rinominare con un numero casuale i file in fallback
  190. files = sorted(glob("fallback/*.m4a"))
  191. for file in files:
  192. fname = str(random.randrange(10**6)).zfill(14) + "|" + "|".join(os.path.basename(file).split("|")[1:])
  193. fname = os.path.dirname(file) + "/" + fname
  194. os.rename(file, fname)
  195. def getposition(file):
  196. pl = list()
  197. try:
  198. return([x[0] for x in pl].index(file) + 1)
  199. except:
  200. pass
  201. if __name__ == '__main__':
  202. print ("This is a package, use other commands to run it")
  203. getposition("playlist/Itec78/20200404145736|George Baker- Little Green Bag|4b1wt3-zpzQ.m4az")