Created
May 29, 2024 10:20
-
-
Save lincolnthalles/b220586cf9d74234f8f407ce984e6ee4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # Text file importer for Memos | |
| # https://www.usememos.com | |
| # | |
| # This script imports text files (preferably in Markdown format) into your Memos instance. | |
| # | |
| # Provide the instance's URL and acess token, and it will create a new memo for each matching | |
| # file in the source folder and subfolders. | |
| # | |
| # This script is designed to work with Python's 3.10 (or later) standard library. There's | |
| # no need to install any additional packages or deal with virtual environments. | |
| # | |
| # Memo visibility: | |
| # - PUBLIC: everyone can see. | |
| # - PROTECTED: all logged-in users can see. | |
| # - PRIVATE: only you can see. | |
| # | |
| # NOTES | |
| # ----- | |
| # - Memos imposes a 8 KiB limit for a single memo content. | |
| # | |
| # USAGE | |
| # ----- | |
| # python import_text_files.py --url=http://127.0.0.1:5230/ --token="YOUR_TOKEN" \ | |
| # --folder="~/Desktop/Obsidian" --visibility=PUBLIC --extensions .txt .md | |
| # | |
| import json | |
| from argparse import ArgumentParser | |
| from http.client import HTTPConnection, HTTPResponse, HTTPSConnection | |
| from pathlib import Path | |
| from sys import exit | |
| from urllib.parse import urlparse | |
| ########## DEFAULT SETTINGS ########## | |
| SOURCE_FOLDER = r"~/Desktop/Obsidian" | |
| SOURCE_EXTENSIONS = [".txt", ".md"] | |
| # Format: [http|https]://host:port | |
| MEMOS_URL = "http://127.0.0.1:32768/" | |
| # Token from Settings -> My Account | |
| MEMOS_TOKEN = r"YOUR_TOKEN" | |
| # PUBLIC, PROTECTED or PRIVATE | |
| MEMO_VISIBILITY = "PUBLIC" | |
| ##################################### | |
| def connect_to_memos(server_url: str) -> HTTPSConnection | HTTPConnection: | |
| url = urlparse(server_url) | |
| if not url.hostname: | |
| error = "invalid Memos server URL" | |
| raise ValueError(error) | |
| if url.scheme == "https": | |
| return HTTPSConnection(url.hostname, port=url.port or 443, timeout=5) | |
| return HTTPConnection(url.hostname, port=url.port or 80, timeout=5) | |
| def create_memo( | |
| http_conn: HTTPSConnection | HTTPConnection, token: str, content: str, visibility: str | |
| ) -> tuple[HTTPResponse, str]: | |
| http_conn.request( | |
| method="POST", | |
| url="/api/v2/memos", | |
| body=json.dumps({"content": content, "visibility": visibility.upper()}), | |
| headers={ | |
| "Content-Type": "application/json", | |
| "Authorization": f"Bearer {token}", | |
| }, | |
| ) | |
| response = http_conn.getresponse() | |
| response_body = response.read().decode(errors="ignore") | |
| return response, response_body | |
| if __name__ == "__main__": | |
| parser = ArgumentParser() | |
| parser.add_argument( | |
| "--url", "-u", default=MEMOS_URL, help='"Something like "http://127.0.0.1:5230/"' | |
| ) | |
| parser.add_argument("--token", "-t", default=MEMOS_TOKEN, help="Your Memos token") | |
| parser.add_argument( | |
| "--visibility", "-v", default=MEMO_VISIBILITY, help="PUBLIC, PROTECTED or PRIVATE" | |
| ) | |
| parser.add_argument( | |
| "--folder", "-f", default=SOURCE_FOLDER, help="Folder containing the text files" | |
| ) | |
| parser.add_argument( | |
| "--extensions", | |
| "-e", | |
| nargs="*", | |
| default=SOURCE_EXTENSIONS, | |
| help="Comma-separated list of file extensions", | |
| ) | |
| args = parser.parse_args() | |
| try: | |
| connection = connect_to_memos(args.url) | |
| except ValueError: | |
| raise | |
| root = Path(args.folder).expanduser().resolve() | |
| if not root.is_dir(): | |
| exit("Invalid source folder") | |
| print(f"Creating memos from {args.extensions} files in `{root}`...") | |
| col_width = len(args.url) + 28 | |
| ok, failed = 0, 0 | |
| for file in root.glob("**/*"): | |
| if not file.is_file() or file.suffix not in args.extensions: | |
| continue | |
| response, response_body = create_memo( | |
| http_conn=connection, | |
| token=args.token, | |
| content=file.read_text(encoding="utf-8"), | |
| visibility=args.visibility, | |
| ) | |
| filename = f"{file.parent.name}/{file.name}" | |
| body = json.loads(response_body) | |
| if response.status != 200: | |
| error = body.get("message") | |
| print( | |
| f"[❌] {response.reason} ({response.status}) - {error}".ljust(col_width) | |
| + f" ❌ {filename}" | |
| ) | |
| failed += 1 | |
| else: | |
| memo_uuid = body.get("memo").get("name") | |
| memo_url = args.url.rstrip("/") + f"/m/{memo_uuid}" | |
| print(f"[✅] {memo_url}".ljust(col_width) + f" ⏪ {filename}") | |
| ok += 1 | |
| print(f"[DONE] {ok} memos were created successfully. Failed: {failed}.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment