Empecemos por la idea. Resulta que yo utilizo mucho youtube como un reproductor de música. Las listas de reproducción de youtube están bastante bien (aunque el modo aleatorio sea BASURA), puedo crear tantas como quiero y mientras trabajo dejo youtube en una pestañita con música.

Ademas, para evitar la publi, existen adblockers, por lo que mientras que no lo tengas a pantalla completa, no te comes un solo anuncio.

Bien, pues con eso en mente, y mi actitud “Quema canciones” (cuando me da por una no paro de escucharla hasta que la aborrezco) decido meterme a hacer una app. Sincronizas las listas que selecciones y puedes escucharlas en el móvil sin gastar un solo mega. Mi caso, escucharlas en el coche, claramente, cada dos por tres cambio de canción o de artista “burning del momento”, y es muy, pero que muy aburrido tener que coger el pendrive, subirlo al ordenador, ir copiando y pegando todas las canciones que quiero escuchar, pasarlas al pen y volver a bajarlo al coche sin que se me olvide en casa. Eso cuando no se me olvida subírmelo. Si, tardo en actualizar la música del coche, siempre se me olvida el puto pen…

Entonces, una app. Un reproductor de música, que ademas de escuchar la música que ya tienes en tu móvil, te logeas con tu cuenta de youtube, ves tus listas de reproducción y seleccionas las que quieras que se mantengan sincronizadas. Se irán comprobando en background si hay cambios y así borrar las canciones que has quitado y bajar las nuevas, siempre y cuando estés con wifi, (o no, en caso de que te sobren los megas, típica opción de configuración). En mi caso personal, como estoy con robastar y los megas que tengo son BASURA, me interesa comprobar que solo vaya por wifi. ¿Pasáis wifi?

Pues todo lo dicho, me dispongo a hacer el reproductor y resulta que el SDK de apple para reproducir música es pinta y colorea, prácticamente un juego, una vez te lees un poquito la documentación y las 4 cosas que tiene, el mayor trabajo esta en el diseño de la interfaz y todo eso. Pensando que el auténtico reto está en bajarme las canciones de youtube e intentar violar todos los derechos posibles (intentare subirla al app store respetándolos claro 😜), hago 4 búsquedas en google y para mi decepción, bajarse las canciones de youtube es pinta y colorea también 😂

¿Como bajarlas? Pues 4 lineas, resulta que hay un API GRATIS y fácil de usar que dada una url de una canción, te bajas un JSON con la información de ésta y un link para descargarte el mp3.

Mientes, show me the fucking code:

import PlaygroundSupport


let fetcher = "http://www.youtubeinmp3.com/fetch/?format=JSON&video="
let video = "https://www.youtube.com/watch?v=z8pFXY5cGGc"


let url = URL(string: "\(fetcher)\(video)")!
let session = URLSession.shared
var request = URLRequest(url: url)


let task = session.dataTask(with: url) { (data, response, error) in

    if let data = data {
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String : Any]
            let link = json["link"]

            print("Link: \(link)")
            //Otra task aquí para descargar la canción
            print(json)
        } catch {
            print(error)
        }
    }

    print("Response: \(response)")
    print("Error: \(error)")
}

task.resume()


PlaygroundPage.current.needsIndefiniteExecution = true

Pues ahí lo tenéis, un playground que os da el link. Luego bajarse la canción es una downloadrequest y guardar el archivo…. Nada del otro mundo.

Así que, aunque útil (personalmente), nada complicado. Ya iré contando como transcurre la aplicación.

Para la descarga de canciones tengo pensado utilizar todo el frameworks de Operation de apple, que con swift 3 quedan chulas y sencillas.

Aquí un ejemplo:

class BaseOperation: Operation {

    enum State: String {
        case Ready
        case Executing
        case Finished

        var keyPath: String {
            return "is\(self.rawValue)"
        }
    }

    override var isAsynchronous: Bool { return true }

    var state = State.Ready {
        willSet {
            self.willChangeValue(forKey: self.state.keyPath)
            self.willChangeValue(forKey: newValue.keyPath)
        }
        didSet {
            self.didChangeValue(forKey: oldValue.keyPath)
            self.didChangeValue(forKey: self.state.keyPath)
        }
    }

    override var isExecuting: Bool {
        return self.state == .Executing
    }

    override var isFinished: Bool {
        return self.state == .Finished
    }

    override func start() {
        if self.isCancelled {
            state = .Finished
        } else {
            state = .Ready
            self.main()
        }
    }

}

Y poco mas que contar por hoy. Solo aliviar un poco la frustración de que sea tan relativamente fácil conseguir descargar las canciones 😑