playlistalo.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. from telegram.ext import Updater, MessageHandler, Filters
  15. scriptpath = os.path.dirname(os.path.realpath(__file__))
  16. def add(url, user = "-unknown-", sortrandom = False):
  17. #print ('--- Inizio ---')
  18. init()
  19. ydl_opts = {
  20. 'format': 'bestaudio[ext=m4a]',
  21. 'outtmpl': 'cache/%(id)s.m4a',
  22. 'noplaylist': True,
  23. 'quiet': True,
  24. }
  25. url = url.strip()
  26. print ("url: " + url)
  27. print ("user: " + user)
  28. if not validators.url(url):
  29. print ('--- URL malformato ---')
  30. return ("Err: url non valido")
  31. with youtube_dl.YoutubeDL(ydl_opts) as ydl:
  32. try:
  33. meta = ydl.extract_info(url, download = False)
  34. except youtube_dl.DownloadError as detail:
  35. print ('--- Errore video non disponibile ---')
  36. print(str(detail))
  37. return ("Err: " + str(detail))
  38. id = meta.get('id').strip()
  39. title = __normalizetext(meta.get('title'))
  40. print ('id: %s' %(id))
  41. print ('title: %s' %(title))
  42. #scrivo il json
  43. with open(os.path.join("cache", id + ".json"), 'w') as outfile:
  44. json.dump(meta, outfile, indent=4)
  45. #ho letto le info, ora controllo se il file esiste altrimenti lo scarico
  46. #miglioria: controllare se upload_date e' uguale a quella del json gia' esistente
  47. filetemp = os.path.join("cache", id + ".m4a")
  48. if not glob(filetemp):
  49. print ('--- Scarico ---')
  50. ydl.download([url]) #non ho capito perche' ma senza [] fa un carattere per volta
  51. if not os.path.isfile(filetemp):
  52. return("Err: file non scaricato")
  53. #se il file esiste gia' in playlist salto (potrebbe esserci, anche rinominato)
  54. if glob(scriptpath + "/playlist/**/*|" + id + ".*"):
  55. print ('--- File già presente ---')
  56. return ("Err: %s [%s] già presente" %(title, id))
  57. if not os.path.exists("playlist/" + user):
  58. os.makedirs("playlist/" + user)
  59. #qui compone il nome del file
  60. if sortrandom:
  61. fileout = str(random.randrange(10**6)).zfill(14) + "|" + title + "|" + id + ".m4a"
  62. else:
  63. fileout = time.strftime("%Y%m%d%H%M%S") + "|" + title + "|" + id + ".m4a"
  64. fileout = os.path.join("playlist/" + user, fileout)
  65. print ('--- Converto ---')
  66. print (fileout)
  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. def __msg_parser(bot, update):
  202. print("Messaggio ricevuto")
  203. urlz = update.message.text
  204. u = update.message.from_user
  205. user = "t_" + "-".join([i for i in [str(u.id), u.username] if i])
  206. #print (urlz)
  207. #print (user)
  208. #update.message.reply_text("Ciao " + update.message.from_user.username)
  209. update.message.reply_text("Messaggio ricevuto. Elaboro...")
  210. for url in [s for s in urlz.splitlines() if s.strip() != ""]:
  211. #update.message.reply_text("Scarico %s" %(url))
  212. # start the download
  213. dl = playlistalo.add(url, user)
  214. update.message.reply_text(dl)
  215. def telegram_bot():
  216. print ("Bot avviato")
  217. # Create the EventHandler and pass it your bot's token.
  218. updater = Updater(os.environ['TELEGRAM_TOKEN'])
  219. # Get the dispatcher to register handlers
  220. dp = updater.dispatcher
  221. # parse message
  222. dp.add_handler(MessageHandler(Filters.text, __msg_parser))
  223. # Start the Bot
  224. updater.start_polling()
  225. # Run the bot until you press Ctrl-C
  226. updater.idle()
  227. if __name__ == '__main__':
  228. print ("This is a package, use other commands to run it")