-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroll_seed.js
227 lines (200 loc) · 8.8 KB
/
roll_seed.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
const { PythonShell } = require('python-shell');
const proc = require('process');
const fetch = require('node-fetch');
const fs = require('fs');
const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js')
const { metadata } = require("./metadata.js");
const presetList = {
'Lite': '--override=weights/beginner_override.json',
'Intermediate': '--override=weights/intermediate_override.json',
'DDR': '--override=weights/ddr_override.json',
'Bingo': '--override=weights/bingo_override.json',
}
// Make button to unlock spoiler log
const unlockLogButton = new ButtonBuilder()
.setCustomId('unlock_log')
.setLabel('Unlock Spoiler Log')
.setStyle(ButtonStyle.Danger);
const logUnlockedButton = new ButtonBuilder()
.setCustomId('log_unlocked')
.setLabel('Log Unlocked')
.setStyle(ButtonStyle.Secondary)
.setDisabled(true);
function makeSeedButtons(seedUrl, unlocked) {
const seedButton = new ButtonBuilder()
.setURL(seedUrl)
.setLabel("Download Seed")
.setStyle(ButtonStyle.Link);
const row = new ActionRowBuilder()
.addComponents(seedButton);
if(unlocked === null) { /* pass */ }
else if(unlocked) { row.addComponents(logUnlockedButton); }
else { row.addComponents(unlockLogButton); }
return row;
}
// Load the seed log
let seedLog = null;
const seedLogPath = 'data/seed_log.json';
if(fs.existsSync(seedLogPath)) {
seedLog = JSON.parse(fs.readFileSync(seedLogPath));
} else {
seedLog = {};
fs.writeFileSync(seedLogPath, JSON.stringify(seedLog, null, 4));
}
function rollSeed(interaction, userinfo, currentTime) {
// Test if the user has requested too many seeds
const eligibility = checkSeedEligibility(userinfo, currentTime);
if(!eligibility.status) {
interaction.update({
content: `Please wait at least ${eligibility.cooldown / 60} minutes between seeds. You have ${eligibility.remaining} seconds remaining.`,
components: []
});
return;
}
// Parse the preset and update message
let preset = null;
const presetName = interaction.customId.split("roll_")[1];
if(presetName in presetList) {
interaction.update({content: `Rolling a seed with ${presetName} weights`, components: [] });
preset = presetList[presetName];
} else {
interaction.update({content: `Rolling a seed with Season ${metadata.season} weights`, components: [] });
}
// Roll the seed
proc.chdir('plando-random-settings')
const pythonRSLArgs = preset === null ? ['--no_seed'] : ['--no_seed', preset];
const pythonOptions = { pythonPath: '/usr/bin/python3.9', args: pythonRSLArgs };
PythonShell.run("RandomSettingsGenerator.py", pythonOptions, (error, results) => {
if(error) throw error;
if(results.at(-1).startsWith('Plando File')) {
const plandoPath = 'plando-random-settings/data/' + results.at(-1).split(':').at(-1).trim();
const settings = JSON.parse(fs.readFileSync(plandoPath)).settings;
settings.world_count = 1;
settings.create_spoiler = true;
settings.randomize_settings = false;
// Make the POST request to roll the seed
fetch(`https://ootrandomizer.com/api/v2/seed/create?key=${process.env.OOTR_API_KEY}&version=devRSL_${metadata.ootrVersion}&locked`, {
method: 'post',
body: JSON.stringify(settings),
headers: {'Content-Type': 'application/json'}
})
.then(res => {
if(res.status === 200)
return res.json();
else
throw Error(res.status);
})
.then(json => {
checkSeedGenerationStatus(json.id, interaction, userinfo.username, currentTime, presetName);
})
.catch(error => {
console.log(`[${currentTime}] ${error}`);
})
}
})
proc.chdir('..');
}
function checkSeedGenerationStatus(seedId, interaction, username, currentTime, presetName) {
const statusCheckInterval = setInterval(() => {
fetch(`https://ootrandomizer.com/api/v2/seed/status?key=${process.env.OOTR_API_KEY}&id=${seedId}`)
.then(res => {
if (res.status === 200) { return res.json(); }
else { throw Error(res.status); }
})
.then(res => {
const status = res.status;
const progress = res.progress
if (status === 0) {
if (res.positionQueue > 0) {
interaction.editReply({content: `Position in queue: ${res.positionQueue}%`})
} else {
interaction.editReply({content: `Generating your seed: ${progress}%`})
}
} else if (status === 1) {
clearInterval(statusCheckInterval);
const seedUrl = `https://ootrandomizer.com/seed/get?id=${seedId}`;
interaction.editReply({
content: `Here is your seed rolled with ${presetName} weights (v${metadata.rslVersion})`,
components: [makeSeedButtons(seedUrl, false)]
});
addSeedToLog(username, currentTime, seedId);
} else if (status === 3) {
clearInterval(statusCheckInterval);
interaction.editReply({
content: `Generation of seed ${seedId} failed. This happens sometimes with certain settings combinations.
Please try again. If this has happen multiple times, please dm \`xopar\` on discord or in the Ocarina
of Time Randomizer discord server.`
})
console.log(`[${currentTime}] Seed ${seedId} failed to generate`);
}
})
.catch(error => {
clearInterval(statusCheckInterval);
console.log(`[${currentTime}] Error checking seed status: ${error}`);
});
}, 5000);
};
function unlockSeed(interaction) {
const seedUrl = interaction.message.components[0].components[0].data.url;
const seedId = seedUrl.split("=")[1]
interaction.update({content: interaction.message.content, components: [makeSeedButtons(seedUrl, null)] })
.then(() => {
// Unlock the log
return fetch(`https://ootrandomizer.com/api/v2/seed/unlock?key=${process.env.OOTR_API_KEY}&id=${seedId}`,
{method: 'post', body: '', headers: {'Content-Type': 'application/json'}
});
})
.then(res => {
// Catch errors
if(res.status === 200) { return res.text() }
else if(res.status === 404) { interaction.followUp({content: "Seed not found, did the seed have an error while generating?"}); throw Error(res.status); }
else if(res.status === 204) {
interaction.editReply({content: interaction.message.content, components: [makeSeedButtons(seedUrl, false)]});
interaction.followUp({content: "The seed is still generating, please try again in a minute."});
throw Error(res.status); }
else if(res.status === 208) { interaction.followUp({content: "The log is either already unlocked or there is no log available."}); throw Error(res.status); }
else { throw Error(res.status); }
})
.then(text => {
console.log(text, `for seed ${seedId}`);
interaction.editReply({content: interaction.message.content, components: [makeSeedButtons(seedUrl, true)] });
})
.catch(error => {
console.log(`${error}`)
})
}
function checkSeedEligibility(userInfo, currentTime) {
const cooldownSeconds = {
"admin": 0,
"moderator": 30,
"organizer": 120
}
// Return seed roll eligibility based on user rank and the last time they rolled a seed
const cooldown = userInfo.user_level in cooldownSeconds ? cooldownSeconds[userInfo.user_level] : 15 * 60;
const eligibility = { status: true, cooldown: cooldown, remaining: null };
if(userInfo.username in seedLog) {
const ltime = new Date(seedLog[userInfo.username].timelist.at(-1));
const remainingTime = cooldown * 1000 - (currentTime - ltime);
if(remainingTime > 0) {
eligibility.status = false;
eligibility.remaining = Math.floor(remainingTime / 1000);
}
}
return eligibility;
}
function addSeedToLog(username, currentTime, seedId) {
if(username in seedLog)
seedLog[username] = {
idlist: seedLog[username].idlist.concat(seedId),
timelist: seedLog[username].timelist.concat(currentTime),
nseeds: seedLog[username].nseeds+1
};
else
seedLog[username] = {
idlist: [seedId],
timelist: [currentTime],
nseeds: 1
};
fs.writeFileSync(seedLogPath, JSON.stringify(seedLog, null, 4));
}
module.exports = { rollSeed, unlockSeed };