mirror of
https://github.com/n08i40k/schedule-parser-next.git
synced 2025-12-06 09:47:46 +03:00
1.3.0
Добавлена совместимость с Firebase Cloud Messaging. Сервис и контроллер модуля schedule-replacer были перенесены в модуль schedule.
This commit is contained in:
1113
package-lock.json
generated
1113
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "schedule-parser-next",
|
"name": "schedule-parser-next",
|
||||||
"version": "1.2.0",
|
"version": "1.3.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "N08I40K",
|
"author": "N08I40K",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
|
"firebase-admin": "^12.6.0",
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"mongoose": "^8.6.1",
|
"mongoose": "^8.6.1",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ enum UserRole {
|
|||||||
ADMIN
|
ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FCM {
|
||||||
|
token String
|
||||||
|
topics Json
|
||||||
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @map("_id") @db.ObjectId
|
id String @id @map("_id") @db.ObjectId
|
||||||
//
|
//
|
||||||
@@ -37,4 +42,6 @@ model User {
|
|||||||
//
|
//
|
||||||
group String
|
group String
|
||||||
role UserRole
|
role UserRole
|
||||||
|
//
|
||||||
|
fcm FCM?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { AuthModule } from "./auth/auth.module";
|
|||||||
import { UsersModule } from "./users/users.module";
|
import { UsersModule } from "./users/users.module";
|
||||||
import { ScheduleModule } from "./schedule/schedule.module";
|
import { ScheduleModule } from "./schedule/schedule.module";
|
||||||
import { CacheModule } from "@nestjs/cache-manager";
|
import { CacheModule } from "@nestjs/cache-manager";
|
||||||
import { ScheduleReplacerModule } from "./schedule-replacer/schedule-replacer.module";
|
import { FirebaseAdminModule } from "./firebase-admin/firebase-admin.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -11,7 +11,7 @@ import { ScheduleReplacerModule } from "./schedule-replacer/schedule-replacer.mo
|
|||||||
UsersModule,
|
UsersModule,
|
||||||
ScheduleModule,
|
ScheduleModule,
|
||||||
CacheModule.register({ ttl: 5 * 60 * 1000, isGlobal: true }),
|
CacheModule.register({ ttl: 5 * 60 * 1000, isGlobal: true }),
|
||||||
ScheduleReplacerModule,
|
FirebaseAdminModule,
|
||||||
],
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [],
|
providers: [],
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ import { UserToken } from "./auth.decorator";
|
|||||||
@Controller("api/v1/auth")
|
@Controller("api/v1/auth")
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly scheduleService: ScheduleService,
|
|
||||||
private readonly authService: AuthService,
|
private readonly authService: AuthService,
|
||||||
|
private readonly scheduleService: ScheduleService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ApiExtraModels(SignInReqDto)
|
@ApiExtraModels(SignInReqDto)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
import { JwtModule } from "@nestjs/jwt";
|
import { JwtModule } from "@nestjs/jwt";
|
||||||
import { jwtConstants } from "../contants";
|
import { jwtConstants } from "../contants";
|
||||||
import { AuthService } from "./auth.service";
|
import { AuthService } from "./auth.service";
|
||||||
@@ -9,8 +9,8 @@ import { ScheduleModule } from "../schedule/schedule.module";
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
UsersModule,
|
forwardRef(() => UsersModule),
|
||||||
ScheduleModule,
|
forwardRef(() => ScheduleModule),
|
||||||
JwtModule.register({
|
JwtModule.register({
|
||||||
global: true,
|
global: true,
|
||||||
secret: jwtConstants.secret,
|
secret: jwtConstants.secret,
|
||||||
|
|||||||
@@ -14,3 +14,7 @@ export const httpsConstants = {
|
|||||||
export const apiConstants = {
|
export const apiConstants = {
|
||||||
port: process.env.API_PORT ?? 5050,
|
port: process.env.API_PORT ?? 5050,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const firebaseConstants = {
|
||||||
|
serviceAccountPath: process.env.FIREBASE_ACCOUNT_PATH!,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { ApiProperty, OmitType, PickType } from "@nestjs/swagger";
|
import { ApiProperty, OmitType, PickType } from "@nestjs/swagger";
|
||||||
import {
|
import {
|
||||||
|
IsArray,
|
||||||
IsEnum,
|
IsEnum,
|
||||||
IsJWT,
|
IsJWT,
|
||||||
IsMongoId,
|
IsMongoId,
|
||||||
|
IsObject,
|
||||||
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
MaxLength,
|
MaxLength,
|
||||||
MinLength,
|
MinLength,
|
||||||
|
ValidateNested,
|
||||||
} from "class-validator";
|
} from "class-validator";
|
||||||
import { Expose, plainToClass } from "class-transformer";
|
import { Expose, plainToClass, Type } from "class-transformer";
|
||||||
|
|
||||||
export enum UserRoleDto {
|
export enum UserRoleDto {
|
||||||
STUDENT = "STUDENT",
|
STUDENT = "STUDENT",
|
||||||
@@ -15,6 +19,25 @@ export enum UserRoleDto {
|
|||||||
ADMIN = "ADMIN",
|
ADMIN = "ADMIN",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UserFcmDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: "Токен Firebase Cloud Messaging",
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@Expose()
|
||||||
|
token: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: ["schedule-update"],
|
||||||
|
description: "Топики на которые подписан пользователь",
|
||||||
|
})
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@IsString()
|
||||||
|
@Expose()
|
||||||
|
topics: Array<string>;
|
||||||
|
}
|
||||||
|
|
||||||
export class UserDto {
|
export class UserDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
example: "66e1b7e255c5d5f1268cce90",
|
example: "66e1b7e255c5d5f1268cce90",
|
||||||
@@ -67,12 +90,20 @@ export class UserDto {
|
|||||||
@IsEnum(UserRoleDto)
|
@IsEnum(UserRoleDto)
|
||||||
@Expose()
|
@Expose()
|
||||||
role: UserRoleDto;
|
role: UserRoleDto;
|
||||||
|
|
||||||
|
@ApiProperty({ description: "Данные Firebase Cloud Messaging" })
|
||||||
|
@IsObject()
|
||||||
|
@Type(() => UserFcmDto)
|
||||||
|
@IsOptional()
|
||||||
|
@Expose()
|
||||||
|
fcm: UserFcmDto | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClientUserResDto extends OmitType(UserDto, [
|
export class ClientUserResDto extends OmitType(UserDto, [
|
||||||
"password",
|
"password",
|
||||||
"salt",
|
"salt",
|
||||||
"accessToken",
|
"accessToken",
|
||||||
|
"fcm",
|
||||||
]) {
|
]) {
|
||||||
static fromUserDto(userDto: UserDto): ClientUserResDto {
|
static fromUserDto(userDto: UserDto): ClientUserResDto {
|
||||||
return plainToClass(ClientUserResDto, userDto, {
|
return plainToClass(ClientUserResDto, userDto, {
|
||||||
|
|||||||
20
src/firebase-admin/firebase-admin.controller.spec.ts
Normal file
20
src/firebase-admin/firebase-admin.controller.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
|
import { FirebaseAdminController } from "./firebase-admin.controller";
|
||||||
|
|
||||||
|
describe("FirebaseAdminController", () => {
|
||||||
|
let controller: FirebaseAdminController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [FirebaseAdminController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<FirebaseAdminController>(
|
||||||
|
FirebaseAdminController,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be defined", () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
41
src/firebase-admin/firebase-admin.controller.ts
Normal file
41
src/firebase-admin/firebase-admin.controller.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
HttpCode,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
Post,
|
||||||
|
UseGuards,
|
||||||
|
} from "@nestjs/common";
|
||||||
|
import { AuthGuard } from "../auth/auth.guard";
|
||||||
|
import { UserToken } from "../auth/auth.decorator";
|
||||||
|
import { UserFromTokenPipe } from "../auth/auth.pipe";
|
||||||
|
import { UserDto } from "../dto/user.dto";
|
||||||
|
import { ResultDto } from "../utility/validation/class-validator.interceptor";
|
||||||
|
import { FirebaseAdminService } from "./firebase-admin.service";
|
||||||
|
|
||||||
|
@Controller("api/v1/fcm")
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
export class FirebaseAdminController {
|
||||||
|
private readonly defaultTopics = new Set(["schedule-update"]);
|
||||||
|
|
||||||
|
constructor(private readonly firebaseAdminService: FirebaseAdminService) {}
|
||||||
|
|
||||||
|
@Post("set-token/:token")
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@ResultDto(null)
|
||||||
|
async setToken(
|
||||||
|
@Param("token") token: string,
|
||||||
|
@UserToken(UserFromTokenPipe) user: UserDto,
|
||||||
|
): Promise<void> {
|
||||||
|
if (user.fcm?.token === token) return;
|
||||||
|
|
||||||
|
const updatedUser = (
|
||||||
|
await this.firebaseAdminService.updateToken(user, token)
|
||||||
|
).userDto;
|
||||||
|
|
||||||
|
await this.firebaseAdminService.subscribe(
|
||||||
|
updatedUser,
|
||||||
|
this.defaultTopics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/firebase-admin/firebase-admin.module.ts
Normal file
12
src/firebase-admin/firebase-admin.module.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
|
import { FirebaseAdminService } from "./firebase-admin.service";
|
||||||
|
import { UsersModule } from "../users/users.module";
|
||||||
|
import { FirebaseAdminController } from "./firebase-admin.controller";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [forwardRef(() => UsersModule)],
|
||||||
|
providers: [FirebaseAdminService],
|
||||||
|
exports: [FirebaseAdminService],
|
||||||
|
controllers: [FirebaseAdminController],
|
||||||
|
})
|
||||||
|
export class FirebaseAdminModule {}
|
||||||
18
src/firebase-admin/firebase-admin.service.spec.ts
Normal file
18
src/firebase-admin/firebase-admin.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
|
import { FirebaseAdminService } from "./firebase-admin.service";
|
||||||
|
|
||||||
|
describe("FirebaseAdminService", () => {
|
||||||
|
let service: FirebaseAdminService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [FirebaseAdminService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<FirebaseAdminService>(FirebaseAdminService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be defined", () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
99
src/firebase-admin/firebase-admin.service.ts
Normal file
99
src/firebase-admin/firebase-admin.service.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { forwardRef, Inject, Injectable, OnModuleInit } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { initializeApp, App } from "firebase-admin/app";
|
||||||
|
import { credential } from "firebase-admin";
|
||||||
|
import {
|
||||||
|
BaseMessage,
|
||||||
|
getMessaging,
|
||||||
|
Messaging,
|
||||||
|
TopicMessage,
|
||||||
|
} from "firebase-admin/messaging";
|
||||||
|
|
||||||
|
import { firebaseConstants } from "../contants";
|
||||||
|
import { UsersService } from "../users/users.service";
|
||||||
|
import { UserDto } from "../dto/user.dto";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FirebaseAdminService implements OnModuleInit {
|
||||||
|
constructor(
|
||||||
|
@Inject(forwardRef(() => UsersService))
|
||||||
|
private readonly usersService: UsersService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private app: App;
|
||||||
|
private messaging: Messaging;
|
||||||
|
|
||||||
|
onModuleInit() {
|
||||||
|
this.app = initializeApp({
|
||||||
|
credential: credential.cert(firebaseConstants.serviceAccountPath),
|
||||||
|
});
|
||||||
|
this.messaging = getMessaging(this.app);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendByTopic(topic: string, message: BaseMessage): Promise<void> {
|
||||||
|
const topicMessage = message as TopicMessage;
|
||||||
|
topicMessage.topic = topic;
|
||||||
|
|
||||||
|
await this.messaging.send(topicMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateToken(
|
||||||
|
user: UserDto,
|
||||||
|
token: string,
|
||||||
|
): Promise<{ userDto: UserDto; isNew: boolean }> {
|
||||||
|
const isNew = user.fcm === null;
|
||||||
|
|
||||||
|
const fcm = !isNew ? user.fcm : { token: token, topics: [] };
|
||||||
|
if (!isNew) {
|
||||||
|
if (fcm.token === token) return { userDto: user, isNew: false };
|
||||||
|
|
||||||
|
for (const topic in fcm.topics)
|
||||||
|
await this.messaging.subscribeToTopic(token, topic);
|
||||||
|
fcm.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
userDto: await this.usersService.update({
|
||||||
|
where: { id: user.id },
|
||||||
|
data: { fcm: fcm },
|
||||||
|
}),
|
||||||
|
isNew: isNew,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async unsubscribe(user: UserDto, topics: Set<string>): Promise<UserDto> {
|
||||||
|
const fcm = user.fcm;
|
||||||
|
const currentTopics = new Set(fcm.topics);
|
||||||
|
|
||||||
|
for (const topic of topics) {
|
||||||
|
await this.messaging.unsubscribeFromTopic(fcm.token, topic);
|
||||||
|
currentTopics.delete(topic);
|
||||||
|
}
|
||||||
|
if (currentTopics.size === fcm.topics.length) return user;
|
||||||
|
|
||||||
|
fcm.topics = Array.from(currentTopics);
|
||||||
|
|
||||||
|
return await this.usersService.update({
|
||||||
|
where: { id: user.id },
|
||||||
|
data: { fcm: fcm },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async subscribe(user: UserDto, topics: Set<string>): Promise<UserDto> {
|
||||||
|
const fcm = user.fcm;
|
||||||
|
const currentTopics = new Set(fcm.topics);
|
||||||
|
|
||||||
|
for (const topic of topics) {
|
||||||
|
await this.messaging.subscribeToTopic(fcm.token, topic);
|
||||||
|
currentTopics.add(topic);
|
||||||
|
}
|
||||||
|
if (currentTopics.size === fcm.topics.length) return user;
|
||||||
|
|
||||||
|
fcm.topics = Array.from(currentTopics);
|
||||||
|
|
||||||
|
return await this.usersService.update({
|
||||||
|
where: { id: user.id },
|
||||||
|
data: { fcm: fcm },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Module } from "@nestjs/common";
|
|
||||||
import { ScheduleReplacerService } from "./schedule-replacer.service";
|
|
||||||
import { PrismaService } from "../prisma/prisma.service";
|
|
||||||
import { ScheduleReplacerController } from "./schedule-replacer.controller";
|
|
||||||
import { ScheduleModule } from "../schedule/schedule.module";
|
|
||||||
import { AuthService } from "../auth/auth.service";
|
|
||||||
import { UsersModule } from "../users/users.module";
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ScheduleModule, UsersModule],
|
|
||||||
providers: [AuthService, PrismaService, ScheduleReplacerService],
|
|
||||||
exports: [ScheduleReplacerService],
|
|
||||||
controllers: [ScheduleReplacerController],
|
|
||||||
})
|
|
||||||
export class ScheduleReplacerModule {}
|
|
||||||
@@ -149,14 +149,8 @@ export class ScheduleParser {
|
|||||||
!downloadData.new &&
|
!downloadData.new &&
|
||||||
this.lastResult &&
|
this.lastResult &&
|
||||||
this.xlsDownloader.getCacheMode() !== XlsDownloaderCacheMode.NONE
|
this.xlsDownloader.getCacheMode() !== XlsDownloaderCacheMode.NONE
|
||||||
) {
|
)
|
||||||
console.debug(
|
|
||||||
"Так как скачанный XLS не новый, присутствует уже готовый результат и кеширование не отключено...",
|
|
||||||
);
|
|
||||||
console.debug("будет возвращён предыдущий результат.");
|
|
||||||
|
|
||||||
return this.lastResult;
|
return this.lastResult;
|
||||||
}
|
|
||||||
|
|
||||||
const workBook = XLSX.read(downloadData.fileData);
|
const workBook = XLSX.read(downloadData.fileData);
|
||||||
const workSheet = workBook.Sheets[workBook.SheetNames[0]];
|
const workSheet = workBook.Sheets[workBook.SheetNames[0]];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
NotAcceptableException,
|
NotAcceptableException,
|
||||||
ServiceUnavailableException,
|
ServiceUnavailableException,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { ScheduleReplacerService } from "../../../schedule-replacer/schedule-replacer.service";
|
import { ScheduleReplacerService } from "../../schedule-replacer.service";
|
||||||
import { Error } from "mongoose";
|
import { Error } from "mongoose";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
import { AuthRoles } from "../auth-role/auth-role.decorator";
|
import { AuthRoles } from "../auth-role/auth-role.decorator";
|
||||||
import { UserRoleDto } from "../dto/user.dto";
|
import { UserRoleDto } from "../dto/user.dto";
|
||||||
import { ScheduleReplacerService } from "./schedule-replacer.service";
|
import { ScheduleReplacerService } from "./schedule-replacer.service";
|
||||||
import { ScheduleService } from "../schedule/schedule.service";
|
import { ScheduleService } from "./schedule.service";
|
||||||
import { FileInterceptor } from "@nestjs/platform-express";
|
import { FileInterceptor } from "@nestjs/platform-express";
|
||||||
import {
|
import {
|
||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
@@ -7,6 +7,14 @@ import { plainToClass } from "class-transformer";
|
|||||||
export class ScheduleReplacerService {
|
export class ScheduleReplacerService {
|
||||||
constructor(private readonly prismaService: PrismaService) {}
|
constructor(private readonly prismaService: PrismaService) {}
|
||||||
|
|
||||||
|
async hasByEtag(etag: string): Promise<boolean> {
|
||||||
|
return (
|
||||||
|
(await this.prismaService.scheduleReplace.count({
|
||||||
|
where: { etag: etag },
|
||||||
|
})) > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async getByEtag(etag: string): Promise<ScheduleReplacerDto | null> {
|
async getByEtag(etag: string): Promise<ScheduleReplacerDto | null> {
|
||||||
const response = await this.prismaService.scheduleReplace.findUnique({
|
const response = await this.prismaService.scheduleReplace.findUnique({
|
||||||
where: { etag: etag },
|
where: { etag: etag },
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
import { ScheduleService } from "./schedule.service";
|
import { ScheduleService } from "./schedule.service";
|
||||||
import { ScheduleController } from "./schedule.controller";
|
import { ScheduleController } from "./schedule.controller";
|
||||||
import { UsersService } from "../users/users.service";
|
|
||||||
import { PrismaService } from "../prisma/prisma.service";
|
import { PrismaService } from "../prisma/prisma.service";
|
||||||
import { ScheduleReplacerService } from "../schedule-replacer/schedule-replacer.service";
|
import { FirebaseAdminModule } from "../firebase-admin/firebase-admin.module";
|
||||||
|
import { UsersModule } from "src/users/users.module";
|
||||||
|
import { ScheduleReplacerService } from "./schedule-replacer.service";
|
||||||
|
import { ScheduleReplacerController } from "./schedule-replacer.controller";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
imports: [forwardRef(() => UsersModule), FirebaseAdminModule],
|
||||||
ScheduleService,
|
providers: [PrismaService, ScheduleService, ScheduleReplacerService],
|
||||||
ScheduleReplacerService,
|
controllers: [ScheduleController, ScheduleReplacerController],
|
||||||
UsersService,
|
|
||||||
PrismaService,
|
|
||||||
],
|
|
||||||
controllers: [ScheduleController],
|
|
||||||
exports: [ScheduleService],
|
exports: [ScheduleService],
|
||||||
})
|
})
|
||||||
export class ScheduleModule {}
|
export class ScheduleModule {}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { Inject, Injectable, NotFoundException } from "@nestjs/common";
|
import {
|
||||||
|
Inject,
|
||||||
|
Injectable,
|
||||||
|
NotFoundException,
|
||||||
|
} from "@nestjs/common";
|
||||||
import {
|
import {
|
||||||
ScheduleParser,
|
ScheduleParser,
|
||||||
ScheduleParseResult,
|
ScheduleParseResult,
|
||||||
@@ -17,7 +21,8 @@ import { Cache, CACHE_MANAGER } from "@nestjs/cache-manager";
|
|||||||
import { instanceToPlain } from "class-transformer";
|
import { instanceToPlain } from "class-transformer";
|
||||||
import { cacheGetOrFill } from "../utility/cache.util";
|
import { cacheGetOrFill } from "../utility/cache.util";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
import { ScheduleReplacerService } from "../schedule-replacer/schedule-replacer.service";
|
import { ScheduleReplacerService } from "./schedule-replacer.service";
|
||||||
|
import { FirebaseAdminService } from "../firebase-admin/firebase-admin.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScheduleService {
|
export class ScheduleService {
|
||||||
@@ -37,6 +42,7 @@ export class ScheduleService {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
|
@Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
|
||||||
private readonly scheduleReplacerService: ScheduleReplacerService,
|
private readonly scheduleReplacerService: ScheduleReplacerService,
|
||||||
|
private readonly firebaseAdminService: FirebaseAdminService,
|
||||||
) {
|
) {
|
||||||
const xlsDownloader = this.scheduleParser.getXlsDownloader();
|
const xlsDownloader = this.scheduleParser.getXlsDownloader();
|
||||||
|
|
||||||
@@ -77,8 +83,26 @@ export class ScheduleService {
|
|||||||
if (
|
if (
|
||||||
this.scheduleUpdatedAt.valueOf() === 0 ||
|
this.scheduleUpdatedAt.valueOf() === 0 ||
|
||||||
this.cacheHash !== oldHash
|
this.cacheHash !== oldHash
|
||||||
)
|
) {
|
||||||
|
if (this.scheduleUpdatedAt.valueOf() !== 0) {
|
||||||
|
const isReplaced =
|
||||||
|
await this.scheduleReplacerService.hasByEtag(
|
||||||
|
schedule.etag,
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.firebaseAdminService.sendByTopic(
|
||||||
|
"schedule-update",
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
type: "schedule-update",
|
||||||
|
replaced: isReplaced.toString(),
|
||||||
|
etag: schedule.etag,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
this.scheduleUpdatedAt = new Date();
|
this.scheduleUpdatedAt = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
return schedule;
|
return schedule;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
import { UsersService } from "./users.service";
|
import { UsersService } from "./users.service";
|
||||||
import { PrismaService } from "../prisma/prisma.service";
|
import { PrismaService } from "../prisma/prisma.service";
|
||||||
import { UsersController } from "./users.controller";
|
import { UsersController } from "./users.controller";
|
||||||
import { AuthService } from "../auth/auth.service";
|
|
||||||
import { ScheduleModule } from "../schedule/schedule.module";
|
import { ScheduleModule } from "../schedule/schedule.module";
|
||||||
|
import { AuthModule } from "../auth/auth.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ScheduleModule],
|
imports: [forwardRef(() => ScheduleModule), forwardRef(() => AuthModule)],
|
||||||
providers: [PrismaService, UsersService, AuthService],
|
providers: [PrismaService, UsersService],
|
||||||
exports: [UsersService],
|
exports: [UsersService],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ConflictException,
|
ConflictException,
|
||||||
|
forwardRef,
|
||||||
|
Inject,
|
||||||
Injectable,
|
Injectable,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
@@ -16,6 +18,7 @@ import { ScheduleService } from "../schedule/schedule.service";
|
|||||||
export class UsersService {
|
export class UsersService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly prismaService: PrismaService,
|
private readonly prismaService: PrismaService,
|
||||||
|
@Inject(forwardRef(() => ScheduleService))
|
||||||
private readonly scheduleService: ScheduleService,
|
private readonly scheduleService: ScheduleService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user