youtubeid(url) = string(first(split(replace(url, "https://www.youtube.com/watch?v=" => ""), "&t")))
function metadata(url)
id = youtubeid(url)
request = youtube.videos().list(part=["snippet", "statistics"], id=id)
response = request.execute()
description = response["items"][1]["snippet"]["description"]
title = response["items"][1]["snippet"]["title"]
views = parse(Int, response["items"][1]["statistics"]["viewCount"])
if url == "https://www.youtube.com/watch?v=CPb168NUwGc"
# Special case for https://www.youtube.com/watch?v=CPb168NUwGc (description for this is not standard)
return (; description="""
WIN: https://www.youtube.com/watch?v=RVLUX6BUEJI
LOSE / DRAW: https://www.youtube.com/watch?v=jDQqv3zkbIQ
🌐 Website: https://www.cgpgrey.com
💖 Patreon: https://www.patreon.com/cgpgrey
📒 Cortex: http://www.cortexbrand.com
⛔️ Ah01F ✅
""", title="🔴", views)
end
(; description, title, views)
end
function links(url; visited=Dict(), duplicate_links=false)
m = metadata(url)
r = Dict(
:id => youtubeid(url),
:code => last(split(strip(m.description), "\n")), # last line is a special code
:url => url,
:links => [],
:children => [],
:title => m.title,
:views => m.views,
)
for line in split(m.description, "\n")
if occursin("https://www.youtube.com/watch?v=", line)
_status, video = split(line, ":", limit=2)
video = strip(video)
push!(r[:links], Dict(:status => string(_status), :url => string(video)))
end
end
for link in r[:links]
url = link[:url]
if !(url in keys(visited))
visited[url] = Dict()
s = links(url; visited, duplicate_links)
push!(r[:children], s)
visited[url] = s
else
duplicate_links && push!(r[:children], visited[url])
end
end
return r
end
function cached_links(url; duplicate_links)
bfile = """$(youtubeid(url))-$(duplicate_links ? "dup-links" : "no-dup-links").json"""
if isfile(bfile)
return JSON3.read(bfile)
end
r = links(url; duplicate_links)
open(bfile, "w") do f
JSON3.write(f, r)
end
r
end
function _clean_titles(str)
t = join([c for c in str if isascii(c)])
t = strip(t)
if occursin("Cortex", t)
return ""
end
string(t)
end
function _node_builder(nodes, d)
for c in d[:children]
push!(nodes, (; id=c[:id], title=_clean_titles(c[:code]), url=c[:url], views=c[:views]))
_node_builder(nodes, c)
end
end
function _graph_builder(G, d, ids)
from = d[:id]
for c in d[:children]
to = c[:id]
add_edge!(G, findfirst(isequal(from), ids), findfirst(isequal(to), ids))
_graph_builder(G, c, ids)
end
end
function get_nodes(data)
nodes = [(; id=data[:id], title=_clean_titles(data[:title]), url=data[:url], views=data[:views])]
_node_builder(nodes, data)
nodes = unique(nodes)
ids = [n.id for n in nodes]
titles = [n.title for n in nodes]
urls = [n.url for n in nodes]
(; ids, titles, urls, nodes)
end
function grapher(data, ids)
G = SimpleDiGraph(length(ids))
_graph_builder(G, data, ids)
G
end