This repository was archived by the owner on Feb 18, 2024. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathtwitch.js
More file actions
148 lines (128 loc) · 4.98 KB
/
Copy pathtwitch.js
File metadata and controls
148 lines (128 loc) · 4.98 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import { createClient } from "redis"
import { STATUS_CODES } from 'http'
import fetch from 'node-fetch';
import dotenv from 'dotenv';
dotenv.config(); // due to import execution ordering, this file gets handled before anything uses process.env variables, so configure them here
const TWITCH_VALIDATE_URL = 'https://id.twitch.tv/oauth2/validate'
const TWITCH_OAUTH_URL = `https://id.twitch.tv/oauth2/token`
const ONE_HOUR = 60 * 60 // convert 1 hour to seconds
const redisClient = createClient({
socket: {
host: process.env.REDIS_URL,
port: process.env.REDIS_PORT
},
password: process.env.REDIS_PASSWORD || ''
})
redisClient.connect()
export class Twitch {
constructor() {
this.maintain() // get the token on class creation
}
// this is the only method you ever need to directly call!
async maintain() {
let token = await redisClient.HGET('twitch_auth', `twitch_client_credentials_${process.env.CLIENT_ID}`)
if (token) {
console.info('Recovered existing token, validating...')
// verify that the token works
try {
token = JSON.parse(token)
process.env.ACCESS_TOKEN = token.access_token
this.validate() // validate the given token
} catch (e) {
console.warn('Failed to parse token, generating a new one...', e)
this.makeClientCredentials()
}
return // return early
}
this.makeClientCredentials()
}
async validate() {
try {
let res = await fetch(TWITCH_VALIDATE_URL, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.ACCESS_TOKEN}`
}
})
if (!res.ok) {
console.log('Failed to successfully validate token', res.body)
throw new Error('Token validation failed.')
}
res = await res.json()
if (res.expires_in <= ONE_HOUR) {
// looks like something went wrong, let's just try to get a new token instead
console.warn('The token is expiring soon...getting a new one.')
this.makeClientCredentials()
return
}
const hours = Math.floor(res.expires_in / 3600)
console.log(`Token is valid, expires in ${hours} hours.`)
} catch (e) {
console.log('Token validation error', e)
this.makeClientCredentials()
}
}
async makeClientCredentials() {
try {
let tokenURL = new URL(TWITCH_OAUTH_URL)
tokenURL.search = new URLSearchParams([
['client_id', process.env.CLIENT_ID],
['client_secret', process.env.CLIENT_SECRET],
['grant_type', 'client_credentials']
]).toString()
let res = await fetch(tokenURL, {
method: 'POST',
headers: {
'Accept': 'application/json'
}
})
if (!res.ok) {
console.error('Failed to get a token', res.body)
// most likely an unrecoverable error, so just return
return
}
res = await res.json()
res.client_id = process.env.CLIENT_ID // we're going to use this later!
await redisClient.HSET(
'twitch_auth',
`twitch_client_credentials_${process.env.CLIENT_ID}`,
JSON.stringify(res)
)
} catch (e) {
console.error('Failed to get client credentials', e)
}
}
async getUserID(username) {
try {
const response = await fetch(`https://api.twitch.tv/helix/users?login=${username}`, {
method: 'GET',
headers: {'Client-Id': process.env.CLIENT_ID, 'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`}
});
if(!response.ok) {
console.error('Could not retrieve user id', response.body)
return response.status
}
const users = await response.json();
return users.data[0].id
} catch (e) {
console.error('Failed to get User ID', e)
}
}
async getClips(id, limit = 100) {
const url = `https://api.twitch.tv/helix/clips?broadcaster_id=${id}&first=${limit}`
try {
const response = await fetch(url, {
method: 'GET',
headers: {'Client-Id': process.env.CLIENT_ID, 'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`}
})
if(!response.ok) {
console.error('Error getting twitch clips', response.body)
return response.status;
}
const data = await response.json();
return data;
} catch (e) {
console.error('Error getting clips', e)
}
}
}