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
85 changes: 85 additions & 0 deletions config/config.dist.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash
#
# Example configuration file for dashboard.
#
# Copy this file to config.sh and edit it to your needs.
#
# --- GitHub -------------------------------------------------------------------
#
# Your GitHub username.
# Required by: modules/github.sh
#
GITHUB_USER=""

#
# An array of your repository names to fetch stats for.
# Example: REPOS=("repo1" "repo2")
# Required by: modules/github.sh
#
REPOS=()

#
# Your GitHub Personal Access Token (PAT).
# Required for modules/github-sponsors.sh
# Optional for modules/github.sh (to avoid rate limiting).
# Create a token at: https://github.com/settings/tokens
#
GITHUB_TOKEN=""


# --- Hacker News --------------------------------------------------------------
#
# Your Hacker News username.
# Required by: modules/hackernews.sh
#
HN_USER=""


# --- Discord ------------------------------------------------------------------
#
# Your Discord server ID.
# To get this, right-click your server icon in Discord and select "Copy Server ID".
# You may need to enable Developer Mode in your Discord settings first.
# Required by: modules/discord.sh
#
DISCORD_SERVER_ID=""

#
# Note on Discord Stats:
# The current implementation only fetches the number of online users via the
# server's public widget. To get more detailed stats like total member count,
# you would need to create a Discord Bot, give it the "Server Members Intent",
# and use its token to make authenticated API calls. This would require
# modifying the modules/discord.sh script.
#


# --- Crypto Donations ---------------------------------------------------------
#
# Your cryptocurrency wallet addresses.
# The script will try to fetch balances for any address you provide here.
# The variable name should be `CRYPTO_WALLET_{TICKER}`.
#
# Examples:
# CRYPTO_WALLET_BTC="bc1q..."
# CRYPTO_WALLET_ETH="0x..."
# CRYPTO_WALLET_LTC="ltc1q..."
# CRYPTO_WALLET_DOGE="D..."
# CRYPTO_WALLET_DASH="X..."

#
# You can also specify a provider for a given ticker.
# By default, BTC, ETH, LTC, DOGE, and DASH use 'blockcypher'.
# Other EVM-compatible chains can use 'covalent'.
#
# Examples:
# CRYPTO_MATIC_PROVIDER="covalent"
# CRYPTO_WALLET_MATIC="0x..."
# CRYPTO_AVAX_PROVIDER="covalent"
# CRYPTO_WALLET_AVAX="0x..."

#
# API Keys for crypto providers (optional, but recommended).
#
BLOCKCYPHER_TOKEN=""
COVALENT_API_KEY=""
177 changes: 106 additions & 71 deletions dashboard.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# dashboard.sh
#
Expand Down Expand Up @@ -41,14 +41,19 @@ _error() {
printf '[ERROR] %s\n' "$1" >&2
}

AGGREGATE=0

usage() {
echo "Usage: $(basename "$0") [options] [module]"
echo "Options:"
echo " -a, --aggregate Generate a trend report from all .tsv files in the reports/ directory."
echo " -f, --format <format> Set the output format."
echo " Supported formats: ${VALID_FORMATS[*]}"
echo " -o, --output <path> Set the output file or directory."
echo " -h, --help Display this help message."
echo
echo "To save a report, redirect the output to a file. Example:"
echo " ./dashboard.sh > reports/my_report.tsv"
echo
echo "Available modules:"
local modules=()
for module in "${SCRIPT_DIR}/modules"/*; do
Expand All @@ -65,18 +70,17 @@ _debug "$DASHBOARD_NAME v$DASHBOARD_VERSION"

_debug 'parsing command-line arguments'

OUTPUT_PATH=""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-a|--aggregate)
AGGREGATE=1
shift
;;
-f|--format)
FORMAT="$2"
shift 2
;;
-o|--output)
OUTPUT_PATH="$2"
shift 2
;;
-h|--help)
usage
exit 0
Expand Down Expand Up @@ -128,49 +132,6 @@ if ! command -v jq &> /dev/null; then
fi


_debug 'Get list of modules to run'
MODULES_DIR="${SCRIPT_DIR}/modules"
MODULES_TO_RUN=()
if [ -n "$MODULE_TO_RUN" ]; then
# If the user provides 'github', check for 'github.sh'
if [[ ! "$MODULE_TO_RUN" == *.sh ]]; then
MODULE_TO_RUN="${MODULE_TO_RUN}.sh"
fi
MODULE_PATH="${MODULES_DIR}/${MODULE_TO_RUN}"
if [ ! -x "$MODULE_PATH" ]; then
# If 'github.sh' is not found, try without the extension for backward compatibility
MODULE_TO_RUN_NO_EXT="${MODULE_TO_RUN%.sh}"
MODULE_PATH_NO_EXT="${MODULES_DIR}/${MODULE_TO_RUN_NO_EXT}"
if [ -x "$MODULE_PATH_NO_EXT" ]; then
MODULE_PATH="$MODULE_PATH_NO_EXT"
MODULE_TO_RUN="$MODULE_TO_RUN_NO_EXT"
else
_error "Error: Module '${MODULE_TO_RUN}' not found or not executable."
exit 1
fi
fi
MODULES_TO_RUN+=("$MODULE_TO_RUN")
else
# Find all executable files in the modules directory, with or without .sh
for module in "${MODULES_DIR}"/*; do
if [ -x "$module" ]; then
MODULES_TO_RUN+=("$(basename "$module")")
fi
done
fi

_debug "MODULES_TO_RUN: ${MODULES_TO_RUN[*]}"

_debug 'Collect output from all modules'
OUTPUTS=()
for module_name in "${MODULES_TO_RUN[@]}"; do
_debug "Calling $module_name"
module_output=$("$MODULES_DIR/$module_name" "$MODULE_EXEC_FORMAT")
if [ -n "$module_output" ]; then
_debug "Saving output from $module_name: $(echo "$module_output" | wc -c | tr -d ' ') bytes"
OUTPUTS+=("$module_output")
fi
done

generate_report() {
case "$FORMAT" in
Expand Down Expand Up @@ -264,31 +225,105 @@ generate_report() {
esac
}

FINAL_OUTPUT_FILE=""
if [ -n "$OUTPUT_PATH" ]; then
if [ -d "$OUTPUT_PATH" ]; then
# User provided a directory
REPORTS_DIR="$OUTPUT_PATH"
TIMESTAMP=$(date +"%Y-%m-%d-%H-%M")
FINAL_OUTPUT_FILE="${REPORTS_DIR}/${TIMESTAMP}.${FORMAT}"
else
# User provided a file path
FINAL_OUTPUT_FILE="$OUTPUT_PATH"
aggregate_reports() {
local reports_dir="${SCRIPT_DIR}/reports"
_debug "Aggregating reports from ${reports_dir}"
if ! command -v awk &> /dev/null; then
_error "'awk' command not found, which is required for aggregation."
exit 1
fi
else
# Default behavior
REPORTS_DIR="${SCRIPT_DIR}/reports"
mkdir -p "$REPORTS_DIR"
TIMESTAMP=$(date +"%Y-%m-%d-%H-%M")
FINAL_OUTPUT_FILE="${REPORTS_DIR}/${TIMESTAMP}.${FORMAT}"
fi

_debug "Assemble the final report: FORMAT: $FORMAT"
_debug "Output file: $FINAL_OUTPUT_FILE"
local report_files
report_files=$(find "$reports_dir" -name "*.tsv" 2>/dev/null | sort)
if [ -z "$report_files" ]; then
_warn "No .tsv reports found in ${reports_dir} to aggregate."
return
fi

# Use awk to process the tsv files
# We pass the report files to awk, which will process them in alphabetical order.
# Since the filenames start with a timestamp, this will process them in chronological order.
awk '
BEGIN {
FS="\t";
OFS="\t";
print "Metric\tFirst Value\tLast Value\tChange";
print "------\t-----------\t----------\t------";
}
FNR == 1 { next; } # Skip header row of each file
{
metric = $2 OFS $3 OFS $4; # module, channel, namespace
value = $5;
if (!(metric in first_value)) {
first_value[metric] = value;
}
last_value[metric] = value;
}
END {
for (metric in last_value) {
change = last_value[metric] - first_value[metric];
# Add a plus sign for positive changes
if (change > 0) {
change_str = "+" change;
} else {
change_str = change;
}
print metric, first_value[metric], last_value[metric], change_str;
}
}' $report_files
}

# --- Main Execution Flow ----------------------------------------------------

if [ -n "$FINAL_OUTPUT_FILE" ]; then
generate_report > "$FINAL_OUTPUT_FILE"
if [ "$AGGREGATE" -eq 1 ]; then
aggregate_reports
else
# --- Module Data Collection ---------------------------------------------
_debug 'Get list of modules to run'
MODULES_DIR="${SCRIPT_DIR}/modules"
MODULES_TO_RUN=()
if [ -n "$MODULE_TO_RUN" ]; then
# If the user provides 'github', check for 'github.sh'
if [[ ! "$MODULE_TO_RUN" == *.sh ]]; then
MODULE_TO_RUN="${MODULE_TO_RUN}.sh"
fi
MODULE_PATH="${MODULES_DIR}/${MODULE_TO_RUN}"
if [ ! -x "$MODULE_PATH" ]; then
# If 'github.sh' is not found, try without the extension for backward compatibility
MODULE_TO_RUN_NO_EXT="${MODULE_TO_RUN%.sh}"
MODULE_PATH_NO_EXT="${MODULES_DIR}/${MODULE_TO_RUN_NO_EXT}"
if [ -x "$MODULE_PATH_NO_EXT" ]; then
MODULE_PATH="$MODULE_PATH_NO_EXT"
MODULE_TO_RUN="$MODULE_TO_RUN_NO_EXT"
else
_error "Error: Module '${MODULE_TO_RUN}' not found or not executable."
exit 1
fi
fi
MODULES_TO_RUN+=("$MODULE_TO_RUN")
else
# Defined order of execution
ORDERED_MODULES=("github.sh" "hackernews.sh" "discord.sh" "github-sponsors.sh" "crypto.sh")
for module in "${ORDERED_MODULES[@]}"; do
if [ -x "${MODULES_DIR}/${module}" ]; then
MODULES_TO_RUN+=("$module")
fi
done
fi

_debug "MODULES_TO_RUN: ${MODULES_TO_RUN[*]}"

_debug 'Collect output from all modules'
OUTPUTS=()
for module_name in "${MODULES_TO_RUN[@]}"; do
_debug "Calling $module_name"
module_output=$("$MODULES_DIR/$module_name" "$MODULE_EXEC_FORMAT")
if [ -n "$module_output" ]; then
_debug "Saving output from $module_name: $(echo "$module_output" | wc -c | tr -d ' ') bytes"
OUTPUTS+=("$module_output")
fi
done

generate_report
fi

Expand Down
23 changes: 0 additions & 23 deletions docs/render.md

This file was deleted.

2 changes: 1 addition & 1 deletion modules/crypto.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# modules/crypto.sh
#
Expand Down
2 changes: 1 addition & 1 deletion modules/discord.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# modules/discord.sh
#
Expand Down
2 changes: 1 addition & 1 deletion modules/github-sponsors.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# modules/github-sponsors
#
Expand Down
2 changes: 1 addition & 1 deletion modules/github.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# modules/github
#
Expand Down
2 changes: 1 addition & 1 deletion modules/hackernews.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# modules/hackernews
#
Expand Down
6 changes: 0 additions & 6 deletions render.yaml

This file was deleted.

5 changes: 5 additions & 0 deletions reports/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore everything in this directory
*

# Except for this file
!.gitignore
Loading