func ParseVirtualDJTracklist(bufReader *bufio.Reader) []Track { var list []Track for line, _, err := bufReader.ReadLine(); err != io.EOF; line, _, err = bufReader.ReadLine() { data := strings.SplitN(string(line), " : ", 2) trackdata := strings.SplitN(data[1], " - ", 2) if len(trackdata) != 2 { term.OutputError("Error parsing track " + string(data[1])) term.OutputMessage("Please enter an artist for this track: ") artist, err := term.STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect artist entry.") os.Exit(2) } term.OutputMessage("Please enter a name for this track: ") track, err := term.STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect track name entry.") os.Exit(2) } trackdata = []string{artist, track} } thistrack := new(Track) thistrack.Artist = trackdata[0] thistrack.Song = trackdata[1] list = append(list, *thistrack) } return list }
func getCoverUrl(db *bolt.DB, artist string, track string) string { term.OutputMessage(fmt.Sprintf(term.Green+"Searching for %s - %s.."+term.Reset, artist, track)) cover_url := GetData(db, artist, track) if cover_url != "" { term.OutputMessage(term.Green + term.Bold + "DONE!\n" + term.Reset) } else { term.OutputMessage(term.Green + "." + term.Reset) cover_url = itunes.GetCoverFor(artist, track) if cover_url == "" { term.OutputMessage(term.Green + "." + term.Reset) cover_url = google.GetCoverFor(artist, track) } if cover_url == "" { term.OutputMessage(term.Green + ".\n" + term.Reset) term.OutputError(fmt.Sprintf("Unable to find a cover for %s - %s", artist, track)) cover_url = getCoverUrlFromInput() } if cover_url != "" { term.OutputMessage(term.Green + term.Bold + "DONE!\n" + term.Reset) InsertData(db, artist, track, cover_url) } } return cover_url }
func maskImage(dst draw.Image, filename string) { infile, err := os.Open(filename) defer infile.Close() if err != nil { term.OutputError(fmt.Sprintf("Unable to open overlay image - %s", err.Error())) } else { overlay, _, err := image.Decode(infile) if err != nil { term.OutputError(fmt.Sprintf("Unable to decode image file - %s", err.Error())) } else { mask := image.NewUniform(color.Alpha{128}) draw.DrawMask(dst, dst.Bounds(), imaging.Thumbnail(overlay, 480, 480, imaging.CatmullRom), image.Pt(0, 0), mask, image.Pt(0, 0), draw.Over) } } }
func getCoverUrlFromInput() string { term.OutputMessage("Enter a URL the cover image: ") cover_url, err := STD_IN.ReadString('\n') if err != nil { term.OutputError("Error accepting input.") os.Exit(2) } return strings.TrimRightFunc(cover_url, unicode.IsSpace) }
func GetPaginatedCoverFor(artist string, song string, start int) string { query := "site:bandcamp.com " + artist + " - " + song + " bandcamp cover art" cover_search_url := fmt.Sprintf(GOOGLE_URL, url.QueryEscape(query), start) request := BuildHttpRequest(cover_search_url, "GET") client := http.Client{} resp, doError := client.Do(request) defer resp.Body.Close() if doError != nil { term.OutputError("Error fetching artwork for " + artist + " - " + song + ": " + doError.Error()) } var responseObj *Response = new(Response) err := json.NewDecoder(resp.Body).Decode(&responseObj) if err != nil { term.OutputError(err.Error()) os.Exit(2) } var songObj *Result = new(Result) if responseObj.Status != 200 { term.OutputError(fmt.Sprintf("Error fetching artwork from google - %d", responseObj.Status)) } else { for _, result := range responseObj.Data.Results { if strings.Contains(result.OriginalContextUrl, "bandcamp.com") && (strings.Contains(result.ContentNoFormatting, "cover art") || strings.Contains(result.ContentNoFormatting, song) || strings.Contains(result.TitleNoFormatting, song)) || (strings.HasPrefix(result.ContentNoFormatting, song[0:15])) { songObj = &result break } } } if songObj.Url == "" { term.OutputMessage(term.Green + "." + term.Reset) } return songObj.Url }
func parseTracklist(tracklist *string) []Track { var list []Track fin, err := os.Open(*tracklist) if err != nil { term.OutputError(fmt.Sprintf("The file %s does not exist!\n", *tracklist)) os.Exit(1) } defer fin.Close() bufReader := bufio.NewReader(fin) for line, _, err := bufReader.ReadLine(); err != io.EOF; line, _, err = bufReader.ReadLine() { data := strings.SplitN(string(line), " : ", 2) trackdata := strings.SplitN(data[1], " - ", 2) if len(trackdata) != 2 { term.OutputError("Error parsing track " + string(data[1])) term.OutputMessage("Please enter an artist for this track: ") artist, err := STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect artist entry.") os.Exit(2) } term.OutputMessage("Please enter a name for this track: ") track, err := STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect track name entry.") os.Exit(2) } trackdata = []string{artist, track} } thistrack := new(Track) thistrack.Artist = trackdata[0] thistrack.Song = trackdata[1] list = append(list, *thistrack) } return list }
func GetCoverFor(artist string, song string) string { query := artist + " " + song cover_search_url := fmt.Sprintf(ITMS_URL, url.QueryEscape(query), "AU", "song") request := BuildHttpRequest(cover_search_url, "GET") client := http.Client{} resp, doError := client.Do(request) defer resp.Body.Close() if doError != nil { term.OutputError("Error fetching artwork for " + artist + " - " + song + ": " + doError.Error()) } var responseObj *Response = new(Response) err := json.NewDecoder(resp.Body).Decode(&responseObj) if err != nil { term.OutputError(err.Error()) os.Exit(2) } var songObj *Result = new(Result) var emptySongObj *Result = new(Result) if responseObj.Error != "" { fmt.Println(responseObj.Error) } else { for _, result := range responseObj.Results { if ((result.ArtistName == artist) && (result.TrackName == song)) || strings.HasPrefix(result.TrackName, song) { songObj = &result break } } } if songObj != emptySongObj { return songObj.ArtworkUrl600() } else { return "" } }
func ParseBasicTracklist(bufReader *bufio.Reader) []Track { var list []Track regex, err := regexp.Compile(`([0-9]+)(?:.{1}?\s)(.+)(?:\s-\s)(.+)`) if err != nil { term.OutputError("Error matching strings") os.Exit(2) } for line, _, err := bufReader.ReadLine(); err != io.EOF; line, _, err = bufReader.ReadLine() { trackdata := regex.FindAllStringSubmatch(string(line), 3)[0] // trackdata := strings.SplitN(data[1], " - ", 2) // t if len(trackdata) != 4 { term.OutputError("Error parsing track " + string(line)) term.OutputMessage("Please enter an artist for this track: ") artist, err := term.STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect artist entry.") os.Exit(2) } term.OutputMessage("Please enter a name for this track: ") track, err := term.STD_IN.ReadString('\n') if err != nil { term.OutputError("Incorrect track name entry.") os.Exit(2) } trackdata = []string{"0", artist, track} } thistrack := new(Track) thistrack.Artist = trackdata[2] thistrack.Song = trackdata[3] list = append(list, *thistrack) } return list }
func createImage(selection ArtistTrackList, output_filename string, overlay string) { if len(selection) != 9 { term.OutputError("Unable to find enough images to make cover") } else { term.OutputMessage(term.Yellow + "Generating image.." + term.Reset) xt := 3 yt := 3 width := xt * 160 height := yt * 160 dst := image.NewRGBA(image.Rect(0, 0, width, height)) count := 0 for y := 0; y < yt; y++ { for x := 0; x < xt; x++ { term.OutputMessage(term.Yellow + "." + term.Reset) src := selection[count].Tracks[0].CoverImage draw.Draw(dst, image.Rect(x*160, y*160, (x+1)*160, (y+1)*160), imaging.Thumbnail(src, 160, 160, imaging.CatmullRom), image.Pt(0, 0), draw.Src) count = count + 1 } } if overlay != "" { term.OutputMessage(term.Yellow + "." + term.Reset) maskImage(dst, overlay) term.OutputMessage(term.Yellow + "." + term.Reset) } f, err := os.Create(output_filename) if err != nil { term.OutputError("\ncant save picture: " + err.Error()) } defer f.Close() term.OutputMessage(term.Yellow + "." + term.Reset) jpeg.Encode(f, dst, nil) term.OutputMessage(term.Yellow + term.Bold + "DONE!\n" + term.Reset) } }
func FetchImage(artistTrack *ArtistTrack) { term.OutputMessage(term.Yellow + "Fetching image.." + term.Reset) term.OutputMessage(term.Yellow + "." + term.Reset) client := http.Client{} req, err := http.NewRequest("GET", artistTrack.Tracks[0].Cover, nil) if err != nil { fmt.Printf("Error - %s", err.Error()) } resp, doError := client.Do(req) if doError != nil { term.OutputError("Error - " + doError.Error()) } outputImage, _, err := image.Decode(resp.Body) artistTrack.Tracks[0].CoverImage = outputImage term.OutputMessage(term.Yellow + term.Bold + "DONE!\n" + term.Reset) }
func ParseSeratoTracklist(bufReader *bufio.Reader) { term.OutputError("Serato tracklist parsing unsupported") os.Exit(2) }
func main() { flag.Parse(true) showWelcomeMessage() if *aboutFlag == true { showAboutMessage() os.Exit(0) } var tracklist []Track tracklistFileName := "" if *trackListFlag != "" { tracklistFileName = *trackListFlag tracklist = parseTracklist(trackListFlag) } else { if len(os.Args) > 1 { if os.Args[1][0:2] != "--" { tracklistFileName = string(os.Args[1]) tracklist = parseTracklist(&tracklistFileName) } else { term.OutputError("Please provide a tracklist to parse") os.Exit(1) } } else { term.OutputError("Please provide a tracklist to parse") os.Exit(1) } } if len(tracklist) < 9 { term.OutputError("Not enough tracks in tracklist") os.Exit(1) } overlay_filename := "" if *overlayFlag != "" { overlay_filename = *overlayFlag } output_filename := strings.Replace(tracklistFileName, ".txt", ".jpg", -1) if *outputFileFlag != "" { output_filename = *outputFileFlag } else { if len(os.Args) > 2 { if os.Args[2][0:2] != "--" && os.Args[2] != "" { output_filename = string(os.Args[2]) } } } artists := countArtists(tracklist) sortedArtists := sortMapByValue(artists) selection := sortedArtists[:9] db, err := bolt.Open(DATABASE_FILENAME, 0600, nil) if err != nil { term.OutputError(err.Error()) os.Exit(2) } defer db.Close() db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists(DATABASE_BUCKET) if err != nil { return fmt.Errorf("create bucket: %s", err) } return nil }) for i, _ := range selection { j := 0 for !GetCover(db, i, &selection[i]) { replacement := sortedArtists[9+i+j] term.OutputError(fmt.Sprintf("Replacing with %s", replacement.Artist)) selection[i] = replacement j++ } } createImage(selection, output_filename, overlay_filename) }