#!/usr/bin/env python3 # helper script for query-bookmarks.sh # currently supports only Firefox # folder support would be nice, though I doubt it is really useful # useful links: # http://kb.mozillazine.org/Profiles.ini_file # https://stackoverflow.com/a/740183/12005228 # https://wiki.mozilla.org/Places:BookmarksComments import sys import os from pathlib import Path from configparser import ConfigParser import tempfile import shutil import sqlite3 sys.path.insert( 1, os.path.join(os.path.dirname(os.path.dirname(__file__)), "script-resources") ) import common_script_utils # noqa F401 if sys.platform == "darwin": firefox_home = Path.home() / "Library" / "Application Support" / "Firefox" elif os.name == "posix": firefox_home = Path.home() / ".mozilla" / "firefox" else: common_script_utils.platform_not_supported_error() profiles_config = ConfigParser(interpolation=None) profiles_config.read(firefox_home / "profiles.ini") installs_sections = [s for s in profiles_config.sections() if s.startswith("Install")] if not installs_sections: raise Exception("no Firefox installations detected!") if len(installs_sections) > 1: raise Exception("multiple Firefox installations are not supported!") profile_dir = firefox_home / profiles_config.get(installs_sections[0], "Default") db_path = profile_dir / "weave" / "bookmarks.sqlite" if not db_path.is_file(): raise Exception("'{}' is not a file".format(db_path)) # Firefox holds a lock over the database file, so I can't connect to it even # in the readonly mode: https://stackoverflow.com/a/7857866/12005228 # as a workaround I copy the file db_copy_fd, db_copy_path = tempfile.mkstemp(prefix="bookmarks.", suffix=".sqlite") os.close(db_copy_fd) chooser_entries = [] try: shutil.copyfile(db_path, db_copy_path) db = sqlite3.connect(db_copy_path) urls = {} for urlId, url in db.execute("SELECT id, url FROM urls"): urls[urlId] = url for title, urlId, keyword in db.execute( "SELECT title, urlId, keyword FROM items WHERE kind = 1 AND validity AND NOT isDeleted" ): url = urls[urlId] chooser_entries.append((title, url)) if keyword is not None: chooser_entries.append((keyword, url)) finally: os.remove(db_copy_path) chosen_index = common_script_utils.run_chooser( ("{} \u2014\u2014 {}".format(title, url) for title, url in chooser_entries), prompt="bookmark", ) _title, url = chooser_entries[chosen_index] print(url) common_script_utils.set_clipboard(url) common_script_utils.send_notification( os.path.basename(__file__), "bookmark URL copied to clipboard!", url )