123 lines
3.0 KiB
TypeScript
123 lines
3.0 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { Interval } from '@nestjs/schedule';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
import { NowPlayingGateway } from './now-playing.gateway';
|
|
import { RecordStationSyncService } from './record-station-sync.service';
|
|
|
|
interface RecordTrack {
|
|
id: number;
|
|
artist: string;
|
|
song: string;
|
|
image100?: string;
|
|
image200?: string;
|
|
image600?: string;
|
|
}
|
|
|
|
interface RecordNowPlayingItem {
|
|
id: number;
|
|
track: RecordTrack;
|
|
}
|
|
|
|
@Injectable()
|
|
export class NowPlayingService {
|
|
private readonly logger = new Logger(NowPlayingService.name);
|
|
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
private readonly gateway: NowPlayingGateway,
|
|
private readonly recordSync: RecordStationSyncService,
|
|
) {}
|
|
|
|
@Interval(30000)
|
|
async pollRecordNowPlaying() {
|
|
try {
|
|
const response = await fetch(
|
|
'https://www.radiorecord.ru/api/stations/now/',
|
|
{ headers: { 'Accept-Encoding': 'gzip, deflate' } },
|
|
);
|
|
if (!response.ok) {
|
|
this.logger.warn(`Record API returned ${response.status}`);
|
|
return;
|
|
}
|
|
|
|
const data = (await response.json()) as {
|
|
result: RecordNowPlayingItem[];
|
|
};
|
|
const nowPlaying = data.result ?? [];
|
|
|
|
for (const np of nowPlaying) {
|
|
const stationId =
|
|
this.recordSync.getStationIdByNowPlayingId(np.id);
|
|
if (!stationId) continue;
|
|
|
|
const coverUrl = np.track.image600 ?? np.track.image200 ?? np.track.image100;
|
|
|
|
const updated = await this.prisma.nowPlaying.upsert({
|
|
where: { stationId },
|
|
create: {
|
|
stationId,
|
|
song: np.track.song,
|
|
artist: np.track.artist,
|
|
coverUrl,
|
|
},
|
|
update: {
|
|
song: np.track.song,
|
|
artist: np.track.artist,
|
|
coverUrl,
|
|
},
|
|
});
|
|
|
|
this.gateway.broadcastNowPlaying(stationId, {
|
|
song: np.track.song,
|
|
artist: np.track.artist,
|
|
coverUrl,
|
|
updatedAt: updated.updatedAt,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
this.logger.error(`Failed to poll now playing: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
async updateNowPlaying(
|
|
stationId: string,
|
|
data: { song: string; artist: string; coverUrl?: string },
|
|
) {
|
|
const nowPlaying = await this.prisma.nowPlaying.upsert({
|
|
where: { stationId },
|
|
create: {
|
|
stationId,
|
|
song: data.song,
|
|
artist: data.artist,
|
|
coverUrl: data.coverUrl,
|
|
},
|
|
update: {
|
|
song: data.song,
|
|
artist: data.artist,
|
|
coverUrl: data.coverUrl,
|
|
},
|
|
});
|
|
|
|
this.gateway.broadcastNowPlaying(stationId, {
|
|
song: data.song,
|
|
artist: data.artist,
|
|
coverUrl: data.coverUrl,
|
|
updatedAt: nowPlaying.updatedAt,
|
|
});
|
|
|
|
return nowPlaying;
|
|
}
|
|
|
|
async getNowPlaying(stationId: string) {
|
|
return this.prisma.nowPlaying.findUnique({
|
|
where: { stationId },
|
|
});
|
|
}
|
|
|
|
async getAllNowPlaying() {
|
|
return this.prisma.nowPlaying.findMany({
|
|
include: { station: true },
|
|
});
|
|
}
|
|
}
|