7th August 2024
Life Management⚑
Time management⚑
Org Mode⚑
-
New: Change the default org-todo-keywords.
orig = '''* NEW_TODO_STATE First entry * NEW_DONE_STATE Second entry''' doc = loads(orig, environment={ 'org-todo-keywords': "NEW_TODO_STATE | NEW_DONE_STATE" })
Knowledge Management⚑
Aleph⚑
-
New: API Usage.
The Aleph web interface is powered by a Flask HTTP API. Aleph supports an extensive API for searching documents and entities. It can also be used to retrieve raw metadata, source documents and other useful details. Aleph's API tries to follow a pragmatic approach based on the following principles:
- All API calls are prefixed with an API version; this version is /api/2/.
- Responses and requests are both encoded as JSON. Requests should have the Content-Type and Accept headers set to application/json.
- The application uses Representational State Transfer (REST) principles where convenient, but also has some procedural API calls.
- The API allows API Authorization via an API key or JSON Web Tokens.
Authentication and authorization
By default, any Aleph search will return only public documents in responses to API requests.
If you want to access documents which are not marked public, you will need to sign into the tool. This can be done through the use on an API key. The API key for any account can be found by clicking on the "Profile" menu item in the navigation menu.
The API key must be sent on all queries using the Authorization HTTP header:
Authorization: ApiKey 363af1e2b03b41c6b3adc604956e2f66
Alternatively, the API key can also be sent as a query parameter under the api_key key.
Similarly, a JWT can be sent in the Authorization header, after it has been returned by the login and/or OAuth processes. Aleph does not use session cookies or any other type of stateful API.
-
New: Crossreferencing mentions with entities.
Mentions are names of people or companies that Aleph automatically extracts from files you upload. Aleph includes mentions when cross-referencing a collection, but only in one direction.
Consider the following example:
- "Collection A" contains a file. The file mentions "John Doe".
- "Collection B" contains a Person entity named "John Doe".
If you cross-reference “Collection A”, Aleph includes the mention of “John Doe” in the cross-referencing and will find a match for it in “Collection B”.
However, if you cross-reference “Collection B”, Aleph doesn't consider mentions when trying to find a match for the Person entity.
As long as you only want to compare the mentions in one specific collection against entities (but not mentions) in another collection, Aleph’s cross-ref should be able to do that. If you want to compare entities in a specific collection against other entities and mentions in other collections, you will have to do that yourself.
If you have a limited number of collection, one option might be to fetch all mentions and automatically create entities for each mention using the API.
To fetch a list of mentions for a collection you can use the
/api/2/entities?filter:collection_id=137&filter:schemata=Mention
API request.
Coding⚑
Languages⚑
Configure Docker to host the application⚑
-
New: Minify the images.
dive and slim are two cli tools you can use to optimise the size of your dockers.
Python Snippets⚑
-
New: Send a linux desktop notification.
To show a Linux desktop notification from a Python script, you can use the
notify2
library (although it's last commit was done on 2017. This library provides an easy way to send desktop notifications on Linux.Alternatively, you can use the
subprocess
module to call thenotify-send
command-line utility directly. This is a more straightforward method but requiresnotify-send
to be installed.import subprocess def send_notification(title: str, message: str = "", urgency: str = "normal") -> None: """Send a desktop notification using notify-send. Args: title (str): The title of the notification. message (str): The message body of the notification. Defaults to an empty string. urgency (str): The urgency level of the notification. Can be 'low', 'normal', or 'critical'. Defaults to 'normal'. """ subprocess.run(["notify-send", "-u", urgency, title, message])
-
import traceback def cause_error(): return 1 / 0 # This will raise a ZeroDivisionError try: cause_error() except Exception as error: # Capture the exception traceback as a string error_message = "".join(traceback.format_exception(None, error, error.__traceback__)) print("An error occurred:\n", error_message)
Coding tools⚑
Coding with AI⚑
-
New: Add new prompts for developers.
- trigger: :polish form: | Polish the next code [[code]] with the next conditions: - Use type hints on all functions and methods - Add or update the docstring using google style on all functions and methods form_fields: code: multiline: true - trigger: :commit form: | Act as an expert developer. Create a message commit with the next conditions: - follow semantic versioning - create a semantic version comment per change - include all comments in a raw code block so that it's easy to copy for the following diff [[text]] form_fields: text: multiline: true
Espanso⚑
-
New: Desktop application to add words easily.
Going into the espanso config files to add words is cumbersome, to make things easier you can use the
espansadd
Python script.I'm going to assume that you have the following prerequisites:
- A Linux distribution with i3 window manager installed.
- Python 3 installed.
- Espanso installed and configured.
ruyaml
andtkinter
Python libraries installed.notify-send
installed.- Basic knowledge of editing configuration files in i3.
Installation
Create a new Python script named
espansadd.py
with the following content:import tkinter as tk from tkinter import simpledialog import traceback import subprocess import os import sys from ruyaml import YAML from ruyaml.scanner import ScannerError file_path = os.path.expanduser("~/.config/espanso/match/typofixer_overwrite.yml") def append_to_yaml(file_path: str, trigger: str, replace: str) -> None: """Appends a new entry to the YAML file. Args:ath file_path (str): The file to append the new entry. trigger (str): The trigger string to be added. replace (str): The replacement string to be added. """ # Define the new snippet new_entry = { "trigger": trigger, "replace": replace, "propagate_case": True, "word": True, } # Load existing data or initialize an empty list try: with open(os.path.expanduser(file_path), "r") as f: try: data = YAML().load(f) except ScannerError as e: send_notification( f"Error parsing yaml of configuration file {file_path}", f"{e.problem_mark}: {e.problem}", "critical", ) sys.exit(1) except FileNotFoundError: send_notification( f"Error opening the espanso file {file_path}", urgency="critical" ) sys.exit(1) data["matches"].append(new_entry) # Write the updated data back to the file with open(os.path.expanduser(file_path), "w+") as f: yaml = YAML() yaml.default_flow_style = False yaml.dump(data, f) def send_notification(title: str, message: str = "", urgency: str = "normal") -> None: """Send a desktop notification using notify-send. Args: title (str): The title of the notification. message (str): The message body of the notification. Defaults to an empty string. urgency (str): The urgency level of the notification. Can be 'low', 'normal', or 'critical'. Defaults to 'normal'. """ subprocess.run(["notify-send", "-u", urgency, title, message]) def main() -> None: """Main function to prompt user for input and append to the YAML file.""" # Create the main Tkinter window (it won't be shown) window = tk.Tk() window.withdraw() # Hide the main window # Prompt the user for input trigger = simpledialog.askstring("Espanso add input", "Enter trigger:") replace = simpledialog.askstring("Espanso add input", "Enter replace:") # Check if both inputs were provided try: if trigger and replace: append_to_yaml(file_path, trigger, replace) send_notification("Espanso snippet added successfully") else: send_notification( "Both trigger and replace are required", urgency="critical" ) except Exception as error: error_message = "".join( traceback.format_exception(None, error, error.__traceback__) ) send_notification( "There was an unknown error adding the espanso entry", error_message, urgency="critical", ) if __name__ == "__main__": main()
Ensure the script has executable permissions. Run the following command:
chmod +x espansadd.py
To make the
espansadd
script easily accessible, we can configure a key binding in i3 to run the script. Open your i3 configuration file, typically located at~/.config/i3/config
or~/.i3/config
, and add the following lines:bindsym $mod+Shift+e exec --no-startup-id /path/to/your/espansadd.py
Replace
/path/to/your/espansadd.py
with the actual path to your script.If you also want the popup windows to be in floating mode add
for_window [title="Espanso add input"] floating enable
After editing the configuration file, reload i3 to apply the changes. You can do this by pressing
Mod
+Shift
+R
(whereMod
is typically theSuper
orWindows
key) or by running the following command:i3-msg reload
Usage
Now that everything is set up, you can use the
espansadd
script by pressingMod
+Shift
+E
. This will open a dialog where you can enter the trigger and replacement text for the new Espanso snippet. After entering the information and pressing Enter, a notification will appear confirming the snippet has been added, or showing an error message if something went wrong.
Operating Systems⚑
Linux⚑
Wireguard⚑
-
New: Check the status of the tunnel.
One method is to do ping between VPN IP addresses or run command
wg show`` from the server or from the client. Below you can see
wg show`` command output where VPN is not up.$: wg show interface: wg0 public key: qZ7+xNeXCjKdRNM33Diohj2Y/KSOXwvFfgTS1LRx+EE= private key: (hidden) listening port: 45703 peer: mhLzGkqD1JujPjEfZ6gkbusf3sfFzy+1KXBwVNBRBHs= endpoint: 3.133.147.235:51820 allowed ips: 10.100.100.1/32 transfer: 0 B received, 592 B sent persistent keepalive: every 21 seconds
The below output from the
wg show
command indicates the VPN link is up. See the line withlast handshake time
$: wg show interface: wg0 public key: qZ7+xNeXCjKdRNM33Diohj2Y/KSOXwvFfgTS1LRx+EE= private key: (hidden) listening port: 49785 peer: 6lf4SymMbY+WboI4jEsM+P9DhogzebSULrkFowDTt0M= endpoint: 3.133.147.235:51820 allowed ips: 10.100.100.1/32 latest handshake: 14 seconds ago transfer: 732 B received, 820 B sent persistent keepalive: every 21 seconds