diff --git a/src/app.ts b/src/app.ts index 715ab56..a538d2a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -16,24 +16,28 @@ import * as http from "node:http"; import {NotificationsService} from "./app/services/Notifications/NotificationsService"; import {postgresBookingRepository} from "./infrastructure/db/repository/PostgresQL/BookingRepoImplement"; import {postgresUserRepository} from "./infrastructure/db/repository/PostgresQL/UserRepoImplement"; +import {Expo} from "expo-server-sdk"; +import {CronJob} from "cron"; +import {FirebaseService} from "./app/services/Firebase/FirebaseService"; dotenv.config(); const app = express(); const router = express.Router(); const server = http.createServer(app) +const expo = new Expo() app.use(express.json()) app.use(cookieParser()) app.use(multer().any()); app.use( - bodyParser.urlencoded({ - extended: false, - }) + bodyParser.urlencoded({ + extended: false, + }) ); app.use(cors({ - credentials: true, - origin: process.env.CLIENT_URL, + credentials: true, + origin: process.env.CLIENT_URL, })) @@ -44,30 +48,51 @@ userRoutes.initRoutes(router) bookingRoutes.initRoutes(router) uploadRoutes.initRoutes(router) -router.post("/saveTokenApp", async (req, res) => { - const {token, userId} = req.body; - await firebase.saveToken(token, userId); - res.status(200).send("Token saved") -}) app.use("/api", router) app.use(ErrorMiddleware) // Firebase -const firebase = new NotificationsService(postgresBookingRepository, postgresUserRepository) +const firebase = new FirebaseService(postgresBookingRepository, postgresUserRepository) +const notificationExpo = new NotificationsService(postgresBookingRepository, + postgresUserRepository, + firebase, + expo) + +router.post("/saveTokenApp", async (req, res) => { + const {token, userId} = req.body; + await firebase.saveToken(token, userId); + res.status(200).send("Token saved") +}) + +router.post("/sendNotification", async (req, res) => { + const {userId} = req.body; + const {token} = await firebase.getToken(userId); + console.log(userId, token) + expo.sendPushNotificationsAsync([{ + to: token, + sound: 'default', + title: 'Backend hello', + body: 'asdasdasdasdasd!', + data: {someData: 'kek'}, + }]) + res.status(200).send("Notification send") +}) +// new CronJob('*/20 * * * * *', async () => { +// notificationExpo.sendAlertReservationNotification() +// }).start() const port = process.env.PORT; app.get('/api', (req, res) => { - res.send('Express + TypeScript Server'); + res.send('Express + TypeScript Server'); }); - server.listen(port, () => { - console.log(`⚡️[server]: Server is running at http://localhost:${port}/api`); + console.log(`⚡️[server]: Server is running at http://localhost:${port}/api`); }); diff --git a/src/app/services/Firebase/FirebaseService.ts b/src/app/services/Firebase/FirebaseService.ts new file mode 100644 index 0000000..56bf16c --- /dev/null +++ b/src/app/services/Firebase/FirebaseService.ts @@ -0,0 +1,44 @@ +import {child, get, getDatabase, ref, set} from "firebase/database"; +import process from "node:process"; +import {initializeApp} from "firebase/app"; +import {BookingRepo} from "../../repositories/BookingRepo"; +import {UserRepo} from "../../repositories/UserRepo"; + +export class FirebaseService { + + private readonly db: any + private dbRef: any + constructor( + private BookingRepo: BookingRepo, + private UserRepo: UserRepo, + ) { + + const firebaseConfig = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + projectId: process.env.FIREBASE_PROJECT_ID, + storageBucket: process.env.FIREBASE_STORAGE_BUCKET, + messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, + databaseURL: process.env.FIREBASE_DATABASE_URL + }; + + initializeApp(firebaseConfig); + // const analytics = getAnalytics(app); + + this.db = getDatabase() + this.dbRef = ref(this.db) + } + + async saveToken(token: string, userId: string) { + + const values = (await get(child(this.dbRef, `userTokens/${userId}`))).val() ?? {}; + const payload = {...values, token}; + set(ref(this.db, `userTokens/${userId}`), payload); + } + + async getToken(userId: string){ + return (await get(child(this.dbRef, `userTokens/${userId}`))).val() ?? {}; + } +} \ No newline at end of file diff --git a/src/app/services/Notifications/NotificationsService.ts b/src/app/services/Notifications/NotificationsService.ts index beb6e0e..0bf2573 100644 --- a/src/app/services/Notifications/NotificationsService.ts +++ b/src/app/services/Notifications/NotificationsService.ts @@ -2,36 +2,17 @@ import {BookingStatus} from "../../../infrastructure/shared/types/Booking"; import {equalDateTimeBookingExpired} from "../../../infrastructure/helpers/Date"; import {BookingRepo} from "../../repositories/BookingRepo"; import {UserRepo} from "../../repositories/UserRepo"; -import {child, get, getDatabase, ref, set} from "firebase/database" -import {initializeApp} from "firebase/app"; -import * as process from "node:process"; - +import {FirebaseService} from "../Firebase/FirebaseService"; +import {Expo} from "expo-server-sdk"; export class NotificationsService { - private db: any - private dbRef: any constructor( private BookingRepo: BookingRepo, private UserRepo: UserRepo, + private firebase: FirebaseService, + private expo: Expo ) { - - const firebaseConfig = { - apiKey: process.env.FIREBASE_API_KEY, - authDomain: process.env.FIREBASE_AUTH_DOMAIN, - projectId: process.env.FIREBASE_PROJECT_ID, - storageBucket: process.env.FIREBASE_STORAGE_BUCKET, - messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID, - appId: process.env.FIREBASE_APP_ID, - measurementId: process.env.FIREBASE_MEASUREMENT_ID, - databaseURL: process.env.FIREBASE_DATABASE_URL - }; - - const app = initializeApp(firebaseConfig); - // const analytics = getAnalytics(app); - - this.db = getDatabase() - this.dbRef = ref(this.db) } @@ -40,36 +21,50 @@ export class NotificationsService { id: true }) listUsers.forEach(async ({id: user_id}: { id: number }) => { - const listBookings = await this.BookingRepo.getBySelect({ status: BookingStatus.CREATED, user_id }, { time_from: true, time_to: true, - date: true + date: true, + equipment_id: true }) listBookings?.forEach((booking: any) => { - const {date, time_to} = booking + const {date, time_to} = booking; if (equalDateTimeBookingExpired(date, time_to)) { - console.log("check") + this.firebase.getToken(String(user_id)).then((data: any) => { + const {token} = data; + if(token) { + this.sendExpoNotification(token, { + date, + time_to + }) + } else { + console.log("Token not found!") + } + + }) } }) }) } - async saveToken(token: string, userId: string) { - - const values = (await get(child(this.dbRef, `userTokens/${userId}`))).val() ?? {}; - const payload = {...values, token}; - set(ref(this.db, `userTokens/${userId}`), payload); + private async sendExpoNotification(token: string, data: any) { + this.expo.sendPushNotificationsAsync([ + { + to: token, + sound: 'default', + title: 'Внимание!', + body: 'Ваша бронь просрочена!', + data, + } + ]) + console.log("send notification!") } - async getTokens() { - const values = (await get(child(this.dbRef, `userTokens`))).val() ?? {}; - return values; - } + } diff --git a/src/infrastructure/helpers/Date.ts b/src/infrastructure/helpers/Date.ts index 0fc1e9a..1d523d5 100644 --- a/src/infrastructure/helpers/Date.ts +++ b/src/infrastructure/helpers/Date.ts @@ -1,14 +1,12 @@ -import moment from "moment"; +import moment from "moment-timezone" export const equalDateTimeBookingExpired = (date: Date, time_to: string) => { - //@ts-ignore const currDate = moment().tz("Europe/Moscow").format("YYYY-MM-DD") const comparisonDate = moment(date).format("YYYY-MM-DD") if(currDate > comparisonDate) { return true } else if(currDate == comparisonDate) { - //@ts-ignore const currTime = moment().tz("Europe/Moscow").format("HH:mm") return currTime > time_to }