You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FLAD/src/Api/src/controllers/spotifyController.ts

132 lines
4.3 KiB

import IController from './interfaces/IController';
import { Router, Request, Response, NextFunction } from 'express';
import HttpException from '../exception/HttpException';
import axios from 'axios';
import qs from 'qs';
class SpotifyController implements IController {
public path = '/spotify';
public router = Router();
public readonly CLIENT_ID_SPOTIFY = process.env.CLIENT_ID_SPOTIFY;
public readonly CLIENT_SECRET_SPOTIFY = process.env.CLIENT_SECRET_SPOTIFY;
private readonly API_URL = "https://accounts.spotify.com/api/token";
private readonly CALLBACK = 'http://localhost:8080/api/spotify/callback';
private readonly SCOPES = 'user-read-private user-read-email user-read-playback-state user-read-currently-playing user-read-recently-played playlist-modify-public ugc-image-upload user-modify-playback-state';
constructor() {
this.initRoutes();
}
initRoutes() {
this.router.get(`${this.path}/exchange`, this.login);
this.router.get(`${this.path}/callback`, this.getAccessToken);
this.router.get(`${this.path}/refresh`, this.getRefreshToken);
}
private readonly clientRedirect = 'spotify_final_redirect-uri-key';
private login = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const redirectResponse = req.query.redirectUrl ? req.query.redirectUrl : req.headers.referer;
res.cookie(this.clientRedirect, redirectResponse);
res.redirect('https://accounts.spotify.com/authorize?' +
qs.stringify({
response_type: 'code',
client_id: this.CLIENT_ID_SPOTIFY,
scope: this.SCOPES,
redirect_uri: this.CALLBACK,
}));
} catch (error) {
next(new HttpException(400, "Cannot connect: " + error.message));
}
};
private getRefreshToken = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const params = req.query.refresh_token;
if (!req.query.refresh_token) {
return res.json({
"error": "Parameter refresh_token missing"
});
}
let authOptions = {
method: 'POST',
url: 'https://accounts.spotify.com/api/token',
data: qs.stringify({
grant_type: 'refresh_token',
refresh_token: params
}),
headers: {
'Authorization': 'Basic ' + (Buffer.from(this.CLIENT_ID_SPOTIFY + ':' + this.CLIENT_SECRET_SPOTIFY).toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded'
},
json: true
};
axios(authOptions)
.then(session => {
if (session.status === 200) {
res.send({
"access_token": session.data.access_token,
"refresh_token": session.data.refresh_token,
"expires_in": session.data.expires_in
});
}
});
} catch (error) {
next(new HttpException(400, 'Cannot get a new refresh token'));
}
}
private getAccessToken = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
let code = req.query.code;
let storedRedirectUri = req.cookies ? req.cookies[this.clientRedirect] : null;
var authOptions = {
method: 'POST',
url: this.API_URL,
data: qs.stringify({
code: code,
redirect_uri: this.CALLBACK,
grant_type: 'authorization_code'
}),
headers: {
'Authorization': 'Basic ' + (Buffer.from(this.CLIENT_ID_SPOTIFY + ':' + this.CLIENT_SECRET_SPOTIFY).toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded'
},
json: true
};
try {
var resp = await axios(authOptions);
if (resp.status === 200) {
let access_token = resp.data.access_token;
let expiration = resp.data.expires_in;
let refresh = resp.data.refresh_token
res.clearCookie(this.clientRedirect);
res.redirect(`${storedRedirectUri}?` +
qs.stringify({
"access_token": access_token,
"expires_in": expiration,
"refresh_token": refresh
}));
}
} catch (error) {
console.log(error);
next(new HttpException(400, 'Error connection: ' + error.message));
}
};
}
export default SpotifyController;