enh: youtube watch param support

This commit is contained in:
Timothy J. Baek 2024-10-07 18:19:13 -07:00
parent e7ae9a2107
commit f099b277c8
6 changed files with 159 additions and 73 deletions

View File

@ -824,6 +824,32 @@ class PipelineMiddleware(BaseHTTPMiddleware):
app.add_middleware(PipelineMiddleware)
from urllib.parse import urlencode, parse_qs, urlparse
class RedirectMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# Check if the request is a GET request
if request.method == "GET":
path = request.url.path
query_params = dict(parse_qs(urlparse(str(request.url)).query))
# Check for the specific watch path and the presence of 'v' parameter
if path.endswith("/watch") and "v" in query_params:
video_id = query_params["v"][0] # Extract the first 'v' parameter
encoded_video_id = urlencode({"youtube": video_id})
redirect_url = f"/?{encoded_video_id}"
return RedirectResponse(url=redirect_url)
# Proceed with the normal flow of other requests
response = await call_next(request)
return response
# Add the middleware to the app
app.add_middleware(RedirectMiddleware)
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGIN,
@ -2416,6 +2442,7 @@ async def healthcheck_with_db():
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
app.mount("/cache", StaticFiles(directory=CACHE_DIR), name="cache")
if os.path.exists(FRONTEND_BUILD_DIR):
mimetypes.add_type("text/javascript", ".js")
app.mount(

View File

@ -53,7 +53,7 @@
updateChatById
} from '$lib/apis/chats';
import { generateOpenAIChatCompletion } from '$lib/apis/openai';
import { processWebSearch } from '$lib/apis/retrieval';
import { processWeb, processWebSearch, processYoutubeVideo } from '$lib/apis/retrieval';
import { createOpenAITextStream } from '$lib/apis/streaming';
import { queryMemory } from '$lib/apis/memories';
import { getAndUpdateUserLocation, getUserSettings } from '$lib/apis/users';
@ -308,6 +308,74 @@
$socket?.off('chat-events');
});
// File upload functions
const uploadWeb = async (url) => {
console.log(url);
const fileItem = {
type: 'doc',
name: url,
collection_name: '',
status: 'uploading',
url: url,
error: ''
};
try {
files = [...files, fileItem];
const res = await processWeb(localStorage.token, '', url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(JSON.stringify(e));
}
};
const uploadYoutubeTranscription = async (url) => {
console.log(url);
const fileItem = {
type: 'doc',
name: url,
collection_name: '',
status: 'uploading',
context: 'full',
url: url,
error: ''
};
try {
files = [...files, fileItem];
const res = await processYoutubeVideo(localStorage.token, url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(e);
}
};
//////////////////////////
// Web functions
//////////////////////////
@ -348,6 +416,10 @@
selectedModels = [''];
}
if ($page.url.searchParams.get('youtube')) {
uploadYoutubeTranscription(`https://www.youtube.com/watch?v=NqxUExCZJ5Y`);
}
if ($page.url.searchParams.get('web-search') === 'true') {
webSearchEnabled = true;
}
@ -366,6 +438,11 @@
.filter((id) => id);
}
if ($page.url.searchParams.get('call') === 'true') {
showCallOverlay.set(true);
showControls.set(true);
}
if ($page.url.searchParams.get('q')) {
prompt = $page.url.searchParams.get('q') ?? '';
@ -375,11 +452,6 @@
}
}
if ($page.url.searchParams.get('call') === 'true') {
showCallOverlay.set(true);
showControls.set(true);
}
selectedModels = selectedModels.map((modelId) =>
$models.map((m) => m.id).includes(modelId) ? modelId : ''
);
@ -2060,6 +2132,15 @@
transparentBackground={$settings?.backgroundImageUrl ?? false}
{stopResponse}
{createMessagePair}
on:upload={async (e) => {
const { type, data } = e.detail;
if (type === 'web') {
await uploadWeb(data);
} else if (type === 'youtube') {
await uploadYoutubeTranscription(data);
}
}}
on:submit={async (e) => {
if (e.detail) {
prompt = '';
@ -2095,6 +2176,15 @@
transparentBackground={$settings?.backgroundImageUrl ?? false}
{stopResponse}
{createMessagePair}
on:upload={async (e) => {
const { type, data } = e.detail;
if (type === 'web') {
await uploadWeb(data);
} else if (type === 'youtube') {
await uploadYoutubeTranscription(data);
}
}}
on:submit={async (e) => {
if (e.detail) {
prompt = '';

View File

@ -300,6 +300,9 @@
bind:this={commandsElement}
bind:prompt
bind:files
on:upload={(e) => {
dispatch('upload', e.detail);
}}
on:select={(e) => {
const data = e.detail;

View File

@ -26,71 +26,6 @@
let command = '';
$: command = (prompt?.trim() ?? '').split(' ')?.at(-1) ?? '';
const uploadWeb = async (url) => {
console.log(url);
const fileItem = {
type: 'doc',
name: url,
collection_name: '',
status: 'uploading',
url: url,
error: ''
};
try {
files = [...files, fileItem];
const res = await processWeb(localStorage.token, '', url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(JSON.stringify(e));
}
};
const uploadYoutubeTranscription = async (url) => {
console.log(url);
const fileItem = {
type: 'doc',
name: url,
collection_name: '',
status: 'uploading',
url: url,
error: ''
};
try {
files = [...files, fileItem];
const res = await processYoutubeVideo(localStorage.token, url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(e);
}
};
</script>
{#if ['/', '#', '@'].includes(command?.charAt(0))}
@ -103,11 +38,17 @@
{command}
on:youtube={(e) => {
console.log(e);
uploadYoutubeTranscription(e.detail);
dispatch('upload', {
type: 'youtube',
data: e.detail
});
}}
on:url={(e) => {
console.log(e);
uploadWeb(e.detail);
dispatch('upload', {
type: 'web',
data: e.detail
});
}}
on:select={(e) => {
console.log(e);

View File

@ -204,6 +204,9 @@
{stopResponse}
{createMessagePair}
placeholder={$i18n.t('How can I help you today?')}
on:upload={(e) => {
dispatch('upload', e.detail);
}}
on:submit={(e) => {
dispatch('submit', e.detail);
}}

View File

@ -0,0 +1,22 @@
<script>
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
onMount(() => {
// Get the current URL search parameters
const params = new URLSearchParams(window.location.search);
// Check if 'v' parameter exists
if (params.has('v')) {
// Get the value of 'v' parameter
const videoId = params.get('v');
// Redirect to root with 'youtube' parameter
goto(`/?youtube=${encodeURIComponent(videoId)}`);
} else {
// Redirect to root if 'v' parameter doesn't exist
goto('/');
}
});
</script>