[GH-ISSUE #218] Python script for msg sender with AES-256-CBC #195

Closed
opened 2026-03-03 11:37:52 +03:00 by kerem · 0 comments
Owner

Originally created by @cfbsks on GitHub (Oct 2, 2023).
Original GitHub issue: https://github.com/Finb/Bark/issues/218

"""
Bark Notification Script
------------------------

This script allows you to send encrypted notifications using the Bark API.

Usage:
1. Set up your configuration:
   - Set `DEVICE_KEY` to your Bark device key.
   - Set `encryption_key` to your chosen AES key. (Ensure it's secure and kept private.)

2. The `send_notification` function can be used to send notifications. It accepts the following keyword arguments:
   - `title`: The title of the notification.
   - `body`: The body content of the notification.
   - `level`: The urgency level of the notification.
   - `autoCopy`: Whether to automatically copy content.
   - `copy`: The copied content.
   - `sound`: The sound of the notification.
   - `icon`: The icon URL of the notification.
   - `group`: The group of the notification.
   - `isArchive`: Whether the notification is archived.
   - `url`: The URL to open upon clicking the notification.

3. By default, all parameters have `None` value. If you want to set any default values, update the respective constants at the top of the script.

4. Use the `main` function to test or send out notifications as required.

Example:
    send_notification(body='This is a custom message.')
    send_notification(body='Another message', sound='bell', group='new_group')

Note:
Always remember not to hard-code sensitive information like `DEVICE_KEY` and `encryption_key` directly in the script. Consider safer methods like environment variables or secure config files.

"""

import base64
import json
import logging
import random

import requests
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import algorithms, modes, Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES

TIMEOUT_REQUEST_SEC = 10
MAX_RETRIES = 3
LOG_LEVEL = logging.WARNING

API_BASE = 'https://api.day.app'
DEVICE_KEY = "this is your device_key"

# Encryption key and IV (Initialization Vector)
encryption_key = '12345678901234567890123456789012'

# Set Default Values
TITLE = None
BODY = None
LEVEL = None
GROUP = None
AUTOCOPY = None
COPY = None
SOUND = None
ICON = None
URL = None
ISARCHIVE = None

# Set up logging
logging.basicConfig(filename='Bark.log', level=LOG_LEVEL,
                    format='%(asctime)s - %(levelname)s - %(message)s')


def encrypt_payload(payload: bytes, aes_key: bytes, aes_iv: bytes):
    """
    Encrypt the given payload using AES-256-CBC with PKCS7 padding.
    """

    # Add padding to the payload
    padder = padding.PKCS7(AES.block_size).padder()
    padded_data = padder.update(payload) + padder.finalize()

    # Create the cipher
    cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend())

    # Encrypt the padded data
    encryptor = cipher.encryptor()
    encrypted = encryptor.update(padded_data) + encryptor.finalize()

    # Return the Base64 encoded ciphertext
    return base64.b64encode(encrypted).decode()


def send_notification(**kwargs):
    defaults = {
        'title': TITLE,
        'body': BODY,
        'level': LEVEL,
        'autoCopy': AUTOCOPY,
        'copy': COPY,
        'sound': SOUND,
        'icon': ICON,
        'group': GROUP,
        'isArchive': ISARCHIVE,
        'url': URL
    }

    for key, value in defaults.items():
        defaults[key] = kwargs.get(key, value)
    # Remove keys with empty string values
    cleaned_data = {k: v for k, v in defaults.items() if v}

    for _ in range(MAX_RETRIES):
        try:
            url = API_BASE + "/" + DEVICE_KEY
            headers = {'Content-Type': 'application/x-www-form-urlencoded'}

            json_data = json.dumps(cleaned_data)

            encryption_iv = bytes(random.randint(32, 126) for _ in range(16))
            encrypted_payload = encrypt_payload(json_data.encode(), encryption_key.encode(), encryption_iv)

            payload = {
                'ciphertext': encrypted_payload,
                'iv': encryption_iv.decode()
            }
            response = requests.request("GET", url, headers=headers, data=payload, timeout=TIMEOUT_REQUEST_SEC)

            if response.status_code == 200:
                logging.info(f"Sending notification. Response: {response.text}")
                return
            else:
                logging.warning(
                    f"Retrying notification. Status code: {response.status_code}, Response: {response.text}")
        except requests.RequestException as e:
            logging.warning(f"Retrying due to requests exception: {e}")
        except Exception as e:
            logging.error(f"Error sending notification: {e}")

    logging.error(f"Failed to send notification after {MAX_RETRIES} attempts. Content: {cleaned_data.get('body', '')}")


def main():
    send_notification(body='This is a custom message.')
    send_notification(body='Another message', sound='bell', group='new_group')


if __name__ == '__main__':
    main()

Originally created by @cfbsks on GitHub (Oct 2, 2023). Original GitHub issue: https://github.com/Finb/Bark/issues/218 ``` """ Bark Notification Script ------------------------ This script allows you to send encrypted notifications using the Bark API. Usage: 1. Set up your configuration: - Set `DEVICE_KEY` to your Bark device key. - Set `encryption_key` to your chosen AES key. (Ensure it's secure and kept private.) 2. The `send_notification` function can be used to send notifications. It accepts the following keyword arguments: - `title`: The title of the notification. - `body`: The body content of the notification. - `level`: The urgency level of the notification. - `autoCopy`: Whether to automatically copy content. - `copy`: The copied content. - `sound`: The sound of the notification. - `icon`: The icon URL of the notification. - `group`: The group of the notification. - `isArchive`: Whether the notification is archived. - `url`: The URL to open upon clicking the notification. 3. By default, all parameters have `None` value. If you want to set any default values, update the respective constants at the top of the script. 4. Use the `main` function to test or send out notifications as required. Example: send_notification(body='This is a custom message.') send_notification(body='Another message', sound='bell', group='new_group') Note: Always remember not to hard-code sensitive information like `DEVICE_KEY` and `encryption_key` directly in the script. Consider safer methods like environment variables or secure config files. """ import base64 import json import logging import random import requests from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding from cryptography.hazmat.primitives.ciphers import algorithms, modes, Cipher from cryptography.hazmat.primitives.ciphers.algorithms import AES TIMEOUT_REQUEST_SEC = 10 MAX_RETRIES = 3 LOG_LEVEL = logging.WARNING API_BASE = 'https://api.day.app' DEVICE_KEY = "this is your device_key" # Encryption key and IV (Initialization Vector) encryption_key = '12345678901234567890123456789012' # Set Default Values TITLE = None BODY = None LEVEL = None GROUP = None AUTOCOPY = None COPY = None SOUND = None ICON = None URL = None ISARCHIVE = None # Set up logging logging.basicConfig(filename='Bark.log', level=LOG_LEVEL, format='%(asctime)s - %(levelname)s - %(message)s') def encrypt_payload(payload: bytes, aes_key: bytes, aes_iv: bytes): """ Encrypt the given payload using AES-256-CBC with PKCS7 padding. """ # Add padding to the payload padder = padding.PKCS7(AES.block_size).padder() padded_data = padder.update(payload) + padder.finalize() # Create the cipher cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend()) # Encrypt the padded data encryptor = cipher.encryptor() encrypted = encryptor.update(padded_data) + encryptor.finalize() # Return the Base64 encoded ciphertext return base64.b64encode(encrypted).decode() def send_notification(**kwargs): defaults = { 'title': TITLE, 'body': BODY, 'level': LEVEL, 'autoCopy': AUTOCOPY, 'copy': COPY, 'sound': SOUND, 'icon': ICON, 'group': GROUP, 'isArchive': ISARCHIVE, 'url': URL } for key, value in defaults.items(): defaults[key] = kwargs.get(key, value) # Remove keys with empty string values cleaned_data = {k: v for k, v in defaults.items() if v} for _ in range(MAX_RETRIES): try: url = API_BASE + "/" + DEVICE_KEY headers = {'Content-Type': 'application/x-www-form-urlencoded'} json_data = json.dumps(cleaned_data) encryption_iv = bytes(random.randint(32, 126) for _ in range(16)) encrypted_payload = encrypt_payload(json_data.encode(), encryption_key.encode(), encryption_iv) payload = { 'ciphertext': encrypted_payload, 'iv': encryption_iv.decode() } response = requests.request("GET", url, headers=headers, data=payload, timeout=TIMEOUT_REQUEST_SEC) if response.status_code == 200: logging.info(f"Sending notification. Response: {response.text}") return else: logging.warning( f"Retrying notification. Status code: {response.status_code}, Response: {response.text}") except requests.RequestException as e: logging.warning(f"Retrying due to requests exception: {e}") except Exception as e: logging.error(f"Error sending notification: {e}") logging.error(f"Failed to send notification after {MAX_RETRIES} attempts. Content: {cleaned_data.get('body', '')}") def main(): send_notification(body='This is a custom message.') send_notification(body='Another message', sound='bell', group='new_group') if __name__ == '__main__': main() ```
kerem closed this issue 2026-03-03 11:37:53 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Bark#195
No description provided.