btrtracks/src/lastfm.js

132 lines
3.6 KiB
JavaScript
Raw Permalink Normal View History

2019-01-25 15:00:35 +00:00
import path from 'path'
2019-12-18 12:57:02 +00:00
import rp from 'request-promise-native'
2019-01-25 15:00:35 +00:00
import crypto from 'crypto'
import { dbPromise } from './database'
import { addListExternal } from './external'
2019-12-18 12:57:02 +00:00
import { parseStringPromise } from 'xml2js'
2019-01-25 15:00:35 +00:00
const values = require(path.join(process.cwd(), 'values.json'))
function createHash (data) {
2019-01-25 21:11:58 +00:00
return crypto
.createHash('sha1')
.update(data.artist + data.name)
.digest('hex')
2019-01-25 15:00:35 +00:00
.substr(0, 8)
}
async function search (track, limit = 30) {
if (!values.lastfm) return []
2019-01-25 21:11:58 +00:00
2019-01-25 15:00:35 +00:00
let data
try {
2019-12-18 12:57:02 +00:00
data = await rp(`http://ws.audioscrobbler.com/2.0/?method=track.search&track=${track}&api_key=${values.lastfm.key}&format=json&limit=${limit}`)
2019-01-25 15:00:35 +00:00
data = JSON.parse(data)
2019-01-25 21:11:58 +00:00
if (!data.results || !data.results.trackmatches || !data.results.trackmatches.track) {
throw new Error('No results')
}
2019-01-25 15:00:35 +00:00
} catch (e) {
return []
}
2019-01-25 21:11:58 +00:00
const final = []
for (const i in data.results.trackmatches.track) {
const res = data.results.trackmatches.track[i]
2019-01-25 21:11:58 +00:00
let clean = {
id: createHash(res),
artist: res.artist,
title: res.name,
external: true,
mbid: res.mbid
2019-01-25 15:00:35 +00:00
}
2019-01-25 21:11:58 +00:00
clean = addListExternal(clean.id, clean)
2019-01-25 21:11:58 +00:00
final.push(clean)
2019-01-25 15:00:35 +00:00
}
2019-01-25 21:11:58 +00:00
2019-01-25 15:00:35 +00:00
return final
}
2019-12-18 12:57:02 +00:00
// Authentication
function getAPISig (params) {
let allStrings = []
const qs = {}
params.api_key = values.lastfm.key
for (const key in params) {
const val = params[key]
2019-12-18 12:57:02 +00:00
if (val == null || val === '') continue
allStrings.push(key + val)
qs[key] = val
}
allStrings = allStrings.sort()
allStrings.push(values.lastfm.secret)
qs.api_sig = crypto.createHash('md5').update(allStrings.join('')).digest('hex')
2019-12-18 12:57:02 +00:00
return qs
}
function getAuthURL () {
return 'http://www.last.fm/api/auth/?api_key=' + values.lastfm.key + '&cb=' + values.lastfm.redirectUri
}
async function getSession (token) {
const sessSig = getAPISig({ token, method: 'auth.getSession' })
const res = await rp('http://ws.audioscrobbler.com/2.0/', { qs: sessSig })
const rep = await parseStringPromise(res)
const name = rep.lfm.session[0].name[0]
const key = rep.lfm.session[0].key[0]
2019-12-18 12:57:02 +00:00
return { name, key }
}
async function storeSession (userId, session) {
if (!session.name || !session.key) throw new Error('Invalid session parameter.')
const db = await dbPromise
const existing = await db.get('SELECT * FROM LastFM WHERE userId = ?', userId)
2019-12-18 12:57:02 +00:00
if (existing) {
await db.run('UPDATE LastFM SET name = ?, key = ? WHERE userId = ?', session.name, session.key, userId)
} else {
await db.run('INSERT INTO LastFM (userId,name,key,created) VALUES (?,?,?,?)', userId, session.name, session.key, new Date())
}
return true
}
async function disregardSession (userId) {
const db = await dbPromise
2019-12-18 12:57:02 +00:00
return db.run('DELETE FROM LastFM WHERE userId = ?', userId)
}
async function getSessionForUser (userId) {
const db = await dbPromise
2019-12-18 12:57:02 +00:00
return db.get('SELECT * FROM LastFM WHERE userId = ?', userId)
}
async function scrobbleTrack (userId, trackData) {
const sess = await getSessionForUser(userId)
2019-12-18 12:57:02 +00:00
if (!sess) throw new Error('User does not have a LastFM session.')
const scrobbleSig = getAPISig({
2019-12-18 12:57:02 +00:00
sk: sess.key,
method: 'track.scrobble',
artist: trackData.artist || 'Unknown',
title: trackData.title,
album: trackData.album,
duration: trackData.duration,
mbid: trackData.mbid,
timestamp: Math.floor(Date.now() / 1000)
})
await rp.post('http://ws.audioscrobbler.com/2.0/', { form: scrobbleSig })
return true
}
2020-10-04 08:01:16 +00:00
export {
search,
getAPISig,
getAuthURL,
getSession,
getSessionForUser,
storeSession,
disregardSession,
scrobbleTrack
}