Skip to content

Instantly share code, notes, and snippets.

@kevinoid
Created December 23, 2016 04:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kevinoid/f0084067e4c611fa7c85800c33e80683 to your computer and use it in GitHub Desktop.
Save kevinoid/f0084067e4c611fa7c85800c33e80683 to your computer and use it in GitHub Desktop.
Script to convert Firefox Session Manager sessions to bookmarks.html
#!/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("&", "&amp;") # Must be done first!
s = s.replace("<", "&lt;")
s = s.replace(">", "&gt;")
if quote:
s = s.replace('"', "&quot;")
s = s.replace('\'', "&#x27;")
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