Skip to content

Commit

Permalink
Merge pull request #30 from itamarshubin/subscribe-to-alert
Browse files Browse the repository at this point in the history
Subscribe to alert
  • Loading branch information
itamarshubin authored Mar 18, 2024
2 parents 548c391 + 5f05e1a commit 4254308
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 28 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# whatsapp-shabbat

this code looks like shit, so feal free to pr me
this code looks like shit, so feel free to pr me

how to use:

1. go to google firebase and get yourself firebaseConfig.
2. put it in the app.
3. the bot is running



my setup is ec2 in aws.
I didn't use Docker, so if you want your project to run on linux (at least ubuntu) you need to install all the packages in the Docker file.
I didn't use Docker, so if you want your project to run on linux (at least ubuntu) you need to install all the packages in the Docker file.
6 changes: 4 additions & 2 deletions src/constants/help-message.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BOT_MANAGER } from "./bot-manager"
import { BOT_MANAGER } from "./bot-manager";

export const HELP_MESSAGE: string = `
היי, זה בוט השבתות ויו"ט של דרך חיים, הוא לא יודע לעשות הרבה. זה מה שאפשר לעשות בנתיים:
Expand All @@ -9,5 +9,7 @@ export const HELP_MESSAGE: string = `
מי מעניין - אפשרות לסינון מחזורים שמעניינים אותך על הפקודה 'מי מגיע'
כולם מעניינים אותי - ביטול הסינונים על הפקודה 'מי מגיע'
בעתיד יתווספו פעולות נוספות 😁
עדכן אותי - אפשרות לקבלת עדכונים על משתמש
אל תעדכן - להפסיק לקבל עדכונים על משתמש
אם ישנה בעייה צור קשר עם ${BOT_MANAGER.name} (${BOT_MANAGER.phoneNumber})
` as const;
` as const;
18 changes: 7 additions & 11 deletions src/constants/special-response.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import fs from "fs";
import { Client } from "whatsapp-web.js";

let specialMessages:any;
fs.readFile(
"special-messages.json",
"utf-8",
(err, data) => {
if (err) return null;

specialMessages= JSON.parse(data);
}
);
let specialMessages: any;
fs.readFile("special-messages.json", "utf-8", (err, data) => {
if (err) return null;

specialMessages = JSON.parse(data);
});

export const sendSpecialMessages = (from: string, client: Client) => {
if (specialMessages[from]) client.sendMessage(from, specialMessages[from]);
if (specialMessages && specialMessages[from])
client.sendMessage(from, specialMessages[from]);
};
173 changes: 173 additions & 0 deletions src/constants/subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import {
arrayUnion,
DocumentData,
getDocFromServer,
QueryDocumentSnapshot,
arrayRemove,
DocumentSnapshot,
updateDoc,
collection,
getDocs,
query,
DocumentReference,
} from "@firebase/firestore";

import { Client, Message } from "whatsapp-web.js";
import { fireStore, getUserRef } from "../firebase/shabbas-manage";
import { client } from "../app";

type User = { phone: string; name: string };
export const updateRelevantUsers = async (
userRef: QueryDocumentSnapshot<DocumentData>,
client: Client,
coming: boolean
): Promise<void> => {
const subscribedUsers: DocumentReference<User>[] =
userRef.get("subscribedUsers");

subscribedUsers?.forEach(async (user) => {
const userData = (await getDocFromServer<User>(user)).data();
userData &&
client.sendMessage(
userData.phone,
`${userRef.get("name")} ${coming ? "מגיע" : "לא מגיע"} לשבת`
);
});
};

let users: QueryDocumentSnapshot<DocumentData>[] = [];
export const sessionedAddSubscribersAlert: Record<
string,
{ matches: QueryDocumentSnapshot<DocumentData>[] }
> = {};
export const sessionedRemoveSubscribersAlert: Record<
string,
{ followers: DocumentSnapshot<User>[] }
> = {};

//refetch users twice a day and save it in the cache.
//you probably should use some library to fetch user by name.
//but I didn't want to get all the users every time
setInterval(() => {
users = [];
}, 43200000);

export const removeAlertSubscription = async (msg: Message) => {
if (!users.length) {
const docs = await getDocs(query(collection(fireStore, "/users")));
docs.forEach((doc) => {
users.push(doc);
});
}
if (!sessionedRemoveSubscribersAlert[msg.from]) {
const userRef = await getUserRef(msg);

const followersRef: DocumentReference<User>[] =
userRef.data().subscribedUsers;
const followers = await Promise.all(
followersRef.map((followerRef) => getDocFromServer(followerRef))
);

let response = "אלה האנשים שאתה תקבל עליהם עדכונים: \n";

followers.forEach((follower, index) => {
response += index + 1 + ". " + String(follower.data()?.name) + "\n";
});

client.sendMessage(
msg.from,
response + " שלח את המספר של מי שאתה רוצה להסיר"
);
sessionedRemoveSubscribersAlert[msg.from] = { followers };
return;
}

if (msg.body === "בטל") {
return delete sessionedRemoveSubscribersAlert[msg.from];
}

const userRef = await getUserRef(msg);

const userToRemove =
sessionedRemoveSubscribersAlert[msg.from].followers[Number(msg.body) - 1];
if (!userToRemove) {
return client.sendMessage(
msg.from,
"הזן מספר תקין או כתוב 'בטל' בשביל להפסיק את הפעולה"
);
}

await updateDoc(userRef.ref, {
subscribedUsers: arrayRemove(userToRemove.ref),
});
client.sendMessage(
msg.from,
`הסרנו את ${userToRemove.data()?.name}, לא תקבל יותר עדכונים עליו`
);
delete sessionedRemoveSubscribersAlert[msg.from];
};

export const createAlertSubscription = async (msg: Message) => {
if (!users.length) {
const docs = await getDocs(query(collection(fireStore, "/users")));
docs.forEach((doc) => {
users.push(doc);
});
}
if (!sessionedAddSubscribersAlert[msg.from]) {
client.sendMessage(
msg.from,
"כתוב שם (מלא או חלקי) של מישהו שתרצה לקבל עדכון כשהוא מגיע"
);
sessionedAddSubscribersAlert[msg.from] = { matches: [] };
return;
}
if (msg.body === "בטל") {
return delete sessionedAddSubscribersAlert[msg.from];
}

if (!sessionedAddSubscribersAlert[msg.from].matches.length) {
const matches = users.filter((user) =>
user.data().name?.includes(msg.body)
);
if (!matches) {
return client.sendMessage(
msg.from,
"לא נמצא משתמש עם שם כזה, הזן שם אחר או 'בטל' כדי להפסיק את הפעולה"
);
}
let response = "";
matches.forEach((match, index) => {
response += String(
index +
1 +
". " +
match.data().name +
", מחזור: " +
match.data().year +
"\n"
);
});

client.sendMessage(msg.from, response);
sessionedAddSubscribersAlert[msg.from].matches = matches;
return;
}

const userRef = await getUserRef(msg);

const userToAdd =
sessionedAddSubscribersAlert[msg.from].matches[Number(msg.body) - 1];
if (!userToAdd) {
return client.sendMessage(
msg.from,
"הזן מספר תקין או כתוב 'בטל' בשביל להפסיק את הפעולה"
);
}
await updateDoc(userRef.ref, { subscribedUsers: arrayUnion(userToAdd.ref) });
client.sendMessage(
msg.from,
`תקבל הודעה כש${userToAdd.data().name} יעדכן על מצב ההגעה שלו`
);
delete sessionedAddSubscribersAlert[msg.from];
};
9 changes: 7 additions & 2 deletions src/firebase/shabbas-manage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import {
import { Message } from "whatsapp-web.js";
import { client } from "../app";
import { ALL_YESHIVA_YEARS } from "../constants/yeshiva-years";
import { updateRelevantUsers } from "../constants/subscription";

const fireStore = getFirestore();
export const fireStore = getFirestore();

const getShabbasDoc = async (): Promise<
QueryDocumentSnapshot<DocumentData>
Expand All @@ -35,7 +36,7 @@ const getShabbasDoc = async (): Promise<
return shabbasDocs.docs[0];
};

const getUserRef = async (msg: Message) => {
export const getUserRef = async (msg: Message) => {
const userRef = (
await getDocs(
query(collection(fireStore, "/users"), where("phone", "==", msg.from))
Expand All @@ -58,6 +59,7 @@ export const addUser = async (msg: Message) => {
await updateDoc(shabbas.ref, { participants: arrayUnion(userRef.ref) });
await client.sendMessage(msg.from, "נהדר! נשמח לראותך.");
}
await updateRelevantUsers(userRef, client, true);
};

export const addAlcoholic = async (msg: Message) => {
Expand Down Expand Up @@ -151,6 +153,7 @@ export const removeUser = async (msg: Message) => {
await updateDoc(shabbas.ref, { participants: arrayRemove(userRef.ref) });
}
await client.sendMessage(msg.from, "טוב נו... פעם הבאה.");
await updateRelevantUsers(userRef, client, false);
};

export const getParticipants = async (msg: Message) => {
Expand Down Expand Up @@ -326,3 +329,5 @@ export const resetSubscribedYears = async (
msg.from
);
};

const alertSubscribers = async (msg: Message) => {};
50 changes: 41 additions & 9 deletions src/message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,50 @@ import {
} from "./firebase/shabbas-manage";
import { HELP_MESSAGE } from "./constants/help-message";
import { sendSpecialMessages } from "./constants/special-response";
import {
createAlertSubscription,
removeAlertSubscription,
sessionedAddSubscribersAlert,
sessionedRemoveSubscribersAlert,
} from "./constants/subscription";

export const messageHandler = async (msg: Message) => {
sendSpecialMessages(msg.from, client);

//prevent interrupt in middle action
if (sessionedSubscribers[msg.from]) {
await addSubscribedYears(msg);
return;
}

if (sessionedAddSubscribersAlert[msg.from]) {
await createAlertSubscription(msg);
return;
}

if (sessionedRemoveSubscribersAlert[msg.from]) {
await removeAlertSubscription(msg);
return;
}

if (msg.body.includes("מי מעניין")) {
await addSubscribedYears(msg);
return;
}

if (
msg.body.includes("עדכן אותי") ||
sessionedAddSubscribersAlert[msg.from]
) {
await createAlertSubscription(msg);
return;
}

if (msg.body.includes("אל תעדכן")) {
await removeAlertSubscription(msg);
return;
}

if (msg.body.startsWith("!new") && (await isAdmin(msg))) {
await addShabbas(msg);
return;
Expand All @@ -38,10 +78,6 @@ export const messageHandler = async (msg: Message) => {
}

if (msg.body.includes("מי מגיע")) {
await client.sendMessage(
msg.from,
"*פיצ'ר חדש!!!* מעכשיו תוכל לערוך אילו מחזורים מעניינים אותך על ידי הפקודה מי מעניין "
);
await getParticipants(msg);
return;
}
Expand All @@ -51,10 +87,6 @@ export const messageHandler = async (msg: Message) => {
return;
}

if (msg.body.includes("מי מעניין") || sessionedSubscribers[msg.from]) {
await addSubscribedYears(msg);
return;
}
if (msg.body.includes("כולם מעניינים אותי")) {
await resetSubscribedYears(msg);
await client.sendMessage(msg.from, " די נו איזה חמוד אתה 🤓");
Expand All @@ -63,7 +95,7 @@ export const messageHandler = async (msg: Message) => {
if (!(await auth(msg))) {
return;
}

if (msg.body.includes("מי מביא אלכוהול")) {
await getAlcoholics(msg);
return;
Expand Down

0 comments on commit 4254308

Please sign in to comment.