Better YouTube integration
This commit is contained in:
		
							parent
							
								
									f150aa24ab
								
							
						
					
					
						commit
						bd146bdfb3
					
				@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user