JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
auth working. rename auth.coffee -> api.coffee
[libre-fm-client-daemon.git] / api.coffee
1 fs = require 'fs'
2 http = require 'http'
3 crypto = require 'crypto'
4 xml = require 'node-xml'
5
6 # soooo annoying that setTimeout takes the ms arg last
7 timeout = (ms, func) -> setTimeout func, ms
8
9 auth = {}
10
11 md5 = (str) ->
12         sum = crypto.createHash 'md5'
13         sum.update str
14         return sum.digest 'hex'
15
16 new_auth_token = (user, pass) ->
17         token = md5(user + md5(pass))
18         auth.user = user
19         auth.token = token
20         return token
21
22 auth_file = "#{process.env.HOME}/.libre.fm-cmus.auth"
23 save_auth = (user, pass, callback) ->
24         token = new_auth_token(user, pass)
25         text = JSON.stringify user: user, token: new_auth_token(user, pass)
26         fs.writeFile auth_file, text, 'utf8', callback
27         return token
28
29 # load login credentials from settings file
30 load_auth = (callback) ->
31         if auth.user and auth.token
32                 callback auth
33                 return
34
35         fs.readFile auth_file, 'utf8', (err, data) ->
36                 if err
37                         callback err
38                 else
39                         callback null, JSON.parse data
40
41 # login and get a session key
42 login = (callback) ->
43         load_auth (err, auth) ->
44                 return callback(err) if err?
45
46                 http.get { host: 'alpha.libre.fm', port: 80, path: "/2.0/?method=auth.getmobilesession&username=#{auth.user}&authToken=#{auth.token}"}, (res) ->
47                         if res.statusCode != 200
48                                 console.log "login response code: #{res.statusCode}"
49                                 callback "login response code: #{res.statusCode}"
50                                 return
51
52                         res.setEncoding 'utf8'
53                         body = ''
54                         res.on 'data', (chunk) ->
55                                 body += chunk
56                         res.on 'end', ->
57                                 element = ''
58                                 content = ''
59                                 done = false
60                                 huh = ->
61                                         # FIXME switch to an xml parser that will tell me when it's done
62                                         unless done
63                                                 done = true
64                                                 callback "xml parser failed to do anything with login server response"
65                                                 console.log "xml parser didn't exit: #{body}"
66                                 parser = new xml.SaxParser (cb) ->
67                                         cb.onStartElementNS (name, attrs, prefix, uri, namespaces) ->
68                                                 element = name
69                                                 content = ''
70                                         cb.onCharacters (str) ->
71                                                 content += str
72                                         cb.onEndElementNS (name, attrs, prefix, uri, namespaces) ->
73                                                 if element is 'key'
74                                                         done = true
75                                                         auth.sk = content
76                                                         console.log("got key \"#{content}\"")
77                                                         callback null, content
78                                                 else if element is 'error'
79                                                         done = true
80                                                         callback "login failed: \"#{content}\""
81                                                 # ignore other tags stuff in there
82                                         cb.onEndDocument huh
83                                 parser.parseString body
84                                 timeout 1, huh
85
86
87 exports.login = login # fixme remove this from the API and call it automatically
88 exports.new_auth_token = new_auth_token
89 exports.save_auth = save_auth