July 26th, 2008

last.fm CakePHP component for songs submission

Tags: , , , ,

Ayer comentaba sobre la clase PHP para enviar canciones a last.fm. Bueno dado que lo voy a utilizar desde CakePHP lo más lógico era construir un componente, y gracias al HttpSocket de CakePHP el código se redujo bastante. Aquí les dejo el código para usarlo libremente (MIT License)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
< ?php
/**
 * last.fm component for songs submissions 
 * Send songs to last.fm using cakephp
 *
 *
 * PHP versions 4 and 5
 *
 * Copyright 2008, Pablo Viojo
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @copyright			Copyright 2008, Pablo Viojo (http://pviojo.net)
 * @link						http://projects.pviojo.net/lastfm 
 * @version				0.1.1
 * @lastmodified		2008-07-26
 * @license					http://www.opensource.org/licenses/mit-license.php The MIT License
 *
 * Usage sample:
 * 
 
 if($this->Lastfm->connect($user, $password)){
	if(
		$this->Lastfm->submit(
			array(
				'artist'=>'Artist',
				'title'=>'Song Name',
				'album'=>'Album nane',
				'duration'=>duration(secs)
			)
		)
	 ){ 
		// ...submission success
  	}
  }
 
 *
 */	
 
 
 
if (!defined('LASTFM_CONNECTED')){
	define ('LASTFM_CONNECTED', 'OK');
}
if (!defined('LASTFM_ERROR')){
	define ('LASTFM_ERROR', 'ERROR');
}
 
App::import('core','HttpSocket');
 
class LastfmComponent extends Object {
 
/**
 * Constructor.
 */
	function startup(&$controller) {
		$this->controller = $controller;
 
		$this->clientId = "tst";
		$this->clientVer = "1.0";
 
		$this->socket = new HttpSocket();
 
	}
 
 
 
/**
 * Connects to lastfm using user and password
 */	
	function connect($user, $password){
		$this->user = $user;
		$this->password = $password;
		return $this->_handShake();
 
	}
/**
 * Returns true if connected to last.fm
 *
 * @return boolean Connection Status
 * @access public
 */
 	function isConnected(){
		if ($this->status==LASTFM_CONNECTED){
			return true;
		}
 
		return false;
	}
/**
 * Performs a handshake
 *
 * @return Status (LASTFM_CONNECTED on success, LASTFM_ERROR otherwise)
 * @access private
 */	
	function _handShake(){
 
		$this->status = false;
 
		$timestamp = time();
		$auth = md5(md5($this->password) . $timestamp);
 
		$url = "http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=" . $this->clientId . "&v=" . $this->clientVer . "&u=" . $this->user . "&t=" . $timestamp . "&a=" . $auth ;
		$rsp = $this->_execute($url,  array('username'=>$this->user, 'password'=>$this->password));
		if ($rsp){
			$rsp = split("\n",$rsp);
			$this->status = $rsp[0];
			switch($this->status){
				case "OK":
					$this->status = LASTFM_CONNECTED;
					$this->sessionId = $rsp[1];
					$this->urls['nowPlaying'] = $rsp[2];
					$this->urls['submission'] = $rsp[3];
					break;
				default:
					$this->status = LASTFM_ERROR;
					$this->sessionId = null;
					break;
			}
		}
		return $this->status ;
	}
 
/**
 * Submit a song to last.fm
 * @param array $song array ("artist", "title", "duration", "album"[, "start"] ) 
 * @return boolean Submission Status
 * @access public
 */	
	function submit($song){
 
		$timestamp = time();
		$auth = md5(md5($this->password) . $timestamp);
 
		$data = array(
			"s"=>$this->sessionId,
			"a[0]"=>$song['artist'],
			"t[0]"=>$song['title'],
			"i[0]"=>(isset($song['start'])?$song['start']:time()),
			"o[0]"=>"P",
			"r[0]"=>"",
			"l[0]"=>$song['duration'],
			"b[0]"=>$song['album'],
			"n[0]"=>"",
			"m[0]"=>""
		);
 
 
		$url = $this->urls['submission'];
		$rsp = $this->_execute($url,  array('username'=>$this->user, 'password'=>$this->password), 'POST', $data);
		switch(trim($rsp)){
			case "OK":
				return true;
				break;
			default:
				return false;
		}
	}
 
 
/**
 * Execute a request
 * @access private
 */		
	function _execute($url, $auth = null, $method = 'GET', $data = null){
 
 
		$request = array(
			'method' => $method, 
			'uri' => $url
		);
 
		if ($auth){
			$request = am(
				$request,
				array(
					'auth' => array(
						'method' => 'basic',
						'user' => $auth["username"],
						'pass' => $auth["password"]
					)
				)
			);
		}
 
		if (strtoupper($method)=="POST"){
			if ($data){
				foreach($data as $key=>$value ) {
					$postData[$key] = $value;
				}
				$request['body'] = $postData;
			}
		}
 
 
		$output = $this->socket->request($request);
		return $output;
 
	}
 
 
 
 
}

Tags: , , , ,

5 Comments Add your own

  • Victor San Martin | July 26th, 2008 at 18:14


    Que tal,

    Buen componente y ejemplo de como usar la API de LastFM, aunque tengo una duda.
    Porque no pusiste App::import(’core’,'HttpSocket’); al principio, o sea fuera del método _execute(). Y al igual que $socket = new HttpSocket();, no seria mejor ponerlo en startup() onda, $this->httpSocket = new HttpSocket();.

    Saludos.

  • pviojo | July 26th, 2008 at 21:54


    Toda la razón, ya está corregido. Muchas gracias!

  • Fabian Ramirez | July 28th, 2008 at 10:04


    Me parece raro usar define() en una clase.

    Quizas no habria sido mejor declararlas como atributos privados de una clase?

    private $connected = true;
    private $error = true;

    Asi puedes tener metodos accesadores y modificadores para estas variables y modificarlas cuando estimes. En cambio con define son estaticas.

    Ejemplo:

    if($lastfm->error()):
    $lastfm->setConnected(false);
    endif;

    if($lastfm->connected == true) {
    // Hace lo que tienes que hacer
    } else {
    return $lastfm->error;
    }

  • pviojo | July 28th, 2008 at 10:59


    @Fabián: El define esta fuera de la clase, y con el tema de declarlas como privadas no estoy muy de acuerdo, ya que connected y error son dos valores posibles para el atributo status, y no atributos de la clase.

    En cualquier caso debería declararlas como constantes (const) pero como PHP4 no lo soporta están definidas como están.

    Saludos

  • Fabian Ramirez | July 29th, 2008 at 22:28


    Pablo es el arte de programar de cada uno :)

  • Leave a Reply

    XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="">

    (required)

    (required)

qrcode for this url (http://pviojo.net/posts/lastfm-cakephp-component-for-songs-submission/)

About

Mi nombre es Pablo Viojo y tengo 27 años. Nací en Uruguay el 7 de agosto de 1981. Actualmente vivo en Santiago, Chile

Aparte de esto me interesa todo lo que tenga que ver con Internet y las nuevas tecnologías. Más info aquí, en mi hCard o en formato FOAF

View Pablo Viojo's profile on LinkedIn



Recent Comments

Pages

Feeds

Posts by tags

Posts by month