Refactor how youtube videos are handled, log errors via hook
This commit is contained in:
parent
2d5df49aa9
commit
f6ae387e49
@ -1,5 +1,5 @@
|
|||||||
HASHTAG_FILTER = ichlausche,music,musik,nowplaying,tunetuesday
|
HASHTAG_FILTER = ichlausche,music,musik,nowplaying,tunetuesday
|
||||||
URL_FILTER = song.link,album.link,youtube.com,youtu.be,spotify.com,music.apple.com,bandcamp.com
|
URL_FILTER = song.link,album.link,spotify.com,music.apple.com,bandcamp.com
|
||||||
YOUTUBE_API_KEY = CHANGE_ME
|
YOUTUBE_API_KEY = CHANGE_ME
|
||||||
VERBOSE = false
|
VERBOSE = false
|
||||||
|
|
||||||
|
12
src/hooks.server.ts
Normal file
12
src/hooks.server.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import type { HandleServerError } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const handleError = (({ error }) => {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.error('Something went wrong: ', error.name, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: 'Whoops!',
|
||||||
|
code: (error as any)?.code ?? 'UNKNOWN'
|
||||||
|
};
|
||||||
|
}) satisfies HandleServerError;
|
@ -3,7 +3,7 @@ import type { Post, Tag, TimelineEvent } from '$lib/mastodon/response';
|
|||||||
import { savePost } from '$lib/server/db';
|
import { savePost } from '$lib/server/db';
|
||||||
import { WebSocket } from "ws";
|
import { WebSocket } from "ws";
|
||||||
|
|
||||||
const YOUTUBE_REGEX = new RegExp('https?:\/\/(www\.)?youtu((be.com\/.*v=)|(\.be\/))(?<videoId>[a-zA-Z_0-9-]+)');
|
const YOUTUBE_REGEX = new RegExp(/https?:\/\/(www\.)?youtu((be.com\/.*v=)|(\.be\/))(?<videoId>[a-zA-Z_0-9-]+)/gm);
|
||||||
|
|
||||||
export class TimelineReader {
|
export class TimelineReader {
|
||||||
private static _instance: TimelineReader;
|
private static _instance: TimelineReader;
|
||||||
@ -16,10 +16,16 @@ export class TimelineReader {
|
|||||||
const youtubeVideoUrl = new URL(`https://www.googleapis.com/youtube/v3/videos?${searchParams}`);
|
const youtubeVideoUrl = new URL(`https://www.googleapis.com/youtube/v3/videos?${searchParams}`);
|
||||||
const resp = await fetch(youtubeVideoUrl);
|
const resp = await fetch(youtubeVideoUrl);
|
||||||
const respObj = await resp.json();
|
const respObj = await resp.json();
|
||||||
|
if (!respObj.items.length) {
|
||||||
|
console.warn('Could not find video with id', videoId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const item = respObj.items[0];
|
const item = respObj.items[0];
|
||||||
if (item.tags?.includes('music')) {
|
if (item.tags?.includes('music')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const categorySearchParams = new URLSearchParams([
|
const categorySearchParams = new URLSearchParams([
|
||||||
['part', 'snippet'],
|
['part', 'snippet'],
|
||||||
['id', item.categoryId],
|
['id', item.categoryId],
|
||||||
@ -29,8 +35,26 @@ export class TimelineReader {
|
|||||||
return categoryTitle === 'Music';
|
return categoryTitle === 'Music';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async checkYoutubeMatches(postContent: string): Promise<boolean> {
|
||||||
|
const matches = postContent.matchAll(YOUTUBE_REGEX);
|
||||||
|
for (let match of matches) {
|
||||||
|
if (match === undefined || match.groups === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const videoId = match.groups.videoId.toString();
|
||||||
|
try {
|
||||||
|
const isMusic = await TimelineReader.isMusicVideo(videoId);
|
||||||
|
if (isMusic) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Could not check if', videoId, 'is a music video', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
//const socket = new WebSocket("wss://metalhead.club/api/v1/streaming/public/local")
|
|
||||||
const socket = new WebSocket("wss://metalhead.club/api/v1/streaming")
|
const socket = new WebSocket("wss://metalhead.club/api/v1/streaming")
|
||||||
socket.onopen = (_event) => {
|
socket.onopen = (_event) => {
|
||||||
socket.send('{ "type": "subscribe", "stream": "public:local"}');
|
socket.send('{ "type": "subscribe", "stream": "public:local"}');
|
||||||
@ -48,33 +72,13 @@ export class TimelineReader {
|
|||||||
const urls: string[] = URL_FILTER.split(',');
|
const urls: string[] = URL_FILTER.split(',');
|
||||||
const found_urls = urls.filter(t => post.content.includes(t));
|
const found_urls = urls.filter(t => post.content.includes(t));
|
||||||
|
|
||||||
if (found_urls.length === 0 && found_tags.length === 0) {
|
// If we don't have any tags or non-youtube urls, check youtube
|
||||||
|
// YT is handled separately, because it requires an API call and therefore is slower
|
||||||
|
if (found_urls.length === 0 &&
|
||||||
|
found_tags.length === 0 &&
|
||||||
|
!await TimelineReader.checkYoutubeMatches(post.content)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const youtubeMatches = found_urls.map(u => u.match(YOUTUBE_REGEX)).filter(i => i !== null);
|
|
||||||
let hasMusicLink = false;
|
|
||||||
// Only check url if no tags are present and if no other matched URLs (e.g. to bandcamp) are found
|
|
||||||
if (found_tags.length === 0 && found_urls.length > 0 && youtubeMatches.length === found_urls.length) {
|
|
||||||
for (let match of youtubeMatches) {
|
|
||||||
if (match === null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const isMusic = await TimelineReader.isMusicVideo(match.groups?.videoId ?? '');
|
|
||||||
if (isMusic) {
|
|
||||||
hasMusicLink = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Could not check if', youtubeMatches, 'is a music video', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasMusicLink) {
|
|
||||||
console.info('Found youtube urls, but none is music', youtubeMatches);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
savePost(post);
|
savePost(post);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user