Last active
November 17, 2025 19:23
-
-
Save nerun/25bad2359b873351a65c40b1d425766f to your computer and use it in GitHub Desktop.
A daily log of experiences (daybook, journal), a personal organizer or an appointment diary to be run in a linux terminal. Totally written in shell script. Support AES-256 symmetric encryption through 7-Zip.
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
| #!/bin/zsh | |
| ############################################################################## | |
| # DIÁRIO NUM TERMINAL | |
| # | |
| # Copyright (C) 2023, 2024, 2025 Daniel Dias Rodrigues | |
| # | |
| # Source code is available at: | |
| # https://gist.github.com/nerun/25bad2359b873351a65c40b1d425766f | |
| # | |
| # This program is free software; you can redistribute it and/or modify it | |
| # under the terms of the Creative Commons Zero 1.0 Universal (CC0 1.0) Public | |
| # Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/). | |
| # | |
| # INSTALLATION: | |
| # Copy "diario" to one of: | |
| # ~/.local/bin | |
| # /usr/bin | |
| # /usr/local/bin | |
| ############################################################################## | |
| # Settings | |
| journal="$HOME/.diario" | |
| editor="nano" | |
| software_title="Diário num terminal" | |
| crypt_journal="journal.7z" | |
| if [[ ! -d "$journal" ]]; then | |
| mkdir -p "$journal" | |
| fi | |
| about=" | |
| Copyright (C) 2023, 2024, 2025 Daniel Dias Rodrigues | |
| Source code is available at: | |
| https://gist.github.com/nerun/25bad2359b873351a65c40b1d425766f | |
| This program is free software; you can redistribute it and/or modify it under the terms of the Creative Commons Zero 1.0 Universal (CC0 1.0) Public Domain Dedication: | |
| https://creativecommons.org/publicdomain/zero/1.0 | |
| " | |
| # Auxiliary function for selecting a record. | |
| select_record() { | |
| local title="$1" | |
| local message="$2" | |
| # Create an array of items for the menu. | |
| local menu_items=() | |
| local records=($(find "$journal" -type f -not -name "$crypt_journal" | sort -r)) | |
| for record in "${records[@]}"; do | |
| local filename=$(basename "$record") | |
| local preview=$(cut -c 1-46 "$record" 2>/dev/null | sed 's/[[:cntrl:]]//g') | |
| # If preview is empty, show "(empty)" | |
| if [[ -z "$preview" ]]; then | |
| preview="(vazio)" | |
| fi | |
| # Add to array: "filename" "preview" | |
| menu_items+=("$filename" "$preview") | |
| done | |
| if [[ ${#menu_items[@]} -eq 0 ]]; then | |
| dialog --clear --backtitle "$software_title" \ | |
| --title "Nenhum Registro" \ | |
| --msgbox "\nNão há registros disponíveis." 7 40 | |
| echo "" | |
| return 1 | |
| fi | |
| local selected_record=$(dialog --clear --backtitle "$software_title" \ | |
| --title "$title" \ | |
| --menu "$message" 17 72 10 \ | |
| "${menu_items[@]}" \ | |
| 3>&1 1>&2 2>&3 3>&-) | |
| echo "$selected_record" | |
| } | |
| crypt(){ | |
| # Use 7-ZIP with 7zAES:19, that means | |
| # AES-256 + (2^19) SHA-256 iterations in password to key function | |
| # encrypt = $crypt_journal and delete text files | |
| # decrypt = delete $crypt_journal | |
| if [[ "$2" = "Encriptar diário" ]]; then | |
| 7za a -mhe=on -mx=0 -P"$1" $journal/$crypt_journal $journal/* >/dev/null | |
| if [[ -f $journal/$crypt_journal ]]; then | |
| find $journal -type f -not -name "$crypt_journal" -delete | |
| fi | |
| else | |
| # "$2" = "Decriptar diário" | |
| 7za x -P"$1" $journal/$crypt_journal -o"$journal" >/dev/null | |
| if [[ $? = 0 ]]; then | |
| rm $journal/$crypt_journal | |
| else | |
| dialog --clear --backtitle "$software_title" \ | |
| --title "Senha Incorreta" \ | |
| --msgbox "\n A senha está incorreta!" 6 29 | |
| fi | |
| fi | |
| } | |
| menu(){ | |
| clear | |
| local records=($(find $journal -type f)) | |
| if [[ ! "${records[@]}" =~ "$crypt_journal" ]]; then | |
| # Journal IS NOT encrypted | |
| if [[ ${#records[@]} > 0 ]]; then | |
| local num_registros="Foi encontrado 1 registro." | |
| if [[ ${#records[@]} > 1 ]]; then | |
| local num_registros="Foram encontrados ${#records[@]} registros." | |
| fi | |
| local choice=$(dialog --clear --backtitle "$software_title" \ | |
| --title "Menu Principal" \ | |
| --menu "\n$num_registros\n\nO que deseja fazer?" 15 40 4 \ | |
| 1 "Criar um novo registro" \ | |
| 2 "Editar e/ou Ler um registro" \ | |
| 3 "Apagar um registro" \ | |
| 4 "Encriptar diário" \ | |
| 5 "Sobre" \ | |
| 3>&1 1>&2 2>&3 3>&- ) | |
| # "3>&1 1>&2 2>&3 3>&-" means: | |
| # 3>&1 opens a new file descriptor which points to stdout | |
| # 1>&2 redirects stdout to stderr | |
| # 2>&3 points stderr to stdout | |
| # 3>&- deletes the files descriptor 3 after the command has been | |
| # executed. | |
| else | |
| local choice=$(dialog --clear --backtitle "$software_title" \ | |
| --title "Menu Principal" \ | |
| --menu "\nNenhum registro foi encontrado.\n\nO que deseja fazer?" 12 40 4 \ | |
| 1 "Criar um novo registro" \ | |
| 5 "Sobre" \ | |
| 3>&1 1>&2 2>&3 3>&- ) | |
| fi | |
| local crypt="Encriptar diário" | |
| else | |
| # Journal IS encrypted and MUST be decrypted first | |
| local choice=4 | |
| local crypt="Decriptar diário" | |
| fi | |
| actions $choice $crypt | |
| } | |
| actions(){ | |
| case $1 in | |
| 1) | |
| $editor "$journal/$(date +%Y%m%d_%Hh%Mm%Ss)" && menu | |
| ;; | |
| 2) | |
| local record=$(select_record "Escolha um registro para Editar e/ou Ler" "\nArquivos:") | |
| if [[ -n "$record" && "$record" != "$journal/" ]]; then | |
| $editor "$journal/$record" | |
| fi | |
| menu | |
| ;; | |
| 3) | |
| local record=$(select_record "Escolha um registro para Apagar" "\nArquivos:") | |
| if [[ -n "$record" && "$record" != "$journal/" ]]; then | |
| rm -f "$journal/$record" | |
| fi | |
| menu | |
| ;; | |
| 4) | |
| if [[ $2 = "Decriptar diário" ]]; then | |
| passphrase=$(dialog --clear --backtitle "$software_title" \ | |
| --title "$2" --insecure \ | |
| --passwordbox "\nFoi encontrado um diário encriptado. | |
| Decripte-o primeiro.\n\nDigite a senha:" 11 45 \ | |
| 3>&1 1>&2 2>&3 3>&- ) | |
| if [[ $? = 1 ]]; then | |
| exit | |
| else | |
| crypt $(echo "$passphrase" | sha256sum | cut -d' ' -f1) "$2" | |
| passphrase='' | |
| menu | |
| fi | |
| else | |
| # $2 = "Encriptar diário" | |
| passphrase=$(dialog --clear --backtitle "$software_title" \ | |
| --title "$2" --insecure \ | |
| --passwordform "\nDefina uma senha a seguir." 11 45 3 \ | |
| "Senha:" 1 1 "" 1 9 31 0 \ | |
| "Repita:" 3 1 "" 3 9 31 0 \ | |
| 3>&1 1>&2 2>&3 3>&- ) | |
| if [[ $? = 1 ]]; then | |
| menu | |
| else | |
| if [[ "$(echo $passphrase | head -1)" = | |
| "$(echo $passphrase | tail -1)" && | |
| $(echo $passphrase | wc -l) > 1 ]]; then | |
| crypt "$(echo "$passphrase" | head -1 | sha256sum | cut -d' ' -f1)" "$2" | |
| passphrase='' | |
| else | |
| dialog --clear --backtitle "$software_title" \ | |
| --title "Senhas não conferem" \ | |
| --msgbox "\nAs senhas digitadas não são iguais. Tente novamente." 7 31 | |
| fi | |
| menu | |
| fi | |
| fi | |
| ;; | |
| 5) | |
| dialog --clear --backtitle "$software_title" \ | |
| --title "Sobre \"$software_title\"" \ | |
| --msgbox "$about" 17 72 | |
| menu | |
| ;; | |
| *) | |
| clear | |
| exit | |
| ;; | |
| esac | |
| } | |
| menu |
Author
nerun
commented
Jan 5, 2024

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