Better YouTube integration

This commit is contained in:
jeffser 2024-06-26 14:26:41 -06:00
parent f150aa24ab
commit bd146bdfb3
3 changed files with 36 additions and 35 deletions

View File

@ -1,6 +1,8 @@
# dialogs.py # dialogs.py
from gi.repository import Adw, Gtk, Gdk, GLib, GtkSource, Gio, GdkPixbuf from gi.repository import Adw, Gtk, Gdk, GLib, GtkSource, Gio, GdkPixbuf
import os
from pytube import YouTube
# CLEAR CHAT | WORKS # CLEAR CHAT | WORKS
@ -269,9 +271,22 @@ def youtube_caption_response(self, dialog, task, video_url, caption_drop_down):
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False).replace(video_url, "") text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False).replace(video_url, "")
buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
buffer.insert(buffer.get_start_iter(), text, len(text)) buffer.insert(buffer.get_start_iter(), text, len(text))
self.attach_file("{}&caption_lang={}".format(video_url, caption_drop_down.get_selected_item().get_string().split(' | ')[1]), 'youtube')
def youtube_caption(self, video_title, video_url, captions): yt = YouTube(video_url)
text = "{}\n{}\n{}\n\n".format(yt.title, yt.author, yt.watch_url)
for event in yt.captions[caption_drop_down.get_selected_item().get_string().split(' | ')[1]].json_captions['events']:
text += "{}\n".format(event['segs'][0]['utf8'].replace('\n', '\\n'))
if not os.path.exists('/tmp/alpaca/youtube'):
os.makedirs('/tmp/alpaca/youtube')
file_path = os.path.join('/tmp/alpaca/youtube', self.generate_numbered_name(yt.title, os.listdir('/tmp/alpaca/youtube')))
with open(file_path, 'w+') as f:
f.write(text)
self.attach_file(file_path, 'youtube')
def youtube_caption(self, video_url):
yt = YouTube(video_url)
video_title = yt.title
captions = yt.captions
if len(captions) == 0: if len(captions) == 0:
self.show_toast("error", 9, self.main_overlay) self.show_toast("error", 9, self.main_overlay)
return return

View File

@ -22,7 +22,6 @@ gi.require_version('GtkSource', '5')
gi.require_version('GdkPixbuf', '2.0') gi.require_version('GdkPixbuf', '2.0')
from gi.repository import Adw, Gtk, Gdk, GLib, GtkSource, Gio, GdkPixbuf from gi.repository import Adw, Gtk, Gdk, GLib, GtkSource, Gio, GdkPixbuf
import json, requests, threading, os, re, base64, sys, gettext, locale, webbrowser, subprocess, uuid, shutil, tarfile, tempfile #, docx import json, requests, threading, os, re, base64, sys, gettext, locale, webbrowser, subprocess, uuid, shutil, tarfile, tempfile #, docx
from pytube import YouTube
from time import sleep from time import sleep
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image
@ -191,14 +190,10 @@ class AlpacaWindow(Adw.ApplicationWindow):
for name, content in self.attachments.items(): for name, content in self.attachments.items():
if content["type"] == 'image' and can_use_images: attached_images.append(name) if content["type"] == 'image' and can_use_images: attached_images.append(name)
else: else:
if content["type"] == 'youtube': attached_files[name] = content['type']
attached_files[content['path']] = content['type']
else:
attached_files[name] = content['type']
if not os.path.exists(os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id)): if not os.path.exists(os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id)):
os.makedirs(os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id)) os.makedirs(os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id))
if content["type"] != 'youtube': shutil.copy(content['path'], os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name))
shutil.copy(content['path'], os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name))
content["button"].get_parent().remove(content["button"]) content["button"].get_parent().remove(content["button"])
self.attachments = {} self.attachments = {}
self.attachment_box.set_visible(False) self.attachment_box.set_visible(False)
@ -438,7 +433,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
buffer.insert(buffer.get_start_iter(), content, len(content)) buffer.insert(buffer.get_start_iter(), content, len(content))
if file_type == 'youtube': if file_type == 'youtube':
self.file_preview_dialog.set_title(YouTube(file_path).title) self.file_preview_dialog.set_title(content.split('\n')[0])
else: else:
self.file_preview_dialog.set_title(os.path.basename(file_path)) self.file_preview_dialog.set_title(os.path.basename(file_path))
self.file_preview_dialog.present(self) self.file_preview_dialog.present(self)
@ -451,10 +446,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
del new_message['files'] del new_message['files']
new_message['content'] = '' new_message['content'] = ''
for name, file_type in message['files'].items(): for name, file_type in message['files'].items():
if file_type == 'youtube': file_path = os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name)
file_path = name
else:
file_path = os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name)
file_data = self.get_content_of_file(file_path, file_type) file_data = self.get_content_of_file(file_path, file_type)
if file_data: new_message['content'] += f"```[{name}]\n{file_data}\n```" if file_data: new_message['content'] += f"```[{name}]\n{file_data}\n```"
new_message['content'] += message['content'] new_message['content'] += message['content']
@ -554,8 +546,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
) )
for name, file_type in files.items(): for name, file_type in files.items():
if file_type == 'youtube': if file_type == 'youtube':
yt = YouTube(name) shown_name=name[:20] + (name[20:] and '..')
shown_name=yt.title[:20] + (yt.title[20:] and '..')
else: else:
shown_name='.'.join(name.split(".")[:-1])[:20] + (name[20:] and '..') + f".{name.split('.')[-1]}" shown_name='.'.join(name.split(".")[:-1])[:20] + (name[20:] and '..') + f".{name.split('.')[-1]}"
@ -568,13 +559,10 @@ class AlpacaWindow(Adw.ApplicationWindow):
valign=3, valign=3,
name=name, name=name,
css_classes=["flat"], css_classes=["flat"],
tooltip_text=name if file_type != 'youtube' else yt.title, tooltip_text=name,
child=button_content child=button_content
) )
if file_type == 'youtube': file_path = os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name)
file_path = name
else:
file_path = os.path.join(self.data_dir, "chats", self.chats['selected_chat'], id, name)
button.connect("clicked", lambda button, file_path=file_path, file_type=file_type: self.preview_file(file_path, file_type)) button.connect("clicked", lambda button, file_path=file_path, file_type=file_type: self.preview_file(file_path, file_type))
file_container.append(button) file_container.append(button)
message_box.append(file_scroller) message_box.append(file_scroller)
@ -1174,7 +1162,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
self.verify_connection() self.verify_connection()
def get_content_of_file(self, file_path, file_type): def get_content_of_file(self, file_path, file_type):
if file_type != 'youtube' and not os.path.exists(file_path): return None if not os.path.exists(file_path): return None
if file_type == 'image': if file_type == 'image':
try: try:
with Image.open(file_path) as img: with Image.open(file_path) as img:
@ -1193,7 +1181,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
return base64.b64encode(image_data).decode("utf-8") return base64.b64encode(image_data).decode("utf-8")
except Exception as e: except Exception as e:
self.show_toast("error", 5, self.main_overlay) self.show_toast("error", 5, self.main_overlay)
elif file_type == 'plain_text': elif file_type == 'plain_text' or file_type == 'youtube':
with open(file_path, 'r') as f: with open(file_path, 'r') as f:
return f.read() return f.read()
elif file_type == 'pdf': elif file_type == 'pdf':
@ -1203,12 +1191,6 @@ class AlpacaWindow(Adw.ApplicationWindow):
for i, page in enumerate(reader.pages): for i, page in enumerate(reader.pages):
text += f"\n- Page {i}\n{page.extract_text()}\n" text += f"\n- Page {i}\n{page.extract_text()}\n"
return text return text
elif file_type == 'youtube':
yt = YouTube(file_path)
text = "{}\n{}\n\n".format(yt.title, yt.author)
for event in yt.captions[file_path.split('&caption_lang=')[1]].json_captions['events']:
text += "{}\n".format(event['segs'][0]['utf8'].replace('\n', '\\n'))
return text
#elif file_type == 'docx': #elif file_type == 'docx':
#document = docx.Document(file_path) #document = docx.Document(file_path)
#if len(document.paragraphs) == 0: return None #if len(document.paragraphs) == 0: return None
@ -1223,10 +1205,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
if len(self.attachments) == 0: self.attachment_box.set_visible(False) if len(self.attachments) == 0: self.attachment_box.set_visible(False)
def attach_file(self, file_path, file_type): def attach_file(self, file_path, file_type):
if file_type == "youtube": name = self.generate_numbered_name(os.path.basename(file_path), self.attachments.keys())
name = YouTube(file_path).title
else:
name = self.generate_numbered_name(os.path.basename(file_path), self.attachments.keys())
content = self.get_content_of_file(file_path, file_type) content = self.get_content_of_file(file_path, file_type)
if content: if content:
if file_type == "youtube": if file_type == "youtube":
@ -1280,8 +1259,7 @@ class AlpacaWindow(Adw.ApplicationWindow):
r'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})') r'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
if youtube_regex.match(text): if youtube_regex.match(text):
try: try:
yt = YouTube(text) dialogs.youtube_caption(self, text)
dialogs.youtube_caption(self, yt.title, text, yt.captions)
except Exception as e: except Exception as e:
self.show_toast("error", 10, self.main_overlay) self.show_toast("error", 10, self.main_overlay)

View File

@ -698,8 +698,16 @@
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<property name="margin-start">12</property> <property name="margin-start">12</property>
<property name="margin-end">12</property> <property name="margin-end">12</property>
<style>
<class name="card" />
<class name="view" />
</style>
<child> <child>
<object class="GtkTextView" id="file_preview_text_view"> <object class="GtkTextView" id="file_preview_text_view">
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="hexpand">true</property> <property name="hexpand">true</property>
<property name="vexpand">true</property> <property name="vexpand">true</property>
<property name="editable">false</property> <property name="editable">false</property>