Compare commits
2 Commits
main
...
feat/cover
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46d427363f | ||
|
|
0b8b58e915 |
BIN
back/artist.jpeg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
back/background_cover.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
back/icon_dark.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
10950
back/package-lock.json
generated
@@ -21,6 +21,7 @@
|
|||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@jimp/plugin-circle": "^0.22.10",
|
||||||
"@nestjs-modules/mailer": "^1.9.1",
|
"@nestjs-modules/mailer": "^1.9.1",
|
||||||
"@nestjs/common": "^10.1.0",
|
"@nestjs/common": "^10.1.0",
|
||||||
"@nestjs/config": "^3.0.0",
|
"@nestjs/config": "^3.0.0",
|
||||||
@@ -36,9 +37,9 @@
|
|||||||
"@types/passport": "^1.0.12",
|
"@types/passport": "^1.0.12",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.13.2",
|
|
||||||
"json-logger-service": "^9.0.1",
|
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
|
"jimp": "^0.22.10",
|
||||||
|
"json-logger-service": "^9.0.1",
|
||||||
"node-fetch": "^2.6.12",
|
"node-fetch": "^2.6.12",
|
||||||
"nodemailer": "^6.9.5",
|
"nodemailer": "^6.9.5",
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
|
|||||||
BIN
back/radioart.jpeg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
back/radioart2.jpeg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
back/radioart3.jpeg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
back/radioart4.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -37,6 +37,7 @@ import { Song as _Song } from 'src/_gen/prisma-class/song';
|
|||||||
import { SongHistory } from 'src/_gen/prisma-class/song_history';
|
import { SongHistory } from 'src/_gen/prisma-class/song_history';
|
||||||
import { IncludeMap, mapInclude } from 'src/utils/include';
|
import { IncludeMap, mapInclude } from 'src/utils/include';
|
||||||
import { Public } from 'src/auth/public';
|
import { Public } from 'src/auth/public';
|
||||||
|
import Jimp from 'jimp';
|
||||||
|
|
||||||
class SongHistoryResult {
|
class SongHistoryResult {
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
@@ -45,6 +46,9 @@ class SongHistoryResult {
|
|||||||
history: SongHistory[];
|
history: SongHistory[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BACKGROUND_COVER = 'radioart3.jpeg';
|
||||||
|
const ICON = 'icon_dark.png';
|
||||||
|
|
||||||
@Controller('song')
|
@Controller('song')
|
||||||
@ApiTags('song')
|
@ApiTags('song')
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@@ -85,6 +89,21 @@ export class SongController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async gen_illustration(song: Song) {
|
||||||
|
const img = await Jimp.read(BACKGROUND_COVER);
|
||||||
|
// @ts-ignore
|
||||||
|
const artist_img = await Jimp.read(`/assets/artists/${song.artist.name}/illustration.png`);
|
||||||
|
const logo = await Jimp.read(ICON);
|
||||||
|
img.cover(600, 600);
|
||||||
|
artist_img.cover(400, 400);
|
||||||
|
logo.cover(70, 70);
|
||||||
|
artist_img.circle();
|
||||||
|
img.composite(artist_img, 100, 100);
|
||||||
|
img.composite(logo, 10, 10);
|
||||||
|
return img;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Get(':id/illustration')
|
@Get(':id/illustration')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
description: 'Streams the illustration of the requested song',
|
description: 'Streams the illustration of the requested song',
|
||||||
@@ -93,13 +112,16 @@ export class SongController {
|
|||||||
@ApiOkResponse({ description: 'Returns the illustration succesfully' })
|
@ApiOkResponse({ description: 'Returns the illustration succesfully' })
|
||||||
@Public()
|
@Public()
|
||||||
async getIllustration(@Param('id', ParseIntPipe) id: number) {
|
async getIllustration(@Param('id', ParseIntPipe) id: number) {
|
||||||
const song = await this.songService.song({ id });
|
|
||||||
|
const song = await this.songService.song({ id }, { artist: true } );
|
||||||
if (!song) throw new NotFoundException('Song not found');
|
if (!song) throw new NotFoundException('Song not found');
|
||||||
|
//await this.gen_illustration(song);
|
||||||
|
|
||||||
if (song.illustrationPath === null) throw new NotFoundException();
|
if (song.illustrationPath === null) throw new NotFoundException();
|
||||||
if (!existsSync(song.illustrationPath))
|
if (!existsSync(song.illustrationPath)) {
|
||||||
throw new NotFoundException('Illustration not found');
|
let img = await this.gen_illustration(song);
|
||||||
|
img.write(song.illustrationPath);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const file = createReadStream(song.illustrationPath);
|
const file = createReadStream(song.illustrationPath);
|
||||||
return new StreamableFile(file);
|
return new StreamableFile(file);
|
||||||
|
|||||||