forked from traPtitech/traQ-group-editor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.js
87 lines (75 loc) · 2.49 KB
/
utils.js
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
const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
export function randomString (length) {
let array = new Uint8Array(length)
window.crypto.getRandomValues(array)
array = array.map(x => validChars.charCodeAt(x % validChars.length))
return String.fromCharCode(...array)
}
const b64Chars = { '+': '-', '/': '_', '=': '' }
function urlEncodeB64 (input) {
return input.replace(/[+/=]/g, m => b64Chars[m])
}
function bufferToBase64UrlEncoded (input) {
const bytes = new Uint8Array(input)
return urlEncodeB64(window.btoa(String.fromCharCode(...bytes)))
}
function sha256 (message) {
const data = new TextEncoder().encode(message)
return window.crypto.subtle.digest('SHA-256', data)
}
function buf2hex (buf) {
return Array.prototype.map.call(new Uint8Array(buf), x => (('00' + x.toString(16)).slice(-2))).join('')
}
export async function hmacsha1 (message, secret) {
const key = await window.crypto.subtle.importKey('raw', new TextEncoder().encode(secret), {
name: 'HMAC',
hash: 'SHA-1'
}, true, ['sign'])
const buf = new TextEncoder().encode(message)
const sig = await window.crypto.subtle.sign('HMAC', key, buf)
return buf2hex(sig)
}
export async function pkce (verifier) {
return sha256(verifier).then(bufferToBase64UrlEncoded)
}
export function parseAPIChannelList (channels) {
function dfs (c, root) {
c.channelName = root + c.name
c.children.forEach(e => dfs(e, c.channelName + '/'))
}
function flatMap (channels) {
const children = channels.flatMap(c => flatMap(c.children))
channels.forEach(c => { delete c['children'] })
return [...channels, ...children]
}
let pool = {}
let root = ''
channels.filter(c => !c.dm).forEach(c => {
pool[c.channelId] = {
channelId: c.channelId,
name: c.name,
channelName: c.name,
children: [],
visibility: c.visibility,
private: c.private,
parent: c.parent
}
})
Object.keys(pool)
.filter(id => pool[id].channelId !== '')
.forEach(id => { pool[pool[id].parent].children.push(pool[id]) })
Object.keys(pool)
.forEach(id => {
pool[pool[id].parent].children.sort((lhs, rhs) => {
if (lhs.name < rhs.name) return -1
if (lhs.name > rhs.name) return 1
return 0
})
})
pool[root].children.forEach(e => dfs(e, '#'))
return flatMap(pool[root].children).sort((lhs, rhs) => {
if (lhs.channelName < rhs.channelName) return -1
if (lhs.channelName > rhs.channelName) return 1
return 0
})
}