Skip to content

Instantly share code, notes, and snippets.

@punmechanic
Created April 6, 2022 14:22
Show Gist options
  • Save punmechanic/a7ef1a638dfb9a2d55fac4b5f14823b4 to your computer and use it in GitHub Desktop.
Save punmechanic/a7ef1a638dfb9a2d55fac4b5f14823b4 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"net/http"
"os"
"strings"
"sync"
"golang.org/x/net/html"
)
func getMetaTags(document *html.Node) map[string]string {
meta := map[string]string{}
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "meta" {
// Meta tags will have multiple attributes, name, property and content.
var k, v string
for _, attr := range n.Attr {
switch attr.Key {
case "property":
k = attr.Val
break
case "content":
v = attr.Val
break
}
}
if k == "" || v == "" {
return
}
meta[k] = v
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(document)
return meta
}
type Task struct {
Link string
Title, Artist string
Error error
}
func startWorker(inputCh <-chan string, outputCh chan<- Task) {
for url := range inputCh {
task := Task{Link: url}
resp, err := http.Get(url)
if err != nil {
task.Error = err
outputCh <- task
}
defer resp.Body.Close()
doc, err := html.Parse(resp.Body)
if err != nil {
task.Error = err
outputCh <- task
}
meta := getMetaTags(doc)
task.Title = meta["twitter:title"]
// Spotify uses an emdot to split artist from the rest.
task.Artist = strings.TrimSpace(strings.Split(meta["twitter:description"], "·")[0])
outputCh <- task
}
}
func main() {
inputCh := make(chan string, 100)
outputCh := make(chan Task)
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
inputCh <- scanner.Text()
}
close(inputCh)
}()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
startWorker(inputCh, outputCh)
wg.Done()
}()
}
go func() {
wg.Wait()
close(outputCh)
}()
for response := range outputCh {
if response.Error != nil {
fmt.Printf("[ERR] %s - %s", response.Link, response.Error)
continue
}
fmt.Printf("%s - %s\n", response.Artist, response.Title)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment