#!/usr/bin/env bash ### # JItsi Log Observer - command line interface # # Bash script for Jitsi Meet components (Videobridge, Jicofo, etc.) logs parsing # Command line interface (jilo-cli) ### ### Configuration file (overrides default configs) CONFIG_FILE="./jilo.conf" ### Default configuration # Default database type (sqlite, mysql|mariadb) DEFAULT_DB_TYPE="sqlite" # Default SQLite database file DEFAULT_DB="./jilo.db" # Default MySQL/MariaDB configuration DEFAULT_MYSQL_HOST="localhost" DEFAULT_MYSQL_USER="jilo" DEFAULT_MYSQL_PASS="jilopass" DEFAULT_MYSQL_DB="jilo_db" # Load configurations from the config file if it exists if [[ -f "$CONFIG_FILE" ]]; then source "$CONFIG_FILE" fi # use default values if not overriden by config file DB=${DB:-$DEFAULT_DB} DB_TYPE=${DB_TYPE:-$DEFAULT_DB_TYPE} MYSQL_HOST=${MYSQL_HOST:-$DEFAULT_MYSQL_HOST} MYSQL_USER=${MYSQL_USER:-$DEFAULT_MYSQL_USER} MYSQL_PASS=${MYSQL_PASS:-$DEFAULT_MYSQL_PASS} MYSQL_DB=${MYSQL_DB:-$DEFAULT_MYSQL_DB} ### # DB queries db_stats_conferences_all_template="SELECT * FROM conferences;" db_stats_conferences_name_template="SELECT * FROM conferences WHERE conference_name='%s';" db_stats_conferences_id_template="SELECT * FROM conferences WHERE conference_id='%s';" db_stats_conferences_time_template="SELECT * FROM conferences WHERE start >= '%s' AND end <= '%s';" db_stats_participants_all_template="SELECT * FROM participants;" db_stats_participants_conference_template="SELECT * FROM participants WHERE conference_id='%s';" db_stats_participants_event_template="SELECT * FROM participants WHERE event_type LIKE '%%%s%%';" db_stats_participants_endpoint_template="SELECT * FROM participants WHERE endpoint_id='%s';" db_stats_participants_statsid_template="SELECT * FROM participants WHERE stats_id LIKE '%%%s%%';" db_stats_participants_ip_template="SELECT * FROM participants WHERE participant_ip='%s';" help="Usage: $0 [OPTION] Options: --conference|-c [conference ID or name] - show specific conference(s), all of empty --participant|-p [conference ID, participant IP, or word from the event type or stats ID] - show specific participant(s), all if empty --time|-t - show stats for a time interval" ### # First we check for requirements check_requirements() { # required programs, anything non-bash - edit as needed # deb packages - sqlite3 local required_programs=("sqlite3") local requirements_missing='' for program in "${required_programs[@]}"; do if ! command -v "$program" &> /dev/null; then requirements_missing+="$program, " fi done if [[ "$requirements_missing" != '' ]]; then requirements_missing=${requirements_missing::-2} echo "Error: $requirements_missing - not found. Please install to proceed." fi } check_requirements ### # DB functions for Sqlite3 and for MySQL/MariaDB # execute a query and return the result db_query() { local query=$1 if [[ "$DB_TYPE" == "sqlite" ]]; then sqlite3 "$DB" "$query" elif [[ "$DB_TYPE" == "mysql" || "$DB_TYPE" == "mariadb" ]]; then mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p "$MYSQL_PASS" -D "$MYSQL_DB" -se "$query" else echo "Error: unknown database type $DB_TYPE." exit 1 fi } ### input parameters parsing # time parameters parse_time_range() { local time_range="$1" ## exact times # exact date given (YYYY-MM-DD) if [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then from_time="${BASH_REMATCH[0]}" until_time="${BASH_REMATCH[0]}" # exact month given (YYYY-MM) elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})$ ]]; then from_time="${BASH_REMATCH[0]}-01" until_time="${BASH_REMATCH[0]}-31" # exact year given (YYYY) elif [[ "$time_range" =~ ^([0-9]{4})$ ]]; then from_time="${BASH_REMATCH[0]}-01-01" until_time="${BASH_REMATCH[0]}-12-31" ## exact periods # from date to date elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2}):([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}" until_time="${BASH_REMATCH[4]}-${BASH_REMATCH[5]}-${BASH_REMATCH[6]}" # from month to month elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2}):([0-9]{4})-([0-9]{2})$ ]]; then from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-01" until_time="${BASH_REMATCH[3]}-${BASH_REMATCH[4]}-31" # from year to year elif [[ "$time_range" =~ ^([0-9]{4}):([0-9]{4})$ ]]; then from_time="${BASH_REMATCH[1]}-01-01" until_time="${BASH_REMATCH[2]}-12-31" ## only end time given # from begining until date (:YYYY-MM-DD) elif [[ "$time_range" =~ ^:([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then from_time="0000-01-01" until_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}" # from begining until month (:YYYY-MM) elif [[ "$time_range" =~ ^:([0-9]{4})-([0-9]{2})$ ]]; then from_time="0000-01-01" until_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-31" # from begining until year (:YYYY) elif [[ "$time_range" =~ ^:([0-9]{4})$ ]]; then from_time="0000-01-01" until_time="${BASH_REMATCH[0]}-12-31" ## only start time given # from date until end (YYYY-MM-DD:) elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2}):$ ]]; then from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}" until_time="9999-12-31" # from month until end (YYYY-MM:) elif [[ "$time_range" =~ ^([0-9]{4})-([0-9]{2}):$ ]]; then from_time="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-01" until_time="9999-12-31" # from year until end (YYYY:) elif [[ "$time_range" =~ ^([0-9]{4}):$ ]]; then from_time="${BASH_REMATCH[1]}-01-01" until_time="9999-12-31" else echo -e "Invalid time range. Expected formats: - exact times YYYY-MM-DD, YYYY-MM, YYYY - exact periods YYYY-MM-DD:YYYY-MM-DD, YYYY-MM:YYYY-MM, YYYY:YYYY - from begining to given time :YYYY-MM-DD, :YYYY-MM, :YYYY - from given time until end YYYY-MM-DD:, YYYY-MM:, YYYY:" >&2 exit 1 fi time_range_specified=true } ### commandline options cmd="" conference_arg="" participant_arg="" from_time="" until_time="" time_range_specified=false while [[ $# -gt 0 ]]; do case "$1" in -c | --conference ) cmd="--conference" if [[ -n "$2" && "$2" != -* ]]; then conference_arg="$2" shift 2 else shift fi ;; -p | --participant) cmd="--participant" if [[ -n "$2" && "$2" != -* ]]; then participant_arg="$2" shift 2 else shift fi ;; -t | --time) cmd="--time" if [[ -n "$2" && "$2" != -* ]]; then parse_time_range "$2" shift 2 else echo "Option -t needs time range argument in format 'from-time - until-time', YYYY-MM-DD - YYYY-MM-DD" >&2 exit 1 fi ;; -h | --help) echo -e "$help" exit 0 ;; *) echo "Invalid option: $1" >&2 echo -e "$help" exit 1 ;; esac done case "$cmd" in --conference) if [[ -n "$conference_arg" ]]; then db_stats_conferences_id=$(printf "$db_stats_conferences_id_template" "$conference_arg") db_query "$db_stats_conferences_id" db_stats_conferences_name=$(printf "$db_stats_conferences_name_template" "$conference_arg") db_query "$db_stats_conferences_name" exit 0 else db_stats_conferences_all=$(printf "$db_stats_conferences_all_template") db_query "$db_stats_conferences_all" exit 0 fi ;; --participant) if [[ -n "$participant_arg" ]]; then db_stats_participants_conference=$(printf "$db_stats_participants_conference_template" "$participant_arg") db_query "$db_stats_participants_conference" db_stats_participants_event=$(printf "$db_stats_participants_event_template" "$participant_arg") db_query "$db_stats_participants_event" db_stats_participants_endpoint=$(printf "$db_stats_participants_endpoint_template" "$participant_arg") db_query "$db_stats_participants_endpoint" db_stats_participants_statsid=$(printf "$db_stats_participants_statsid_template" "$participant_arg") db_query "$db_stats_participants_statsid" db_stats_participants_ip=$(printf "$db_stats_participants_ip_template" "$participant_arg") db_query "$db_stats_participants_ip" exit 0 else db_stats_participants_all=$(printf "$db_stats_participants_all_template" ) db_query "$db_stats_participants_all" exit 0 fi ;; --time) if [[ "$time_range_specified" == true ]]; then db_stats_conferences_time=$(printf "$db_stats_conferences_time_template" "$from_time" "$until_time") db_query "$db_stats_conferences_time" fi exit 0 ;; *) echo -e "$help" exit 1 ;; esac