refactor playlist adders
This commit is contained in:
5
src/lib/server/playlist/playlistAdder.ts
Normal file
5
src/lib/server/playlist/playlistAdder.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { SongInfo } from '$lib/odesliResponse';
|
||||||
|
|
||||||
|
export interface PlaylistAdder {
|
||||||
|
addToPlaylist(song: SongInfo): Promise<void>;
|
||||||
|
}
|
@ -3,8 +3,9 @@ import { Logger } from '$lib/log';
|
|||||||
import type { OauthResponse } from '$lib/mastodon/response';
|
import type { OauthResponse } from '$lib/mastodon/response';
|
||||||
import type { SongInfo } from '$lib/odesliResponse';
|
import type { SongInfo } from '$lib/odesliResponse';
|
||||||
import { OauthPlaylistAdder } from './oauthPlaylistAdder';
|
import { OauthPlaylistAdder } from './oauthPlaylistAdder';
|
||||||
|
import type { PlaylistAdder } from './playlistAdder';
|
||||||
|
|
||||||
export class SpotifyPlaylistAdder extends OauthPlaylistAdder {
|
export class SpotifyPlaylistAdder extends OauthPlaylistAdder implements PlaylistAdder {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super('https://api.spotify.com/v1', 'spotify_auth_token');
|
super('https://api.spotify.com/v1', 'spotify_auth_token');
|
||||||
this.logger = new Logger('SpotifyPlaylistAdder');
|
this.logger = new Logger('SpotifyPlaylistAdder');
|
@ -8,8 +8,9 @@ import { log } from '$lib/log';
|
|||||||
import type { OauthResponse } from '$lib/mastodon/response';
|
import type { OauthResponse } from '$lib/mastodon/response';
|
||||||
import type { SongInfo } from '$lib/odesliResponse';
|
import type { SongInfo } from '$lib/odesliResponse';
|
||||||
import { OauthPlaylistAdder } from './oauthPlaylistAdder';
|
import { OauthPlaylistAdder } from './oauthPlaylistAdder';
|
||||||
|
import type { PlaylistAdder } from './playlistAdder';
|
||||||
|
|
||||||
export class YoutubePlaylistAdder extends OauthPlaylistAdder {
|
export class YoutubePlaylistAdder extends OauthPlaylistAdder implements PlaylistAdder {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super('https://www.googleapis.com/youtube/v3', 'yt_auth_token');
|
super('https://www.googleapis.com/youtube/v3', 'yt_auth_token');
|
||||||
}
|
}
|
@ -25,8 +25,9 @@ import {
|
|||||||
savePost,
|
savePost,
|
||||||
saveSongThumbnail
|
saveSongThumbnail
|
||||||
} from '$lib/server/db';
|
} from '$lib/server/db';
|
||||||
|
import { SpotifyPlaylistAdder } from '$lib/server/playlist/spotifyPlaylistAdder';
|
||||||
|
import { YoutubePlaylistAdder } from '$lib/server/playlist/ytPlaylistAdder';
|
||||||
import { createFeed, saveAtomFeed } from '$lib/server/rss';
|
import { createFeed, saveAtomFeed } from '$lib/server/rss';
|
||||||
import { YoutubePlaylistAdder } from '$lib/server/ytPlaylistAdder';
|
|
||||||
import { sleep } from '$lib/sleep';
|
import { sleep } from '$lib/sleep';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
@ -34,7 +35,7 @@ import { console } from 'inspector/promises';
|
|||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { URL, URLSearchParams } from 'url';
|
import { URL, URLSearchParams } from 'url';
|
||||||
import { WebSocket } from 'ws';
|
import { WebSocket } from 'ws';
|
||||||
import { SpotifyPlaylistAdder } from './spotifyPlaylistAdder';
|
import type { PlaylistAdder } from './playlist/playlistAdder';
|
||||||
|
|
||||||
const URL_REGEX = new RegExp(/href="(?<postUrl>[^>]+?)" target="_blank"/gm);
|
const URL_REGEX = new RegExp(/href="(?<postUrl>[^>]+?)" target="_blank"/gm);
|
||||||
const INVIDIOUS_REGEX = new RegExp(/invidious.*?watch.*?v=(?<videoId>[a-zA-Z_0-9-]+)/gm);
|
const INVIDIOUS_REGEX = new RegExp(/invidious.*?watch.*?v=(?<videoId>[a-zA-Z_0-9-]+)/gm);
|
||||||
@ -45,8 +46,7 @@ const YOUTUBE_REGEX = new RegExp(
|
|||||||
export class TimelineReader {
|
export class TimelineReader {
|
||||||
private static _instance: TimelineReader;
|
private static _instance: TimelineReader;
|
||||||
private lastPosts: string[] = [];
|
private lastPosts: string[] = [];
|
||||||
private youtubePlaylistAdder: YoutubePlaylistAdder;
|
private playlistAdders: PlaylistAdder[];
|
||||||
private spotifyPlaylistAdder: SpotifyPlaylistAdder;
|
|
||||||
|
|
||||||
private static async isMusicVideo(videoId: string) {
|
private static async isMusicVideo(videoId: string) {
|
||||||
if (!YOUTUBE_API_KEY || YOUTUBE_API_KEY === 'CHANGE_ME') {
|
if (!YOUTUBE_API_KEY || YOUTUBE_API_KEY === 'CHANGE_ME') {
|
||||||
@ -190,86 +190,10 @@ export class TimelineReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
private async addToYoutubePlaylist(song: SongInfo) {
|
|
||||||
log.debug('addToYoutubePlaylist');
|
|
||||||
let token: OauthResponse;
|
|
||||||
try {
|
|
||||||
const youtube_token_file = await fs.readFile('yt_auth_token', { encoding: 'utf8' });
|
|
||||||
token = JSON.parse(youtube_token_file);
|
|
||||||
log.debug('read youtube access token', token);
|
|
||||||
} catch (e) {
|
|
||||||
log.error('Could not read youtube access token', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!YOUTUBE_PLAYLIST_ID || YOUTUBE_PLAYLIST_ID === 'CHANGE_ME') {
|
|
||||||
log.debug('no playlist ID configured');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!song.youtubeUrl) {
|
|
||||||
log.debug('Skip adding song to YT playlist, no youtube Url', song);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const songUrl = new URL(song.youtubeUrl);
|
|
||||||
const youtubeId = songUrl.searchParams.get('v');
|
|
||||||
if (!youtubeId) {
|
|
||||||
log.debug(
|
|
||||||
'Skip adding song to YT playlist, could not extract YT id from URL',
|
|
||||||
song.youtubeUrl
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.debug('Found YT id from URL', song.youtubeUrl, youtubeId);
|
|
||||||
|
|
||||||
const playlistItemsUrl = new URL('https://www.googleapis.com/youtube/v3/playlistItems');
|
|
||||||
playlistItemsUrl.searchParams.append('videoId', youtubeId);
|
|
||||||
playlistItemsUrl.searchParams.append('playlistId', YOUTUBE_PLAYLIST_ID);
|
|
||||||
playlistItemsUrl.searchParams.append('part', 'id');
|
|
||||||
const existingPlaylistItem = await fetch(
|
|
||||||
'https://www.googleapis.com/youtube/v3/playlistItems',
|
|
||||||
{
|
|
||||||
headers: { Authorization: `${token.token_type} ${token.access_token}` }
|
|
||||||
}
|
|
||||||
).then((r) => r.json());
|
|
||||||
log.debug('existingPlaylistItem', existingPlaylistItem);
|
|
||||||
if (existingPlaylistItem.pageInfo && existingPlaylistItem.pageInfo.totalResults > 0) {
|
|
||||||
log.info('Item already in playlist');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchParams = new URLSearchParams([
|
|
||||||
['part', 'snippet']
|
|
||||||
//['key', token.access_token]
|
|
||||||
]);
|
|
||||||
const options: RequestInit = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { Authorization: `${token.token_type} ${token.access_token}` },
|
|
||||||
body: JSON.stringify({
|
|
||||||
snippet: {
|
|
||||||
playlistId: YOUTUBE_PLAYLIST_ID,
|
|
||||||
resourceId: {
|
|
||||||
videoId: youtubeId,
|
|
||||||
kind: 'youtube#video'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
const youtubeApiUrl = new URL(
|
|
||||||
`https://www.googleapis.com/youtube/v3/playlistItems?${searchParams}`
|
|
||||||
);
|
|
||||||
const resp = await fetch(youtubeApiUrl, options);
|
|
||||||
const respObj = await resp.json();
|
|
||||||
log.debug('Added to playlist', options, respObj);
|
|
||||||
if (respObj.error) {
|
|
||||||
log.debug('Add to playlist failed', respObj.error.errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
private async addToPlaylist(song: SongInfo) {
|
private async addToPlaylist(song: SongInfo) {
|
||||||
await this.youtubePlaylistAdder.addToPlaylist(song);
|
for (let adder of this.playlistAdders) {
|
||||||
await this.spotifyPlaylistAdder.addToPlaylist(song);
|
await adder.addToPlaylist(song);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async resizeAvatar(
|
private static async resizeAvatar(
|
||||||
@ -554,8 +478,7 @@ export class TimelineReader {
|
|||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
log.log('Constructing timeline object');
|
log.log('Constructing timeline object');
|
||||||
this.youtubePlaylistAdder = new YoutubePlaylistAdder();
|
this.playlistAdders = [new YoutubePlaylistAdder(), new SpotifyPlaylistAdder()];
|
||||||
this.spotifyPlaylistAdder = new SpotifyPlaylistAdder();
|
|
||||||
this.startWebsocket();
|
this.startWebsocket();
|
||||||
|
|
||||||
this.loadPostsSinceLastRun()
|
this.loadPostsSinceLastRun()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { log } from '$lib/log';
|
import { log } from '$lib/log';
|
||||||
import { SpotifyPlaylistAdder } from '$lib/server/spotifyPlaylistAdder';
|
import { SpotifyPlaylistAdder } from '$lib/server/playlist/spotifyPlaylistAdder';
|
||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { log } from '$lib/log';
|
import { log } from '$lib/log';
|
||||||
import { YoutubePlaylistAdder } from '$lib/server/ytPlaylistAdder';
|
import { YoutubePlaylistAdder } from '$lib/server/playlist/ytPlaylistAdder';
|
||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user