Merge pull request #152 from oregonpillow/feature
bookmarks_importer.py script added
This commit is contained in:
commit
9db46faabe
2 changed files with 184 additions and 1 deletions
167
.dev/bookmarks_importer.py
Executable file
167
.dev/bookmarks_importer.py
Executable file
|
@ -0,0 +1,167 @@
|
||||||
|
import sqlite3
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from PIL import Image, UnidentifiedImageError
|
||||||
|
from io import BytesIO
|
||||||
|
import re
|
||||||
|
import base64
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Imports html bookmarks file into Flame.
|
||||||
|
Tested only on Firefox html exports so far.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 bookmarks_importer.py --bookmarks <path to bookmarks file> --data <path to flame data dir>
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--bookmarks', type=str, required=True)
|
||||||
|
parser.add_argument('--data', type=str, required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
bookmarks_path = args.bookmarks
|
||||||
|
data_path = args.data
|
||||||
|
created = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] + datetime.now().astimezone().strftime(" %z")
|
||||||
|
updated = created
|
||||||
|
if data_path[-1] != '/':
|
||||||
|
data_path = data_path + '/'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def Base64toPNG(codec, name):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Convert base64 encoded image to png file
|
||||||
|
Reference: https://github.com/python-pillow/Pillow/issues/3400#issuecomment-428104239
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
codec (str): icon in html bookmark format.e.g. 'data:image/png;base64,<image encoding>'
|
||||||
|
name (str): name for export file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
icon_name(str): name of png output E.g. 1636473849374--mybookmark.png
|
||||||
|
None: if image not produced successfully
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
unix_t = str(int(datetime.now(tz=timezone.utc).timestamp() * 1000))
|
||||||
|
icon_name = unix_t + '--' + re.sub(r'\W+', '', name).lower() + '.png'
|
||||||
|
image_path = data_path + 'uploads/' + icon_name
|
||||||
|
if os.path.exists(image_path):
|
||||||
|
return image_path
|
||||||
|
base64_data = re.sub('^data:image/.+;base64,', '', codec)
|
||||||
|
byte_data = base64.b64decode(base64_data)
|
||||||
|
image_data = BytesIO(byte_data)
|
||||||
|
img = Image.open(image_data)
|
||||||
|
img.save(image_path, "PNG")
|
||||||
|
return icon_name
|
||||||
|
except UnidentifiedImageError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def FlameBookmarkParser(bookmarks_path):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Parses HTML bookmarks file
|
||||||
|
Reference: https://stackoverflow.com/questions/68621107/extracting-bookmarks-and-folder-hierarchy-from-google-chrome-with-beautifulsoup
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
bookmarks_path (str): path to bookmarks.html
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
soup = BeautifulSoup()
|
||||||
|
with open(bookmarks_path) as f:
|
||||||
|
soup = BeautifulSoup(f.read(), 'lxml')
|
||||||
|
|
||||||
|
dt = soup.find_all('dt')
|
||||||
|
folder_name =''
|
||||||
|
for i in dt:
|
||||||
|
n = i.find_next()
|
||||||
|
if n.name == 'h3':
|
||||||
|
folder_name = n.text
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
url = n.get("href")
|
||||||
|
website_name = n.text
|
||||||
|
icon = n.get("icon")
|
||||||
|
if icon != None:
|
||||||
|
icon_name = Base64toPNG(icon, website_name)
|
||||||
|
cat_id = AddFlameCategory(folder_name)
|
||||||
|
AddFlameBookmark(website_name, url, cat_id, icon_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def AddFlameCategory(cat_name):
|
||||||
|
"""
|
||||||
|
Parses HTML bookmarks file
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
cat_name (str): category name
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
cat_id (int): primary key id of cat_name
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
con = sqlite3.connect(data_path + 'db.sqlite')
|
||||||
|
cur = con.cursor()
|
||||||
|
count_sql = ("SELECT count(*) FROM categories WHERE name = ?;")
|
||||||
|
cur.execute(count_sql, [cat_name])
|
||||||
|
count = int(cur.fetchall()[0][0])
|
||||||
|
if count > 0:
|
||||||
|
getid_sql = ("SELECT id FROM categories WHERE name = ?;")
|
||||||
|
cur.execute(getid_sql, [cat_name])
|
||||||
|
cat_id = int(cur.fetchall()[0][0])
|
||||||
|
return cat_id
|
||||||
|
|
||||||
|
is_pinned = 1
|
||||||
|
|
||||||
|
insert_sql = "INSERT OR IGNORE INTO categories(name, isPinned, createdAt, updatedAt) VALUES (?, ?, ?, ?);"
|
||||||
|
cur.execute(insert_sql, (cat_name, is_pinned, created, updated))
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
getid_sql = ("SELECT id FROM categories WHERE name = ?;")
|
||||||
|
cur.execute(getid_sql, [cat_name])
|
||||||
|
cat_id = int(cur.fetchall()[0][0])
|
||||||
|
return cat_id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def AddFlameBookmark(website_name, url, cat_id, icon_name):
|
||||||
|
con = sqlite3.connect(data_path + 'db.sqlite')
|
||||||
|
cur = con.cursor()
|
||||||
|
if icon_name == None:
|
||||||
|
insert_sql = "INSERT OR IGNORE INTO bookmarks(name, url, categoryId, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?);"
|
||||||
|
cur.execute(insert_sql, (website_name, url, cat_id, created, updated))
|
||||||
|
con.commit()
|
||||||
|
else:
|
||||||
|
insert_sql = "INSERT OR IGNORE INTO bookmarks(name, url, categoryId, icon, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?);"
|
||||||
|
cur.execute(insert_sql, (website_name, url, cat_id, icon_name, created, updated))
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
FlameBookmarkParser(bookmarks_path)
|
||||||
|
|
18
README.md
18
README.md
|
@ -106,6 +106,7 @@ Follow instructions from wiki: [Installation without Docker](https://github.com/
|
||||||
- Bookmarks
|
- Bookmarks
|
||||||
- Create, update, delete and organize bookmarks and categories using GUI
|
- Create, update, delete and organize bookmarks and categories using GUI
|
||||||
- Pin your favourite categories to the homescreen
|
- Pin your favourite categories to the homescreen
|
||||||
|
- Import html bookmarks (experimental)
|
||||||
|
|
||||||
![Homescreen screenshot](./.github/_bookmarks.png)
|
![Homescreen screenshot](./.github/_bookmarks.png)
|
||||||
|
|
||||||
|
@ -120,6 +121,21 @@ Follow instructions from wiki: [Installation without Docker](https://github.com/
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Import HTML Bookmarks (Experimental)
|
||||||
|
- Requirements
|
||||||
|
- Python3
|
||||||
|
- pip packages: Pillow, beautifulsoup4
|
||||||
|
- Backup your db.sqlite before running script!
|
||||||
|
- Known Issues:
|
||||||
|
- generated icons are sometimes incorrect
|
||||||
|
```shell
|
||||||
|
|
||||||
|
pip3 install Pillow, beautifulsoup4
|
||||||
|
|
||||||
|
cd flame/.dev
|
||||||
|
python3 bookmarks_importer.py --bookmarks <path to bookmarks.html> --data <path to flame data folder>
|
||||||
|
```
|
||||||
|
|
||||||
### Search bar
|
### Search bar
|
||||||
|
|
||||||
#### Searching
|
#### Searching
|
||||||
|
@ -202,4 +218,4 @@ metadata:
|
||||||
|
|
||||||
### Custom CSS and themes
|
### Custom CSS and themes
|
||||||
|
|
||||||
See project wiki for [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) and [Custom theme with CSS](https://github.com/pawelmalak/flame/wiki/Custom-theme-with-CSS).
|
See project wiki for [Custom CSS](https://github.com/pawelmalak/flame/wiki/Custom-CSS) and [Custom theme with CSS](https://github.com/pawelmalak/flame/wiki/Custom-theme-with-CSS).
|
||||||
|
|
Loading…
Reference in a new issue