summaryrefslogtreecommitdiff
path: root/scripts/importer.py
diff options
context:
space:
mode:
authorRyan Farley <ryan.farley@gmx.com>2017-11-06 00:51:41 -0600
committerRyan Farley <ryan.farley@gmx.com>2017-11-06 21:19:57 -0600
commitf5d719dfd4410e996709a519f4ecb7ca976863a5 (patch)
treed03e23d5f60f0f834a1ddd6fd64f659585a6f17b /scripts/importer.py
parent4d8ac7486ccdd512b9a4f5d753be79aef418478c (diff)
downloadqutebrowser-f5d719dfd4410e996709a519f4ecb7ca976863a5.tar.gz
qutebrowser-f5d719dfd4410e996709a519f4ecb7ca976863a5.zip
importer: Chrome support
This adds Chrome/Chromium support to the importer (which ought to be the last of these). Bookmarks are read from JSON, while keywords/search engines (the same thing here) are read from the Web Data sqlite3 database, and converted from OpenSearch format. importer: add tests for opensearch
Diffstat (limited to 'scripts/importer.py')
-rwxr-xr-xscripts/importer.py80
1 files changed, 78 insertions, 2 deletions
diff --git a/scripts/importer.py b/scripts/importer.py
index d664af7c1..f41a23b10 100755
--- a/scripts/importer.py
+++ b/scripts/importer.py
@@ -30,9 +30,13 @@ profiles is supported.
import argparse
import sqlite3
import os
+import urllib.parse
+import json
+import string
browser_default_input_format = {
- 'chromium': 'netscape',
+ 'chromium': 'chrome',
+ 'chrome': 'chrome',
'ie': 'netscape',
'firefox': 'mozilla',
'seamonkey': 'mozilla',
@@ -73,7 +77,8 @@ def main():
import_function = {
'netscape': import_netscape_bookmarks,
- 'mozilla': import_moz_places
+ 'mozilla': import_moz_places,
+ 'chrome': import_chrome
}
import_function[input_format](args.bookmarks, bookmark_types,
output_format)
@@ -154,6 +159,33 @@ def search_escape(url):
return url.replace('{', '{{').replace('}', '}}')
+def opensearch_convert(url):
+ """Convert a basic OpenSearch URL into something Qutebrowser can use.
+
+ Exceptions:
+ KeyError:
+ An unknown and required parameter is present in the URL. This
+ usually means there's browser/addon specific functionality needed
+ to build the URL (I'm looking at you and your browser, Google) that
+ obviously won't be present here.
+ """
+ subst = {
+ 'searchTerms': '%s', # for proper escaping later
+ 'language': '*',
+ 'inputEncoding': 'UTF-8',
+ 'outputEncoding': 'UTF-8'
+ }
+
+ # remove optional parameters (even those we don't support)
+ for param in string.Formatter().parse(url):
+ if param[1]:
+ if param[1].endswith('?'):
+ url = url.replace('{' + param[1] + '}', '')
+ elif param[2] and param[2].endswith('?'):
+ url = url.replace('{' + param[1] + ':' + param[2] + '}', '')
+ return search_escape(url.format(**subst)).replace('%s', '{}')
+
+
def import_netscape_bookmarks(bookmarks_file, bookmark_types, output_format):
"""Import bookmarks from a NETSCAPE-Bookmark-file v1.
@@ -268,5 +300,49 @@ def import_moz_places(profile, bookmark_types, output_format):
print(out_template[output_format][typ].format(**row))
+def import_chrome(profile, bookmark_types, output_format):
+ """Import bookmarks and search keywords from Chrome-type profiles.
+
+ On Chrome, keywords and search engines are the same thing and handled in
+ their own database table; bookmarks cannot have associated keywords. This
+ is why the dictionary lookups here are much simpler.
+ """
+ out_template = {
+ 'bookmark': '{url} {name}',
+ 'quickmark': '{name} {url}',
+ 'search': "c.url.searchengines['{keyword}'] = '{url}'",
+ 'oldsearch': '{keyword} {url}'
+ }
+
+ if 'search' in bookmark_types:
+ webdata = sqlite3.connect(os.path.join(profile, 'Web Data'))
+ c = webdata.cursor()
+ c.execute('SELECT keyword,url FROM keywords;')
+ for keyword, url in c:
+ try:
+ url = opensearch_convert(url)
+ print(out_template[output_format].format(
+ keyword=keyword, url=url))
+ except KeyError:
+ print('# Unsupported parameter in url for {}; skipping....'.
+ format(keyword))
+
+ else:
+ with open(os.path.join(profile, 'Bookmarks'), encoding='utf-8') as f:
+ bookmarks = json.load(f)
+
+ def bm_tree_walk(bm, template):
+ assert 'type' in bm
+ if bm['type'] == 'url':
+ if urllib.parse.urlparse(bm['url']).scheme != 'chrome':
+ print(template.format(**bm))
+ elif bm['type'] == 'folder':
+ for child in bm['children']:
+ bm_tree_walk(child, template)
+
+ for root in bookmarks['roots'].values():
+ bm_tree_walk(root, out_template[output_format])
+
+
if __name__ == '__main__':
main()