mirror of
https://github.com/open-webui/open-webui
synced 2025-05-13 18:13:35 +00:00
enh: youtube watch param support
This commit is contained in:
parent
e7ae9a2107
commit
f099b277c8
@ -824,6 +824,32 @@ class PipelineMiddleware(BaseHTTPMiddleware):
|
|||||||
app.add_middleware(PipelineMiddleware)
|
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(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=CORS_ALLOW_ORIGIN,
|
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("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
||||||
app.mount("/cache", StaticFiles(directory=CACHE_DIR), name="cache")
|
app.mount("/cache", StaticFiles(directory=CACHE_DIR), name="cache")
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists(FRONTEND_BUILD_DIR):
|
if os.path.exists(FRONTEND_BUILD_DIR):
|
||||||
mimetypes.add_type("text/javascript", ".js")
|
mimetypes.add_type("text/javascript", ".js")
|
||||||
app.mount(
|
app.mount(
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
updateChatById
|
updateChatById
|
||||||
} from '$lib/apis/chats';
|
} from '$lib/apis/chats';
|
||||||
import { generateOpenAIChatCompletion } from '$lib/apis/openai';
|
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 { createOpenAITextStream } from '$lib/apis/streaming';
|
||||||
import { queryMemory } from '$lib/apis/memories';
|
import { queryMemory } from '$lib/apis/memories';
|
||||||
import { getAndUpdateUserLocation, getUserSettings } from '$lib/apis/users';
|
import { getAndUpdateUserLocation, getUserSettings } from '$lib/apis/users';
|
||||||
@ -308,6 +308,74 @@
|
|||||||
$socket?.off('chat-events');
|
$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
|
// Web functions
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
@ -348,6 +416,10 @@
|
|||||||
selectedModels = [''];
|
selectedModels = [''];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($page.url.searchParams.get('youtube')) {
|
||||||
|
uploadYoutubeTranscription(`https://www.youtube.com/watch?v=NqxUExCZJ5Y`);
|
||||||
|
}
|
||||||
|
|
||||||
if ($page.url.searchParams.get('web-search') === 'true') {
|
if ($page.url.searchParams.get('web-search') === 'true') {
|
||||||
webSearchEnabled = true;
|
webSearchEnabled = true;
|
||||||
}
|
}
|
||||||
@ -366,6 +438,11 @@
|
|||||||
.filter((id) => id);
|
.filter((id) => id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($page.url.searchParams.get('call') === 'true') {
|
||||||
|
showCallOverlay.set(true);
|
||||||
|
showControls.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ($page.url.searchParams.get('q')) {
|
if ($page.url.searchParams.get('q')) {
|
||||||
prompt = $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) =>
|
selectedModels = selectedModels.map((modelId) =>
|
||||||
$models.map((m) => m.id).includes(modelId) ? modelId : ''
|
$models.map((m) => m.id).includes(modelId) ? modelId : ''
|
||||||
);
|
);
|
||||||
@ -2060,6 +2132,15 @@
|
|||||||
transparentBackground={$settings?.backgroundImageUrl ?? false}
|
transparentBackground={$settings?.backgroundImageUrl ?? false}
|
||||||
{stopResponse}
|
{stopResponse}
|
||||||
{createMessagePair}
|
{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) => {
|
on:submit={async (e) => {
|
||||||
if (e.detail) {
|
if (e.detail) {
|
||||||
prompt = '';
|
prompt = '';
|
||||||
@ -2095,6 +2176,15 @@
|
|||||||
transparentBackground={$settings?.backgroundImageUrl ?? false}
|
transparentBackground={$settings?.backgroundImageUrl ?? false}
|
||||||
{stopResponse}
|
{stopResponse}
|
||||||
{createMessagePair}
|
{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) => {
|
on:submit={async (e) => {
|
||||||
if (e.detail) {
|
if (e.detail) {
|
||||||
prompt = '';
|
prompt = '';
|
||||||
|
@ -300,6 +300,9 @@
|
|||||||
bind:this={commandsElement}
|
bind:this={commandsElement}
|
||||||
bind:prompt
|
bind:prompt
|
||||||
bind:files
|
bind:files
|
||||||
|
on:upload={(e) => {
|
||||||
|
dispatch('upload', e.detail);
|
||||||
|
}}
|
||||||
on:select={(e) => {
|
on:select={(e) => {
|
||||||
const data = e.detail;
|
const data = e.detail;
|
||||||
|
|
||||||
|
@ -26,71 +26,6 @@
|
|||||||
|
|
||||||
let command = '';
|
let command = '';
|
||||||
$: command = (prompt?.trim() ?? '').split(' ')?.at(-1) ?? '';
|
$: 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>
|
</script>
|
||||||
|
|
||||||
{#if ['/', '#', '@'].includes(command?.charAt(0))}
|
{#if ['/', '#', '@'].includes(command?.charAt(0))}
|
||||||
@ -103,11 +38,17 @@
|
|||||||
{command}
|
{command}
|
||||||
on:youtube={(e) => {
|
on:youtube={(e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
uploadYoutubeTranscription(e.detail);
|
dispatch('upload', {
|
||||||
|
type: 'youtube',
|
||||||
|
data: e.detail
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
on:url={(e) => {
|
on:url={(e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
uploadWeb(e.detail);
|
dispatch('upload', {
|
||||||
|
type: 'web',
|
||||||
|
data: e.detail
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
on:select={(e) => {
|
on:select={(e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
@ -204,6 +204,9 @@
|
|||||||
{stopResponse}
|
{stopResponse}
|
||||||
{createMessagePair}
|
{createMessagePair}
|
||||||
placeholder={$i18n.t('How can I help you today?')}
|
placeholder={$i18n.t('How can I help you today?')}
|
||||||
|
on:upload={(e) => {
|
||||||
|
dispatch('upload', e.detail);
|
||||||
|
}}
|
||||||
on:submit={(e) => {
|
on:submit={(e) => {
|
||||||
dispatch('submit', e.detail);
|
dispatch('submit', e.detail);
|
||||||
}}
|
}}
|
||||||
|
22
src/routes/watch/+page.svelte
Normal file
22
src/routes/watch/+page.svelte
Normal 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>
|
Loading…
Reference in New Issue
Block a user