This commit is contained in:
m5r 2024-10-17 22:45:29 +02:00
parent 984d0c3be4
commit e3c8aa7084
Signed by: mokhtar
GPG Key ID: 1509B54946D08A95
8 changed files with 1150 additions and 5189 deletions

View File

@ -1,6 +0,0 @@
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
],
};

4
src/main.ts → main.ts Normal file → Executable file
View File

@ -1,4 +1,6 @@
import run from "./run"; #!/usr/bin/env -S npx tsx
import run from "./src/run.js";
async function main() { async function main() {
while (true) { while (true) {

6227
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,26 +2,25 @@
"name": "cosmosarb", "name": "cosmosarb",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "type": "module",
"module": "main.ts",
"scripts": { "scripts": {
"start": "node ./build/main.js", "start": "./main.ts",
"build": "tsc -p tsconfig.json", "dev": "tsx watch ./main.ts"
"dev": "ts-node-dev --respawn ./src/main.ts"
}, },
"keywords": [], "keywords": [],
"author": "m5r", "author": "m5r",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@babel/core": "7.15.8", "@tsconfig/node20": "20.1.4",
"@babel/preset-env": "7.15.8", "@types/node": "22.7.6",
"@babel/preset-typescript": "7.15.0", "typescript": "5.6.3"
"@types/node": "16.11.6",
"ts-node-dev": "1.1.8",
"typescript": "4.4.4"
}, },
"dependencies": { "dependencies": {
"dotenv": "10.0.0", "dotenv": "16.4.5",
"got": "11.8.2", "got": "14.4.3",
"twilio": "3.71.3" "telegraf": "4.16.3",
"tsx": "4.19.1",
"twilio": "5.3.4"
} }
} }

View File

@ -1,16 +1,41 @@
import twilio from "twilio";
import dotenv from "dotenv"; import dotenv from "dotenv";
import twilio from "twilio";
import { Telegraf } from "telegraf";
const pad = (str: number) => str.toString().padStart(2, "0");
const format = (date: Date) => `RDV chez Bag dispo le ${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${pad(date.getFullYear())} à ${pad(date.getHours())}:${pad(date.getMinutes())}.\nhttps://booking.wavy.pro/hairnewscoiffure`;
dotenv.config(); dotenv.config();
const twilioClient = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); /* const twilioClient = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
export default async function notify(date: Date) { async function sendSMS(date: Date, to: string) {
await twilioClient.messages.create({ await twilioClient.messages.create({
body: `RDV chez Bag dispo le ${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${pad(date.getFullYear())} à ${pad(date.getHours())}:${pad(date.getMinutes())}.\nhttps://booking.wavy.pro/hairnewscoiffure`, body: format(date),
to: "+33613370787", to,
from: "+33757592025", from: "+33757592025",
}); });
} }
const pad = (str: number) => str.toString().padStart(2, "0"); // const notifiers = ["+33613370787", "+33673899359"] as const;
const notifiers = ["+33613370787"] as const;
export default async function notify(date: Date) {
await Promise.all(notifiers.map(async phoneNumber => sendSMS(date, phoneNumber)));
}
*/
const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN!);
bot.launch();
// Enable graceful stop
process.once("SIGINT", () => bot.stop("SIGINT"))
process.once("SIGTERM", () => bot.stop("SIGTERM"))
const notifiers = [
async (date: Date) => bot.telegram.sendMessage(716477900, format(date)),
];
export default async function notify(date: Date) {
await Promise.all(notifiers.map(notifier => notifier(date)));
}

View File

@ -1,5 +1,5 @@
import notify from "./notify"; import notify from "./notify.js";
import { getFirstAvailableSlot, getSlots } from "./slots"; import { getFirstAvailableSlot, getSlots } from "./slots.js";
export default async function run() { export default async function run() {
const slots = await getSlots(); const slots = await getSlots();
@ -9,6 +9,11 @@ export default async function run() {
return sleep(); return sleep();
} }
if (new Date() > availableSlot) {
console.log("found one but already expired", availableSlot.toISOString());
return sleep();
}
console.log("found one", availableSlot.toISOString()); console.log("found one", availableSlot.toISOString());
await notify(availableSlot); await notify(availableSlot);
} }

View File

@ -1,6 +1,6 @@
import got from "got"; import got from "got";
import { addKnownSlot, getKnownSlots } from "./cache"; import { addKnownSlot, getKnownSlots } from "./cache.js";
export function getFirstAvailableSlot(response: Response): Date | null { export function getFirstAvailableSlot(response: Response): Date | null {
const knownSlots = getKnownSlots(); const knownSlots = getKnownSlots();
@ -29,15 +29,15 @@ export function getFirstAvailableSlot(response: Response): Date | null {
export async function getSlots() { export async function getSlots() {
const { body } = await got.post<Response>( const { body } = await got.post<Response>(
"https://booking.wavy.pro/api/shops/c5593def-a89c-4296-ac87-f484d8a22ecb/booking/v2/slot", "https://api.wavy.fr/shops/c5593def-a89c-4296-ac87-f484d8a22ecb/booking/v2/slot",
{ {
body: JSON.stringify({ body: JSON.stringify({
startDate: "2021-12-12T23:00:00.000Z", startDate: "2024-06-05T22:00:00.000Z",
endDate: "2021-12-29T22:59:59.999Z", endDate: "2024-06-22T21:59:59.999Z",
itemsQuery: [{ itemsQuery: [{
"id": "5cb74891ff800f00007f32d5", id: "5cb74891ff800f00007f32d5",
"priceValue": 15, priceValue: 16,
"staffIds": ["5cb721b52561230000f9f5dd", "5cb721b52561230000f9f5dd"], staffIds: ["5cb721b52561230000f9f5dd","5cb721b52561230000f9f5dd"],
}], }],
}), }),
headers: { "Content-Type": "application/json;charset=utf-8" }, headers: { "Content-Type": "application/json;charset=utf-8" },
@ -45,6 +45,8 @@ export async function getSlots() {
}, },
); );
console.log("body", body)
return body; return body;
} }

View File

@ -1,14 +1,9 @@
{ {
"extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"target": "ES2021", "module": "NodeNext",
"lib": ["ESNext"], "moduleResolution": "NodeNext",
"moduleResolution": "node", "noEmit": true,
"module": "commonjs",
"outDir": "build",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true
}, },
"include": ["src/**/*"] "include": ["src/**/*", "main.ts"]
} }