forked from benediktwerner/Twitch-Chat-vs-Streamer-Lichess
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
126 lines (112 loc) · 4.01 KB
/
index.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
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
const OPTS = require('./config.js');
const USER_AGENT = 'Twitch-Prediction-Lichess';
const { StaticAuthProvider } = require('@twurple/auth');
const { ApiClient } = require('@twurple/api');
const authProvider = new StaticAuthProvider(OPTS.TWITCH_API_CLIENT_ID, OPTS.TWITCH_API_TOKEN, ['channel:read:predictions', 'channel:manage:predictions']);
const api = new ApiClient({ authProvider });
let broadcaster;
let prediction;
let lichessName;
let gameColor;
let gameId;
async function getLichessId() {
// https://lichess.org/api#tag/Account/operation/accountMe
const headers = {
Authorization: `Bearer ${OPTS.LICHESS_API_TOKEN}`,
'User-Agent': USER_AGENT
};
user = await fetch('https://lichess.org/api/account', {headers: headers})
.then((res) => res.json());
console.log(`Lichess streamer: ${user.streamer?.twitch?.channel}`);
lichessName = user.title ? `${user.title} ${user.username}` : user.username;
}
async function streamIncomingEvents() {
// https://lichess.org/api#tag/Board/operation/apiStreamEvent
const headers = {
Authorization: `Bearer ${OPTS.LICHESS_API_TOKEN}`,
'User-Agent': USER_AGENT
};
const response = await fetch('https://lichess.org/api/stream/event', {headers: headers})
for await (const chunk of response.body) {
// Ignore keep-alive 1-byte chunks
if (chunk.length > 1) try {
const data = Buffer.from(chunk).toString('utf8');
let json = JSON.parse(data);
let game = json.game;
// Do not create a prediction if some other process already created one
if (json.type == 'gameStart' && game.source != 'simul' && game.speed != 'correspondence' && !prediction) {
gameColor = game.color;
gameId = game.id;
console.log(`Game ${game.id} started!`);
createPrediction(game);
}
if (json.type == 'gameFinish' && game.id == gameId && prediction) {
console.log(`Game ${game.id} finished!`);
endPrediction(game.winner || game.status?.name);
gameColor = undefined;
gameId = undefined;
prediction = undefined;
}
} catch (e) {
console.error(e);
}
}
}
async function getBroadcaster() {
broadcaster = await api.users.getUserByName(OPTS.TWITCH_CHANNEL);
}
async function getPrediction() {
const predictions = await api.predictions.getPredictions(broadcaster, {limit: 1});
if (predictions?.data?.length && /^(?:ACTIVE|LOCKED)$/.test(predictions.data[0].status)) {
prediction = predictions.data[0];
}
return predictions;
}
async function createPrediction(game) {
prediction = await api.predictions.createPrediction(broadcaster, {
title: `Who will win? #${game.id}`,
outcomes: [lichessName, game.opponent.username, "Draw"],
autoLockAfter: Math.min(game.secondsLeft, OPTS.PREDICTION_PERIOD)
});
console.log(`- Prediction ${prediction.id} is ${prediction.status}`);
}
async function cancelPrediction(predictionId) {
return await api.predictions.cancelPrediction(broadcaster, predictionId);
}
async function resolvePrediction(predictionId, outcomeId) {
return await api.predictions.resolvePrediction(broadcaster, predictionId, outcomeId);
}
async function endPrediction(outcome) {
const predictionId = prediction.id;
const outcomes = prediction.outcomes;
let outcomeId;
switch (outcome) {
case gameColor:
console.log(`- ${lichessName} won!`);
outcomeId = outcomes[0].id;
break;
case 'black':
case 'white':
console.log(`- ${lichessName} lost!`);
outcomeId = outcomes[1].id;
break;
case 'draw':
case 'stalemate':
console.log(`- ${lichessName} drew!`);
outcomeId = outcomes[2].id;
break;
default:
console.log(`- Game ${outcome}!`);
}
if (outcomeId) {
resolvePrediction(predictionId, outcomeId);
console.log(`- Prediction ${predictionId} resolved.`);
} else {
cancelPrediction(predictionId);
console.log(`- Prediction ${predictionId} canceled.`);
}
}
getBroadcaster()
.then(_ => getPrediction())
.then(_ => getLichessId())
.then(_ => streamIncomingEvents());