Forked from vtdocs/resyBot
Public
Script
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
import { blob } from "https://esm.town/v/std/blob?v=12";
import { resyAuth } from "https://esm.town/v/vtdocs/resyAuth";
import { resyBookSlot } from "https://esm.town/v/vtdocs/resyBookSlot";
import { resyGetMatchingSlot } from "https://esm.town/v/vtdocs/resyGetMatchingSlot";
import { resyGetSlotBookingToken } from "https://esm.town/v/vtdocs/resyGetSlotBookingToken";
import { resyVenueIdFromSlugAndCity } from "https://esm.town/v/vtdocs/resyVenueIdFromSlugAndCity";
import { sha256 } from "https://esm.town/v/vtdocs/sha256";
export const resyBot = async (opts: {
slug: string; // amaro-bar
city: string; // ldn
day: string; // 2023-07-05
start: string; // 19:00
end: string; // 21:00
partySize: number; // 2
email?: string; // resy email
password?: string;
}): Promise<string> => {
let { slug, city, day, start, end, partySize, email, password } = opts;
email ??= Deno.env.get("RESY_EMAIL");
password ??= Deno.env.get("RESY_PASSWORD");
let resyBotData = await blob.getJSON("resyBotData");
// Avoid duplicate bookings by looking for a successful booking for the current parameters
const key = [
slug,
city,
day,
start,
end,
partySize,
await sha256(email),
].join(",");
if (resyBotData === undefined) {
resyBotData = {};
}
if (resyBotData[key] !== undefined) {
throw new Error(
`not running resy bot – successful booking exists for ${key}`,
);
}
const auth = await resyAuth(email, password);
const venue = await resyVenueIdFromSlugAndCity(
auth.token,
slug,
city,
);
// If there are no matching slots, an error is thrown
const matchingSlot = await resyGetMatchingSlot(
auth.token,
venue.id,
day,
start,
end,
partySize,
);
// At this point, there's a bookable slot (but it could still be sniped from us!)
const { bookToken } = await resyGetSlotBookingToken(
auth.token,
matchingSlot.config.token,
matchingSlot.date.start,
partySize,
);
if (auth.paymentMethods.length === 0) {
throw new Error("no payment methods on account (add one and try again)");
}
const bookingMetadata = await resyBookSlot(
auth.token,
bookToken,
auth.paymentMethods[0].id,
);
// Store successful booking to avoid duplicate bookings
resyBotData[key] = bookingMetadata;
await blob.setJSON("resyBotData", resyBotData);
return `Booked ${slug} in ${city} at ${matchingSlot.date.start} for ${partySize} people.
Check https://resy.com/account/reservations-and-notify for more details!`;
};
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
v3 was merged from the PR "Update the cron example to use the current api" by maxm
Comments
Nobody has commented on this val yet: be the first!
September 6, 2024