Compare commits

3 Commits

3 changed files with 152 additions and 2 deletions

View File

@@ -1,3 +1,3 @@
# Bookmark-Sync
# Bookmark Sync
This Python module synchronizes the bookmarks between various browsers.
This Python module snychronizes the bookmarks between various browsers.

87
bookmark_sync/__init__.py Normal file
View File

@@ -0,0 +1,87 @@
from abc import ABC, abstractmethod
class BookmarkElement(ABC):
def __init__(self,data):
self._data = data
@property
@abstractmethod
def children(self):
pass
@property
@abstractmethod
def name(self):
pass
@property
@abstractmethod
def parent(self):
pass
@property
@abstractmethod
def date_added(self):
pass
@property
@abstractmethod
def position(self):
pass
class Bookmark(BookmarkElement):
@property
@abstractmethod
def address(self):
pass
@property
def children(self):
return []
class Folder(BookmarkElement):
@property
@abstractmethod
def date_modified(self):
pass
@abstractmethod
def is_root(self):
pass
@abstractmethod
def is_toolbar(self):
pass
class Bookmarks(ABC):
def __init__(self, profile_name="default"):
self.profile = profile_name
self.read_data()
@abstractmethod
def read_data(self):
pass
@property
@abstractmethod
def folders(self):
pass
@property
@abstractmethod
def bookmarks(self):
pass
@property
def root_folder(self):
pass
@property
@abstractmethod
def toolbar_folder(self):
pass
@property
@abstractmethod
def other_bookmarks(self):
pass

View File

@@ -0,0 +1,63 @@
from platform import system
from pathlib import Path
from more_itertools import only
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, MetaData
from . import Bookmarks, Bookmark, Folder
class FirefoxBookmarks(Bookmarks):
_locations = {
"Windows": Path.home()/"AppData/Roaming/Mozilla/Firefox/Profiles",
"Linux": Path.home()/".mozilla/firefox",
"Darwin": Path.home()/"Library/Application Support/Firefox/Profiles"
}
def read_data(self):
try:
self.bookmarks_file = only(self._locations[system()].glob(
"*.default-release"))/"places.sqlite"
except KeyError:
# Assume everthing that isn't Windows or MacOS works like Linux
self.bookmarks_file = only(self._locations["Linux"].glob(
"*.default-release"))/"places.sqlite"
if not self.bookmarks_file.exists():
raise RuntimeError(
"Firefox profile cannot be found or does not exist")
else:
self._engine = create_engine(f"sqlite:///{self.bookmarks_file}")
self._base = automap_base()
self._base.metadata = MetaData(bind=self._engine)
self._base.prepare(self._engine, reflect=True,
classname_for_table=lambda base, name, table: name.replace("moz_", ""))
self._session = Session(self._engine)
@property
def _all_elements(self):
return (self._session.query(self._base.classes.bookmarks, self._base.classes.places)
.outerjoin(self._base.classes.places, self._base.classes.bookmarks.fk == self._base.classes.places.id)
.order_by(self._base.classes.moz_bookmarks.parent, self._base.classes.moz_bookmarks.position)
)
@property
def folders(self):
return self._all_elements.filter(self._base.classes.bookmarks.type == 2)
@property
def bookmarks(self):
return self._all_elements.filter(self._base.classes.bookmarks.type == 1)
@property
def root_folder(self):
return only(self.folders.filter(self._base.classes.bookmarks.id == 1))
@property
def toolbar_folder(self):
return only(self.folders
.filter(self._base.classes.bookmarks.id < 7)
.filter(self._base.classes.bookmarks.title == "toolbar")
)