Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
360 changes: 189 additions & 171 deletions dashboard.sh

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions docs/dashboard-reporters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Reporters

Reporters are scripts that analyze the historical data collected by the modules. While the modules are responsible for _gathering_ data, reporters are responsible for _interpreting_ it.

## How to Run a Reporter

You can run any reporter using the `-r` flag on the main `dashboard.sh` script:

```bash
./dashboard.sh -r <reporter_name> [reporter_options]
```

For example, to run the `top-stars` reporter, you would use:

```bash
./dashboard.sh -r top-stars
```

Some reporters accept their own arguments, which you can pass after the reporter's name:

```bash
./dashboard.sh -r top-stars 5
```

## Available Reporters

Here is a list of the currently available reporters.

### `timespan`

The `timespan` reporter shows the change in each metric over a period of time. It reads all the `.tsv` report files from the `reports/` directory and calculates the difference between the first and last recorded values for each metric.

**Usage:**

```bash
./dashboard.sh -r timespan [days]
```

- **`[days]`** (optional): The number of days of history to analyze.

**Behavior:**

- If `[days]` is not provided, it will analyze all reports in your `reports/` directory to show the all-time change.
- If `[days]` is provided, it will show the change over the last `N` days.

**Note on `[days]` filtering:** This feature is currently not working as expected due to limitations in the `date` command of the execution environment. The script is unable to parse dates from the report filenames reliably. At present, the `timespan` reporter will always show the all-time history regardless of this argument.

### `top-stars`

The `top-stars` reporter finds the most recent report file and lists the top repositories by their star count.

**Usage:**

```bash
./dashboard.sh -r top-stars [count]
```

- **`[count]`** (optional): The number of top repositories to display. Defaults to 10.

**Example Output:**

```
Top 10 repositories by stars (from 2025-09-10_18-52-24.tsv)
----------------------------------------------------
Rank Stars Repository
1 1 attogram/dashboard
```

## Creating Your Own Reporter

You can easily create your own reporter by adding a new executable shell script to the `reporters/` directory.

A reporter script should:

1. Be placed in the `reporters/` directory.
2. Be executable (`chmod +x reporters/my_reporter.sh`).
3. Read data from the `.tsv` files in the `reports/` directory. The path to the reports directory can be found relative to the script's own location: `REPORTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../reports"`.
4. Parse its own arguments if needed.
5. Print its analysis to standard output.
36 changes: 28 additions & 8 deletions docs/dashboard-script.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
# The Main Script (`dashboard.sh`)

The `dashboard.sh` script is the main entry point for the application. It serves as an orchestrator, responsible for parsing arguments, loading configuration, and running the modules to generate a report.
The `dashboard.sh` script is the main entry point for the application. It serves as an orchestrator, responsible for parsing arguments, loading configuration, and running modules for data collection, or running reporters for data analysis.

## Usage

To collect data from modules:

```
./dashboard.sh [options] [module]
```

To run a reporter:

```
./dashboard.sh -r <reporter_name> [reporter_options]
```

### Options

- `-f, --format <format>`: Specify the output format. See [Output Formats](./dashboard-output-formats.md) for a full list of supported formats. If not provided, the default is `tsv`.
- `-o, --output <path>`: Write the report to a specific file or directory. If a directory is provided, a timestamped filename will be automatically generated.
- `-f, --format <format>`: (For module runs only) Specify the output format. See [Output Formats](./dashboard-output-formats.md) for a full list of supported formats. If not provided, the default is `tsv`.
- `-r, --reporter <name>`: Run a specific reporter from the `reporters/` directory. Any subsequent arguments will be passed to the reporter script.
- `-h, --help`: Display a help message with usage information and exit.

### Arguments

- `[module]`: (Optional) The name of a single module to run (e.g., `github`, `hackernews`). If a module name is provided, only that module's report will be generated. If omitted, the script will run all executable modules found in the `modules/` directory.
- `[module]`: (Optional, for module runs only) The name of a single module to run (e.g., `github`, `hackernews`). If a module name is provided, only that module's data will be collected. If omitted, the script will run all executable modules found in the `modules/` directory.

## Execution Flow

The script follows these steps during execution:
The script has two main modes of operation: data collection and reporting.

### Data Collection Mode

1. **Argument Parsing**: It first parses any command-line options and arguments to determine the desired output format and whether to run a single module or all of them.
This is the default mode when the `-r` flag is not used.

1. **Argument Parsing**: It parses command-line options (`-f`, `-h`) and an optional module name.

2. **Configuration Loading**: It checks for the existence of `config/config.sh`. If the file is not found, it will print an error message and exit. If found, it will source the file to load all the user-defined variables into the script's environment.

3. **Dependency Check**: It verifies that the required command-line tools, `curl` and `jq`, are installed and available in the system's `PATH`. If a dependency is missing, it will exit with an error.
3. **Dependency Check**: It verifies that the required command-line tools, `curl` and `jq`, are installed and available in the system's `PATH`.

4. **Module Execution**:
- If a single module was requested, it executes only that module's script.
- If no module was specified, it finds all executable files within the `modules/` directory and runs them one by one.

5. **Report Aggregation**: The script collects the output from each executed module. For structured formats like `json`, `xml`, and `html`, it wraps the collected outputs with the appropriate root elements and separators to create a single, well-formed document. For simpler formats like `plain` or `csv`, it concatenates the outputs.
5. **Report Generation**: The script collects the output from each executed module. For structured formats like `json`, `xml`, and `html`, it wraps the collected outputs with the appropriate root elements. For simpler formats like `plain` or `csv`, it concatenates the outputs. The final report is printed to standard output, which can be redirected to a file.

### Reporter Mode

This mode is triggered by the `-r` flag.

1. **Argument Parsing**: The script looks for the `-r` flag. When found, it takes the next argument as the reporter's name. All following arguments are passed directly to the reporter.

2. **Reporter Execution**: The script looks for an executable file with the given name in the `reporters/` directory and runs it, passing along any reporter-specific arguments. The output of the reporter is printed to standard output.
51 changes: 3 additions & 48 deletions modules/crypto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# modules/crypto.sh
#
# Fetches crypto wallet balances using multiple providers.
# Fetches crypto wallet balances using multiple providers and outputs them in TSV format.
#

# --- Configuration and Setup ---
Expand All @@ -12,13 +12,6 @@ if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
fi

# --- Input ---
FORMAT="$1"
if [ -z "$FORMAT" ]; then
echo "Usage: $(basename "$0") <format>" >&2
exit 1
fi

# --- Data Fetching ---

# Function to format a raw balance string using its decimals value.
Expand Down Expand Up @@ -170,43 +163,5 @@ fi
DATA=$ALL_BALANCES_JSON

# --- Output Formatting ---
case "$FORMAT" in
plain | pretty)
echo 'Crypto Donations'
echo "$DATA" | jq -r '.[] | "\(.chain) (\(.address))\n" + (.tokens[] | " - \(.symbol): \(.balance)")'
;;
json)
echo "\"crypto\":${DATA}"
;;
xml)
echo '<crypto>'
echo "$DATA" | jq -r '.[] | " <wallet chain=\"\(.chain)\" address=\"\(.address)\">\n" + (.tokens[] | " <token symbol=\"\(.symbol)\" balance=\"\(.balance)\"/>") + "\n </wallet>"'
echo '</crypto>'
;;
html)
echo '<h2>Crypto Donations</h2>'
echo '<ul>'
echo "$DATA" | jq -r '.[] | " <li><b>\(.chain)</b> (<code>\(.address)</code>)<ul>" + (.tokens[] | "<li>\(.symbol): \(.balance)</li>") + "</ul></li>"'
echo '</ul>'
;;
yaml)
echo 'crypto:'
echo "$DATA" | jq -r '.[] | " - chain: \(.chain)\n address: \(.address)\n tokens:\n" + (.tokens[] | " - symbol: \(.symbol)\n balance: \"\(.balance)\"")'
;;
csv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "$DATA" | jq -r --arg now "$now" '.[] | . as $parent | .tokens[] | [$now, "crypto", "balance", "crypto." + $parent.chain + "." + $parent.address + "." + .symbol, .balance] | @csv'
;;
tsv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "$DATA" | jq -r --arg now "$now" '.[] | . as $parent | .tokens[] | [$now, "crypto", "balance", "crypto." + $parent.chain + "." + $parent.address + "." + .symbol, .balance] | @tsv'
;;
markdown)
echo '### Crypto Donations'
echo "$DATA" | jq -r '.[] | "* **\(.chain)** (`\(.address)`)\n" + (.tokens[] | " * **\(.symbol)**: \(.balance)")'
;;
*)
echo "Error: Unsupported format '$FORMAT'" >&2
exit 1
;;
esac
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "$DATA" | jq -r --arg now "$now" '.[] | . as $parent | .tokens[] | [$now, "crypto", "balance", "crypto." + $parent.chain + "." + $parent.address + "." + .symbol, .balance] | @tsv'
52 changes: 3 additions & 49 deletions modules/discord.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
# modules/discord.sh
#
# Discord module for the dashboard.
# Fetches online member count from a Discord server widget.
# Fetches online member count from a Discord server widget and outputs it in TSV format.
#

#echo 'modules/discord.sh started'

# --- Configuration and Setup ------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="${SCRIPT_DIR}/../config/config.sh"
Expand All @@ -25,13 +23,6 @@ if [ -z "$DISCORD_SERVER_ID" ]; then
exit 0
fi

# --- Input ------------------------------------------------------------------
FORMAT="$1"
if [ -z "$FORMAT" ]; then
echo "Usage: $(basename "$0") <format>" >&2
exit 1
fi

# --- Data Fetching ----------------------------------------------------------
API_URL="https://discord.com/api/v9/guilds/${DISCORD_SERVER_ID}/widget.json"
API_RESPONSE=$(curl -s "$API_URL")
Expand Down Expand Up @@ -62,42 +53,5 @@ if [ "$ONLINE_COUNT" == "null" ]; then
fi

# --- Output Formatting ------------------------------------------------------
case "$FORMAT" in
plain)
echo "Discord"
echo "Online: $ONLINE_COUNT"
;;
pretty)
echo -e "\e[1mDiscord\e[0m"
echo "Online: $ONLINE_COUNT"
;;
json)
echo "\"discord\":{\"online\":${ONLINE_COUNT}}"
;;
xml)
echo "<discord><online>${ONLINE_COUNT}</online></discord>"
;;
html)
echo "<h2>Discord</h2><ul><li>Online: ${ONLINE_COUNT}</li></ul>"
;;
yaml)
echo "discord:"
echo " online: ${ONLINE_COUNT}"
;;
csv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s,discord,online,discord,%s\n" "$now" "$ONLINE_COUNT"
;;
tsv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s\tdiscord\tonline\tdiscord\t%s\n" "$now" "$ONLINE_COUNT"
;;
markdown)
echo "### Discord"
echo "- Online: ${ONLINE_COUNT}"
;;
*)
echo "Error: Unsupported format '$FORMAT'" >&2
exit 1
;;
esac
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s\tdiscord\tonline\tdiscord\t%s\n" "$now" "$ONLINE_COUNT"
55 changes: 3 additions & 52 deletions modules/github-sponsors.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
# modules/github-sponsors
#
# GitHub Sponsors module for the dashboard.
# Fetches sponsor count for the authenticated user.
# Fetches sponsor count for the authenticated user and outputs it in TSV format.
#
# Usage: ./modules/github-sponsors <format>
#

#echo 'modules/github-sponsors.sh started'

# --- Configuration and Setup ------------------------------------------------

Expand All @@ -32,14 +28,6 @@ then
exit 0
fi

# --- Input ------------------------------------------------------------------

FORMAT="$1"
if [ -z "$FORMAT" ]; then
echo "Usage: $(basename "$0") <format>" >&2
exit 1
fi

# --- Data Fetching ----------------------------------------------------------

GRAPHQL_QUERY="{ \\\"query\\\": \\\"query { viewer { sponsorshipsAsMaintainer(first: 1) { totalCount } } }\\\" }"
Expand Down Expand Up @@ -72,42 +60,5 @@ fi

# --- Output Formatting ------------------------------------------------------

case "$FORMAT" in
plain)
echo "GitHub Sponsors"
echo "Sponsors: $SPONSORS_COUNT"
;;
pretty)
echo -e "\e[1mGitHub Sponsors\e[0m"
echo "Sponsors: $SPONSORS_COUNT"
;;
json)
echo "\"github-sponsors\":{\"sponsors\":${SPONSORS_COUNT}}"
;;
xml)
echo "<github_sponsors><sponsors>${SPONSORS_COUNT}</sponsors></github_sponsors>"
;;
html)
echo "<h2>GitHub Sponsors</h2><ul><li>Sponsors: ${SPONSORS_COUNT}</li></ul>"
;;
yaml)
echo "github-sponsors:"
echo " sponsors: ${SPONSORS_COUNT}"
;;
csv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s,github-sponsors,sponsors,github-sponsors,%s\n" "$now" "$SPONSORS_COUNT"
;;
tsv)
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s\tgithub-sponsors\tsponsors\tgithub-sponsors\t%s\n" "$now" "$SPONSORS_COUNT"
;;
markdown)
echo "### GitHub Sponsors"
echo "- Sponsors: ${SPONSORS_COUNT}"
;;
*)
echo "Error: Unsupported format '$FORMAT'" >&2
exit 1
;;
esac
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf "%s\tgithub-sponsors\tsponsors\tgithub-sponsors\t%s\n" "$now" "$SPONSORS_COUNT"
Loading