Created
July 9, 2019 14:57
-
-
Save max1220/9db93e507a1c55c60a44458c1b8ca17d to your computer and use it in GitHub Desktop.
A Chrome(-ium) Bookmark downloader for youtube videos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
return { | |
-- file extensions that are possibly a downloaded youtube video | |
file_extensions = {"mp3", "opus", "m4a", "ogg"}, | |
-- directorys to scan for youtube id's | |
local_dirs = { | |
"/media/your/music/library/folder/that/contains/youtube_dl/downloaded/videos/" | |
}, | |
-- where to store the downloaded files | |
download_dir = "/media/your/music/library/folder/some/download/folder/", | |
-- The filename of the bookmarks JSON file | |
bookmarks_file = "/home/max/.config/chromium/Default/Bookmarks", | |
-- list of folder names that are scanned for youtube id's(recursivly) | |
bookmarks_folders = { | |
"Music" | |
}, | |
-- where to write the list of failed downloads | |
failed_file = "failed.txt", | |
-- enable better output using terminal escape sequences(disable if writing to log) | |
enable_term = true, | |
-- (internal) command used to find the files in a folder | |
_find_cmd = "find %s -type f", | |
-- (internal) command used to download a youtube URL to a path | |
_download_cmd = "cd %s; youtube-dl -x %s" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env lua5.1 | |
local config = require("config") | |
local json = require("cjson") | |
local function youtube_id_from_path(filepath) | |
for _, extension in ipairs(config.file_extensions) do | |
local lower = filepath:lower() | |
if lower:match("%-...........%." .. extension .. "$") then | |
local youtube_id = filepath:match("%-(...........)%." .. extension .. "$") | |
return youtube_id | |
end | |
end | |
end | |
local function find_local_files() | |
local match = {} | |
local miss = {} | |
for _, local_dir in ipairs(config.local_dirs) do | |
local proc = io.popen(config._find_cmd:format(local_dir)) | |
for line in proc:lines() do | |
local youtube_id = youtube_id_from_path(line) | |
if youtube_id then | |
table.insert(match, { | |
filepath = line, | |
youtube_id = youtube_id | |
}) | |
else | |
table.insert(miss, { | |
filepath = line, | |
}) | |
end | |
end | |
proc:close() | |
end | |
return match, miss | |
end | |
local function get_bookmark_folder_recursive(folder, folder_name) | |
for _,child in ipairs(folder.children) do | |
if child.type == "folder" then | |
if child.name == folder_name then | |
return child | |
end | |
local ret = get_bookmark_folder_recursive(child, folder_name) | |
if ret then | |
return ret | |
end | |
end | |
end | |
end | |
local function get_bookmark_urls_recursive(folder, urls) | |
local urls = urls or {} | |
for _,child in ipairs(folder.children) do | |
if child.type == "url" then | |
table.insert(urls, child) | |
elseif child.type == "folder" then | |
get_bookmark_urls_recursive(child, urls) | |
end | |
end | |
end | |
local function youtube_id_from_url(url) | |
local args = url:match("%?(.+)$") | |
if args then | |
local youtube_id = args:match("&?v=(...........)") | |
return youtube_id | |
end | |
end | |
local function get_bookmarks_urls() | |
local json_f = assert(io.open(config.bookmarks_file, "rb"), "Can't open bookmarks file!") | |
local obj = json.decode(json_f:read("*a")) | |
json_f:close() | |
local _urls = {} | |
for _,folder_name in ipairs(config.bookmarks_folders) do | |
local folder = assert(get_bookmark_folder_recursive(obj.roots.bookmark_bar, folder_name), "Can't find folder in bookmarks!") | |
get_bookmark_urls_recursive(folder, _urls) | |
end | |
local urls = {} | |
for _,entry in ipairs(_urls) do | |
local youtube_id = youtube_id_from_url(entry.url) | |
if youtube_id then | |
table.insert(urls, { | |
youtube_id = youtube_id, | |
entry = entry | |
}) | |
end | |
end | |
return urls | |
end | |
local function download_youtube_id(youtube_id) | |
local youtube_url = "https://youtube.com/watch?v=" .. youtube_id | |
local ret = os.execute(config._download_cmd:format(config.download_dir, youtube_url)) | |
--local ret = os.execute(("echo %s; sleep 1; echo %s; sleep 1"):format(config.download_dir, youtube_url)) | |
return ret == 0 | |
end | |
local function download_youtube_ids(entries) | |
local len = #entries | |
local failed = {} | |
local j = 0 | |
for i, entry in ipairs(entries) do | |
if config.enable_term then | |
print(("\027[2J\027[HDownloading %d/%d, ok: %d, failed: %d ... "):format(i, len, j, #failed)) | |
else | |
print(("Downloading %d/%d, ok: %d, failed: %d ... "):format(i, len, j, #failed)) | |
end | |
print() | |
if download_youtube_id(entry.youtube_id) then | |
j = j + 1 | |
else | |
print("Download failed!") | |
table.insert(failed, entry) | |
end | |
end | |
return failed | |
end | |
print("Collecting bookmarks...") | |
local bookmarks_ids = get_bookmarks_urls() | |
print("Collecting files...") | |
local local_ids = find_local_files() | |
local missing_files = {} | |
local by_youtube_id = {} | |
for _,entry in ipairs(local_ids) do | |
by_youtube_id[entry.youtube_id] = entry | |
end | |
for _,entry in ipairs(bookmarks_ids) do | |
if not by_youtube_id[entry.youtube_id] then | |
table.insert(missing_files, entry) | |
end | |
end | |
print("total bookmarks:", #bookmarks_ids) | |
print("total files:", #local_ids) | |
print("total missing files:", #missing_files) | |
print("Starting download...") | |
local failed = download_youtube_ids(missing_files) | |
print("total failed:", #failed) | |
if config.failed_file then | |
local failed_f = assert(io.open(config.failed_file, "w")) | |
for i, fail in ipairs(failed) do | |
failed_f:write("https://youtube.com/watch?v=" .. fail.youtube_id) | |
end | |
end | |
print("Done!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment