Browse Source

Initial Commit

master
HayWo 2 years ago
commit
633057628e
Signed by: haywo GPG Key ID: CE8467F36EF907E4
  1. 1
      .gitignore
  2. 44
      README.md
  3. 142
      fridaydisco.py

1
.gitignore

@ -0,0 +1 @@
fridaydisco-*/*

44
README.md

@ -0,0 +1,44 @@
# Fridaydiso
## Was ist die Fridaydisco?
Mehr oder weniger regelmäßig freitags nachmittags/abends/nachts treffen sich einige coole Menschen auf Mastodon unter dem Hashtag `#fridaydisco`.
Dort werden dann Links zu verschiedensten Songs auf YouTube geteilt.
## Was tut fridaydisco.py?
Das script `fridaydisco.py` extrahiert die Links zu den Songs aus den Toots.
Die Songs werden als mp3 heruntergeladen und in einem Ordner mit dem aktuellen Datum gespeichert.
## Benutzung von fridaydisco.py
### Benötigte Programme und Bibliotheken
#### notwendig
- python3.x
- youtube_dl
#### optional
- mplayer
### Als live Player unter Linux (ungetestet - funktioniert in der Theorie)
- `cd fridaydisco`
- `python fridaydisco.py`
- create a cron-job or systemd-timer to run `python fridaydisco.py` every few minutes
- play music with `mplayer fridaydisco-YYYY-MM-DD/*`
### Zur Archivierung
- `cd fridaydisco`
- `python fridaydisco.py`
Bei wiederholter Ausführung des Scripts werden lediglich neue Songs heruntergeladen
### Funktion
- es werden aktuell immer die 80 neuesten Toots abgefragt. Als Api-Endpoint wird `https://mastodon.matrix.org/api/v1/timelines/tag/fridaydisco` verwendet.
- es werden nur öffentliche Toots mit dem aktuellem Datum analysiert
- es werden nur Links der Form `https://www.youtube.com/watch?v=` berücksichtigt
- es werden keine vollständigen Playlists von YouTube heruntergeladen
- es wird eine Datei mit Namen `fridaydisco-YYYY-MM-DD.json` erstellt, hier werden zu jedem Song Titel, Länge, Link und Dateiname gespeichert. Schlägt ein Download fehl wird sein Link in eine eigene Liste aufgenommen. So können fehlgeschlagene Downloads später manuell wiederholt werden.
alle Dateien werden in einem Ordner mit Namen `fridaydisco-YYYY-MM-DD/` gespeichert
### Fehlende Funktionen
- Konsolenparameter für:
- Mastodon Instanz `-i`
- Datum `-d`
- Anzahl der abgefragten Toots `-n`
- Abgefragtes Hashtag `-t`
- Toots die nach Mitternacht getrötet werden sollten optional weiterhin im Ordner vom Vortag gespeichert werden. Insbesondere für den 'Live-Modus' nützlich.

142
fridaydisco.py

@ -0,0 +1,142 @@
import requests
import os
import json
import youtube_dl
from datetime import date
dl_options = {
'format': 'bestaudio/best',
'noplaylist': True,
'keep_video': False,
'prefer_ffmpeg': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192', }]
}
date = date.today().strftime("%Y-%m-%d")
dir_name = "fridaydisco-" + date
def get_info(url):
with youtube_dl.YoutubeDL(dl_options) as ytdl:
try:
info_dict = ytdl.extract_info(url)
info = {
'title': info_dict["title"],
'duration': info_dict["duration"]
}
return info
except (
youtube_dl.utils.DownloadError,
youtube_dl.utils.ContentTooShortError,
youtube_dl.utils.ExtractorError,
youtube_dl.utils.UnavailableVideoError
) as e:
return { 'title':'Download Failed!','duration':0}
def dl_song(url, title):
dl_options["outtmpl"] = f'{dir_name}/{title}.mp3'
with youtube_dl.YoutubeDL(dl_options) as ytdl:
try:
ytdl.download([url])
return dl_options["outtmpl"]
except (
youtube_dl.utils.DownloadError,
youtube_dl.utils.ContentTooShortError,
youtube_dl.utils.ExtractorError,
youtube_dl.utils.UnavailableVideoError
) as e:
return "Download Failed!"
json_file_name = dir_name + "/fridaydisco-" + date + ".json"
links_json = {}
if not os.path.exists(json_file_name):
if not os.path.exists(dir_name):
os.mkdir(dir_name, 0o0755 )
print("Created Directory: " + dir_name)
else:
print("Using Directory: " + dir_name)
links_file = open(json_file_name, 'w')
links_json["songs"] = []
links_json["failed"] = []
print("Creadted File: " + json_file_name)
else:
links_file = open(json_file_name, 'r')
links_json = json.load(links_file)
print("Using Directory: " + dir_name)
print("Using File: " + json_file_name)
failed_links = []
links = []
for elem in links_json["songs"]:
links.append(elem["url"])
youtube_base = "https://www.youtube.com/watch?v="
print("Getting 80 newest Toots from: https://mastodon.matrix.org/api/v1/timelines/tag/fridaydisco")
response = requests.get("https://mastodon.matrix.org/api/v1/timelines/tag/fridaydisco?limit=80")
posts = json.loads(response.text)
print("Looking for public posts with timestamp: " + date)
print("Collecting Urls with this basepath: " + youtube_base)
dl_counter = 0
for post in posts:
if post["visibility"] == "public":
post_date_end = post["created_at"].find("T")
post_date = post["created_at"][0:post_date_end]
if post_date == date:
content = post["content"]
cursor_pos = 0
content_length = len(content)
while cursor_pos < content_length:
link_start = content.find(youtube_base, cursor_pos, content_length)
if link_start == -1:
break
link_end = content.find("\" ", link_start, content_length)
full_link = content[link_start:link_end]
link_params_start = full_link.find("&amp;")
if link_params_start != -1:
full_link = full_link[0:link_params_start]
if full_link not in links:
song_info = get_info(full_link)
song_name_no_spaces = song_info["title"].replace(" ", "_")
file_name = dl_song(full_link, song_name_no_spaces)
if song_info["title"] != "Download Failed!" and file_name != "Download Failed!":
links_json["songs"].append({
"title":song_info["title"],
"duration":song_info["duration"],
"url":full_link,
"file":file_name
})
links.append(full_link)
dl_counter += 1
else:
if file_name == "Download Failed!" and song_info["title"] != "Download Failed!":
links_json["failed"].append({
"url":full_link,
"title":song_info["title"],
"file":"none"
})
else:
links_json["failed"].append({
"url":full_link,
"title":"unknown",
"file":"none"
})
failed_links.append(full_link)
cursor_pos = link_end
with open(json_file_name, 'w') as outfile:
json.dump(links_json, outfile)
print("Downloaded " + str(dl_counter) + " Songs")
print("Directory " + dir_name + " contains " + str(len(links)) + " Songs now")
print(str(len(failed_links)) + " Downloads failed!")
if len(failed_links) > 0:
print("Failed to download:")
for link in failed_links:
print("\t" + link)
print("Done")
Loading…
Cancel
Save