first commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import {Body, Controller, Delete, Get, Param, Post, Put, Res, StreamableFile} from '@nestjs/common';
|
||||
import {TrackService} from "./track.service";
|
||||
import {TrackModel} from "./track.model";
|
||||
import {TrackEntity} from "./track.entity";
|
||||
import {createReadStream} from "fs";
|
||||
import { join } from 'path';
|
||||
import type { Response } from 'express';
|
||||
|
||||
@Controller('track')
|
||||
export class TrackController {
|
||||
|
||||
constructor(private readonly service: TrackService) {
|
||||
}
|
||||
|
||||
@Get()
|
||||
getAll(): Promise<TrackModel[]> {
|
||||
return this.service.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
get(@Param('id') id: number): Promise<TrackModel> {
|
||||
return this.service.findOne(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() track: TrackModel): Promise<TrackModel> {
|
||||
return this.service.create(track as TrackEntity);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
update(@Param('id') id: number, @Body() track: TrackModel): Promise<void> {
|
||||
return this.service.update(id, track as TrackEntity);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
delete(@Param('id') id: number): Promise<void> {
|
||||
return this.service.remove(id);
|
||||
}
|
||||
|
||||
@Get('download/:id')
|
||||
async getFile(@Res({ passthrough: true }) res: Response, @Param('id') id: number): Promise<StreamableFile> {
|
||||
const track = await this.service.findOne(id);
|
||||
const file = createReadStream(join(process.cwd(), 'downloads', `${track.artist} - ${track.song}.mp3`));
|
||||
res.set({'Content-Disposition': `attachment; filename="${track.artist} - ${track.song}.mp3"`,});
|
||||
return new StreamableFile(file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
|
||||
import {PlaylistEntity} from "../playlist/playlist.entity";
|
||||
import {TrackStatusEnum} from "./track.model";
|
||||
|
||||
@Entity()
|
||||
export class TrackEntity {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id?: number;
|
||||
|
||||
@Column()
|
||||
artist: string;
|
||||
|
||||
@Column()
|
||||
song: string;
|
||||
|
||||
@Column()
|
||||
spotifyUrl: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
youtubeUrl?: string;
|
||||
|
||||
@Column({default: TrackStatusEnum.New})
|
||||
status?: TrackStatusEnum;
|
||||
|
||||
@ManyToOne(() => PlaylistEntity, playlist => playlist.tracks)
|
||||
playlist?: PlaylistEntity;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import {PlaylistModel} from "../playlist/playlist.model";
|
||||
|
||||
export interface TrackModel {
|
||||
id?: number;
|
||||
artist: string;
|
||||
song: string;
|
||||
spotifyUrl: string;
|
||||
youtubeUrl?: string;
|
||||
status?: TrackStatusEnum,
|
||||
playlist?: PlaylistModel;
|
||||
}
|
||||
|
||||
export enum TrackStatusEnum {
|
||||
New,
|
||||
Queued,
|
||||
Completed,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import {TrackEntity} from "./track.entity";
|
||||
import {TrackService} from "./track.service";
|
||||
import {TrackController} from "./track.controller";
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([TrackEntity])],
|
||||
providers: [TrackService],
|
||||
controllers: [TrackController],
|
||||
exports: [TrackService],
|
||||
})
|
||||
export class TrackModule {}
|
||||
@@ -0,0 +1,58 @@
|
||||
import {Injectable} from '@nestjs/common';
|
||||
import {InjectRepository} from '@nestjs/typeorm';
|
||||
import {Repository} from 'typeorm';
|
||||
import {TrackEntity} from "./track.entity";
|
||||
import {PlaylistEntity} from "../playlist/playlist.entity";
|
||||
import {Interval} from "@nestjs/schedule";
|
||||
import {TrackStatusEnum} from "./track.model";
|
||||
import * as yts from 'yt-search';
|
||||
import * as ytdl from 'ytdl-core';
|
||||
import * as fs from 'fs';
|
||||
|
||||
@Injectable()
|
||||
export class TrackService {
|
||||
constructor(
|
||||
@InjectRepository(TrackEntity)
|
||||
private repository: Repository<TrackEntity>,
|
||||
) {}
|
||||
|
||||
findAll(criteria?: Partial<TrackEntity>): Promise<TrackEntity[]> {
|
||||
return this.repository.find({where: criteria});
|
||||
}
|
||||
|
||||
findOne(id: number): Promise<TrackEntity | null> {
|
||||
return this.repository.findOneBy({ id });
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<void> {
|
||||
await this.repository.delete(id);
|
||||
}
|
||||
|
||||
async create(track: TrackEntity, playlist?: PlaylistEntity): Promise<TrackEntity> {
|
||||
return this.repository.save({...track, playlist});
|
||||
}
|
||||
|
||||
async update(id: number, track: TrackEntity): Promise<void> {
|
||||
await this.repository.update(id, track);
|
||||
}
|
||||
|
||||
@Interval(3000)
|
||||
async findOnYoutube() {
|
||||
const newTracks = await this.findAll({status: TrackStatusEnum.New});
|
||||
newTracks.forEach(async track => {
|
||||
const youtubeResult = await yts(`${track.artist} - ${track.song}`);
|
||||
await this.update(track.id, {...track, youtubeUrl: youtubeResult.videos[0].url, status: TrackStatusEnum.Queued})
|
||||
});
|
||||
}
|
||||
|
||||
@Interval(3000)
|
||||
async download() {
|
||||
const queuedTracks = await this.findAll({status: TrackStatusEnum.Queued});
|
||||
queuedTracks.forEach(async track => {
|
||||
await ytdl(track.youtubeUrl, {quality: "highestaudio", filter: "audioonly"}).pipe(
|
||||
fs.createWriteStream(`downloads/${track.artist} - ${track.song.replace('/', '')}.mp3`)
|
||||
);
|
||||
await this.update(track.id, {...track, status: TrackStatusEnum.Completed})
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user