shell cleanup/reordering
This commit is contained in:
		
							
								
								
									
										213
									
								
								src/Python/Scripts/GTK/edit-path
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										213
									
								
								src/Python/Scripts/GTK/edit-path
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,213 @@ | ||||
| #!/usr/sbin/python | ||||
|  | ||||
| # GTK Imports | ||||
| import gi, faulthandler, signal | ||||
| gi.require_version('Gtk', '3.0') | ||||
|  | ||||
| from gi.repository import Gtk | ||||
| from gi.repository import GLib | ||||
|  | ||||
|  | ||||
| # Python Imports | ||||
| import os, threading, time | ||||
|  | ||||
| from setproctitle import setproctitle | ||||
|  | ||||
|  | ||||
|  | ||||
| app_name = "PATH Edit Tool" | ||||
|  | ||||
|  | ||||
|  | ||||
| def threaded(fn): | ||||
|     def wrapper(*args, **kwargs): | ||||
|         threading.Thread(target=fn, args=args, kwargs=kwargs).start() | ||||
|     return wrapper | ||||
|  | ||||
|  | ||||
| class Main(Gtk.Window): | ||||
|     def __init__(self): | ||||
|         super(Main, self).__init__() | ||||
|         self._USER_HOME    = os.path.expanduser('~') | ||||
|         PREFERED_BASH_PATH = f"{self._USER_HOME}/.bash_paths" | ||||
|  | ||||
|         icon_size           = 16 | ||||
|         box                 = Gtk.Box() | ||||
|         box2                = Gtk.Box() | ||||
|         separator           = Gtk.Separator() | ||||
|         self._insert_entry  = Gtk.Entry() | ||||
|         self.message_widget = Gtk.Popover.new(separator) | ||||
|         self.message_label  = Gtk.Label() | ||||
|         add_button          = Gtk.Button.new_from_icon_name("gtk-add", icon_size) | ||||
|         delete_button       = Gtk.Button.new_from_icon_name("gtk-delete", icon_size) | ||||
|         save_button         = Gtk.Button.new_from_icon_name("gtk-save", icon_size) | ||||
|  | ||||
|         scroll_vw, grid, self.store = self._create_treeview_widget(title="PATHs") | ||||
|         tree_selection     = grid.get_selection() | ||||
|  | ||||
|         box2.add(self._insert_entry) | ||||
|         box2.add(add_button) | ||||
|         box2.add(delete_button) | ||||
|  | ||||
|         box.add(separator) | ||||
|         box.add(scroll_vw) | ||||
|         box.add(box2) | ||||
|         box.add(save_button) | ||||
|  | ||||
|         self.message_widget.add(self.message_label) | ||||
|         self.add(box) | ||||
|         self.add(self.message_widget) | ||||
|  | ||||
|         self.message_widget.set_default_widget(self.message_label) | ||||
|         self._insert_entry.set_hexpand(True) | ||||
|         self._insert_entry.set_placeholder_text("Path...") | ||||
|         save_button.set_label("Save") | ||||
|         scroll_vw.set_vexpand(True) | ||||
|         box.set_orientation(1) | ||||
|         box.set_vexpand(True) | ||||
|         self.set_default_size(480, 560) | ||||
|         self.set_title(f"{app_name}") | ||||
|         self.set_icon_name("applications-accessories") | ||||
|  | ||||
|         add_button.connect("clicked", self.add_entry) | ||||
|         delete_button.connect("clicked", self.delete_entry) | ||||
|         save_button.connect("clicked", self.save_enteries) | ||||
|         tree_selection.connect("changed", self._set_selected) | ||||
|  | ||||
|         self.connect("delete-event", Gtk.main_quit) | ||||
|         GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit) | ||||
|  | ||||
|         self.success       = "#88cc27" | ||||
|         self.warning       = "#ffa800" | ||||
|         self.error         = "#ff0000" | ||||
|         self.selected      = None | ||||
|  | ||||
|         if os.path.isfile(PREFERED_BASH_PATH): | ||||
|             self.bashrc_path = PREFERED_BASH_PATH | ||||
|         else: | ||||
|             self.bashrc_path = f"{self._USER_HOME}/.bashrc" | ||||
|  | ||||
|         self._load_paths_data() | ||||
|  | ||||
|         self.message_widget.show_all() | ||||
|         self.message_widget.popdown() | ||||
|         box.show_all() | ||||
|         box2.show_all() | ||||
|         self.show_all() | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     def add_entry(self, widget): | ||||
|         path = self._insert_entry.get_text().strip() | ||||
|  | ||||
|         if os.path.isdir(path): | ||||
|             self.store.append([path]) | ||||
|         else: | ||||
|             self.display_message(self.warning, "Not a directory!") | ||||
|  | ||||
|     def delete_entry(self, widget): | ||||
|         self.store.remove(self.selected) | ||||
|  | ||||
|     def save_enteries(self, widget): | ||||
|         try: | ||||
|             paths = list() | ||||
|             iter  = self.store.get_iter_first() | ||||
|             while iter != None: | ||||
|                 pth = self.store.get_value(iter, 0) | ||||
|                 pth = pth.replace(self._USER_HOME, "$HOME") | ||||
|                 paths.append(pth) | ||||
|                 iter = self.store.iter_next(iter) | ||||
|  | ||||
|  | ||||
|             toExport = "export PATH=\"" + ':'.join(paths) + "\"\n\n" | ||||
|             file     = open(self.bashrc_path, mode='r') | ||||
|             for line in file: | ||||
|                 if "export PATH=" in line: | ||||
|                     continue | ||||
|                 else: | ||||
|                     toExport += line | ||||
|  | ||||
|             file.close() | ||||
|             file = open(self.bashrc_path, mode='w') | ||||
|             file.write(toExport) | ||||
|             file.close() | ||||
|             self.display_message(self.success, "Successfully saved file!") | ||||
|         except Exception as e: | ||||
|             self.display_message(self.error, "Opening/Writing to file failed!") | ||||
|             print("Opening/Writing to file failed with the following:\n\n") | ||||
|             print(e) | ||||
|  | ||||
|  | ||||
|     def _set_selected(self, user_data): | ||||
|         selected = user_data.get_selected()[1] | ||||
|         if selected: | ||||
|             self.selected = selected | ||||
|  | ||||
|     def _load_paths_data(self): | ||||
|         PATH_str = os.getenv("PATH") | ||||
|  | ||||
|         # If path exists in bashrc replace default selection... | ||||
|         file = open(self.bashrc_path, mode='r') | ||||
|         for line in file: | ||||
|             if "export PATH=" in line: | ||||
|                 part     = line.replace("export PATH=", "") | ||||
|                 cleaned  = part.replace("\"", "") | ||||
|                 PATH_str = cleaned.strip() | ||||
|  | ||||
|         # Split string into list/tuple and add parts to store | ||||
|         paths = PATH_str.split(":") | ||||
|         for path in paths: | ||||
|             self.store.append([path]) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     def display_message(self, type, text): | ||||
|         markup = f"<span foreground='{type}'>{text}</span>" | ||||
|         self.message_label.set_markup(markup) | ||||
|         self.message_widget.popup() | ||||
|         self.hide_message_timed() | ||||
|  | ||||
|     @threaded | ||||
|     def hide_message_timed(self): | ||||
|         time.sleep(3) | ||||
|         GLib.idle_add(self.message_widget.popdown) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     def _create_treeview_widget(self, title = "Not Set"): | ||||
|         scroll = Gtk.ScrolledWindow() | ||||
|         grid   = Gtk.TreeView() | ||||
|         store  = Gtk.ListStore(str) | ||||
|         column = Gtk.TreeViewColumn(title) | ||||
|         name   = Gtk.CellRendererText() | ||||
|         selec  = grid.get_selection() | ||||
|  | ||||
|         grid.set_model(store) | ||||
|         selec.set_mode(2) | ||||
|  | ||||
|         column.pack_start(name, True) | ||||
|         column.add_attribute(name, "text", 0) | ||||
|         column.set_expand(False) | ||||
|  | ||||
|         grid.append_column(column) | ||||
|         grid.set_search_column(0) | ||||
|         grid.set_headers_visible(True) | ||||
|         grid.set_enable_tree_lines(False) | ||||
|  | ||||
|         grid.show_all() | ||||
|         scroll.add(grid) | ||||
|         grid.columns_autosize() | ||||
|         return scroll, grid, store | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     faulthandler.enable()  # For better debug info | ||||
|     setproctitle(f"{app_name}") | ||||
|  | ||||
|     main = Main() | ||||
|     Gtk.main() | ||||
| @@ -1,151 +0,0 @@ | ||||
| #!/usr/bin/python3 | ||||
|  | ||||
| # GTK Imports | ||||
| import gi, faulthandler, signal | ||||
| gi.require_version('Gtk', '3.0') | ||||
|  | ||||
| from gi.repository import Gtk as gtk | ||||
| from gi.repository import GLib | ||||
|  | ||||
|  | ||||
| # Python Imports | ||||
| import os, threading, time | ||||
|  | ||||
| from setproctitle import setproctitle | ||||
|  | ||||
|  | ||||
| def threaded(fn): | ||||
|     def wrapper(*args, **kwargs): | ||||
|         threading.Thread(target=fn, args=args, kwargs=kwargs).start() | ||||
|  | ||||
|     return wrapper | ||||
|  | ||||
|  | ||||
|  | ||||
| class Main: | ||||
|     def __init__(self): | ||||
|         setproctitle('PATH Edit Tool') | ||||
|         GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit) | ||||
|         faulthandler.enable()  # For better debug info | ||||
|  | ||||
|         self.HOME          = os.path.expanduser('~') | ||||
|         PREFERED_BASH_PATH = self.HOME + "/" + ".bash_paths" | ||||
|         SCRIPT_PTH         = os.path.dirname(os.path.realpath(__file__)) + "/" | ||||
|         GLADE_FILE         = "main.glade" | ||||
|  | ||||
|         self.builder = gtk.Builder() | ||||
|         self.builder.add_from_file(SCRIPT_PTH + GLADE_FILE) | ||||
|         self.builder.connect_signals(self) | ||||
|  | ||||
|         self.pathTreeView  = self.builder.get_object("pathTreeView") | ||||
|         self.messageWidget = self.builder.get_object("messageWidget") | ||||
|         self.messageLabel  = self.builder.get_object("messageLabel") | ||||
|  | ||||
|         self.pathListStore = gtk.ListStore(str) | ||||
|         self.success       = "#88cc27" | ||||
|         self.warning       = "#ffa800" | ||||
|         self.error         = "#ff0000" | ||||
|         self.selected      = None | ||||
|         self.bashrcPath    = "" | ||||
|  | ||||
|         if os.path.isfile(PREFERED_BASH_PATH): | ||||
|             self.bashrcPath = PREFERED_BASH_PATH | ||||
|         else: | ||||
|             self.bashrcPath = self.HOME + "/" + ".bashrc" | ||||
|  | ||||
|         self.setupTreeview() | ||||
|         self.loadPaths() | ||||
|  | ||||
|         window = self.builder.get_object("Main_Window") | ||||
|         window.connect("delete-event", gtk.main_quit) | ||||
|         window.show() | ||||
|  | ||||
|  | ||||
|  | ||||
|     def addEntry(self, widget): | ||||
|         toAddPathTxt = self.builder.get_object("toAddPathEntry").get_text().strip() | ||||
|  | ||||
|         if os.path.isdir(toAddPathTxt): | ||||
|             self.pathListStore.append([toAddPathTxt]) | ||||
|         else: | ||||
|             self.displayMessage(self.warning, "Not a directory!") | ||||
|  | ||||
|     def deleteEntry(self, widget): | ||||
|         self.pathListStore.remove(self.selected) | ||||
|  | ||||
|     def saveToBashrc(self, widget): | ||||
|         try: | ||||
|             paths = list() | ||||
|             iter  = self.pathListStore.get_iter_first() | ||||
|             while iter != None: | ||||
|                 pth = self.pathListStore.get_value(iter, 0) | ||||
|                 pth = pth.replace(self.HOME, "$HOME") | ||||
|                 paths.append(pth) | ||||
|                 # paths.append(self.pathListStore.get_value(iter, 0)) | ||||
|                 iter = self.pathListStore.iter_next(iter) | ||||
|  | ||||
|  | ||||
|             toExport = "export PATH=\"" + ':'.join(paths) + "\"\n\n" | ||||
|             file     = open(self.bashrcPath, mode='r') | ||||
|             for line in file: | ||||
|                 if "export PATH=" in line: | ||||
|                     continue | ||||
|                 else: | ||||
|                     toExport += line | ||||
|  | ||||
|             file.close() | ||||
|             file = open(self.bashrcPath, mode='w') | ||||
|             file.write(toExport) | ||||
|             file.close() | ||||
|             self.displayMessage(self.success, "Successfully saved file!") | ||||
|         except Exception as e: | ||||
|             self.displayMessage(self.error, "Opening/Writing to file failed!") | ||||
|             print("Opening/Writing to file failed with the following:\n\n") | ||||
|             print(e) | ||||
|  | ||||
|  | ||||
|     def setSelected(self, user_data): | ||||
|         selected = user_data.get_selected()[1] | ||||
|         if selected: | ||||
|             self.selected = selected | ||||
|  | ||||
|     def loadPaths(self): | ||||
|         pathsStr = os.getenv("PATH") | ||||
|  | ||||
|         # If path exists in bashrc replace default selection... | ||||
|         file = open(self.bashrcPath, mode='r') | ||||
|         for line in file: | ||||
|             if "export PATH=" in line: | ||||
|                 part     = line.replace("export PATH=", "") | ||||
|                 cleaned  = part.replace("\"", "") | ||||
|                 pathsStr = cleaned.strip() | ||||
|  | ||||
|         # Split string into list/tuple and add parts to store | ||||
|         paths = pathsStr.split(":") | ||||
|         for path in paths: | ||||
|             self.pathListStore.append([path]) | ||||
|  | ||||
|  | ||||
|     def setupTreeview(self): | ||||
|         renderer   = gtk.CellRendererText() | ||||
|         pathColumn = gtk.TreeViewColumn(title="Paths", cell_renderer=renderer, text=0) | ||||
|         self.pathTreeView.append_column(pathColumn) | ||||
|         self.pathTreeView.set_model(self.pathListStore) | ||||
|  | ||||
|  | ||||
|     def displayMessage(self, type, text): | ||||
|         markup = "<span foreground='" + type + "'>" + text + "</span>" | ||||
|         self.messageLabel.set_markup(markup) | ||||
|         self.messageWidget.popup() | ||||
|         self.hideMessageTimed() | ||||
|  | ||||
|     @threaded | ||||
|     def hideMessageTimed(self): | ||||
|         time.sleep(3) | ||||
|         GLib.idle_add(self.messageWidget.popdown) | ||||
|  | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     main = Main() | ||||
|     gtk.main() | ||||
| @@ -1,162 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- Generated with glade 3.22.1 --> | ||||
| <interface> | ||||
|   <requires lib="gtk+" version="3.20"/> | ||||
|   <object class="GtkImage" id="delImage"> | ||||
|     <property name="visible">True</property> | ||||
|     <property name="can_focus">False</property> | ||||
|     <property name="stock">gtk-delete</property> | ||||
|   </object> | ||||
|   <object class="GtkImage" id="plusImage"> | ||||
|     <property name="visible">True</property> | ||||
|     <property name="can_focus">False</property> | ||||
|     <property name="stock">gtk-add</property> | ||||
|   </object> | ||||
|   <object class="GtkWindow" id="Main_Window"> | ||||
|     <property name="can_focus">False</property> | ||||
|     <property name="title" translatable="yes">Edit PATH App</property> | ||||
|     <property name="window_position">center</property> | ||||
|     <property name="default_width">480</property> | ||||
|     <property name="default_height">560</property> | ||||
|     <property name="icon_name">applications-accessories</property> | ||||
|     <property name="gravity">center</property> | ||||
|     <child> | ||||
|       <placeholder/> | ||||
|     </child> | ||||
|     <child> | ||||
|       <object class="GtkBox"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can_focus">False</property> | ||||
|         <property name="orientation">vertical</property> | ||||
|         <child> | ||||
|           <object class="GtkSeparator" id="separator1"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can_focus">False</property> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">0</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkScrolledWindow"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can_focus">True</property> | ||||
|             <property name="shadow_type">in</property> | ||||
|             <child> | ||||
|               <object class="GtkViewport"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">False</property> | ||||
|                 <child> | ||||
|                   <object class="GtkTreeView" id="pathTreeView"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="can_focus">True</property> | ||||
|                     <child internal-child="selection"> | ||||
|                       <object class="GtkTreeSelection"> | ||||
|                         <signal name="changed" handler="setSelected" swapped="no"/> | ||||
|                       </object> | ||||
|                     </child> | ||||
|                   </object> | ||||
|                 </child> | ||||
|               </object> | ||||
|             </child> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">True</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">1</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkBox"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can_focus">False</property> | ||||
|             <child> | ||||
|               <object class="GtkEntry" id="toAddPathEntry"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">True</property> | ||||
|                 <property name="placeholder_text" translatable="yes">Path...</property> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="expand">True</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">0</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|             <child> | ||||
|               <object class="GtkButton"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">True</property> | ||||
|                 <property name="receives_default">True</property> | ||||
|                 <property name="tooltip_text" translatable="yes">Add path...</property> | ||||
|                 <property name="image">plusImage</property> | ||||
|                 <property name="always_show_image">True</property> | ||||
|                 <signal name="clicked" handler="addEntry" swapped="no"/> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="expand">False</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">1</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|             <child> | ||||
|               <object class="GtkButton"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">True</property> | ||||
|                 <property name="receives_default">True</property> | ||||
|                 <property name="tooltip_text" translatable="yes">Delete...</property> | ||||
|                 <property name="image">delImage</property> | ||||
|                 <property name="always_show_image">True</property> | ||||
|                 <signal name="clicked" handler="deleteEntry" swapped="no"/> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="expand">False</property> | ||||
|                 <property name="fill">True</property> | ||||
|                 <property name="position">2</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">2</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkButton"> | ||||
|             <property name="label">gtk-save</property> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can_focus">True</property> | ||||
|             <property name="receives_default">True</property> | ||||
|             <property name="tooltip_text" translatable="yes">Save...</property> | ||||
|             <property name="use_stock">True</property> | ||||
|             <property name="always_show_image">True</property> | ||||
|             <signal name="clicked" handler="saveToBashrc" swapped="no"/> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="expand">False</property> | ||||
|             <property name="fill">True</property> | ||||
|             <property name="position">3</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|       </object> | ||||
|     </child> | ||||
|   </object> | ||||
|   <object class="GtkPopover" id="messageWidget"> | ||||
|     <property name="width_request">320</property> | ||||
|     <property name="can_focus">False</property> | ||||
|     <property name="relative_to">separator1</property> | ||||
|     <property name="position">bottom</property> | ||||
|     <child> | ||||
|       <object class="GtkLabel" id="messageLabel"> | ||||
|         <property name="visible">True</property> | ||||
|         <property name="can_focus">False</property> | ||||
|         <property name="justify">center</property> | ||||
|         <attributes> | ||||
|           <attribute name="scale" value="2"/> | ||||
|         </attributes> | ||||
|       </object> | ||||
|     </child> | ||||
|   </object> | ||||
| </interface> | ||||
							
								
								
									
										373
									
								
								src/Shell/Utils/ani-cli
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										373
									
								
								src/Shell/Utils/ani-cli
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,373 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| # dependencies: grep sed curl video_player | ||||
| # video_player ( needs to be able to play urls ) | ||||
| player_fn="mpv" | ||||
|  | ||||
| prog="ani-cli" | ||||
| logfile="${XDG_CACHE_HOME:-$HOME/.cache}/ani-hsts" | ||||
|  | ||||
| c_red="\033[1;31m" | ||||
| c_green="\033[1;32m" | ||||
| c_yellow="\033[1;33m" | ||||
| c_blue="\033[1;34m" | ||||
| c_magenta="\033[1;35m" | ||||
| c_cyan="\033[1;36m" | ||||
| c_reset="\033[0m" | ||||
|  | ||||
|  | ||||
| help_text () { | ||||
| 	while IFS= read line; do | ||||
| 		printf "%s\n" "$line" | ||||
| 	done <<-EOF | ||||
| 	USAGE: $prog <query> | ||||
| 	 -h	 show this help text | ||||
| 	 -d	 download episode | ||||
| 	 -H	 continue where you left off | ||||
| 	 -q	 set video quality (best/worst/360/480/720/..) | ||||
| 	EOF | ||||
| } | ||||
|  | ||||
|  | ||||
| die () { | ||||
| 	printf "$c_red%s$c_reset\n" "$*" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| err () { | ||||
| 	printf "$c_red%s$c_reset\n" "$*" >&2 | ||||
| } | ||||
|  | ||||
| search_anime () { | ||||
| 	# get anime name along with its id | ||||
| 	search=$(printf '%s' "$1" | tr ' ' '-' ) | ||||
| 	titlepattern='<a href="/category/' | ||||
|  | ||||
| 	curl -s "https://gogoanime.pe//search.html" \ | ||||
| 		-G \ | ||||
| 		-d "keyword=$search" | | ||||
| 	sed -n -E ' | ||||
| 		s_^[[:space:]]*<a href="/category/([^"]*)" title="([^"]*)".*_\1_p | ||||
| 		' | ||||
| } | ||||
|  | ||||
| search_eps () { | ||||
| 	# get available episodes for anime_id | ||||
| 	anime_id=$1 | ||||
|  | ||||
| 	curl -s "https://gogoanime.pe/category/$anime_id" | | ||||
| 	sed -n -E ' | ||||
| 		/^[[:space:]]*<a href="#" class="active" ep_start/{ | ||||
| 		s/.* '\''([0-9]*)'\'' ep_end = '\''([0-9]*)'\''.*/\2/p | ||||
| 		q | ||||
| 		} | ||||
| 		' | ||||
| } | ||||
|  | ||||
| get_embedded_video_link() { | ||||
| 	# get the download page url | ||||
| 	anime_id=$1 | ||||
| 	ep_no=$2 | ||||
|  | ||||
| 	# credits to fork: https://github.com/Dink4n/ani-cli for the fix | ||||
| 	curl -s "https://gogoanime.pe/$anime_id-episode-$ep_no" | | ||||
| 	sed -n -E ' | ||||
| 		/^[[:space:]]*<a href="#" rel="100"/{ | ||||
| 		s/.*data-video="([^"]*)".*/https:\1/p | ||||
| 		q | ||||
| 		}' | ||||
| } | ||||
|  | ||||
| get_video_quality() { | ||||
| 	embedded_video_url=$1 | ||||
| 	video_url=$2 | ||||
|  | ||||
| 	video_file=$(curl -s --referer "$embedded_video_url" "$video_url") | ||||
| 	available_qualities=$(printf '%s' "$video_file" | sed -n -E 's/.*NAME="([^p]*)p"/\1/p') | ||||
| 	case $quality in | ||||
| 		best) | ||||
| 			printf '%s' "$available_qualities" | tail -n 1 | ||||
| 			;; | ||||
|  | ||||
| 		worst) | ||||
| 			printf '%s' "$available_qualities" | head -n 1 | ||||
| 			;; | ||||
|  | ||||
| 		*) | ||||
| 			is_quality_avail=$(printf '%s' "$available_qualities" | grep "$quality") | ||||
| 			video_quality="$quality" | ||||
| 			if [ -z "$is_quality_avail" ]; then | ||||
| 				printf "$c_red%s$c_reset\n" "Current video quality is not available (defaulting to highest quality)" >&2 | ||||
| 				quality=best | ||||
| 				video_quality=$(printf '%s' "$available_qualities" | tail -n 1) | ||||
| 			fi | ||||
| 			printf '%s' "$video_quality" | ||||
| 			;; | ||||
| 	esac | ||||
|  | ||||
| } | ||||
|  | ||||
| get_links () { | ||||
| 	embedded_video_url="$1" | ||||
| 	video_url=$(curl -s "$embedded_video_url" | | ||||
| 	sed -n -E ' | ||||
| 		/^[[:space:]]*sources:/{ | ||||
| 		s/.*(https[^'\'']*).*/\1/p | ||||
| 		q | ||||
| 		} | ||||
| 		') | ||||
|  | ||||
| 	video_quality=$(get_video_quality "$embedded_video_url" "$video_url") | ||||
|  | ||||
| 	# Replace the video with highest quality video | ||||
| 	printf '%s' "$video_url" | sed -n -E "s/(.*)\.m3u8/\1.$video_quality.m3u8/p" | ||||
| } | ||||
|  | ||||
| dep_ch () { | ||||
| 	for dep; do | ||||
| 		if ! command -v "$dep" >/dev/null ; then | ||||
| 			die "Program \"$dep\" not found. Please install it." | ||||
| 		fi | ||||
| 	done | ||||
| } | ||||
|  | ||||
| # get query | ||||
| get_search_query () { | ||||
| 	if [ -z "$*" ]; then | ||||
| 		printf "Search Anime: " | ||||
| 		read -r query | ||||
| 	else | ||||
| 		query=$* | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| # create history file | ||||
| [ -f "$logfile" ] || : > "$logfile" | ||||
|  | ||||
| ##################### | ||||
| ## Anime selection ## | ||||
| ##################### | ||||
|  | ||||
| anime_selection () { | ||||
| 	search_results=$* | ||||
| 	menu_format_string='[%d] %s\n' | ||||
| 	menu_format_string_c1="$c_blue[$c_cyan%d$c_blue] $c_reset%s\n" | ||||
| 	menu_format_string_c2="$c_blue[$c_cyan%d$c_blue] $c_yellow%s$c_reset\n" | ||||
|  | ||||
| 	count=1 | ||||
| 	while read anime_id; do | ||||
| 		# alternating colors for menu | ||||
| 		[ $((count % 2)) -eq 0 ] && | ||||
| 			menu_format_string=$menu_format_string_c1 || | ||||
| 			menu_format_string=$menu_format_string_c2 | ||||
|  | ||||
| 		printf "$menu_format_string" "$count" "$anime_id" | ||||
| 		count=$((count+1)) | ||||
| 	done <<-EOF | ||||
| 	$search_results | ||||
| 	EOF | ||||
|  | ||||
| 	# User input | ||||
| 	printf "$c_blue%s$c_green" "Enter number: " | ||||
| 	read choice | ||||
| 	printf "$c_reset" | ||||
|  | ||||
| 	# Check if input is a number | ||||
| 	[ "$choice" -eq "$choice" ] 2>/dev/null || die "Invalid number entered" | ||||
|  | ||||
| 	# Select respective anime_id | ||||
| 	count=1 | ||||
| 	while read anime_id; do | ||||
| 		if [ $count -eq $choice ]; then | ||||
| 			selection_id=$anime_id | ||||
| 			break | ||||
| 		fi | ||||
| 		count=$((count+1)) | ||||
| 	done <<-EOF | ||||
| 	$search_results | ||||
| 	EOF | ||||
|  | ||||
| 	[ -z "$selection_id" ] && die "Invalid number entered" | ||||
|  | ||||
| 	read last_ep_number <<-EOF | ||||
| 	$(search_eps "$selection_id") | ||||
| 	EOF | ||||
| } | ||||
|  | ||||
| ################## | ||||
| ## Ep selection ## | ||||
| ################## | ||||
|  | ||||
| episode_selection () { | ||||
| 	[ $is_download -eq 1 ] && | ||||
| 		printf "Range of episodes can be specified: start_number end_number\n" | ||||
|  | ||||
| 	printf "${c_blue}Choose episode $c_cyan[1-%d]$c_reset:$c_green " $last_ep_number | ||||
| 	read ep_choice_start ep_choice_end | ||||
| 	printf "$c_reset" | ||||
|  | ||||
| } | ||||
|  | ||||
| open_episode () { | ||||
| 	anime_id=$1 | ||||
| 	episode=$2 | ||||
|  | ||||
| 	# Cool way of clearing screen | ||||
| 	tput reset | ||||
| 	if [ $episode -lt 1 ] || [ $episode -gt $last_ep_number ]; then | ||||
| 		err "Episode out of range" | ||||
| 		printf "${c_blue}Choose episode $c_cyan[1-%d]$c_reset:$c_green " $last_ep_number | ||||
| 		read episode | ||||
| 		printf "$c_reset" | ||||
| 	fi | ||||
|  | ||||
| 	printf "Getting data for episode %d\n" $episode | ||||
|  | ||||
| 	embedded_video_url=$(get_embedded_video_link "$anime_id" "$episode") | ||||
| 	video_url=$(get_links "$embedded_video_url") | ||||
|  | ||||
| 	case $video_url in | ||||
| 		*streamtape*) | ||||
| 			# If direct download not available then scrape streamtape.com | ||||
| 			BROWSER=${BROWSER:-firefox} | ||||
| 			printf "scraping streamtape.com\n" | ||||
| 			video_url=$(curl -s "$video_url" | sed -n -E ' | ||||
| 				/^<script>document/{ | ||||
| 				s/^[^"]*"([^"]*)" \+ '\''([^'\'']*).*/https:\1\2\&dl=1/p | ||||
| 				q | ||||
| 				} | ||||
| 			');; | ||||
| 	esac | ||||
|  | ||||
| 	if [ $is_download -eq 0 ]; then | ||||
| 		# write anime and episode number | ||||
| 		sed -E " | ||||
| 			s/^${selection_id}\t[0-9]+/${selection_id}\t$((episode+1))/ | ||||
| 		" "$logfile" > "${logfile}.new" && mv "${logfile}.new" "$logfile" | ||||
|  | ||||
| 		setsid -f $player_fn --http-header-fields="Referer: $embedded_video_url" "$video_url" >/dev/null 2>&1 | ||||
| 	else | ||||
| 		printf "Downloading episode $episode ...\n" | ||||
| 		printf "%s\n" "$video_url" | ||||
| 		# add 0 padding to the episode name | ||||
| 		episode=$(printf "%03d" $episode) | ||||
| 		{ | ||||
| 			curl -L -# -C - "$video_url" -G -e 'https://streamani.io/' \ | ||||
| 				-o "${HOME}/Downloads/${anime_id}-${episode}.mp4" "$video_url" >/dev/null 2>&1 && | ||||
| 				printf "${c_green}Downloaded episode: %s${c_reset}\n" "$episode" || | ||||
| 				printf "${c_red}Download failed episode: %s${c_reset}\n" "$episode" | ||||
| 		} | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| ############ | ||||
| # Start Up # | ||||
| ############ | ||||
|  | ||||
| # to clear the colors when exited using SIGINT | ||||
| trap "printf '$c_reset'" INT HUP | ||||
|  | ||||
| dep_ch "$player_fn" "curl" "sed" "grep" | ||||
|  | ||||
| # option parsing | ||||
| is_download=0 | ||||
| quality=best | ||||
| scrape=query | ||||
| while getopts 'hdHq:' OPT; do | ||||
| 	case $OPT in | ||||
| 		h) | ||||
| 			help_text | ||||
| 			exit 0 | ||||
| 			;; | ||||
| 		d) | ||||
| 			is_download=1 | ||||
| 			;; | ||||
| 		H) | ||||
| 			scrape=history | ||||
| 			;; | ||||
| 		q) | ||||
| 			quality=$OPTARG | ||||
| 			;; | ||||
| 	esac | ||||
| done | ||||
| shift $((OPTIND - 1)) | ||||
|  | ||||
| ######## | ||||
| # main # | ||||
| ######## | ||||
|  | ||||
| case $scrape in | ||||
| 	query) | ||||
| 		get_search_query "$*" | ||||
| 		search_results=$(search_anime "$query") | ||||
| 		[ -z "$search_results" ] && die "No search results found" | ||||
| 		anime_selection "$search_results" | ||||
| 		episode_selection | ||||
| 		;; | ||||
| 	history) | ||||
| 		search_results=$(sed -n -E 's/\t[0-9]*//p' "$logfile") | ||||
| 		[ -z "$search_results" ] && die "History is empty" | ||||
| 		anime_selection "$search_results" | ||||
| 		ep_choice_start=$(sed -n -E "s/${selection_id}\t//p" "$logfile") | ||||
| 		;; | ||||
| esac | ||||
|  | ||||
| { # checking input | ||||
| 	[ "$ep_choice_start" -eq "$ep_choice_start" ] 2>/dev/null || die "Invalid number entered" | ||||
| 	episodes=$ep_choice_start | ||||
|  | ||||
| 	if [ -n "$ep_choice_end" ]; then | ||||
| 		[ "$ep_choice_end" -eq "$ep_choice_end" ] 2>/dev/null || die "Invalid number entered" | ||||
| 		# create list of episodes to download/watch | ||||
| 		episodes=$(seq $ep_choice_start $ep_choice_end) | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| # add anime to history file | ||||
| grep -q -w "${selection_id}" "$logfile" || | ||||
| 	printf "%s\t%d\n" "$selection_id" $((episode+1)) >> "$logfile" | ||||
|  | ||||
| for ep in $episodes | ||||
| do | ||||
| 	open_episode "$selection_id" "$ep" | ||||
| done | ||||
| episode=${ep_choice_end:-$ep_choice_start} | ||||
|  | ||||
| while :; do | ||||
| 	printf "\n${c_green}Currently playing %s episode ${c_cyan}%d/%d\n" "$selection_id" $episode $last_ep_number | ||||
| 	printf "$c_blue[${c_cyan}%s$c_blue] $c_yellow%s$c_reset\n" "n" "next episode" | ||||
| 	printf "$c_blue[${c_cyan}%s$c_blue] $c_magenta%s$c_reset\n" "p" "previous episode" | ||||
| 	printf "$c_blue[${c_cyan}%s$c_blue] $c_yellow%s$c_reset\n" "s" "select episode" | ||||
| 	printf "$c_blue[${c_cyan}%s$c_blue] $c_magenta%s$c_reset\n" "r" "replay current episode" | ||||
| 	printf "$c_blue[${c_cyan}%s$c_blue] $c_red%s$c_reset\n" "q" "exit" | ||||
| 	printf "${c_blue}Enter choice:${c_green} " | ||||
| 	read choice | ||||
| 	printf "$c_reset" | ||||
| 	case $choice in | ||||
| 		n) | ||||
| 			episode=$((episode + 1)) | ||||
| 			;; | ||||
| 		p) | ||||
| 			episode=$((episode - 1)) | ||||
| 			;; | ||||
|  | ||||
| 		s)	printf "${c_blue}Choose episode $c_cyan[1-%d]$c_reset:$c_green " $last_ep_number | ||||
| 			read episode | ||||
| 			printf "$c_reset" | ||||
| 			[ "$episode" -eq "$episode" ] 2>/dev/null || die "Invalid number entered" | ||||
| 			;; | ||||
|  | ||||
| 		r) | ||||
| 			episode=$((episode)) | ||||
| 			;; | ||||
|  | ||||
| 		q) | ||||
| 			break;; | ||||
|  | ||||
| 		*) | ||||
| 			die "invalid choice" | ||||
| 			;; | ||||
| 	esac | ||||
|  | ||||
| 	open_episode "$selection_id" "$episode" | ||||
| done | ||||
							
								
								
									
										29
									
								
								src/Shell/download-full-website.sh → src/Shell/Utils/download-full-website
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										29
									
								
								src/Shell/download-full-website.sh → src/Shell/Utils/download-full-website
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -7,11 +7,31 @@ | ||||
| # set -o errunset     ## To exit if a variable is referenced but not set | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| function main() { | ||||
|     SCRIPTPATH="$( cd "$(dirname "")" >/dev/null 2>&1 ; pwd -P )" | ||||
|     domain='' | ||||
|     path='' | ||||
|     verbose='false' | ||||
| 
 | ||||
|     cd "${SCRIPTPATH}" | ||||
|     echo "Working Dir: " $(pwd) | ||||
| 
 | ||||
|     while getopts 'dp:v' flag; do | ||||
|         case "${flag}" in | ||||
|             d) domain="${OPTARG}" ;; | ||||
|             p) path="${OPTARG}" ;; | ||||
|             v) verbose='true' ;; | ||||
|             *) print_usage | ||||
|             exit 1 ;; | ||||
|         esac | ||||
|     done | ||||
| 
 | ||||
|     if [[ -z "${domain}" || -z "${path}" ]]; then | ||||
|         print_usage | ||||
|         exit 1 | ||||
|     fi | ||||
| 
 | ||||
|     wget \ | ||||
|          --recursive \ | ||||
|          --no-clobber \ | ||||
| @@ -19,8 +39,13 @@ function main() { | ||||
|          --html-extension \ | ||||
|          --convert-links \ | ||||
|          --restrict-file-names=windows \ | ||||
|          --domains schlechtwetterfront.github.io \ | ||||
|          --domains "${domain}" \ | ||||
|          --no-parent \ | ||||
|              "schlechtwetterfront.github.io/ze_filetypes/index.html" | ||||
|              "${path}" | ||||
| } | ||||
| 
 | ||||
| print_usage() { | ||||
|   printf "Usage: -d for domain and -p for the starting path..." | ||||
| } | ||||
| 
 | ||||
| main $@; | ||||
							
								
								
									
										0
									
								
								src/Shell/get-list-of-emoji-icons-for-linux-shell.sh → src/Shell/Utils/get-list-of-emoji-icons-for-linux-shell
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/Shell/get-list-of-emoji-icons-for-linux-shell.sh → src/Shell/Utils/get-list-of-emoji-icons-for-linux-shell
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										11
									
								
								src/Shell/Utils/install-base-flask-libs
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								src/Shell/Utils/install-base-flask-libs
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # set -o xtrace       ## To debug scripts | ||||
| # set -o errexit      ## To exit on error | ||||
| # set -o errunset     ## To exit if a variable is referenced but not set | ||||
|  | ||||
|  | ||||
| function main() { | ||||
|     pip3 install flask simplejson watchdog | ||||
| } | ||||
| main $@; | ||||
| @@ -1,3 +1,4 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # By Maxim F. Stewart | ||||
| # Contact: [1itdominator@gmail.com] | ||||
| @@ -17,7 +18,6 @@ | ||||
| #    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| #---------------------------------------------------------------------------------------# | ||||
| #!/bin/bash | ||||
| 
 | ||||
| 
 | ||||
| # . CONFIG.sh | ||||
| @@ -1,3 +1,4 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # By Maxim F. Stewart | ||||
| # Contact: [1itdominator.com] | ||||
| @@ -17,7 +18,6 @@ | ||||
| #    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| #---------------------------------------------------------------------------------------# | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # . CONFIG.sh | ||||
| # set -o xtrace       ## To debug scripts | ||||
							
								
								
									
										0
									
								
								src/Shell/xbox-controller.sh → src/Shell/Utils/xbox-controller
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/Shell/xbox-controller.sh → src/Shell/Utils/xbox-controller
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										200
									
								
								src/Shell/Utils/yt-cli
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										200
									
								
								src/Shell/Utils/yt-cli
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,200 @@ | ||||
| #!/bin/bash | ||||
| # dependencies: mpv youtube-dl fzf rofi/dmenu gnu-grep | ||||
|  | ||||
| # NOTE:  if you dont have gnu grep you can replace grep with rg | ||||
|  | ||||
| # explain usage | ||||
| function usage () { | ||||
|     echo "usage: yt" | ||||
|     echo "    -h        help" | ||||
|     echo "    -c        channels/subscriptions" | ||||
|     echo "    -s query  search" | ||||
|     echo "    -g / -r   gui mode (rofi/dmenu)" | ||||
|     echo "    -m        music mode (audio only) [dont use with -r]" | ||||
|     echo "  nothing     use defaults (search from prompt)" | ||||
| 	echo | ||||
| 	echo "add channel names to the file $sublistpath to show them" | ||||
| 	echo "in yt -c option. First word should be channel url, optionally" | ||||
| 	echo "followed by tab and then anything else (channel name/description)" | ||||
| 	echo "channels not in sublist can be viewed by typing their url in the prompt" | ||||
| 	echo  | ||||
| 	echo "example file format:" | ||||
| 	echo "markrober       Mark Rober" | ||||
| 	echo "vsauce1         VSauce          Michael Steven's Channel" | ||||
| 	echo "BlackGryph0n    Black Gryph0n   Gabriel Brown signs stuff" | ||||
| 	echo "TomScottGo      Tom Scott" | ||||
| 	echo "danielthrasher  Daniel Thrasher" | ||||
|     exit 0 | ||||
| } | ||||
|  | ||||
| # dont use defaults | ||||
| useDefaults="f" | ||||
|  | ||||
| # no args -> use defaults | ||||
| if [[ ${#} -eq 0 ]]; then | ||||
|     useDefaults="t" | ||||
| fi | ||||
|  | ||||
| # available flags | ||||
| optstring=":s:cgrhm" | ||||
|  | ||||
| defcmd="fzf" | ||||
| defaction="s" | ||||
| guicmd="rofi -dmenu -i" #uncomment next line for dmenu | ||||
| #guicmd="dmenu -i -l 15" | ||||
|  | ||||
| #Defaults | ||||
| promptcmd="$defcmd" | ||||
| action="$defaction" | ||||
| isGui="f" | ||||
| query="" | ||||
| mpv_options="" | ||||
|  | ||||
| # subscription list | ||||
| mkdir -p "${HOME:-}/.config/yt" | ||||
| sublistpath="${HOME:-}/.config/yt/sublist" | ||||
| sublist="" | ||||
| [ -f "$sublistpath" ] && sublist=$(cat "$sublistpath")  | ||||
|  | ||||
| # if not using defaults search for flags | ||||
| if [[ $useDefaults = "f" ]]; then | ||||
|     while getopts ${optstring} arg; do | ||||
|         case "${arg}" in | ||||
|             s)  | ||||
|                 # search in youtube for a query | ||||
|                 action="s" | ||||
|                 query="${OPTARG}" ;; | ||||
|             c)  | ||||
|                 # search in subscriptions for specific channel | ||||
|                 action="c" | ||||
|                 query="${OPTARG}" ;; | ||||
|             g|r)  | ||||
|                 # set gui mode to true and change the prompt to gui prompt | ||||
|                 isGui="t" | ||||
|                 promptcmd="$guicmd" ;; | ||||
|             m) | ||||
|                # make the mpv headless | ||||
|                 mpv_options+="--no-video" ;; | ||||
|             h)  | ||||
|                 # display help / usage | ||||
|                 usage ;; | ||||
|             \?)  | ||||
|                 # wrong args -> exit with explanation of usage | ||||
|                 echo "invalid option: -${OPTARG}" | ||||
|                 echo | ||||
|                 usage | ||||
| 				exit 1 ;; | ||||
|             :)  | ||||
|                 # missing args -> exit with explanation of usage | ||||
|                 echo "Option -${OPTARG} needs an argument" | ||||
|                 echo | ||||
|                 usage | ||||
| 				exit 1 ;; | ||||
|  | ||||
|         esac | ||||
|     done | ||||
| fi | ||||
|  | ||||
| # if no query is set with flags then ask for one | ||||
| if [ -z "$query" ]; then | ||||
|     # ask for a channel | ||||
|     if [[ $action = "c" ]]; then | ||||
|         # if in gui mode use gui prompt | ||||
|         if [[ $isGui = "t" ]]; then  | ||||
| 			query=$($promptcmd -p "Channel: " <<< "$sublist") | ||||
|             promptcmd="$promptcmd -p Video:" | ||||
|         else | ||||
|             query=$($promptcmd --print-query <<< "$sublist" | tail -n1) | ||||
|         fi | ||||
| 		query=$(echo "$query" | awk '{print $1}') | ||||
|     else | ||||
|         # ask for a query | ||||
|         # if in gui mode use gui prompt | ||||
|         if [[ $isGui = "t" ]]; then  | ||||
|             query=$(echo | $promptcmd -p "Search: ") | ||||
|             promptcmd="$promptcmd -p Video:" | ||||
|         else | ||||
|             echo -n "Search: " | ||||
|             read -r query | ||||
|         fi | ||||
|     fi | ||||
| fi  | ||||
|  | ||||
| # program cancelled -> exit | ||||
| if [ -z "$query" ]; then exit; fi  | ||||
|  | ||||
| # clean query / channel | ||||
| query=$(sed \ | ||||
|   -e 's|+|%2B|g'\ | ||||
|   -e 's|#|%23|g'\ | ||||
|   -e 's|&|%26|g'\ | ||||
|   -e 's| |+|g' <<< "$query") | ||||
|  | ||||
|  | ||||
| # if channel look for channel vids | ||||
| if [[ $action = "c" ]]; then | ||||
|     response=$(curl -s "https://www.youtube.com/c/$query/videos" |\ | ||||
|       sed "s/{\"gridVideoRenderer/\n\n&/g" |\ | ||||
|       sed "s/}]}}}]}}/&\n\n/g" |\ | ||||
|       awk -v ORS="\n\n" '/gridVideoRenderer/') | ||||
|  | ||||
|     # if unable to fetch the youtube results page, inform and exit | ||||
|     if ! grep -q "gridVideoRenderer" <<< "$response"; then echo "unable to fetch yt"; exit 1; fi | ||||
|  | ||||
|     # regex expression to match video entries from yt channel page | ||||
|     # get the list of videos and their ids to ids | ||||
|     ids=$(awk -F '[""]' '{print $6 "\t" $50;}' <<< "$response" | grep "^\S") | ||||
|  | ||||
|     # url prefix for videos | ||||
|     videolink="https://youtu.be/" | ||||
|  | ||||
|     # prompt the results to user infinitely until they exit (escape) | ||||
|     while true; do | ||||
|       choice=$(echo -e "$ids" | cut -d'	' -f2 | $promptcmd) # dont show id | ||||
|       if [ -z "$choice" ]; then exit; fi	# if esc-ed then exit | ||||
|       id=$(echo -e "$ids" | grep -Fwm1 "$choice" | cut -d'	' -f1) # get id of choice | ||||
|       echo -e "$choice\t($id)" | ||||
|       case $id in | ||||
|           ???????????) mpv "$videolink$id" "$mpv_options" ;; | ||||
|           *) exit ;; | ||||
|       esac | ||||
|     done | ||||
| else | ||||
|     # if in search show query result vids | ||||
|     response="$(curl -s "https://www.youtube.com/results?search_query=$query" |\ | ||||
|       sed 's|\\.||g')" | ||||
|     # if unable to fetch the youtube results page, inform and exit | ||||
|     if ! grep -q "script" <<< "$response"; then echo "unable to fetch yt"; exit 1; fi | ||||
|     # regex expression to match video and playlist entries from yt result page | ||||
|     vgrep='"videoRenderer":{"videoId":"\K.{11}".+?"text":".+?[^\\](?=")' | ||||
|     pgrep='"playlistRenderer":{"playlistId":"\K.{34}?","title":{"simpleText":".+?[^\"](?=")' | ||||
|     # grep the id and title | ||||
|     # return them in format id (type) title | ||||
|     getresults() { | ||||
|         grep -oP "$1" <<< "$response" |\ | ||||
|           awk -F\" -v p="$2" '{ print $1 "\t" p " " $NF}' | ||||
|     } | ||||
|     # get the list of videos/playlists and their ids in videoids and playlistids | ||||
|     videoids=$(getresults "$vgrep") | ||||
|     playlistids=$(getresults "$pgrep" "(playlist)") | ||||
|     # if there are playlists or videos, append them to list | ||||
|     [ -n "$playlistids" ] && ids="$playlistids\n" | ||||
|     [ -n "$videoids" ] && ids="$ids$videoids" | ||||
|     # url prefix for videos and playlists | ||||
|     videolink="https://youtu.be/" | ||||
|     playlink="https://youtube.com/playlist?list=" | ||||
|     # prompt the results to user infinitely until they exit (escape) | ||||
|     while true; do | ||||
|         choice=$(echo -e "$ids" | cut -d'	' -f2 | $promptcmd) # dont show id | ||||
|         if [ -z "$choice" ]; then exit; fi	# if esc-ed then exit | ||||
|         id=$(echo -e "$ids" | grep -Fwm1 "$choice" | cut -d'	' -f1) # get id of choice | ||||
|         echo -e "$choice\t($id)" | ||||
|         case $id in | ||||
|             # 11 digit id = video | ||||
|             ???????????) mpv "$videolink$id" "$mpv_options" ;; | ||||
|             # 34 digit id = playlist | ||||
|             ??????????????????????????????????) mpv "$playlink$id" "$mpv_options" ;; | ||||
|             *) exit ;; | ||||
|         esac | ||||
|     done | ||||
| fi | ||||
		Reference in New Issue
	
	Block a user