mirror of
https://github.com/TangentFoxy/FindingMusic.git
synced 2024-11-25 10:24:21 +00:00
jesus christ what am I doing
This commit is contained in:
commit
632b2a903f
35
ReadMe.md
Normal file
35
ReadMe.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
Note: Due to commas existing in the source data, all CSV files in `sources` are
|
||||||
|
not actually csv files, except `music-cleaned-2.csv`, which is tab-delimmited to
|
||||||
|
handle this. It also was abandoned because of handling issues with the `csv`
|
||||||
|
library on LuaRocks.
|
||||||
|
|
||||||
|
## music.json
|
||||||
|
|
||||||
|
An object of objects, each track indexed by a normalized form of its name, which
|
||||||
|
is all lowercase alphanumeric characters only.
|
||||||
|
|
||||||
|
- `names`: A list of names equivalent to this track (some tracks have duplicate
|
||||||
|
names due to formatting differences)
|
||||||
|
- `downloaded`: (TRUE or NULL) whether or not I have downloaded it
|
||||||
|
- `url`: (String or NULL) representing where I downloaded it
|
||||||
|
- `note`: (String or NULL) misc. note
|
||||||
|
- `buy`: (String or NULL) a URL where it can be bought (or where I bought it)
|
||||||
|
- `favorite`: (TRUE or NULL) a favorite track
|
||||||
|
- `genre`: (String or NULL) primary genre
|
||||||
|
|
||||||
|
(Note: I'm sure I've downloaded many tracks that aren't marked as downloaded.)
|
||||||
|
|
||||||
|
## music.lua
|
||||||
|
|
||||||
|
A simple interface library to use in a Lua REPL.
|
||||||
|
|
||||||
|
- `load(force)` (called immediately) loads `music.json`
|
||||||
|
- `save()` saves to `music.json`
|
||||||
|
- `add(str)` adds a new track (checks for duplicates)
|
||||||
|
- `find(str)` finds possible track matches by normalizing the input string,
|
||||||
|
returns them in a list
|
||||||
|
- `set(match, info)` match can be a list (as is returned by find) or a
|
||||||
|
normalized track name, info must be a table of key-value pairs, these will be
|
||||||
|
set on the matched tracks, overwriting existing values if a key is already in
|
||||||
|
use
|
||||||
|
- `normalize(str)` returns a normalized form of the input string
|
23
music-from-fnt-225.csv
Normal file
23
music-from-fnt-225.csv
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Download URL,Note,Track Name
|
||||||
|
https://www.youtube.com/watch?v=5t5QSiydF9Y,needs end cut
|
||||||
|
https://www.youtube.com/watch?v=bChlP50NkuA,needs end cut
|
||||||
|
https://www.youtube.com/watch?v=hzaJntUd9gE,needs end cut
|
||||||
|
https://www.youtube.com/watch?v=h-V7H4hBImw,needs end cut
|
||||||
|
https://www.youtube.com/watch?v=_mmZAiD0RXE,might need edit
|
||||||
|
https://www.youtube.com/watch?v=bur01adAU4s,might need edit
|
||||||
|
https://www.youtube.com/watch?v=n1MbdC5aP40,favorite and needs edit
|
||||||
|
https://www.youtube.com/watch?v=SgaXBskuJjU,needs edit
|
||||||
|
https://www.youtube.com/watch?v=qNCDnm96TJE,might need edit
|
||||||
|
https://www.youtube.com/watch?v=DFUVFprXYEM,needs edit
|
||||||
|
https://www.youtube.com/watch?v=PNwuP3L01yg,needs edit
|
||||||
|
https://www.youtube.com/watch?v=XWfsKsCulOc,needs edit
|
||||||
|
https://www.youtube.com/watch?v=2bPYEk_FGr0,needs edit
|
||||||
|
https://www.youtube.com/watch?v=cQuT39S4SoI,needs edit
|
||||||
|
https://www.youtube.com/watch?v=4JkIs37a2JE,needs edit
|
||||||
|
https://www.youtube.com/watch?v=KgHkNJcXbqs,might need edit
|
||||||
|
https://www.youtube.com/watch?v=6N8Cf_iIm0s,fuck idk
|
||||||
|
|
||||||
|
https://www.youtube.com/watch?v=B1lNhNHdoPI
|
||||||
|
https://www.youtube.com/watch?v=mYox1YFfGw4,favorite
|
||||||
|
https://www.youtube.com/watch?v=PZE89NFYb04
|
||||||
|
https://www.youtube.com/watch?v=XHFPuH5iEww,favorite
|
|
1
music.json
Normal file
1
music.json
Normal file
File diff suppressed because one or more lines are too long
88
music.lua
Normal file
88
music.lua
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
-- require this and use it in a REPL to modify the JSON database
|
||||||
|
|
||||||
|
local cjson = require("cjson")
|
||||||
|
|
||||||
|
local music = {}
|
||||||
|
|
||||||
|
function music.normalize(str)
|
||||||
|
return str:gsub("%W", ""):lower()
|
||||||
|
end
|
||||||
|
|
||||||
|
function music.load(force)
|
||||||
|
if music.data and not force then
|
||||||
|
print("Music library was already loaded, use 'music.load(true)' to force load.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local file = io.open("music.json", "r")
|
||||||
|
music.data = cjson.decode(file:read("*a"))
|
||||||
|
file:close()
|
||||||
|
print("Music library loaded.")
|
||||||
|
end
|
||||||
|
|
||||||
|
function music.save()
|
||||||
|
local str = cjson.encode(music.data)
|
||||||
|
local file = io.open("music.json", "w")
|
||||||
|
file:write(str)
|
||||||
|
file:close()
|
||||||
|
print("Music library saved.")
|
||||||
|
end
|
||||||
|
|
||||||
|
function music.find(str)
|
||||||
|
str = music.normalize(str)
|
||||||
|
local matches = {}
|
||||||
|
for key in pairs(music.data) do
|
||||||
|
if key:find(str) then
|
||||||
|
table.insert(matches, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(#matches .. " matches returned.")
|
||||||
|
return matches
|
||||||
|
end
|
||||||
|
|
||||||
|
function music.add(name)
|
||||||
|
local normalized = music.normalize(name)
|
||||||
|
if music.data[normalized] then
|
||||||
|
local duplicate = false
|
||||||
|
for _, existing_name in ipairs(music.data[normalized].names) do
|
||||||
|
if existing_name == name then
|
||||||
|
duplicate = true
|
||||||
|
print("Already in library.")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not duplicate then
|
||||||
|
table.insert(music.data[normalized].names, name)
|
||||||
|
print("Already in library. Added as alternate name of '" .. musoc.data[normalized].names[1] .. "'")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
music.data[normalized] = { names = { name } }
|
||||||
|
print("Track added (normalized to: '" .. normalized .. "')")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- match is a normalized name or a list of normalized names, info is a table of key-value pairs to be set
|
||||||
|
function music.set(match, info)
|
||||||
|
if type(match) == "table" then
|
||||||
|
for _, value in ipairs(match) do
|
||||||
|
music.set(value, info)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
tab = music.data[match]
|
||||||
|
if not tab then
|
||||||
|
print("'" .. tab .. "' does not exist!")
|
||||||
|
end
|
||||||
|
for key, value in pairs(info) do
|
||||||
|
tab[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a list of all tracks with a `url` key but no `downloaded` key.
|
||||||
|
-- function music.generate_needed_downloads()
|
||||||
|
-- print("To be written.")
|
||||||
|
-- end
|
||||||
|
|
||||||
|
music.load()
|
||||||
|
|
||||||
|
return music
|
42
search-tracklist.lua
Executable file
42
search-tracklist.lua
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
local success, urlencode = pcall(function() return require("urlencode") end)
|
||||||
|
if not success then
|
||||||
|
urlencode = nil
|
||||||
|
print("Install 'urlencode' through LuaRocks for this script to function optimally.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local help == [[Usages:
|
||||||
|
|
||||||
|
search-tracklist <file>
|
||||||
|
|
||||||
|
<file>: A newline-delimmited list of tracks to search for.
|
||||||
|
(Opens a new tab in your default browser searching Google for each line.)
|
||||||
|
|
||||||
|
Optionally requires urlencode to be installed from LuaRocks.
|
||||||
|
Currently only tested on MacOS 11.2.1 (Big Sur).
|
||||||
|
]]
|
||||||
|
|
||||||
|
local filename = arg[1]
|
||||||
|
|
||||||
|
if #filename < 1 then
|
||||||
|
print(help)
|
||||||
|
end
|
||||||
|
|
||||||
|
local file, err = io.open(filename, 'r')
|
||||||
|
if not file then
|
||||||
|
error(err)
|
||||||
|
end
|
||||||
|
|
||||||
|
for line in file:lines() do
|
||||||
|
if #line > 0 then
|
||||||
|
if urlencode then
|
||||||
|
line = urlencode.encode_url(line)
|
||||||
|
else
|
||||||
|
line = line:gsub("%s", "+"):gsub("&", "&")
|
||||||
|
end
|
||||||
|
os.execute("open \"https://google.com/search?q=" .. line .. "\"")
|
||||||
|
-- appeared to overstress my server opening so many tabs at once, so I removed this
|
||||||
|
-- os.execute("open \"https://funkwhale.tangentfox.com/search?q=" .. line .. "&type=tracks\"")
|
||||||
|
end
|
||||||
|
end
|
37
sources/csv-to-json.lua
Executable file
37
sources/csv-to-json.lua
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
-- csv library appears to not function correctly here, so a different script was used
|
||||||
|
|
||||||
|
local csv = require("csv")
|
||||||
|
local cjson = require("cjson")
|
||||||
|
|
||||||
|
local input = csv.open("music-cleaned-2.csv", { separator = "\t" })
|
||||||
|
|
||||||
|
local music = {}
|
||||||
|
for fields in input:lines() do
|
||||||
|
music[fields[1]] = {}
|
||||||
|
if fields[2] and #fields[2] > 0 then
|
||||||
|
local alternate_names = fields[2]
|
||||||
|
local names = {}
|
||||||
|
local index = alternate_names:find("|")
|
||||||
|
while index do
|
||||||
|
local name = alternate_names:sub(1, index - 1)
|
||||||
|
if name and #name > 0 then
|
||||||
|
table.insert(names, name)
|
||||||
|
end
|
||||||
|
alternate_names = alternate_names:sub(index + 1)
|
||||||
|
end
|
||||||
|
if alternate_names and #alternate_names > 0 then
|
||||||
|
table.insert(names, alternate_names)
|
||||||
|
end
|
||||||
|
if #names > 0 then
|
||||||
|
music[fields[1]].alternate_names = names
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = cjson.encode(music)
|
||||||
|
|
||||||
|
local output = io.open("music.json", "w")
|
||||||
|
output:write(data)
|
||||||
|
output:close()
|
25
sources/export-grand-tracklist.lua
Executable file
25
sources/export-grand-tracklist.lua
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
local htmlparser = require("htmlparser")
|
||||||
|
|
||||||
|
local input_file, err = io.open("grand-tracklist-150-to-225.html", "r")
|
||||||
|
if not input_file then error(err) end
|
||||||
|
|
||||||
|
local root = htmlparser.parse(input_file:read("*a"), 10000)
|
||||||
|
|
||||||
|
input_file:close()
|
||||||
|
|
||||||
|
local list = root:select("li")
|
||||||
|
|
||||||
|
local output_file = io.open("music.csv", "a")
|
||||||
|
|
||||||
|
for _, item in ipairs(list) do
|
||||||
|
local content = item:getcontent()
|
||||||
|
if #content < 200 then
|
||||||
|
output_file:write(content .. "\n")
|
||||||
|
else
|
||||||
|
print("Item of length " .. #content .. " ignored.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
output_file:close()
|
22
sources/find-duplicates-2.lua
Executable file
22
sources/find-duplicates-2.lua
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
local cjson = require("cjson")
|
||||||
|
|
||||||
|
local music = io.open("music-cleaned.csv", "r")
|
||||||
|
|
||||||
|
local unique_tracks = {}
|
||||||
|
for track in music:lines() do
|
||||||
|
local normalized_track = track:gsub("%W", ""):lower()
|
||||||
|
|
||||||
|
if unique_tracks[normalized_track] then
|
||||||
|
table.insert(unique_tracks[normalized_track].names, track)
|
||||||
|
else
|
||||||
|
unique_tracks[normalized_track] = { names = { track } }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
music:close()
|
||||||
|
|
||||||
|
local output_file = io.open("music.json", "w")
|
||||||
|
output_file:write(cjson.encode(unique_tracks))
|
||||||
|
output_file:close()
|
42
sources/find-duplicates.lua
Executable file
42
sources/find-duplicates.lua
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
-- local csv = require("csv")
|
||||||
|
--
|
||||||
|
-- local music = csv.open("music-cleaned.csv", {
|
||||||
|
-- separator = ",",
|
||||||
|
-- header = true,
|
||||||
|
-- columns = {
|
||||||
|
-- track = { name = "Track" },
|
||||||
|
-- url = { name = "Download URL" },
|
||||||
|
-- note = { name = "Note" },
|
||||||
|
-- duplicate = { name = "Duplicate" },
|
||||||
|
-- }
|
||||||
|
-- })
|
||||||
|
local music = io.open("music-cleaned.csv", "r")
|
||||||
|
|
||||||
|
local unique_tracks = {}
|
||||||
|
-- for fields in music:lines() do
|
||||||
|
-- local track = fields.track
|
||||||
|
for track in music:lines() do
|
||||||
|
local normalized_track = track:gsub("%W", ""):lower()
|
||||||
|
|
||||||
|
if unique_tracks[normalized_track] then
|
||||||
|
table.insert(unique_tracks[normalized_track].alternate_names, track)
|
||||||
|
else
|
||||||
|
unique_tracks[normalized_track] = { name = track, alternate_names = {} }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
music:close()
|
||||||
|
|
||||||
|
local output_file = io.open("music-cleaned-2.csv", "w")
|
||||||
|
|
||||||
|
for _, track in pairs(unique_tracks) do
|
||||||
|
local alternate_names = ""
|
||||||
|
if #track.alternate_names > 0 then
|
||||||
|
alternate_names = table.concat(track.alternate_names, "|")
|
||||||
|
end
|
||||||
|
output_file:write(track.name .. "\t" .. alternate_names .. "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
output_file:close()
|
1546
sources/grand-tracklist-150-to-225.html
Normal file
1546
sources/grand-tracklist-150-to-225.html
Normal file
File diff suppressed because it is too large
Load Diff
2105
sources/music-cleaned-2.csv
Normal file
2105
sources/music-cleaned-2.csv
Normal file
File diff suppressed because it is too large
Load Diff
2559
sources/music-cleaned.csv
Normal file
2559
sources/music-cleaned.csv
Normal file
File diff suppressed because it is too large
Load Diff
3731
sources/music.csv
Normal file
3731
sources/music.csv
Normal file
File diff suppressed because it is too large
Load Diff
19
sources/rm-duplicates.lua
Executable file
19
sources/rm-duplicates.lua
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
local music = io.open("music.csv", "r")
|
||||||
|
|
||||||
|
local unique = {}
|
||||||
|
for line in music:lines() do
|
||||||
|
if not unique[line] then
|
||||||
|
unique[line] = line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
music:close()
|
||||||
|
|
||||||
|
local output_file = io.open("music-cleaned.csv", "w")
|
||||||
|
for line in pairs(unique) do
|
||||||
|
output_file:write(line .. "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
output_file:close()
|
Loading…
Reference in New Issue
Block a user