From b3d0af2de29711abfe6da373786d365d9a6de198 Mon Sep 17 00:00:00 2001 From: "Gabriel A. Giovanini" Date: Wed, 13 Mar 2024 21:17:51 +0100 Subject: feat: Rewrite to golang I have found a nice lib in go to handle XML so I migrate to it. Go is ages easier to deploy then python. --- main.go | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 main.go (limited to 'main.go') diff --git a/main.go b/main.go new file mode 100644 index 0000000..945b30b --- /dev/null +++ b/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "io" + "net/http" + "regexp" + "strings" + + "github.com/beevik/etree" +) + +type ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error + +var RegexCollection = map[string]string{ + "nerdcast": "NerdCast [0-9]+[a-c]* -", + "empreendedor": "Empreendedor [0-9]+ -", + "mamicas": "Caneca de Mamicas [0-9]+ -", + "english": "Speak English [0-9]+ -", + "nerdcash": "NerdCash [0-9]+ -", + "bunker": "Lá do Bunker [0-9]+ -", + "tech": "NerdTech [0-9]+ -", + "genera": "Generacast [0-9]+ -", +} + +const ( + FeedUrl = "https://api.jovemnerd.com.br/feed-nerdcast/" +) + +func getSeries(r *http.Request) []string { + query := r.URL.Query().Get("q") + + var series []string + + for _, q := range strings.Split(query, ",") { + if _, ok := RegexCollection[q]; ok { + series = append(series, q) + } + } + + if len(series) > 0 { + return series + } + + return []string{"nerdcast"} +} + +func match(title string, series []string) bool { + for _, s := range series { + if ok, err := regexp.MatchString(RegexCollection[s], title); err == nil && ok { + return true + } + } + + return false +} + +func fetchXML(_ context.Context) ([]byte, error) { + res, err := http.Get(FeedUrl) + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + return io.ReadAll(res.Body) + } + + return nil, errors.New("Invalid http code") +} + +func appendTag(tag *etree.Element, ap string) { + text := tag.Text() + tag.SetText(text + ap) +} + +func filterBySeries(series []string, xml []byte, temper bool) ([]byte, error) { + doc := etree.NewDocument() + err := doc.ReadFromBytes(xml) + if err != nil { + return nil, err + } + + channel := doc.FindElement("//channel") + + if temper { + tmp := strings.ToUpper(strings.Join(series, ",")) + tmp = fmt.Sprintf(" [%s]", tmp) + appendTag(channel.FindElement("title"), tmp) + appendTag(channel.FindElement("description"), tmp) + appendTag(channel.FindElement("link"), "?"+tmp) + appendTag(channel.FindElement("author[namespace-prefix()='itunes']"), tmp) + appendTag(channel.FindElement("subtitle[namespace-prefix()='itunes']"), tmp) + appendTag(channel.FindElement("summary[namespace-prefix()='itunes']"), tmp) + appendTag(channel.FindElement("author[namespace-prefix()='googleplay']"), tmp) + + } + + for _, tag := range channel.FindElements("item") { + title := tag.FindElement("title").Text() + if !match(title, series) { + channel.RemoveChild(tag) + } + } + + return doc.WriteToBytes() +} + +func wrap(next ErrorRequestHandler) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if err := next(w, r); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + } +} + +func titles(w http.ResponseWriter, r *http.Request) error { + xml, err := fetchXML(r.Context()) + if err != nil { + return err + } + + doc := etree.NewDocument() + err = doc.ReadFromBytes(xml) + if err != nil { + return err + } + + series := getSeries(r) + + els := doc.FindElements("//channel/item") + for _, e := range els { + txt := e.FindElement("title").Text() + "\n" + if match(txt, series) { + _, err = w.Write([]byte(txt)) + if err != nil { + return err + } + } + } + + return nil +} + +func podcast(w http.ResponseWriter, r *http.Request) error { + xml, err := fetchXML(r.Context()) + if err != nil { + return err + } + + series := getSeries(r) + filterdXML, err := filterBySeries(series, xml, true) + if err != nil { + return err + } + + _, err = w.Write(filterdXML) + if err != nil { + return err + } + + return nil +} + +func main() { + var ( + addr = flag.String("addr", ":8080", "Server address") + ) + + flag.Parse() + + mux := http.NewServeMux() + mux.HandleFunc("/titles", wrap(titles)) + mux.HandleFunc("/", wrap(podcast)) + + server := http.Server{ + Handler: mux, + Addr: *addr, + } + + err := server.ListenAndServe() + if err != nil { + fmt.Printf("Server error: %s", err.Error()) + } +} -- cgit v1.2.3