17/06/2024
# Python backend project for kivy,kivymd YouTube downloader
#
import re
from kivy.clock import mainthread
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.properties import StringProperty, ListProperty, BooleanProperty, ObjectProperty
from kivymd.uix.screen import MDScreen
from kivymd.uix.boxlayout import MDBoxLayout
import datetime
from kivy.config import Config
import threading
from kivymd.toast import toast
from kivymd.uix.dialog import MDDialog
from hurry.filesize import size
from kivymd.uix.button import MDFlatButton
from pytube import YouTube,exceptions
from pathlib import Path
from kivy import platform
from kivy.clock import mainthread
from jnius import autoclass
Config.set('kivy', 'window_icon', 'assets/.ico')
class ContentNavigationDrawer(MDBoxLayout):
pass
()
class HomeScreen(MDScreen):
def __init__(self, **kwargs):
print("ClassA init")
super(HomeScreen, self).__init__(**kwargs)
# =================================yOUTUBE CLASS ==================
class YoutubeDownloader(MDScreen):
yt = ObjectProperty()
title = StringProperty('Loading')
thumbnail = StringProperty()
resolution = StringProperty('Loading')
link = StringProperty()
download_icon = StringProperty('download')
length = StringProperty('Loading')
file_size = StringProperty('Loading')
download = BooleanProperty(False)
downloading = BooleanProperty(False)
isNoTDownloadable = BooleanProperty(True)
def __init__(self, **kwargs):
super(YoutubeDownloader, self).__init__(**kwargs)
def completed_function(self, stream,file_path):
# toast("Download Completes.")
print("complete")
self.ids.progress_bar.value = 0
self.ids.downloading.text = file_path
def progress_func(self, stream, chunk, bytes_remaining):
# value = round((1 - bytes_remaining / stream.filesize) * 100, 3)
total_size = stream.filesize
byte_download = total_size - bytes_remaining
percentage_complete = byte_download / total_size * 100
self.ids.progress_bar.value = percentage_complete
self.ids.downloading.text = (str(int(percentage_complete)) + "%")
def go(self):
app = MDApp.get_running_app()
app.isLoading = True
threading.Thread(target=self.start).start()
def start(self):
self.ids.progress_bar.value = 0
self.ids.download_button.disabled = True
self.link = self.ids.get_url_youtube.text
self.ids.title_get.text = "Title: Loading"
self.ids.resolution_get.text = "Resolution: Loading"
self.ids.length.text = "Lenght: Loading"
self.ids.total_size.text = "File Size: Loading"
try:
self.youtube_regex = (r'(https?://)?(www.)?'
'(youtube|youtu|youtube-nocookie)\.(com|be)/'
'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
# Compile the regex pattern
self.youtube_pattern = re.compile(self.youtube_regex)
# Check if the URL matches the pattern
if self.youtube_pattern.match(self.link):
try:
self.yt = YouTube(
self.link,
on_complete_callback=self.progress_func,
on_progress_callback=self.completed_function
)
self.title = self.yt.title
self.thumbnail = str(self.yt.thumbnail_url)
self.resolution = str(self.yt.streams.get_highest_resolution().resolution)
self.length = str(datetime.timedelta(seconds=self.yt.length))
self.file_size = size(self.yt.streams.get_highest_resolution().filesize)
self.ids.download_button.disabled = False
self.ids.thumbnail_image.source = self.thumbnail
self.ids.title_get.text = "Title: " + self.title
self.ids.resolution_get.text = "Resolution: " + self.resolution
self.ids.length.text = "Lenght: " + self.length
self.ids.total_size.text = "File Size: " + self.file_size
except exceptions.PytubeError as e:
toast(str(e))
else:
toast("AngaoBa URL Link Lalene.")
except Exception as e:
app = MDApp.get_running_app()
app.isLoading = False
self.ids.downloading.text = e
toast(text=f'{e}')
def download_command(self):
yt = self.yt
threading.Thread(target=self.download_video, args=(yt,)).start()
def download_video(self, yt):
self.downloading = True
app = MDApp.get_running_app()
try:
yt.streams.get_highest_resolution().download(output_path=app.output_path,skip_existing=False)
except Exception as e:
app = MDApp.get_running_app()
app.isLoading = False
toast(text=f'{e}')
# ++++==============================YOUTUBE END CLASSS ====================== #
# ================aPP MAIN CLASS ============================
class MainApp(MDApp):
isLoading = BooleanProperty(False)
icon = 'logo/download.ico'
if platform == 'win':
output_path = f'{str(Path.home() / "Downloads")}/Youtube Downloader/'
elif platform == 'android':
from android.storage import primary_external_storage_path
output_path = f'{str(primary_external_storage_path())}/Youtube Downloader/'
# Replace with your desired download location
def build(self):
self.title = 'Youtube Downloader'
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "Orange"
self.theme_cls.accent_palette = "Orange"
if platform == 'android':
from android.permissions import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE])
if platform == 'win':
pass
elif platform == 'android':
from android.permission import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE])
return Builder.load_string(KV)
def AppEXIT(self):
self.dialog = MDDialog(text="Are you sure you want to exit?",
buttons=[MDFlatButton(text="CANCEL", on_release=self.close_dialog),
MDFlatButton(text="EXIT", on_release=self.exit_app), ], )
self.dialog.open()
def close_dialog(self, *args):
self.dialog.dismiss()
def exit_app(self, *args):
self.dialog.dismiss()
MDApp.get_running_app().stop()
def re1(self, e):
print(e)
def switch_screen(self, screen_name):
self.root.ids.screen_manager.current = screen_name
self.root.ids.nav_drawer.set_state("close")
if __name__ == '__main__':
MainApp().run()