commit fffeecde795b5ffdd203cc26fc2d60ac756ca904 Author: Kun Deng Date: Thu Sep 29 19:49:34 2022 -0400 Initial commit diff --git a/Main.py b/Main.py new file mode 100644 index 0000000..6f90275 --- /dev/null +++ b/Main.py @@ -0,0 +1,257 @@ +import sys +import io +import json + +import log21 +import simplenote + +import OneNoteManager +import Models + + + + +def contains_title_and_content(content): + + text = "\n\n" + + amount = content.count(text) + + if amount < 0: + return False + + + return True + +def delete_note(cred, note): + sn = simplenote.Simplenote(cred.username, cred.password) + + print("Hehe!!") + return + + sn.delete_note(note.note_id) + + +def get_simplenote_list(cred): + sn = simplenote.Simplenote(cred.username, cred.password) + + elements = sn.get_note_list() + + notes = [] + + for e in elements: + + in_valid = lambda obj : obj == 0 + + if in_valid(e): + continue + + for i in e: + # In Simplenote, notes with no content the 'content' would be the title + content = "" + title = i['content'] + id = i['key'] + + if contains_title_and_content(title): + # Parse the title from the content + # + # The title and content are delimited by '\n\n' + split = title.split("\n\n") + + title = split[0] + + split.remove(split[0]) + content = "\n\n".join(split) + + note = Models.SimpleNote(title, content) + note.note_id = id + notes.append(note) + + return notes + +def iterate_simplenotes(notes): + for note in notes: + print("Title: %s" % (note.title)) + + if note.content == "": + print("Content: None") + else: + print("Content: %s" % (note.content)) + +def is_valid_notebook(onenote_notebooks, chosen_notebook): + res = False + + notes = onenote_notebooks + + for value in notes["value"]: + display_name = value["displayName"] + + if display_name == chosen_notebook: + res = True + break + + return res + +def retrieve_notebook(onenote_notebooks, chosen_notebook): + notes = onenote_notebooks + + for value in notes["value"]: + display_name = value["displayName"] + + if display_name == chosen_notebook: + return value + + return str() + +def is_valid_section(onenote_sections, chosen_section): + res = False + + sections = onenote_sections + + for value in sections["value"]: + display_name = value["displayName"] + + if display_name == chosen_section: + res = True + break + + return res + +def retrieve_section(onenote_sections, chosen_section): + sections = onenote_sections + + for value in sections["value"]: + display_name = value["displayName"] + + if display_name == chosen_section: + return value + + return str() + +def is_valid_note(onenote_notes, onenote_section): + res = False + + notes = onenote_notes + + for value in notes["value"]: + display_name = value["parentSection"]["displayName"] + + print("Section: %s" % (display_name)) + + if display_name == onenote_section["displayName"]: + res = True + break + + + return res + + +def export_to_onenote(simplenotes, onenote_mgr, chosen_notebook=None, chosen_section=None): + onenote_notebooks = onenote_mgr.get_notebooks() + + if not is_valid_notebook(onenote_notebooks, chosen_notebook): + print("Notebook not found for '%s'" % (chosen_notebook)) + return + + onenote_notebook = retrieve_notebook(onenote_notebooks, chosen_notebook) + + if onenote_notebook == "": + print("No notebooks found") + return + + onenote_sections = onenote_mgr.get_sections() + + if not is_valid_section(onenote_sections, chosen_section): + print("Section not found for '%s'" % (chosen_section)) + return + + onenote_section = retrieve_section(onenote_sections, chosen_section) + url="https://graph.microsoft.com/v1.0/me/onenote/sections/" + onenote_section["id"] + "/pages" + onenote_notes = onenote_mgr.get_notes(url) + + count = 0 + + for note in onenote_notes["value"]: + count += 1 + + if not is_valid_note(onenote_notes, onenote_section): + print("Note not foudn for '%s'" % (chosen_section)) + return + + for note in simplenotes: + simplenote_id = note.note_id + + +def main(): + + if len(sys.argv) < 3: + print("Provide arguments\n") + print("main.py 'username' 'password'") + + sys.exit(-1) + + logger.info("simplenote_export running") + + cred = Models.SimplenoteCredentials(sys.argv[1], sys.argv[2]) + + print("Username: %s" % (cred.username)) + + print("Hello") + + notes = get_simplenote_list(cred) + + """ + What's left? + 1. Implement function to retrieve notes from OneNote + 2. Implement function to add note to OneNote + 3. Implement function to see if note exists in OneNote (Optional) + - If this isn't feasible or will require more effort than expected, just retrieve notes from + OneNote after adding a note to get the updated notes + + Will need to add a note to a specific notebook and int a specific notebook + 1. [X] Get list of notebooks + 2. [X] Use the display name to find the desired notebook + 3. [X] If it isn't found, terminate the program. If found, parse out the display name and id of the notebook + 4. [X] Get a list of sections + 5. [X] Check to see if a section exists where the parent notebook is the one you selected. Terminate if not + 6. [X] Get OneNote Notes (By section id and check to see if there is a @data.nextLink) + 7. [X] Check to see if the notes are part of the section + 8. [X] Get a list of OneNote notes that's part of the section + 9. Iterate through Simplenote notes + 10. Check to see if a OneNote note exists that comes from the selected notebook and section. Terminate if not + 11. Check to see if the iterated Simplenote note exists in OneNote with the matched criteria. Terminate if so + 12. Create page in OneNote using the iterated Simplenote note + 13. Retrieve the OneNote pages again + 14. Check to see if the page has been created + 15. Delete the Simplenote note + """ + + onenote_mgr = OneNoteManager.OneNoteManager() + + dev = 1 + + token = Models.ResponseToken() + + if dev == 0: + print("Enter token: ") + token_input = input() + token.access_token = token_input + elif dev == 1: + fi = io.open("token.txt") + token.access_token = fi.read() + else: + token = onenote_mgr.fetch_token() + + onenote_mgr.load_token(token) + + export_to_onenote(notes, onenote_mgr, chosen_notebook="Simplenote", chosen_section="From Simplenote") + + + # iterate_simplenotes(notes) + + +logger = log21.get_logger('My Logger', level_names={21: 'SpecialInfo', log21.WARNING: ' ! ', log21.ERROR: '!!!'}) +logger.log(21, 'Here', '%s', 'GO!', args=('we',)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Models.py b/Models.py new file mode 100644 index 0000000..3046820 --- /dev/null +++ b/Models.py @@ -0,0 +1,57 @@ + +class SimpleNote(object): + def __init__(self, title=None, content=None): + self.title = title + self.content = content + + note_id = 0 + + +class SimplenoteCredentials(object): + def __init__(self, username, password): + self.username = username + self.password = password + +class TokenClaims(object): + def __init__(self, ver=None, iss=None, sub=None, aud=None, exp=None, iat=None, nbf=None, name=None, perferred_username=None, oid=None, tid=None, aio=None): + self.ver = ver + self.iss = iss + self.sub = sub + self.aud = aud + self.exp = exp + self.iat = iat + self.nbf = nbf + self.name = name + self.preferred_username = perferred_username + self.oid = oid + self.tid = tid + self.aio = aio + +class ResponseToken(object): + + + def __init__(self, token_type=None, scope=None, expires_in=None, ext_expires_in=None, access_token=None, refresh_token=None, id_token=None, client_info=None, id_token_claims=None): + self.token_type = token_type + self.scope = scope + self.expires_in = expires_in + self.ext_expires_in = ext_expires_in + self.access_token = access_token + self.refresh_token = refresh_token + self.id_token = id_token + self.client_info = client_info + self.id_token_claims = id_token_claims + + token_type = "" + scope = "" + expires_in = 0 + ext_expires_in = 0 + access_token = "" + refresh_token = "" + id_token = "" + client_info = "" + id_token_claims = TokenClaims() + +class OneNote(object): + def __init__(self, title=None, content=None): + self.title = title + self.content = content \ No newline at end of file diff --git a/OneNoteManager.py b/OneNoteManager.py new file mode 100644 index 0000000..ed3efd7 --- /dev/null +++ b/OneNoteManager.py @@ -0,0 +1,162 @@ +import json +import webbrowser +import subprocess + +import ast +import msal +import requests + +import Models + +""" +APP_ID = "3079e919-8f04-41b7-8b97-5694679bd4f3" +SECRET = "23379d03-b2a5-4dd2-a4d0-233b3b40588f" +SECRET = "v-Z8Q~iy~vA77IarV5izSqG0e3uX-qBtItFHudd2" +# "Notes.Create", "Notes.Read", "Notes.Read.All", "Notes.ReadWrite", "Notes.ReadWrite.All", "Notes.ReadWrite.CreatedByApp" +# SCOPES = [''] +SCOPES = ["Notes.Create", "Notes.Read", "Notes.Read.All", "Notes.ReadWrite", "Notes.ReadWrite.All", "Notes.ReadWrite.CreatedByApp"] + +AUTHORITY_URL = "https://login.microsoftonline.com/consumers/" +base_url = "https://graph.microsoft.com/v1.0/" +endpoint = base_url + "me" +""" + + +class OneNoteManager(object): + + def __init__(self, token=None): + self.token = token + + + def __auth_header(self): + headers = {"Authorization": f"Bearer {self.__token.access_token}"} + + return headers + + # retrieving OneNote notebooks + def get_notebooks(self): + url = "https://graph.microsoft.com/v1.0/me/onenote/notebooks" + + headers = self.__auth_header() + req = requests.get(url, headers=headers) + content = req.content + j_obj = content.decode("utf8") + + + note_d = dict() + note_d = json.loads(j_obj) + + return note_d + + + return json_data + + # retrieving OneNote sections + def get_sections(self): + url = "https://graph.microsoft.com/v1.0/me/onenote/sections" + + headers = self.__auth_header() + req = requests.get(url, headers=headers) + content = req.content + j_obj = content.decode("utf8") + + sect_d = dict() + sect_d = json.loads(j_obj) + + return sect_d + + # retrieving OneNote notes given a url + def get_notes(self, url): + notes = dict() + + headers = self.__auth_header() + req = requests.get(url, headers=headers) + content = req.content + j_obj = content.decode("utf8") + + notes = json.loads(j_obj) + + if "@odata.nextLink" in notes: + nextLink = notes["@odata.nextLink"] + notes_s = self.get_notes(nextLink) + + for note in notes_s["value"]: + notes["value"].append(note) + + return notes + + # Implement this function + def add_note(self, note): + + url = "https://graph.microsoft.com/v1.0/me/onenote/sections/{section-id}/pages" + + data = {"dsfsdf", "sdfsdf"} + headers = self.__auth_header() + req = requests.post(url, data=data, headers=headers) + content = req.content + j_obj = content.decode("utf8").replace("'", '"') + + json_data = json.dumps(j_obj) + + print("Add") + + return json_data + + # Returns string representation of the note used for creating pages + def note_to_data(self, note): + title_str = note.title + content_str = note.content + + data ="" + + if content_str == "": + data = f"title_str " + else: + data = f"title_str content_str" + + return data + + + def fetch_token(self): + app = msal.PublicClientApplication(self.__APP_ID, + authority=self.__AUTHORITY_URL + ) + + accounts = app.get_accounts() + + if accounts: + app.acquire_token_silent(scopes=self.__SCOPES, account=accounts[0]) + + flow = app.initiate_device_flow(scopes=self.__SCOPES) + user_code = flow['user_code'] + print('User code: %s' % (user_code)) + print("Enter code in browser to continue (Has been entered into clipboard)\n") + + + useless_cat_call = subprocess.run(["clip.exe"], stdout=subprocess.PIPE, text=True, input=user_code) + + app_code = flow['message'] + + webbrowser.open(flow['verification_uri']) + + token_response = app.acquire_token_by_device_flow(flow) + + json_data = json.dumps(token_response) + self.__token = Models.ResponseToken(**json.loads((json_data))) + + print("Access token: %s" % (self.__token.access_token)) + + return self.__token + + def load_token(self, token): + self.__token = token + + + __APP_ID = "3079e919-8f04-41b7-8b97-5694679bd4f3" + __SECRET = "v-Z8Q~iy~vA77IarV5izSqG0e3uX-qBtItFHudd2" + __SCOPES = ["Notes.Create", "Notes.Read", "Notes.Read.All", "Notes.ReadWrite", "Notes.ReadWrite.All", "Notes.ReadWrite.CreatedByApp"] + + __AUTHORITY_URL = "https://login.microsoftonline.com/consumers/" + __base_url = "https://graph.microsoft.com/v1.0/" + __endpoint = __base_url + "me" + __token = Models.ResponseToken() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cf94bfd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +simplenote==2.1.4 +log21==2.3.10 +msal==1.18.0 \ No newline at end of file diff --git a/token.txt b/token.txt new file mode 100644 index 0000000..3536539 --- /dev/null +++ b/token.txt @@ -0,0 +1 @@ +Place token here