Skip to content
Snippets Groups Projects
xdgurl.py 13.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • akiraohgaki's avatar
    akiraohgaki committed
    #!/usr/bin/env python
    
    import sys
    import os
    import json
    import urllib
    import urlparse
    import tempfile
    import mimetypes
    import subprocess
    
    akiraohgaki's avatar
    akiraohgaki committed
    import Tkinter
    import tkMessageBox
    
    class XdgUrl:
        """Core class of xdgurl"""
    
        def __init__(self, xdg_url=''):
            self.xdg_url = xdg_url
            self.meta = self.parse()
    
            self.temp_dir = tempfile.gettempdir()
            self.home_dir = os.path.expanduser('~')
            #self.config_dir = os.path.join(self.home_dir, '.config', 'xdgurl')
            self.data_dir = os.path.join(self.home_dir, '.local', 'share')
            self.kde_data_dir = os.path.join(self.home_dir, '.kde', 'share')
    
            #self.config = {}
    
            self.destinations = {
                'downloads': os.path.join(self.home_dir, 'Downloads'),
                'documents': os.path.join(self.home_dir, 'Documents'),
                'pictures': os.path.join(self.home_dir, 'Pictures'),
                'music': os.path.join(self.home_dir, 'Music'),
                'videos': os.path.join(self.home_dir, 'Videos'),
                'wallpapers': os.path.join(self.data_dir, 'wallpapers'),
                'fonts': os.path.join(self.home_dir, '.fonts'),
                'cursors': os.path.join(self.home_dir, '.icons'),
                'icons': os.path.join(self.data_dir, 'icons'),
                'emoticons': os.path.join(self.data_dir, 'emoticons'),
                'themes': os.path.join(self.home_dir, '.themes'),
                'emerald_themes': os.path.join(self.home_dir, '.emerald', 'themes'),
                'enlightenment_themes': os.path.join(self.home_dir, '.e', 'e', 'themes'),
                'enlightenment_backgrounds': os.path.join(self.home_dir, '.e', 'e', 'backgrounds'),
                'fluxbox_styles': os.path.join(self.home_dir, '.fluxbox', 'styles'),
                'pekwm_themes': os.path.join(self.home_dir, '.pekwm', 'themes'),
                'icewm_themes': os.path.join(self.home_dir, '.icewm', 'themes'),
                'plasma_plasmoids': os.path.join(self.data_dir, 'plasma', 'plasmoids'),
                'plasma_look_and_feel': os.path.join(self.data_dir, 'plasma', 'look-and-feel'),
                'plasma_desktopthemes': os.path.join(self.data_dir, 'plasma', 'desktoptheme'),
                'kwin_effects': os.path.join(self.data_dir, 'kwin', 'effects'),
                'kwin_scripts': os.path.join(self.data_dir, 'kwin', 'scripts'),
                'kwin_tabbox': os.path.join(self.data_dir, 'kwin', 'tabbox'),
                'aurorae_themes': os.path.join(self.data_dir, 'aurorae', 'themes'),
                'dekorator_themes': os.path.join(self.data_dir, 'deKorator', 'themes'),
                'qtcurve': os.path.join(self.data_dir, 'QtCurve'),
                'color_schemes': os.path.join(self.data_dir, 'color-schemes'),
                'gnome_shell_extensions': os.path.join(self.data_dir, 'gnome-shell', 'extensions'),
    
                'cinnamon_applets': os.path.join(self.data_dir, 'cinnamon', 'applets'),
    
    akiraohgaki's avatar
    akiraohgaki committed
                'cinnamon_desklets': os.path.join(self.data_dir, 'cinnamon', 'desklets'),
    
                'cinnamon_extensions': os.path.join(self.data_dir, 'cinnamon', 'extensions'),
    
    akiraohgaki's avatar
    akiraohgaki committed
                'nautilus_scripts': os.path.join(self.data_dir, 'nautilus', 'scripts'),
                'amarok_scripts': os.path.join(self.kde_data_dir, 'apps', 'amarok', 'scripts'),
                'yakuake_skins': os.path.join(self.kde_data_dir, 'apps', 'yakuake', 'skins'),
                'cairo_clock_themes': os.path.join(self.home_dir, '.cairo-clock', 'themes')
            }
            self.destinations_alias = {
                'gnome_shell_themes': self.destinations['themes'],
                'cinnamon_themes': self.destinations['themes'],
                'gtk2_themes': self.destinations['themes'],
                'gtk3_themes': self.destinations['themes'],
                'metacity_themes': self.destinations['themes'],
                'xfwm4_themes': self.destinations['themes'],
                'openbox_themes': self.destinations['themes'],
                'kvantum_themes': self.destinations['themes'],
                'compiz_themes': self.destinations['emerald_themes'],
                'beryl_themes': self.destinations['emerald_themes'],
                'plasma4_plasmoids': self.destinations['plasma_plasmoids'],
                'plasma5_plasmoids': self.destinations['plasma_plasmoids'],
                'plasma5_look_and_feel': self.destinations['plasma_look_and_feel'],
                'plasma5_desktopthemes': self.destinations['plasma_desktopthemes'],
                'plasma_color_schemes': self.destinations['color_schemes']
            }
            self.destinations.update(self.destinations_alias)
    
            self.archive_types = {
                'tar': [
                    'application/x-tar',
                    'application/x-gzip',
                    'application/gzip',
                    'application/x-bzip',
                    'application/x-bzip2',
                    'application/x-xz',
                    'application/x-lzma',
                    'application/x-lzip',
                    'application/x-compressed-tar',
                    'application/x-bzip-compressed-tar',
                    'application/x-bzip2-compressed-tar',
                    'application/x-xz-compressed-tar',
                    'application/x-lzma-compressed-tar',
                    'application/x-lzip-compressed-tar'
                ],
                'zip': ['application/zip'],
                '7z': ['application/x-7z-compressed'],
                'rar': [
                    'application/x-rar',
                    'application/x-rar-compressed'
                ]
            }
    
            #self.config.update(self.read_config('config'))
            #self.destinations.update(self.read_config('destinations'))
    
        def read_config(self, name):
            path = os.path.join(self.config_dir, name + '.json')
            data = {}
            if os.path.isfile(path):
    
                f = open(path, 'r')
    
    akiraohgaki's avatar
    akiraohgaki committed
                data = json.load(f)
                f.close()
            return data
    
        def write_config(self, name, data):
            if not os.path.isdir(self.config_dir):
                os.makedirs(self.config_dir)
            path = os.path.join(self.config_dir, name + '.json')
            f = open(path, 'w')
            json.dump(data, f)
            f.close()
    
        def parse(self):
            meta = {
                'command': 'download',
                'url': '',
                'type': 'downloads',
                'filename': ''
            }
    
            parse_result = urlparse.urlparse(self.xdg_url)
            query = urlparse.parse_qs(parse_result.query)
    
            if parse_result.netloc:
                meta['command'] = parse_result.netloc
    
            if 'url' in query and query['url'][0]:
                meta['url'] = urllib.unquote(query['url'][0])
    
            if 'type' in query and query['type'][0]:
                meta['type'] = urllib.unquote(query['type'][0])
    
            if 'filename' in query and query['filename'][0]:
    
                meta['filename'] = urllib.unquote(query['filename'][0]).split('?')[0]
    
    akiraohgaki's avatar
    akiraohgaki committed
    
            if meta['url'] and not meta['filename']:
    
                meta['filename'] = os.path.basename(meta['url']).split('?')[0]
    
    akiraohgaki's avatar
    akiraohgaki committed
    
            return meta
    
        """
        def detect_desktop_environment(self):
            desktop_environment = 'unknown'
            if os.environ.get('KDE_FULL_SESSION') == 'true':
                desktop_environment = 'kde'
            elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
                desktop_environment = 'gnome'
            return desktop_environment
        """
    
        def install_plasmapkg(self, path, type='plasmoid'):
            status = subprocess.call(['plasmapkg2', '-t', type, '-i', path])
            if status == 0:
                return True
            return False
    
        def uncompress_archive(self, path, target_dir):
            (mimetype, encoding) = mimetypes.guess_type(path)
            status = None
    
            if mimetype in self.archive_types['tar']:
                status = subprocess.call(['tar', '-xf', path, '-C', target_dir])
            elif mimetype in self.archive_types['zip']:
                status = subprocess.call(['unzip', '-o', path, '-d', target_dir])
            elif mimetype in self.archive_types['7z']:
                # No space between -o and directory
                status = subprocess.call(['7z', 'x', path, '-o' + target_dir])
            elif mimetype in self.archive_types['rar']:
                status = subprocess.call(['unrar', 'e', path, target_dir])
    
            if status == 0:
                return True
            return False
    
        def download(self):
            url = self.meta['url']
            type = self.meta['type']
            filename = self.meta['filename']
            destination = self.destinations[type]
    
            temp_path = os.path.join(self.temp_dir, filename)
            path = os.path.join(destination, filename)
    
            print('Retrieving a file from ' + url)
            urllib.urlretrieve(url, temp_path)
    
            print('Creating a directory ' + destination)
            if not os.path.isdir(destination):
                os.makedirs(destination)
    
            print('Saving a file to ' + path)
            os.rename(temp_path, path)
    
            print('Done')
    
        def install(self):
            url = self.meta['url']
            type = self.meta['type']
            filename = self.meta['filename']
            destination = self.destinations[type]
    
            temp_path = os.path.join(self.temp_dir, filename)
            path = os.path.join(destination, filename)
    
            print('Retrieving a file from ' + url)
            urllib.urlretrieve(url, temp_path)
    
            print('Creating a directory ' + destination)
            if not os.path.isdir(destination):
                os.makedirs(destination)
    
            print('Installing')
            if (type in ['plasma_plasmoids', 'plasma4_plasmoids', 'plasma5_plasmoids']
            and self.install_plasmapkg(temp_path, 'plasmoid')):
                print('The plasmoid has been installed')
                os.remove(temp_path)
            elif (type in ['plasma_look_and_feel', 'plasma5_look_and_feel']
            and self.install_plasmapkg(temp_path, 'lookandfeel')):
                print('The plasma look and feel has been installed')
                os.remove(temp_path)
            elif (type in ['plasma_desktopthemes', 'plasma5_desktopthemes']
            and self.install_plasmapkg(temp_path, 'theme')):
                print('The plasma desktop theme has been installed')
                os.remove(temp_path)
            elif (type == 'kwin_effects'
            and self.install_plasmapkg(temp_path, 'kwineffect')):
                print('The KWin effect has been installed')
                os.remove(temp_path)
            elif (type == 'kwin_scripts'
            and self.install_plasmapkg(temp_path, 'kwinscript')):
                print('The KWin script has been installed')
                os.remove(temp_path)
            elif (type == 'kwin_tabbox'
            and self.install_plasmapkg(temp_path, 'windowswitcher')):
                print('The KWin window switcher has been installed')
                os.remove(temp_path)
            elif self.uncompress_archive(temp_path, destination):
                print('The archive file has been uncompressed into ' + destination)
                os.remove(temp_path)
            else:
                print('Saving a file to ' + path)
                os.rename(temp_path, path)
    
            print('Done')
    
        def execute(self):
    
    akiraohgaki's avatar
    akiraohgaki committed
            if (self.meta['command'] in ['download', 'install']
            and self.meta['url']
            and self.meta['type'] in self.destinations
            and self.meta['filename']):
                if self.meta['command'] == 'download':
                    self.download()
                elif self.meta['command'] == 'install':
                    self.install()
            else:
                raise Exception('Incorrect XDG-URL ' + self.xdg_url)
    
    akiraohgaki's avatar
    akiraohgaki committed
    
    '''
    class XdgUrlApp(Tkinter.Frame):
        """Confirmation dialog for xdgurl"""
    
        def __init__(self, master=None, core=None):
            Tkinter.Frame.__init__(self, master)
            self.pack()
            self.core = core
            self.master.title('xdgurl')
            self.master.geometry('300x120')
            self.create_widget()
    
        def create_widget(self):
            execute_text = 'Download'
            if self.core.meta['command'] == 'install':
                execute_text = 'Install'
    
            info_label = Tkinter.Label(self, text=execute_text + ': ' + self.core.meta['filename'])
            info_label.pack(padx=10, pady=5, anchor=Tkinter.W)
    
            message_label = Tkinter.Label(self, text='Do you want to continue?')
            message_label.pack(padx=10, pady=5, anchor=Tkinter.W)
    
            execute_button = Tkinter.Button(self, text=execute_text, command=self.execute)
            execute_button.pack(padx=5, pady=10, side=Tkinter.RIGHT)
    
            quit_button = Tkinter.Button(self, text='Cancel', command=self.quit)
            quit_button.pack(padx=5, pady=10, side=Tkinter.RIGHT)
    
        def execute(self):
            self.core.execute()
            sys.exit()
    
        def quit(self):
            sys.exit()
    '''
    
    
    akiraohgaki's avatar
    akiraohgaki committed
    def main():
    
        program = 'xdgurl'
        version = '0.0.0'
    
        parser = argparse.ArgumentParser(
            prog=program,
            description='An install helper program for desktop stuff',
            epilog='Check more information on https://github.com/xdgurl/xdgurl'
        )
        parser.add_argument(
            '-v', '--version',
            action='version',
            version='%(prog)s ' + version
        )
        parser.add_argument('xdg_url', help='XDG-URL')
        args = parser.parse_args()
    
        if args.xdg_url:
    
    akiraohgaki's avatar
    akiraohgaki committed
            """
    
            core = XdgUrl(args.xdg_url)
    
    akiraohgaki's avatar
    akiraohgaki committed
            window = Tkinter.Tk()
            app = XdgUrlApp(window, core)
            app.mainloop()
            """
    
    
            core = XdgUrl(args.xdg_url)
            window = Tkinter.Tk()
            window.withdraw()
    
    akiraohgaki's avatar
    akiraohgaki committed
    
            execute_text = 'Download'
            if core.meta['command'] == 'install':
                execute_text = 'Install'
            info_text = execute_text + ': ' + core.meta['filename'] + '\nFrom: ' + core.meta['url']
    
    
            print(info_text)
            if tkMessageBox.askyesno(program, info_text + '\n\nDo you want to continue?'):
    
    akiraohgaki's avatar
    akiraohgaki committed
                try:
                    core.execute();
                except Exception as e:
    
                    error_message = str(e)
    
    akiraohgaki's avatar
    akiraohgaki committed
                    if e.message:
    
                        error_message = e.message
                    message = execute_text + ' failed\n' + error_message
                    print(message)
                    tkMessageBox.showerror(program, info_text + '\n\n' + message)
    
    akiraohgaki's avatar
    akiraohgaki committed
                else:
    
                    message = execute_text + ' finished'
                    print(message)
                    tkMessageBox.showinfo(program, info_text + '\n\n' + message)
    
    akiraohgaki's avatar
    akiraohgaki committed
            sys.exit()
    
    akiraohgaki's avatar
    akiraohgaki committed
    
    if __name__ == '__main__':
        main()