Пример #1
0
def rebuild_fts_index():
    """
    Rebuild virtual table for FTS (fulltext search)
    populating with all existing notes

    :return:
    """
    # Create empty FTS table from scratch
    try:
        # Remove table in case it existed
        NoteIndex.drop_table()
    except Exception:
        pass
    NoteIndex.create_table()

    # Add all entries into virtual FTS table
    notes = Note.select()
    with db.atomic():
        for note in notes:
            NoteIndex.insert(
                {
                    NoteIndex.uid: note.id,
                    NoteIndex.title: note.title,
                    NoteIndex.body: note.body,
                }
            ).execute()

    if config.DO_NOTIFY:
        notification.show("Rebuilt index", message="FTS index populated from scratch")
Пример #2
0
def rename_conflicting_notes():
    notes = Note.select().where(Note.is_conflict == 1)
    with db.atomic():
        for note in notes:
            if not note.title.endswith("(CONFLICT)"):
                note.title = note.title + " (CONFLICT)"
                num_saved_notes = note.save()
                if num_saved_notes != 1:
                    notification.show_error("Renaming conflicting note", note.title)
Пример #3
0
def list_conflicts():
    """
    List conflicting notes

    :return:
    """

    notes = Note.select().where(Note.is_conflict == 1)
    print("List of conflicting notes:")
    with db.atomic():
        for note in notes:
            print("-----------------------------")
            print("%s %s" % (note.id, note.title))
Пример #4
0
def get_notes_by_id(ids, ordered=False):
    # Find notes with id in uids
    # Peewee: `x << y` stands for `x in y`
    # NOTE: Order in query is unrelated to order in uids
    query = Note.select().where(Note.id << ids).dicts()
    # Debug: [note['id'] for note in query]

    if ordered:
        # Order query list in same order as uids
        dict_query = {note["id"]: note for note in query}
        # Grab note only if in the query
        ordered_notes = [dict_query[id] for id in ids if id in dict_query]
        query = ordered_notes
        # Debug: [note['id'] for note in query]

    return query
Пример #5
0
def find_empty_notes(delete=False):
    """
    Find and report empty notes
    Useful e.g. to find if some note was left empty due to synchronization issues

    :return:
    """

    notes = Note.select().order_by(Note.title)
    print("Listing empty notes:")
    with db.atomic():
        for note in notes:
            if not note.body:
                print("%s %s" % (note.id, note.title))
                if delete:
                    note.delete_instance()
                    print("Deleted")
Пример #6
0
def main():
    """Main program.
    Parse command line, then iterate over files and directories under
    rootdir and upload all files.  Skips some temporary files and
    directories, and avoids duplicate uploads by comparing size and
    mtime with the server.
    """
    # Get list of notes in Facebook notebook
    # These will be skipped in synchronization
    notebook = Folder.get(Folder.title == "fb")
    fb_notebook_id = notebook.id
    # NOTE: If fb folder does not exist, will throw FolderDoesNotExist
    # TODO: Catch it
    query = Note.select().where(Note.parent == fb_notebook_id)
    with db.atomic():
        fb_note_ids = [note.id for note in query]

    args = parser.parse_args()
    if sum([bool(b) for b in (args.yes, args.no, args.default)]) > 1:
        print("At most one of --yes, --no, --default is allowed")
        sys.exit(2)

    folder = args.folder
    rootdir = os.path.expanduser(args.rootdir)
    print("Dropbox folder name:", folder)
    print("Local directory:", rootdir)
    if not os.path.exists(rootdir):
        print(rootdir, "does not exist on your filesystem")
        sys.exit(1)
    elif not os.path.isdir(rootdir):
        print(rootdir, "is not a folder on your filesystem")
        sys.exit(1)

    for dn, dirs, files in os.walk(rootdir):
        subfolder = dn[len(rootdir):].strip(os.path.sep)
        listing = list_folder(dbx, folder, subfolder)
        print("Descending into", subfolder, "...")

        # First do all the files.
        for name in files:
            fullname = os.path.join(dn, name)
            if not isinstance(name, six.text_type):
                name = name.decode("utf-8")
            nname = unicodedata.normalize("NFC", name)
            if name.startswith("."):
                print("Skipping dot file:", name)
            elif name.startswith("@") or name.endswith("~"):
                print("Skipping temporary file:", name)
            elif name.endswith(".pyc") or name.endswith(".pyo"):
                print("Skipping generated file:", name)
            elif nname in listing:
                md = listing[nname]
                mtime = os.path.getmtime(fullname)
                mtime_dt = datetime.datetime(*time.gmtime(mtime)[:6])
                size = os.path.getsize(fullname)
                if (isinstance(md, dropbox.files.FileMetadata)
                        and mtime_dt == md.client_modified
                        and size == md.size):
                    print(name, "is already synced [stats match]")
                else:
                    print(name, "exists with different stats, downloading")
                    res = download(dbx, folder, subfolder, name)
                    with open(fullname) as f:
                        data = f.read()
                    if res == data:
                        print(name, "is already synced [content match]")
                    else:
                        print(name, "has changed since last sync")
                        if yesno("Refresh %s" % name, False, args):
                            upload(dbx,
                                   fullname,
                                   folder,
                                   subfolder,
                                   name,
                                   overwrite=True)
            elif yesno("Upload %s" % name, True, args):
                upload(dbx, fullname, folder, subfolder, name)

        # Then choose which subdirectories to traverse.
        keep = []
        for name in dirs:
            if name.startswith("."):
                print("Skipping dot directory:", name)
            elif name.startswith("@") or name.endswith("~"):
                print("Skipping temporary directory:", name)
            elif name == "__pycache__":
                print("Skipping generated directory:", name)
            elif yesno("Descend into %s" % name, True, args):
                print("Keeping directory:", name)
                keep.append(name)
            else:
                print("OK, skipping directory:", name)
        dirs[:] = keep
from __future__ import print_function
from peewee import fn, Entity
from pathlib2 import Path
import subprocess
from termcolor import colored


from pyjoplin.models import Note, NoteIndex, database as db
from pyjoplin.configuration import config
from pyjoplin import notification

path_repo = Path.home() / 'Backup/joplin'

printc = lambda x: print(colored(x, 'cyan'))

notes = Note.select().order_by(Note.title)
print("Listing empty notes:")
for note in notes:
    if not note.body:
        printc('Empty: %s %s' % (note.id, note.title))
        notefile = '%s.md' % note.id

        cmd = 'git rev-list HEAD -- %s ' % notefile
        out = subprocess.check_output(cmd, shell=True, cwd=str(path_repo))
        for sha in out.strip().split('\n'):
            cmd = 'git show %s:%s' % (sha, notefile)
            note_content = subprocess.check_output(cmd, shell=True, cwd=str(path_repo))
            filtered_lines = list()
            for idx, line in enumerate(note_content.split('\n')):
                if idx in [0, 1]:
                    continue