Graphing CGP Grey's Rock-Paper-Scissors YouTube Game

2 min read Original article ↗

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