1 | module.exports = magnetURIDecode
|
2 | module.exports.decode = magnetURIDecode
|
3 | module.exports.encode = magnetURIEncode
|
4 |
|
5 | var base32 = require('thirty-two')
|
6 | var extend = require('xtend')
|
7 | var flatten = require('flatten')
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | function magnetURIDecode (uri) {
|
16 | var result = {}
|
17 | var data = uri.split('magnet:?')[1]
|
18 |
|
19 | var params = (data && data.length >= 0)
|
20 | ? data.split('&')
|
21 | : []
|
22 |
|
23 | params.forEach(function (param) {
|
24 | var keyval = param.split('=')
|
25 |
|
26 |
|
27 | if (keyval.length !== 2) return
|
28 |
|
29 | var key = keyval[0]
|
30 | var val = keyval[1]
|
31 |
|
32 |
|
33 | if (key === 'dn') val = decodeURIComponent(val).replace(/\+/g, ' ')
|
34 |
|
35 |
|
36 |
|
37 | if (key === 'tr' || key === 'xs' || key === 'as' || key === 'ws') {
|
38 | val = decodeURIComponent(val)
|
39 | }
|
40 |
|
41 |
|
42 | if (key === 'kt') val = decodeURIComponent(val).split('+')
|
43 |
|
44 |
|
45 | if (result[key]) {
|
46 | if (Array.isArray(result[key])) {
|
47 | result[key].push(val)
|
48 | } else {
|
49 | var old = result[key]
|
50 | result[key] = [old, val]
|
51 | }
|
52 | } else {
|
53 | result[key] = val
|
54 | }
|
55 | })
|
56 |
|
57 |
|
58 | var m
|
59 | if (result.xt) {
|
60 | var xts = Array.isArray(result.xt) ? result.xt : [ result.xt ]
|
61 | xts.forEach(function (xt) {
|
62 | if ((m = xt.match(/^urn:btih:(.{40})/))) {
|
63 | result.infoHash = new Buffer(m[1], 'hex').toString('hex')
|
64 | } else if ((m = xt.match(/^urn:btih:(.{32})/))) {
|
65 | var decodedStr = base32.decode(m[1])
|
66 | result.infoHash = new Buffer(decodedStr, 'binary').toString('hex')
|
67 | }
|
68 | })
|
69 | }
|
70 |
|
71 | if (result.dn) result.name = result.dn
|
72 | if (result.kt) result.keywords = result.kt
|
73 |
|
74 | if (typeof result.tr === 'string') result.announce = [ result.tr ]
|
75 | else if (Array.isArray(result.tr)) result.announce = result.tr
|
76 | else result.announce = []
|
77 |
|
78 | result.announceList = result.announce.map(function (url) {
|
79 | return [ url ]
|
80 | })
|
81 |
|
82 | result.urlList = []
|
83 | if (typeof result.as === 'string' || Array.isArray(result.as)) {
|
84 | result.urlList = result.urlList.concat(result.as)
|
85 | }
|
86 | if (typeof result.ws === 'string' || Array.isArray(result.ws)) {
|
87 | result.urlList = result.urlList.concat(result.ws)
|
88 | }
|
89 |
|
90 | return result
|
91 | }
|
92 |
|
93 | function magnetURIEncode (obj) {
|
94 | obj = extend(obj)
|
95 |
|
96 |
|
97 |
|
98 | if (obj.infoHash) obj.xt = 'urn:btih:' + obj.infoHash
|
99 | if (obj.name) obj.dn = obj.name
|
100 | if (obj.keywords) obj.kt = obj.keywords
|
101 | if (obj.announce) obj.tr = obj.announce
|
102 | if (obj.announceList) obj.tr = flatten(obj.announceList)
|
103 | if (obj.urlList) {
|
104 | obj.ws = flatten(obj.urlList)
|
105 | delete obj.as
|
106 | }
|
107 |
|
108 | var result = 'magnet:?'
|
109 | Object.keys(obj)
|
110 | .filter(function (key) {
|
111 | return key.length === 2
|
112 | })
|
113 | .forEach(function (key, i) {
|
114 | var values = Array.isArray(obj[key]) ? obj[key] : [ obj[key] ]
|
115 | values.forEach(function (val, j) {
|
116 | if ((i > 0 || j > 0) && (key !== 'kt' || j === 0)) result += '&'
|
117 |
|
118 | if (key === 'dn') val = encodeURIComponent(val).replace(/%20/g, '+')
|
119 | if (key === 'tr' || key === 'xs' || key === 'as' || key === 'ws') {
|
120 | val = encodeURIComponent(val)
|
121 | }
|
122 | if (key === 'kt') val = encodeURIComponent(val)
|
123 |
|
124 | if (key === 'kt' && j > 0) result += '+' + val
|
125 | else result += key + '=' + val
|
126 | })
|
127 | })
|
128 |
|
129 | return result
|
130 | }
|