Skip to content

Commit

Permalink
Merge pull request #21 from Open-Webtoon-Reader/improvement/admin-routes
Browse files Browse the repository at this point in the history
Merge admin routes to Main
  • Loading branch information
Xen0Xys authored May 15, 2024
2 parents e0c6a32 + 4e1ecad commit 67ab309
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ SSL_CERT_FILE=""

# API
PREFIX="api/v1/"

# Security
ADMIN_KEY="admin"
45 changes: 41 additions & 4 deletions src/modules/webtoon/admin/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,66 @@
import {Body, Controller, Post} from "@nestjs/common";
import {ApiResponse, ApiTags} from "@nestjs/swagger";
import {Body, Controller, Delete, Get, HttpCode, Post, UseGuards} from "@nestjs/common";
import {ApiBearerAuth, ApiResponse, ApiTags} from "@nestjs/swagger";
import {DownloadManagerService} from "../webtoon/download-manager.service";
import {AddWebtoonToQueueDto} from "./models/dto/add-webtoon-to-queue.dto";
import {HttpStatusCode} from "axios";
import CachedWebtoonModel from "../webtoon/models/models/cached-webtoon.model";
import {AdminGuard} from "./guard/admin.guard";


@Controller("admin")
@ApiTags("Admin")
@UseGuards(AdminGuard)
export class AdminController{

constructor(
private readonly downloadManagerService: DownloadManagerService,
){}

@Post("queue")
@ApiResponse({status: HttpStatusCode.Ok, description: "Adds a webtoon to the download queue"})
@ApiBearerAuth()
@ApiResponse({status: HttpStatusCode.Created, description: "Adds a webtoon to the download queue"})
@ApiResponse({status: HttpStatusCode.TooEarly, description: "Cache not loaded."})
async addWebtoonToQueue(@Body() addWebtoonToQueueDto: AddWebtoonToQueueDto): Promise<void>{
return this.downloadManagerService.addWebtoonToQueue(addWebtoonToQueueDto.name, addWebtoonToQueueDto.language);
}

@Post("update/all")
@ApiResponse({status: HttpStatusCode.Ok, description: "Updates all webtoons in the database"})
@ApiBearerAuth()
@ApiResponse({status: HttpStatusCode.Created, description: "Updates all webtoons in the database"})
@ApiResponse({status: HttpStatusCode.TooEarly, description: "Cache not loaded."})
async updateAllWebtoons(): Promise<void>{
return this.downloadManagerService.updateAllWebtoons();
}

@Get("current-download")
@ApiBearerAuth()
@ApiResponse({status: HttpStatusCode.Ok, description: "Returns the current download"})
@ApiResponse({status: HttpStatusCode.NotFound, description: "No download in progress"})
async getCurrentDownload(): Promise<CachedWebtoonModel>{
return this.downloadManagerService.getCurrentDownload();
}

@Get("queue")
@ApiBearerAuth()
@ApiResponse({status: HttpStatusCode.Ok, description: "Returns the current download queue"})
@ApiResponse({status: HttpStatusCode.NotFound, description: "No download in progress"})
async getQueue(): Promise<CachedWebtoonModel[]>{
return this.downloadManagerService.getDownloadQueue();
}

@Delete("current-download")
@ApiBearerAuth()
@HttpCode(HttpStatusCode.NoContent)
@ApiResponse({status: HttpStatusCode.NoContent, description: "Cancels the current download"})
async cancelCurrentDownload(): Promise<void>{
return this.downloadManagerService.skipCurrentDownload();
}

@Delete("queue")
@ApiBearerAuth()
@HttpCode(HttpStatusCode.NoContent)
@ApiResponse({status: HttpStatusCode.NoContent, description: "Clears the download queue"})
async clearQueue(): Promise<void>{
return this.downloadManagerService.clearDownloadQueue();
}
}
20 changes: 20 additions & 0 deletions src/modules/webtoon/admin/guard/admin.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {CanActivate, ExecutionContext, Injectable, UnauthorizedException} from "@nestjs/common";
import {ConfigService} from "@nestjs/config";

@Injectable()
export class AdminGuard implements CanActivate{
constructor(
private readonly configService: ConfigService,
){}

async canActivate(context: ExecutionContext): Promise<boolean>{
const adminKey = this.configService.get("ADMIN_KEY");
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.split(" ")[1];
if(!token)
throw new UnauthorizedException("No token provided");
if(token !== adminKey)
throw new UnauthorizedException("Invalid token");
return true;
}
}
27 changes: 26 additions & 1 deletion src/modules/webtoon/webtoon/download-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {WebtoonParserService} from "./webtoon-parser.service";
import CachedWebtoonModel from "./models/models/cached-webtoon.model";
import EpisodeModel from "./models/models/episode.model";
import EpisodeDataModel from "./models/models/episode-data.model";
import {HttpException, Injectable} from "@nestjs/common";
import {HttpException, Injectable, NotFoundException} from "@nestjs/common";
import WebtoonModel from "./models/models/webtoon.model";
import WebtoonDataModel from "./models/models/webtoon-data.model";
import WebtoonQueue from "../../../common/utils/models/webtoon-queue";
Expand Down Expand Up @@ -71,10 +71,35 @@ export class DownloadManagerService{
const startEpisode: number = await this.webtoonDatabase.getLastSavedEpisodeNumber(this.currentDownload.title, this.currentDownload.language);
const epList: EpisodeModel[] = await this.webtoonParser.getEpisodes(this.currentDownload);
for(let i = startEpisode; i < epList.length; i++){
if(!this.currentDownload)
break;
const epImageLinks: string[] = await this.webtoonParser.getEpisodeLinks(this.currentDownload, epList[i]);
const episodeData: EpisodeDataModel = await this.webtoonDownloader.downloadEpisode(epList[i], epImageLinks);
if(!this.currentDownload)
break;
await this.webtoonDatabase.saveEpisode(this.currentDownload, epList[i], episodeData);
}
}
}

getCurrentDownload(): CachedWebtoonModel | undefined{
if(this.currentDownload)
return this.currentDownload;
throw new NotFoundException("No download in progress.");
}

getDownloadQueue(): CachedWebtoonModel[]{
if(!this.currentDownload)
throw new NotFoundException("No download in progress.");;
return [this.currentDownload, ...this.queue.getElements()];
}

skipCurrentDownload(): void{
this.currentDownload = undefined;
}

clearDownloadQueue(){
this.queue.clear();
this.currentDownload = undefined;
}
}

0 comments on commit 67ab309

Please sign in to comment.