Created
December 23, 2016 04:20
-
-
Save kevinoid/f0084067e4c611fa7c85800c33e80683 to your computer and use it in GitHub Desktop.
Script to convert Firefox Session Manager sessions to bookmarks.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
"""Convert Firefox Session Manager sessions to bookmarks.html.""" | |
import argparse | |
import json | |
import logging | |
import os | |
import sys | |
__version__ = '0.1.0' | |
VERSION_MESSAGE = "%(prog)s " + __version__ + """ | |
Copyright 2016 Kevin Locke <kevin@kevinlocke.name> | |
%(prog)s is free software released under the MIT License.""" | |
_logger = logging.getLogger(__name__) | |
def _setup_logging(level=None): | |
"""Initialize the logging framework with a root logger for the console""" | |
handler = logging.StreamHandler() | |
rootlogger = logging.getLogger() | |
rootlogger.addHandler(handler) | |
if level is not None: | |
rootlogger.setLevel(level) | |
# Copied from Python 3.5 html module | |
def html_escape(s, quote=True): | |
""" | |
Replace special characters "&", "<" and ">" to HTML-safe sequences. | |
If the optional flag quote is true (the default), the quotation mark | |
characters, both double quote (") and single quote (') characters are also | |
translated. | |
""" | |
s = s.replace("&", "&") # Must be done first! | |
s = s.replace("<", "<") | |
s = s.replace(">", ">") | |
if quote: | |
s = s.replace('"', """) | |
s = s.replace('\'', "'") | |
return s | |
def export_window(window, dest): | |
"""Export JSON session window to bookmarks""" | |
for tabnum, tab in enumerate(window["tabs"]): | |
try: | |
entry = tab["entries"][tab["index"] - 1] | |
urlhtml = html_escape(entry["url"]) | |
if "title" in entry: | |
titlehtml = html_escape(entry["title"]) | |
else: | |
titlehtml = urlhtml | |
dest.write('<DT><A HREF="{0}">{1}</A>\n'.format(urlhtml, titlehtml)) | |
except Exception as exc: | |
exc.args += ("Tab " + str(tabnum + 1),) | |
raise | |
def export_session_data(data, dest): | |
"""Export JSON session data to bookmarks""" | |
windows = data["windows"] | |
infolder = len(windows) > 1 | |
for num, window in enumerate(windows): | |
if infolder: | |
dest.write("<DT><H3>Window {0}</H3>\n<DL><p>\n".format(num + 1)) | |
try: | |
export_window(window, dest) | |
except Exception as exc: | |
exc.args += ("Window " + str(num + 1),) | |
raise | |
if infolder: | |
dest.write("</DL><p>\n") | |
def export_session(path, dest): | |
"""Export a session file to bookmarks""" | |
with open(path) as sess: | |
for line in sess: | |
if not line.startswith("{"): | |
continue | |
try: | |
filename = os.path.basename(path) | |
sessname = os.path.splitext(filename)[0] | |
sessnamehtml = html_escape(sessname) | |
dest.write("<DT><H3>{0}</H3>\n<DL><p>\n".format(sessnamehtml)) | |
export_session_data(json.loads(line), dest) | |
dest.write("</DL><p>\n") | |
except Exception as exc: | |
exc.args += (sessname,) | |
raise | |
def export_sessions(dirpath, dest): | |
"""Export all sessions in a directory to bookmarks""" | |
dest.write("""<!DOCTYPE NETSCAPE-Bookmark-file-1> | |
<!-- This is an automatically generated file. | |
It will be read and overwritten. | |
DO NOT EDIT! --> | |
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> | |
<TITLE>Bookmarks</TITLE> | |
<H1>Bookmarks Menu</H1> | |
<DL><p> | |
<DT><H3>Session Manager Sessions</H3> | |
<DL><p> | |
""") | |
for filename in os.listdir(dirpath): | |
if filename.endswith(".session"): | |
export_session(os.path.join(dirpath, filename), dest) | |
dest.write("</DL><p>\n</DL>\n") | |
def main(*argv): | |
"""Entry point for command-line use.""" | |
parser = argparse.ArgumentParser( | |
usage="%(prog)s [options] <sessions dir>", | |
description="Convert Firefox Session Manager sessions to bookmarks.", | |
# Use raw formatter to avoid mangling version text | |
formatter_class=argparse.RawDescriptionHelpFormatter) | |
parser.add_argument( | |
"-o", "--output", type=argparse.FileType('w'), default="-", | |
help="Output file (default: -)") | |
parser.add_argument( | |
"-q", "--quiet", action="count", | |
help="Decrease verbosity (less detailed output)") | |
parser.add_argument( | |
"-v", "--verbose", action="count", | |
help="Increase verbosity (more detailed output)") | |
parser.add_argument( | |
"-V", "--version", action="version", | |
help="Output version and license information", | |
version=VERSION_MESSAGE) | |
parser.add_argument( | |
"sessionsdir", metavar="sessions dir", | |
help="Directory containing .session files") | |
args = parser.parse_args(args=argv[1:]) | |
# Set log level based on verbosity requested (default of INFO) | |
verbosity = (args.quiet or 0) - (args.verbose or 0) | |
_setup_logging(logging.INFO + verbosity * 10) | |
# Log version to aid debugging | |
_logger.debug("%s %s", argv[0], __version__) | |
with args.output: | |
export_sessions(args.sessionsdir, args.output) | |
return 0 | |
if __name__ == "__main__": | |
sys.exit(main(*sys.argv)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment