Skip to content

Instantly share code, notes, and snippets.

@nandini-menon
Last active December 31, 2022 00:53
Show Gist options
  • Save nandini-menon/0b10c1276db767bc0f1af2cfc8aece5b to your computer and use it in GitHub Desktop.
Save nandini-menon/0b10c1276db767bc0f1af2cfc8aece5b to your computer and use it in GitHub Desktop.
Automate Creation of OneNote Notebooks

Automate OneNote Creation

The code for automating OneNote creation was written with a wider scope in mind. I intend on creating a wrapper package for the OneNote API. So, there are a lot of abstractions. If you need any clarifications, just ping me.

Azure App Requirements

Before executing this script, you need to have an App in the Azure AD with the following delegated permissions:-

  • Notes.Create
  • Notes.Read
  • Notes.ReadWrite
  • Notes.Read.All
  • Notes.ReadWrite.All

You also have to set the Redirect URI of your app to https://login.microsoftonline.com/{azure_active_directory_id}/oauth2/token.

You also need to generate a client secret key referred to as client_secret in the program.

Note: Remember to copy and store your key somewhere safely as soon as you generate it. It will not be visible for long due to security reasons.

Other requirements

The Python requests package should be installed

Code

The following code is for generating 1000 OneNote Notebooks with each Notebook having 2 sections and each section having 2 pages.

This is what the Notebokk structure will look like:-

📦Notebook
 ┣ 📂Section_1
 ┃ ┣ 📜Page_1
 ┃ ┗ 📜Page_2
 ┗ 📂Section_2
 ┃ ┣ 📜Page_1
 ┃ ┗ 📜Page_2

To add more notebooks or to change the number of sections/pages, just change the values of the loops.

import requests
import json


class OneNoteAPI:
    def __init__(self, app_id, client_secret, tenant_id):
        self.app_id = app_id
        self.client_secret = client_secret
        self.tenant_id = tenant_id
        self.access_token = None
        self.refresh_token = None


    def authorize(self, username, password):
        url = f'https://login.microsoftonline.com/{self.tenant_id}/oauth2/token'

        token_data = {
            'grant_type': 'password',
            'client_id': self.app_id,
            'client_secret': self.client_secret,
            'resource': 'https://graph.microsoft.com',
            'scopes': ['onedrive.readwrite', 'offline_access'],
            'username': username,
            'password': password,
        }
        token_r = requests.post(url, data=token_data)
        self.access_token = token_r.json().get('access_token')
        self.refresh_token = token_r.json().get('refresh_token')

    def refresh_access_token(self):
        url = f'https://login.microsoftonline.com/{self.tenant_id}/oauth2/token'

        token_data = {
            'grant_type': 'refresh_token',
            'client_id': self.app_id,
            'client_secret': self.client_secret,
            'resource': 'https://graph.microsoft.com',
            'scopes': ['onedrive.readwrite', 'offline_access'],
            'refresh_token': self.refresh_token,
        }
        token_r = requests.post(url, data=token_data)
        self.access_token = token_r.json().get('access_token')
        self.refresh_token = token_r.json().get('refresh_token')


    def create_notebook(self, notebook_name):
        url = 'https://graph.microsoft.com/v1.0/me/onenote/notebooks'
        data = {
            'displayName': notebook_name
        }
        return self._post(url, json=data)

    def create_section(self, notebook_id, section_name):
        url = f'https://graph.microsoft.com/v1.0/me/onenote/notebooks/{notebook_id}/sections'
        data = {
            'displayName': section_name
        }
        return self._post(url, json=data)

    def create_page(self, section_id, data, **kwargs):
        url = f'https://graph.microsoft.com/v1.0/me/onenote/sections/{section_id}/pages'
        kwargs['headers'] = {'Content-Type': 'application/xhtml+html'}
        return self._post(url, params=data, **kwargs)


    def _get(self, url, **kwargs):
        return self._request('GET', url, **kwargs)

    def _post(self, url, **kwargs):
        return self._request('POST', url, **kwargs)

    def _put(self, url, **kwargs):
        return self._request('PUT', url, **kwargs)

    def _patch(self, url, **kwargs):
        return self._request('PATCH', url, **kwargs)

    def _delete(self, url, **kwargs):
        return self._request('DELETE', url, **kwargs)


    def _request(self, method, url, headers=None, **kwargs):
        _headers = {
            'Accept': 'application/json',
        }
        _headers['Authorization'] = 'Bearer ' + self.access_token
        if headers:
            _headers.update(headers)
        if 'files' not in kwargs:
            # If you use the 'files' keyword, the library will set the Content-Type to multipart/form-data
            # and will generate a boundary.
            _headers['Content-Type'] = 'application/json'
        return self._parse(requests.request(method, url, headers=_headers, **kwargs))

    def _parse(self, response):
        if 'application/json' in response.headers['Content-Type']:
            return response.json()
        else:
            return response


def main():
    app_id = '{app_id}'
    client_secret = '{client_secret}'
    tenant_id = '{azure_active_directory_id}'

    username = '{email_id_of_user}'
    password = '{password}'

    client = OneNoteAPI(app_id, client_secret, tenant_id)
    client.authorize(username, password)

    for i in range(1, 1001):
        notebook = client.create_notebook(f'Notebook_{i}')
        try:
            notebook_id = notebook['id']
        except KeyError:
            client.refresh_access_token()
            notebook = client.create_notebook(f'Notebook_{i}')
            print(notebook)
            notebook_id = notebook['id']
        print(f'Notebook {i} created')
        for j in range (1, 3):
            section = client.create_section(notebook_id, f'Note_{i}_Section_{j}')
            try:
                section_id = section['id']
            except KeyError:
                client.refresh_access_token()
                section = client.create_section(notebook_id, f'Note_{i}_Section_{j}')
                print(section)
                section_id = section['id']
            print(f'Notebook {i} Section {j} created')
            for k in range(1, 3):
                page_data = f'<html><head> <title>N_{i}_Sec_{j}_Page_{k}</title> <style>div{{position: absolute; left: 50%; transform: translate(-50%,0); text-align: center;}}h3, button{{text-align: center; font-size: 2rem;}}button{{margin:auto;}}</style></head><body> <div> <h3>Without any modifications</h3> <button>Hello</button> <h3>With padding</h3> <button style="padding:30px;">Hello</button> <h3>With margin</h3> <button style="margin:30px;">Hello</button> <h3>With margin and padding</h3> <button style="margin:30px; padding:30px;">Hello</button> </div></body><html>'
                response = client.create_page(section_id, page_data)
                try:
                    if response.status_code == 401:
                        client.refresh_access_token()
                        print(client.create_page(section_id, page_data))
                except AttributeError:
                    pass
                print(f'Notebook {i} Section {j} Page {k} created')

if __name__ == '__main__':
    main()

To run the program, save the above code to a file and just execute the following command from command prompt/powershell/terminal:-

$ python file_name.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment