From fec49b40dc658222bb6ac9cefd9607534de61887 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:31:55 +0000 Subject: [PATCH 1/2] Initial plan From d34aa0b7879ba405499b051c23ef6da9e38d3e82 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:37:39 +0000 Subject: [PATCH 2/2] Add MkDocs Material documentation with platform guides and GitHub Pages deployment workflow Co-authored-by: cvraut <10603882+cvraut@users.noreply.github.com> --- .github/workflows/docs.yml | 50 ++++++++++++++ docs/api.md | 115 +++++++++++++++++++++++++++++++ docs/index.md | 135 +++++++++++++++++++++++++++++++++++++ docs/platforms/discord.md | 104 ++++++++++++++++++++++++++++ docs/platforms/slack.md | 110 ++++++++++++++++++++++++++++++ docs/platforms/teams.md | 108 +++++++++++++++++++++++++++++ docs/platforms/webex.md | 123 +++++++++++++++++++++++++++++++++ mkdocs.yml | 53 +++++++++++++++ 8 files changed, 798 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/api.md create mode 100644 docs/index.md create mode 100644 docs/platforms/discord.md create mode 100644 docs/platforms/slack.md create mode 100644 docs/platforms/teams.md create mode 100644 docs/platforms/webex.md create mode 100644 mkdocs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..8275c10 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,50 @@ +name: Deploy Documentation + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install MkDocs and Material theme + run: pip install "mkdocs-material" "mkdocs<2" + + - name: Build documentation + run: mkdocs build --strict + + - name: Upload pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: site/ + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..ffbfd45 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,115 @@ +# Python API Reference + +`whecho` exposes a small public Python API that lets you send webhook notifications directly from your scripts without using the command line. + +--- + +## `whecho_simple` + +```python +from whecho.whecho import whecho_simple +``` + +Sends a message to a webhook URL using the simple format. + +### Signature + +```python +def whecho_simple(msg: str, url: str = "", debug: bool = False) -> Optional[requests.models.Response] +``` + +### Parameters + +| Parameter | Type | Default | Description | +|---|---|---|---| +| `msg` | `str` | *(required)* | The message text to send. | +| `url` | `str` | `""` | The webhook URL to post to. If empty or omitted, the URL saved via `whecho --init` is used. | +| `debug` | `bool` | `False` | When `True`, prints request details and returns the `Response` object. | + +### Returns + +- `None` by default. +- `requests.models.Response` when `debug=True`. + +### Raises + +- `ValueError` — if no URL is provided and no default URL is configured. +- `ValueError` — if `msg` is empty. + +### Examples + +**Basic usage (uses saved default URL):** + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Training complete! ✅") +``` + +**With a specific URL:** + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Deployment done!", url="https://discord.com/api/webhooks/...") +``` + +**Debug mode (returns the HTTP response):** + +```python +from whecho.whecho import whecho_simple + +response = whecho_simple("Hello!", debug=True) +print(response.status_code) +``` + +**Notify when a long task finishes:** + +```python +from whecho.whecho import whecho_simple +import time + +def train_model(): + time.sleep(60) # simulate long task + +train_model() +whecho_simple("Model training complete! 🎉") +``` + +--- + +## Platform Auto-Detection + +`whecho_simple` automatically detects the target platform from the URL and formats the JSON payload accordingly: + +| URL contains | Platform | Payload format | +|---|---|---| +| `discord.com` or `discordapp.com` | Discord | `{"username": "user@machine", "content": "..."}` | +| `slack.com` | Slack | `{"text": "..."}` | +| `webhook.office.com` | Microsoft Teams | `{"text": "..."}` | +| `webexapis.com` | Webex | `{"markdown": "..."}` | +| *(anything else)* | Generic | `{"text": "..."}` | + +This means `whecho_simple` works out of the box with all supported platforms — no extra configuration needed beyond the URL. + +--- + +## Configuration + +The configuration (including the default webhook URL) is stored in a platform-specific location: + +| OS | Config path | +|---|---| +| Linux | `~/.config/.whecho/config.toml` | +| macOS | `~/Library/Application Support/.whecho/config.toml` | +| Windows | `%APPDATA%\.whecho\config.toml` | + +Run `whecho --init` to set or update the configuration interactively. + +### Config fields + +| Field | Description | +|---|---| +| `default_url` | The default webhook URL used when no URL is passed. | +| `user` | Your username (auto-detected, used in Discord messages). | +| `machine` | Your machine hostname (auto-detected, used in Discord messages). | diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..86c1de6 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,135 @@ +# whecho + +**Linux echo with webhooks! ⚓** + +Don't guess when a job is finished — have it message you! `whecho` is a command-line tool (and Python library) that sends notifications to messaging platforms like Discord, Slack, Webex, and Microsoft Teams via webhooks, so you know the moment a long-running task completes. + +--- + +## Installation + +```bash +pip install whecho +``` + +**Requirements:** Python 3.6+ + +--- + +## Quickstart + +### 1. Obtain a Webhook URL + +First, generate a webhook URL from your preferred messaging platform: + +| Platform | Guide | +|---|---| +| Discord | [Discord Webhook Setup](platforms/discord.md) | +| Slack | [Slack Webhook Setup](platforms/slack.md) | +| Webex | [Webex Webhook Setup](platforms/webex.md) | +| Microsoft Teams | [Teams Webhook Setup](platforms/teams.md) | + +### 2. Initialize whecho + +Run the interactive setup to save your webhook URL: + +```bash +$ whecho --init +Current config: +[1] default_url: None +[2] user: myuser +[3] machine: my-machine + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): 1 +Please enter the new value for default_url: https://your-webhook-url-here +Successfully modified default_url to https://your-webhook-url-here! +... +Please enter the number/name of the config option you would like to modify (empty or Q to exit): q +Successfully initialized whecho! +``` + +### 3. Send a Message + +```bash +$ whecho "Hello from the terminal!" +``` + +That's it! Your message will appear in your configured messaging platform immediately. + +--- + +## Usage + +### Command-Line + +```bash +# Send a message using your saved default webhook +$ whecho "Build complete!" + +# Send to a specific webhook URL (no init required) +$ whecho -u https://your-webhook-url "Deployment finished!" + +# Use the --msg flag instead of a positional argument +$ whecho --msg "Training complete!" + +# Append whecho to any command to be notified when it finishes +$ sleep 60 && whecho "Sleep done!" +``` + +### Python API + +```python +from whecho.whecho import whecho_simple + +# Use the saved default URL +whecho_simple("I'm inside Python 🐍") + +# Use a specific webhook URL +whecho_simple("Custom URL message", url="https://your-webhook-url") +``` + +See the [Python API reference](api.md) for full details. + +--- + +## CLI Reference + +``` +usage: whecho [-h] [--version] [-m MSG] [--init] [-u URL] [-d] [MSG ...] + +Linux echo with webhooks! ⚓ + +positional arguments: + MSG The message to echo. + +optional arguments: + -h, --help show this help message and exit + --version Prints the version of whecho and exits. + -m MSG, --msg MSG The message to echo (same as 1st positional argument). + --init Initializes whecho. Also used to change current config. + -u URL, --url URL The webhook URL to send the message to. + -d, --debug Whether to print debugging information. +``` + +--- + +## Supported Platforms + +whecho automatically detects the target platform from the webhook URL and formats the message accordingly: + +- **[Discord](platforms/discord.md)** — sends as a bot message with username set to `user@machine` +- **[Slack](platforms/slack.md)** — sends using Slack's incoming webhook text format +- **[Webex](platforms/webex.md)** — sends with Markdown support +- **[Microsoft Teams](platforms/teams.md)** — sends via Office 365 connector webhooks +- **Generic webhooks** — sends a JSON body with a `text` field + +--- + +## Table of Contents + +- [Python API](api.md) +- Messaging Platform Guides + - [Discord](platforms/discord.md) + - [Slack](platforms/slack.md) + - [Webex](platforms/webex.md) + - [Microsoft Teams](platforms/teams.md) diff --git a/docs/platforms/discord.md b/docs/platforms/discord.md new file mode 100644 index 0000000..8de9fa8 --- /dev/null +++ b/docs/platforms/discord.md @@ -0,0 +1,104 @@ +# Discord Webhook Setup + +This guide explains how to obtain a Discord webhook URL and configure `whecho` to send messages to a Discord channel. + +--- + +## Prerequisites + +- A Discord account +- Access to a Discord server where you have **Manage Webhooks** permission (or you own the server) + +--- + +## Step 1 — Open Channel Settings + +1. Open Discord and navigate to the server and channel where you want to receive notifications. +2. Right-click the channel name and select **Edit Channel**, or click the ⚙️ gear icon next to the channel name. + +--- + +## Step 2 — Create a Webhook + +1. In the channel settings sidebar, click **Integrations**. +2. Click **Webhooks**, then click **New Webhook**. +3. Give the webhook a name (e.g., `whecho`) and optionally upload an avatar image. +4. Click **Copy Webhook URL** to copy the URL to your clipboard. +5. Click **Save Changes**. + +!!! tip + The webhook URL will look like: + ``` + https://discord.com/api/webhooks/1234567890/xxxxxxxxxxxxxxxxxxxx + ``` + +--- + +## Step 3 — Configure whecho + +Run the interactive setup and paste your webhook URL: + +```bash +$ whecho --init +Current config: +[1] default_url: None +[2] user: myuser +[3] machine: my-machine + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): 1 +Please enter the new value for default_url: https://discord.com/api/webhooks/1234567890/xxxxxxxxxxxxxxxxxxxx +Successfully modified default_url to https://discord.com/api/webhooks/1234567890/xxxxxxxxxxxxxxxxxxxx! + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): q +Successfully initialized whecho! +``` + +--- + +## Step 4 — Send a Test Message + +```bash +$ whecho "Hello from whecho! 🎉" +``` + +You should see the message appear in your Discord channel almost immediately. + +--- + +## Message Format + +When sending to Discord, `whecho` posts a JSON body with: + +```json +{ + "username": "user@machine", + "content": "your message here" +} +``` + +The `username` field is set to `@` using the values from your `whecho` config, so you can tell which machine sent the notification. + +--- + +## Passing the URL Directly (No Init Required) + +You can skip `--init` and pass the webhook URL directly: + +```bash +$ whecho -u "https://discord.com/api/webhooks/..." "Build complete!" +``` + +Or from Python: + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Build complete!", url="https://discord.com/api/webhooks/...") +``` + +--- + +## References + +- [Discord — Intro to Webhooks](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) +- [Discord — Webhook documentation](https://discord.com/developers/docs/resources/webhook) diff --git a/docs/platforms/slack.md b/docs/platforms/slack.md new file mode 100644 index 0000000..22f3107 --- /dev/null +++ b/docs/platforms/slack.md @@ -0,0 +1,110 @@ +# Slack Webhook Setup + +This guide explains how to obtain a Slack Incoming Webhook URL and configure `whecho` to send messages to a Slack channel. + +--- + +## Prerequisites + +- A Slack account +- A Slack workspace where you have permission to add apps + +--- + +## Step 1 — Create a Slack App + +1. Go to [https://api.slack.com/apps](https://api.slack.com/apps) and click **Create New App**. +2. Choose **From scratch**. +3. Enter an App Name (e.g., `whecho`) and select the Slack workspace you want to use. +4. Click **Create App**. + +--- + +## Step 2 — Enable Incoming Webhooks + +1. In your app's settings page, click **Incoming Webhooks** in the left sidebar (under **Features**). +2. Toggle the switch to turn **Activate Incoming Webhooks** to **On**. + +--- + +## Step 3 — Add a Webhook to Your Workspace + +1. Scroll down and click **Add New Webhook to Workspace**. +2. Select the channel where `whecho` should post messages, then click **Allow**. +3. A new webhook URL will appear under **Webhook URLs for Your Workspace**. Click **Copy** to copy it. + +!!! tip + The webhook URL will look like: + ``` + https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX + ``` + +--- + +## Step 4 — Configure whecho + +Run the interactive setup and paste your webhook URL: + +```bash +$ whecho --init +Current config: +[1] default_url: None +[2] user: myuser +[3] machine: my-machine + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): 1 +Please enter the new value for default_url: https://hooks.slack.com/services/T00000000/B00000000/XXXX +Successfully modified default_url to https://hooks.slack.com/services/T00000000/B00000000/XXXX! + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): q +Successfully initialized whecho! +``` + +--- + +## Step 5 — Send a Test Message + +```bash +$ whecho "Hello from whecho! 🎉" +``` + +You should see the message appear in the selected Slack channel immediately. + +--- + +## Message Format + +When sending to Slack, `whecho` posts a JSON body with: + +```json +{ + "text": "your message here" +} +``` + +Slack's Incoming Webhooks support a subset of [mrkdwn formatting](https://api.slack.com/reference/surfaces/formatting), so you can use `*bold*`, `_italic_`, `` `code` ``, and more in your messages. + +--- + +## Passing the URL Directly (No Init Required) + +You can skip `--init` and pass the webhook URL directly: + +```bash +$ whecho -u "https://hooks.slack.com/services/..." "Deployment done!" +``` + +Or from Python: + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Deployment done!", url="https://hooks.slack.com/services/...") +``` + +--- + +## References + +- [Slack — Sending messages using Incoming Webhooks](https://api.slack.com/messaging/webhooks) +- [Slack — Block Kit formatting](https://api.slack.com/block-kit) diff --git a/docs/platforms/teams.md b/docs/platforms/teams.md new file mode 100644 index 0000000..74e93b6 --- /dev/null +++ b/docs/platforms/teams.md @@ -0,0 +1,108 @@ +# Microsoft Teams Webhook Setup + +This guide explains how to obtain a Microsoft Teams Incoming Webhook URL and configure `whecho` to send messages to a Teams channel. + +--- + +## Prerequisites + +- A Microsoft 365 account with access to Microsoft Teams +- Access to a Teams channel where you want to receive notifications +- Permission to add connectors to the channel (channel owner or admin) + +--- + +## Step 1 — Open Channel Connectors + +1. In Microsoft Teams, navigate to the team and channel where you want to receive notifications. +2. Click the **•••** (More options) menu next to the channel name. +3. Select **Connectors** (or **Manage channel** → **Connectors** in newer Teams versions). + +!!! note "New Teams App" + In the updated Microsoft Teams app, Connectors may be found under **Manage channel** → **Settings** → **Connectors**. If you cannot find Connectors, check with your Teams administrator, as some organizations restrict app installations. + +--- + +## Step 2 — Add an Incoming Webhook + +1. In the Connectors dialog, search for **Incoming Webhook** and click **Add** (or **Configure** if already added). +2. Click **Add** again to confirm. +3. Give the webhook a name (e.g., `whecho`) and optionally upload an image. +4. Click **Create**. +5. Copy the generated webhook URL. + +!!! tip + The webhook URL will look like: + ``` + https://yourorg.webhook.office.com/webhookb2/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@... + ``` + +--- + +## Step 3 — Configure whecho + +Run the interactive setup and paste your webhook URL: + +```bash +$ whecho --init +Current config: +[1] default_url: None +[2] user: myuser +[3] machine: my-machine + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): 1 +Please enter the new value for default_url: https://yourorg.webhook.office.com/webhookb2/XXXX +Successfully modified default_url to https://yourorg.webhook.office.com/webhookb2/XXXX! + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): q +Successfully initialized whecho! +``` + +--- + +## Step 4 — Send a Test Message + +```bash +$ whecho "Hello from whecho! 🎉" +``` + +You should see the message appear in the Teams channel. + +--- + +## Message Format + +When sending to Microsoft Teams, `whecho` posts a JSON body with: + +```json +{ + "text": "your message here" +} +``` + +Teams supports a limited set of HTML and Markdown within the `text` field. For simple text notifications, plain text works perfectly. + +--- + +## Passing the URL Directly (No Init Required) + +You can skip `--init` and pass the webhook URL directly: + +```bash +$ whecho -u "https://yourorg.webhook.office.com/webhookb2/..." "Deployment done!" +``` + +Or from Python: + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Deployment done!", url="https://yourorg.webhook.office.com/webhookb2/...") +``` + +--- + +## References + +- [Microsoft — Create Incoming Webhooks with Workflows for Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) +- [Microsoft — Office 365 Connector cards](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using) diff --git a/docs/platforms/webex.md b/docs/platforms/webex.md new file mode 100644 index 0000000..406e539 --- /dev/null +++ b/docs/platforms/webex.md @@ -0,0 +1,123 @@ +# Webex Webhook Setup + +This guide explains how to obtain a Webex Incoming Webhook URL and configure `whecho` to send messages to a Webex space. + +--- + +## Prerequisites + +- A Webex account (free accounts are supported) +- Access to a Webex space where you want to receive notifications + +--- + +## Step 1 — Open the Webex App Hub + +1. Navigate to the [Webex App Hub — Incoming Webhooks](https://apphub.webex.com/applications/incoming-webhooks-cisco-systems-38054-23307-75252) page. +2. Click **Connect** (you may be prompted to sign in with your Webex account). + +--- + +## Step 2 — Create an Incoming Webhook + +1. After connecting, fill in the form: + - **Webhook name** — a label for this webhook (e.g., `whecho`). + - **Webex Space** — select the space where messages should be posted. +2. Click **Add**. +3. A webhook URL will be generated. Copy it to your clipboard. + +!!! tip + The webhook URL will look like: + ``` + https://webexapis.com/v1/webhooks/incoming/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + ``` + +--- + +## Step 3 — Configure whecho + +Run the interactive setup and paste your webhook URL: + +```bash +$ whecho --init +Current config: +[1] default_url: None +[2] user: myuser +[3] machine: my-machine + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): 1 +Please enter the new value for default_url: https://webexapis.com/v1/webhooks/incoming/XXXX +Successfully modified default_url to https://webexapis.com/v1/webhooks/incoming/XXXX! + +Please enter the number/name of the config option you would like to modify (empty or Q to exit): q +Successfully initialized whecho! +``` + +--- + +## Step 4 — Send a Test Message + +```bash +$ whecho "Hello from whecho! 🎉" +``` + +You should see the message appear in your Webex space. + +--- + +## Message Format + +When sending to Webex, `whecho` posts a JSON body with: + +```json +{ + "markdown": "your message here" +} +``` + +Because the payload uses the `markdown` field, Webex will render Markdown formatting in your messages. This means you can use: + +- `**bold**` or `*bold*` +- `_italic_` +- `` `inline code` `` +- ```` ```code blocks``` ```` +- `[links](https://example.com)` + +### Example with Markdown + +```bash +$ whecho "**Training complete!** Accuracy: \`98.5%\`" +``` + +Or from Python: + +```python +from whecho.whecho import whecho_simple + +whecho_simple("**Build passed** ✅\nAll 247 tests passed.") +``` + +--- + +## Passing the URL Directly (No Init Required) + +You can skip `--init` and pass the webhook URL directly: + +```bash +$ whecho -u "https://webexapis.com/v1/webhooks/incoming/..." "Task finished!" +``` + +Or from Python: + +```python +from whecho.whecho import whecho_simple + +whecho_simple("Task finished!", url="https://webexapis.com/v1/webhooks/incoming/...") +``` + +--- + +## References + +- [Webex App Hub — Incoming Webhooks](https://apphub.webex.com/applications/incoming-webhooks-cisco-systems-38054-23307-75252) +- [Webex — Formatting messages with Markdown](https://developer.webex.com/docs/basics#formatting-messages) diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..65383a6 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,53 @@ +site_name: whecho +site_description: Linux echo with webhooks! +site_url: https://cvraut.github.io/whecho +repo_url: https://github.com/cvraut/whecho +repo_name: cvraut/whecho + +theme: + name: material + palette: + - scheme: default + primary: deep purple + accent: purple + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: deep purple + accent: purple + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - navigation.tabs + - navigation.sections + - navigation.top + - search.suggest + - search.highlight + - content.code.copy + +markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.superfences + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - attr_list + - md_in_html + - toc: + permalink: true + +nav: + - Home: index.md + - Python API: api.md + - Messaging Platforms: + - Discord: platforms/discord.md + - Slack: platforms/slack.md + - Webex: platforms/webex.md + - Microsoft Teams: platforms/teams.md + +plugins: + - search