#!/bin/bash
# ═══════════════════════════════════════════════════════════════
# irc — catgirl wrapper for managing IRC network connections
#
# Usage:
# irc Show all networks by category
# irc <network> Connect to a network
# irc <network> -j #ch Connect and join extra channel
# irc search <term> Search networks by name/host
# irc help Show usage
#
# Config: ~/.config/catgirl/<network>
# Each file is a catgirl config (host, port, nick, join, etc.)
# ═══════════════════════════════════════════════════════════════
CONFIGS="$HOME/.config/catgirl"
NICK="khr1st"
# ─── ANSI Colors ──────────────────────────────────────────────
BOLD='\033[1m'
DIM='\033[2m'
CYAN='\033[36m'
BLUE='\033[34m'
MAGENTA='\033[35m'
GREEN='\033[32m'
YELLOW='\033[33m'
RED='\033[31m'
WHITE='\033[37m'
RESET='\033[0m'
# ─── Network Categories ──────────────────────────────────────
#
# Networks are grouped by purpose. Add new catgirl configs to
# ~/.config/catgirl/ and register them in the appropriate
# category array below.
#
# Tracker networks are organized by content domain so you can
# quickly find the right channel for interviews, recruitment,
# or community participation.
# ── Trackers: Gateway & Recruitment ───────────────────────────
# These are the entry points into the private tracker ecosystem.
# RED and OPS interviews happen here. Build ratio, reach Power
# User, and recruitment threads open the doors to everything.
TRACKERS_GATEWAY="red ops"
# ── Trackers: Cinema & Arthouse ───────────────────────────────
# Channels for film-focused trackers. BakaBT covers anime film.
# KG and PTP recruitment happens via RED/OPS Power User forums,
# not directly on IRC — but these are the community channels.
TRACKERS_CINEMA="bakabt"
# ── Trackers: Literature & Books ──────────────────────────────
# MAM interviews happen Wed & Sat on their IRC. IRChighway and
# Undernet are direct download channels — use @search to find
# books, bot sends via DCC. Essential for rare/OOP titles.
TRACKERS_LITERATURE="mam irchighway undernet"
# ── Trackers: Music & Live Recordings ─────────────────────────
# DimeADozen is the bootleg concert recording community.
# RED/OPS double as music tracker IRC (see Gateway above).
TRACKERS_MUSIC="dime"
# ── General Networks ──────────────────────────────────────────
# Communities for programming, science, privacy, and general
# IRC culture. These are not tracker-related.
GENERAL="libera oftc hackint rizon tilde efnet ircnet"
# ─── Functions ────────────────────────────────────────────────
# Print a single network entry with aligned columns
print_entry() {
_name="$1"
_color="$2"
_conf="$CONFIGS/$_name"
[ ! -f "$_conf" ] && return
_host=$(sed -n 's/^host *= *//p' "$_conf" | head -1)
_join=$(sed -n 's/^join *= *//p' "$_conf" | head -1)
if [ -n "$_join" ]; then
printf " ${_color}%-14s${RESET} ${DIM}%-30s${RESET} %s\n" \
"$_name" "$_host" "$_join"
else
printf " ${_color}%-14s${RESET} ${DIM}%s${RESET}\n" \
"$_name" "$_host"
fi
}
# Print a section header
print_header() {
_icon="$1"
_title="$2"
_color="$3"
printf "\n ${_color}${BOLD}%s %s${RESET}\n" "$_icon" "$_title"
}
# Print all networks in a category
print_section() {
_icon="$1"
_title="$2"
_color="$3"
_networks="$4"
print_header "$_icon" "$_title" "$_color"
for _net in $_networks; do
print_entry "$_net" "$_color"
done
}
# List all networks grouped by category
list_networks() {
printf "${BOLD}${WHITE}"
printf " ╔═══════════════════════════════════════╗\n"
printf " ║ irc — network index ║\n"
printf " ╚═══════════════════════════════════════╝${RESET}\n"
print_section "" "Gateway & Recruitment" "$RED" "$TRACKERS_GATEWAY"
print_section "" "Cinema & Arthouse" "$MAGENTA" "$TRACKERS_CINEMA"
print_section "" "Literature & Books" "$CYAN" "$TRACKERS_LITERATURE"
print_section "" "Music & Live" "$GREEN" "$TRACKERS_MUSIC"
print_section "" "General Networks" "$BLUE" "$GENERAL"
# Check for uncategorized configs
_all_known="$TRACKERS_GATEWAY $TRACKERS_CINEMA $TRACKERS_LITERATURE $TRACKERS_MUSIC $GENERAL"
_uncategorized=""
for _f in "$CONFIGS"/*; do
_name=$(basename "$_f")
_found=0
for _k in $_all_known; do
[ "$_name" = "$_k" ] && _found=1 && break
done
[ "$_found" -eq 0 ] && _uncategorized="$_uncategorized $_name"
done
if [ -n "$_uncategorized" ]; then
print_section "?" "Uncategorized" "$YELLOW" "$_uncategorized"
fi
printf "\n ${DIM}Usage: irc <name> | irc search <term> | irc help${RESET}\n\n"
}
# Search networks by name, host, or channel
search_networks() {
_term="$1"
_found=0
printf "\n ${BOLD}Search: ${YELLOW}%s${RESET}\n\n" "$_term"
for _f in "$CONFIGS"/*; do
_name=$(basename "$_f")
_content=$(cat "$_f" 2>/dev/null)
if echo "$_name $_content" | grep -qi "$_term"; then
print_entry "$_name" "$CYAN"
_found=1
fi
done
[ "$_found" -eq 0 ] && printf " ${DIM}No matches.${RESET}\n"
echo
}
# Show help
show_help() {
printf "${BOLD}${WHITE}irc${RESET} — catgirl wrapper\n\n"
printf " ${CYAN}irc${RESET} List all networks\n"
printf " ${CYAN}irc ${GREEN}<network>${RESET} Connect to a network (invisible)\n"
printf " ${CYAN}irc ${GREEN}<network> -i${RESET} Connect visible (no +i mode)\n"
printf " ${CYAN}irc ${GREEN}<network> -j #ch${RESET} Connect & join extra channel\n"
printf " ${CYAN}irc search ${GREEN}<term>${RESET} Search by name, host, or channel\n"
printf " ${CYAN}irc help${RESET} This message\n\n"
printf " ${DIM}Configs: ~/.config/catgirl/<network>${RESET}\n"
printf " ${DIM}Add a new file there and register it in a${RESET}\n"
printf " ${DIM}category array inside this script.${RESET}\n\n"
}
# Connect to a network
connect() {
_visible=0
_network=""
_extra=""
# Parse flags
for _arg in "$@"; do
case "$_arg" in
-i) _visible=1 ;;
*)
if [ -z "$_network" ]; then
_network="$_arg"
else
_extra="$_extra $_arg"
fi
;;
esac
done
if [ -z "$_network" ]; then
printf "${RED}No network specified.${RESET}\n"
exit 1
fi
if [ ! -f "$CONFIGS/$_network" ]; then
printf "${RED}Unknown network:${RESET} %s\n" "$_network"
printf "${DIM}Run 'irc' to see available networks.${RESET}\n"
exit 1
fi
# If -i (visible), use a temp config without mode = +i
if [ "$_visible" -eq 1 ]; then
_tmp=$(mktemp "$CONFIGS/.tmp-$_network-XXXXXX")
grep -v "^mode" "$CONFIGS/$_network" > "$_tmp"
_tmpname=$(basename "$_tmp")
trap 'rm -f "$_tmp"' EXIT
exec catgirl "$_tmpname" $_extra
fi
exec catgirl "$_network" $_extra
}
# ─── Main ─────────────────────────────────────────────────────
case "${1:-}" in
""|ls|list) list_networks ;;
search|find|grep) shift; search_networks "${1:-}" ;;
-h|--help|help) show_help ;;
-i) shift; connect "$@" -i ;;
*) connect "$@" ;;
esac