seek-tune/spotify/utils.go
Chigozirim Igweamaka 1689cc42b5 Initial commit.
2024-03-05 17:25:27 +01:00

244 lines
4.6 KiB
Go

package spotify
import (
"archive/zip"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/url"
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"strings"
"unicode"
"golang.org/x/text/runes"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
func EncodeParam(s string) string {
return url.QueryEscape(s)
}
func ToLowerCase(s string) string {
var result string
for _, char := range s {
if char >= 'A' && char <= 'Z' {
result += string(char + 32)
} else {
result += string(char)
}
}
return result
}
func isPathValid(path string) bool {
dir, err := os.Stat(path)
if err != nil {
fmt.Println(err)
return false
}
if !dir.IsDir() {
return false
}
return true
}
func NewDir(path string) (string, error) {
if !isPathValid(path) {
return "", errors.New("invalid path")
}
dirName := "YourMusic"
fullPath := filepath.Join(path, dirName)
if runtime.GOOS == "windows" {
fullPath = fullPath + "\\"
} else {
fullPath = fullPath + "/"
}
err := os.Mkdir(fullPath, 0700)
if err != nil {
fmt.Sprintln("Error: %w", err)
return "", err
}
return fullPath, nil
}
func ToZip(dir, zipPath string) error {
zipFile, err := os.Create(zipPath)
if err != nil {
return err
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
err = filepath.Walk(dir, func(filePath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if filePath == dir {
return nil
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name, _ = filepath.Rel(dir, filePath)
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
if !info.IsDir() {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
if err != nil {
return err
}
}
return nil
})
return err
}
func GetFileSize(file string) (int64, error) {
fileInfo, err := os.Stat(file)
if err != nil {
return 0, err
}
size := int64(fileInfo.Size())
return size, nil
}
func RemoveAccents(s string) string {
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
output, _, e := transform.String(t, s)
if e != nil {
panic(e)
}
return output
}
func RemoveInvalidChars(input string, invalidChars []byte) string {
filter := func(r rune) rune {
for _, c := range invalidChars {
if byte(r) == c {
return -1 /* remove the char */
}
}
return r
}
return strings.Map(filter, input)
}
func GetLocalIP() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
return ""
}
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
return ""
}
/* catches interrupt signal (ctrl+c) */
func SetupCloseHandler(tempDir, zipFile string) {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
<-c
DeleteFile(tempDir)
DeleteFile(zipFile)
os.Exit(0)
}()
}
func DeleteFile(filePath string) {
if _, err := os.Stat(filePath); err == nil {
if err := os.RemoveAll(filePath); err != nil {
fmt.Println("Error deleting file:", err)
}
}
}
/* used for the last validation in the Match function */
func ExtractFirstWord(value string) string {
for i := range value {
if value[i] == ' ' {
return value[0:i]
}
}
return value
}
/*
i don't know why, but there are artists who,
due to their name, they add a hyphen
between some words of their names
on one platform and not on the other
*/
func CleanAndNormalize(s string) string {
cleaned := strings.ReplaceAll(s, "-", "")
cleaned = strings.ReplaceAll(cleaned, " ", "")
return cleaned
}
// Convert M4A file from stereo to mono
func ConvertM4aToMono(inputFile, outputFile string) ([]byte, error) {
cmd := exec.Command("ffprobe", "-v", "error", "-show_entries", "stream=channels", "-of", "default=noprint_wrappers=1:nokey=1", inputFile)
output, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("error running ffprobe: %v, %v", err, string(output))
}
audioBytes, err := ioutil.ReadFile(inputFile)
if err != nil {
return nil, fmt.Errorf("error reading input file: %v", err)
}
channels := strings.TrimSpace(string(output))
if channels != "1" {
cmd = exec.Command("ffmpeg", "-i", inputFile, "-af", "pan=mono|c0=c0", outputFile)
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("error running ffmpeg: %v", err)
}
audioBytes, err = ioutil.ReadFile(outputFile)
if err != nil {
return nil, fmt.Errorf("error reading input file: %v", err)
}
}
return audioBytes, nil
}