mirror of
https://github.com/wassname/xbsjsonedit.git
synced 2026-06-27 16:02:52 +08:00
v0.3
This commit is contained in:
Executable
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Chris Nelson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -9,16 +9,22 @@ If you want it to do other functions, grab the code and go for it.
|
||||
## Usage
|
||||
```
|
||||
$ ./xbsjsonedit -h
|
||||
usage: xbsjsonedit [-h] [--dump] Infile
|
||||
usage: xbsjsonedit [-h] [--Print] [--Tags-Print] [--Tags-Count TAGS_COUNT]
|
||||
[-V]
|
||||
Infile
|
||||
|
||||
xBrowserSync json backup editor
|
||||
|
||||
positional arguments:
|
||||
Infile json backup file
|
||||
Infile json backup file
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--dump Dump bookmark hierarchy (redirect to less or a file)
|
||||
-h, --help show this help message and exit
|
||||
--Print, -p Print bookmark hierarchy (redirect to less or a file)
|
||||
--Tags-Print, -t Print tags list
|
||||
--Tags-Count TAGS_COUNT, -c TAGS_COUNT
|
||||
Filter Tags-List for min number of times a tag is used (defult 2). =0 prints only single use tags.
|
||||
-V, --version Return version number and exit.
|
||||
```
|
||||
|
||||
## Internal command menu
|
||||
@@ -61,7 +67,9 @@ Five modes are supported Listing/Deleting based on:
|
||||
- Folders that have tags - there is no value for folders having tags
|
||||
- Empty folders - which may arise if all bookmarks were deleted from a folder
|
||||
|
||||
The Print function prints the full list of bookmarks in folder hierarchical form, listing the ID number and Title of each folder and bookmark. The `--dump` switch may be used for getting a good visual dump of the bookmarks in less or an editor for reference while using the interactive mode.
|
||||
The Print function prints the full list of bookmarks in folder hierarchical form, listing the ID number and Title of each folder and bookmark. The `--Print` switch may be used for getting a good visual dump of the bookmarks in less or an editor for reference while using the interactive mode. The tags on each bookmark are listed as well.
|
||||
|
||||
The `--Tags-Print` switch prints bookmarks by tag name, where a minimum of 2 bookmarks share the same tag, as set by the `--Tags-Count` switch. Setting `--Tags-Count 1` prints all bookmarks with tags. Setting `--Tags-Count 0` prints all bookmarks with only one tag - useful for finding remnant tags.
|
||||
|
||||
A lower case letter `t/g/d/f/x/y` will list the offenders, while an upper case letter
|
||||
`T/G/D/F/X/Y` will allow for selective deletes of the offenders. The lower case List operation
|
||||
@@ -88,3 +96,8 @@ syncID, so you may want to Disable Sync, then create a new sync before restoring
|
||||
- This code only works with Python 3. Development and testing was done on Linux with Python 3.7.3.
|
||||
|
||||
|
||||
## Version history
|
||||
|
||||
- 191206 v0.3 Added tags dump
|
||||
- 191205 v0.2 Updated to xbrowsersync v1.5 and Python 3.x ONLY
|
||||
- 181128 v0.1 New
|
||||
+53
-13
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
"""xBrowserSync json backup editor"""
|
||||
|
||||
__version__ = "v0.3 191206"
|
||||
|
||||
#==========================================================
|
||||
#
|
||||
desc = """xBrowserSync json backup editor"""
|
||||
# Chris Nelson 2018 - 2019
|
||||
#
|
||||
# 191205 Updated to xbrowsersync v1.5 and Python 3.x ONLY
|
||||
# 181128 New
|
||||
# 191206 v0.3 Added tags dump
|
||||
# 191205 v0.2 Updated to xbrowsersync v1.5 and Python 3.x ONLY
|
||||
# 181128 v0.1 New
|
||||
#
|
||||
# Issues, and changes pending
|
||||
# None
|
||||
@@ -31,6 +34,7 @@ NONE_SEARCH = "__NONE__"
|
||||
# Global items
|
||||
url_dict = {}
|
||||
folder_dict = {}
|
||||
tags_dict = {}
|
||||
|
||||
|
||||
def main():
|
||||
@@ -40,15 +44,29 @@ def main():
|
||||
global json_dict
|
||||
global url_dict
|
||||
global folder_dict
|
||||
global tags_dict
|
||||
|
||||
with io.open(args.Infile, encoding='utf8', errors="replace") as json_data:
|
||||
json_dict = json.load(json_data)
|
||||
|
||||
term = NONE_SEARCH
|
||||
|
||||
if args.dump:
|
||||
if args.Print:
|
||||
digin(parent=json_dict["xbrowsersync"]["data"]["bookmarks"], parent_id="", path="/", search_term="", operation="printtree")
|
||||
exit()
|
||||
if args.Tags_Print:
|
||||
digin(parent=json_dict["xbrowsersync"]["data"]["bookmarks"], parent_id="", path="/", search_term="", operation="GatherTags")
|
||||
for tag in sorted(tags_dict.keys()):
|
||||
if args.Tags_Count == 0:
|
||||
if len(tags_dict[tag]) == 1:
|
||||
print ("\n[{}]:".format(tag))
|
||||
print (" {:<4} - {}".format(tags_dict[tag][0]["id"], tags_dict[tag][0]["title"]))
|
||||
else:
|
||||
if len(tags_dict[tag]) >= args.Tags_Count:
|
||||
print ("\n[{}]:".format(tag))
|
||||
for bookmark in tags_dict[tag]:
|
||||
print (" {:<4} - {}".format(bookmark["id"], bookmark["title"]))
|
||||
exit()
|
||||
|
||||
while (1):
|
||||
match_cnt = 0
|
||||
@@ -150,8 +168,7 @@ Options:
|
||||
if ans == "":
|
||||
ans = args.Infile + OFILESUFFIX
|
||||
with io.open(ans, "w", encoding='utf8') as ofile:
|
||||
# json.dump(json_dict, ofile, indent=2) #, encoding="latin-1")
|
||||
json.dump(json_dict, ofile, ensure_ascii=False, indent=2) #, encoding="latin-1")
|
||||
json.dump(json_dict, ofile, ensure_ascii=False, indent=2)
|
||||
elif select == 'q':
|
||||
exit()
|
||||
|
||||
@@ -267,7 +284,12 @@ def digin(parent, parent_id, path, search_term, operation, commit=False, indent=
|
||||
|
||||
else: # ***** Its a Leaf node *****
|
||||
if operation == "printtree":
|
||||
print ("{:<4} - {}{}".format(item["id"], indent, item["title"]))
|
||||
tags = ""
|
||||
if "tags" in item:
|
||||
|
||||
for tag in item["tags"]:
|
||||
tags += tag + ", "
|
||||
print ("{:<4} - {}{} [{}]".format(item["id"], indent, item["title"], tags[:-2]))
|
||||
|
||||
if operation == "DupURLs":
|
||||
log_urls (item["url"], path, item["id"], parent, parent_id, item_index)
|
||||
@@ -311,6 +333,16 @@ def digin(parent, parent_id, path, search_term, operation, commit=False, indent=
|
||||
path_dict = {}
|
||||
return -1
|
||||
|
||||
if operation == "GatherTags":
|
||||
if "tags" in item:
|
||||
if item["tags"] != None:
|
||||
for tag in item["tags"]:
|
||||
if tag not in tags_dict:
|
||||
tags_dict[tag] = [{"title":item["title"], "id":item["id"]}]
|
||||
else:
|
||||
tags_dict[tag].append({"title":item["title"], "id":item["id"]})
|
||||
|
||||
|
||||
|
||||
path_dict = {}
|
||||
def collect_items (path, parent, index):
|
||||
@@ -418,9 +450,9 @@ def dup_urls (commit=False):
|
||||
|
||||
|
||||
def prompt (prompt_text):
|
||||
if sys.version_info[0] < 3:
|
||||
return (raw_input(prompt_text))
|
||||
else:
|
||||
# if sys.version_info[0] < 3:
|
||||
# return (raw_input(prompt_text))
|
||||
# else:
|
||||
return (input(prompt_text))
|
||||
|
||||
|
||||
@@ -470,11 +502,19 @@ def prompt (prompt_text):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('Infile',
|
||||
help="json backup file")
|
||||
parser.add_argument('--dump', action='store_true',
|
||||
help="Dump bookmark hierarchy (redirect to less or a file)")
|
||||
parser.add_argument('--Print', '-p', action='store_true',
|
||||
help="Print bookmark hierarchy (redirect to less or a file)")
|
||||
parser.add_argument('--Tags-Print', '-t', action='store_true',
|
||||
help="Print tags list")
|
||||
parser.add_argument('--Tags-Count', '-c', default=2, type=int,
|
||||
help="Filter Tags-List for min number of times a tag is used (defult 2). =0 prints only single use tags.")
|
||||
parser.add_argument('-V', '--version',
|
||||
help="Return version number and exit.",
|
||||
action='version',
|
||||
version='%(prog)s ' + __version__)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not os.path.exists(args.Infile):
|
||||
|
||||
Reference in New Issue
Block a user