v2.2.1: unified menu with bot management, grouped sections, telemt download fix, QR cleanup, version bump

This commit is contained in:
anten-ka
2026-04-06 21:40:34 +03:00
parent fe9e5fa019
commit fee25f191e
9 changed files with 2306 additions and 1907 deletions

View File

@@ -1,280 +1,280 @@
#!/bin/bash
# GoTelegram v2.2 — Каталог шаблонов сайтов
# Выбор из ~200 шаблонов, превью-ссылки, скачивание через git sparse-checkout
CATALOG_FILE="$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")/templates_catalog.json"
TEMPLATES_CACHE="/tmp/gotelegram_templates"
# ── Загрузка каталога ────────────────────────────────────────────────────────
load_catalog() {
if [ ! -f "$CATALOG_FILE" ]; then
log_error "Каталог шаблонов не найден: $CATALOG_FILE"
return 1
fi
return 0
}
# ── Категории ────────────────────────────────────────────────────────────────
get_categories() {
jq -r '.categories[] | "\(.id)|\(.name)|\(.icon)|\(.templates | length)"' "$CATALOG_FILE" 2>/dev/null
}
get_category_name() {
local cat_id="$1"
jq -r ".categories[] | select(.id == \"$cat_id\") | .name" "$CATALOG_FILE" 2>/dev/null
}
# ── Шаблоны по категории ────────────────────────────────────────────────────
get_templates_by_category() {
local cat_id="$1"
jq -r ".categories[] | select(.id == \"$cat_id\") | .templates[] | \"\(.id)|\(.name)|\(.source)|\(.preview_url)\"" "$CATALOG_FILE" 2>/dev/null
}
# ── Информация о шаблоне ────────────────────────────────────────────────────
get_template_info() {
local tpl_id="$1"
jq ".categories[].templates[] | select(.id == \"$tpl_id\")" "$CATALOG_FILE" 2>/dev/null
}
get_template_field() {
local tpl_id="$1"
local field="$2"
jq -r ".categories[].templates[] | select(.id == \"$tpl_id\") | .$field" "$CATALOG_FILE" 2>/dev/null
}
# ── Интерактивный выбор категории ────────────────────────────────────────────
select_category() {
load_catalog || return 1
echo ""
echo -e " ${BOLD}${WHITE}📂 Категории шаблонов сайтов:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
local cats=()
local i=1
while IFS='|' read -r id name icon count; do
[ "$count" -eq 0 ] && continue
local emoji
case "$icon" in
briefcase) emoji="🏢" ;;
shopping-cart) emoji="🛒" ;;
heart) emoji="🏥" ;;
book) emoji="🎓" ;;
palette) emoji="📸" ;;
home) emoji="🏠" ;;
utensils) emoji="🍕" ;;
rocket) emoji="🎨" ;;
chart-bar) emoji="🔧" ;;
*) emoji="📄" ;;
esac
printf " ${CYAN}%2d)${NC} ${emoji} %-30s ${DIM}(%d шаблонов)${NC}\n" "$i" "$name" "$count"
cats+=("$id")
((i++))
done < <(get_categories)
printf " ${CYAN}%2d)${NC} 🎲 Случайный шаблон\n" "$i"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -ne " ${WHITE}Выбор:${NC} "
read -r choice
# Случайный
if [ "$choice" -eq "$i" ] 2>/dev/null; then
local random_cat="${cats[$((RANDOM % ${#cats[@]}))]}"
echo "$random_cat"
return 0
fi
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then
echo "${cats[$((choice-1))]}"
return 0
fi
log_error "Неверный выбор"
return 1
}
# ── Интерактивный выбор шаблона ──────────────────────────────────────────────
select_template() {
local cat_id="$1"
local cat_name
cat_name=$(get_category_name "$cat_id")
echo ""
echo -e " ${BOLD}${WHITE}📋 $cat_name — доступные шаблоны:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}"
local tpls=()
local i=1
while IFS='|' read -r id name source preview; do
printf " ${CYAN}%2d)${NC} %-30s ${DIM}[%s]${NC}\n" "$i" "$name" "$source"
tpls+=("$id")
((i++))
done < <(get_templates_by_category "$cat_id")
if [ ${#tpls[@]} -eq 0 ]; then
log_info "В этой категории нет шаблонов"
return 1
fi
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}"
echo -ne " ${WHITE}Выбор (1-$((i-1))):${NC} "
read -r choice
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then
local selected_id="${tpls[$((choice-1))]}"
# Показываем превью
show_template_preview "$selected_id"
echo "$selected_id"
return 0
fi
log_error "Неверный выбор"
return 1
}
# ── Показ превью шаблона ────────────────────────────────────────────────────
show_template_preview() {
local tpl_id="$1"
local info
info=$(get_template_info "$tpl_id")
local name source preview_url repo_url description
name=$(echo "$info" | jq -r '.name')
source=$(echo "$info" | jq -r '.source')
preview_url=$(echo "$info" | jq -r '.preview_url // empty')
repo_url=$(echo "$info" | jq -r '.repo_url // empty')
description=$(echo "$info" | jq -r '.description // "—"')
echo ""
echo -e " ${BOLD}${WHITE}🔍 Превью шаблона:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -e " ${WHITE}Название:${NC} $name"
echo -e " ${WHITE}Источник:${NC} $source"
echo -e " ${WHITE}Описание:${NC} $description"
if [ -n "$preview_url" ]; then
echo ""
echo -e " ${GREEN}👁 Превью:${NC} ${CYAN}${preview_url}${NC}"
echo -e " ${DIM}Откройте ссылку в браузере для просмотра шаблона${NC}"
fi
if [ -n "$repo_url" ]; then
echo -e " ${DIM}📦 Репо: ${repo_url}${NC}"
fi
# Благодарность автору
echo ""
echo -e " ${MAGENTA}💜 Спасибо авторам ${source} за открытый код!${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo ""
if ! confirm "Установить этот шаблон?"; then
return 1
fi
return 0
}
# ── Скачивание шаблона ───────────────────────────────────────────────────────
download_template() {
local tpl_id="$1"
local output_dir="${2:-$TEMPLATES_CACHE}"
local info
info=$(get_template_info "$tpl_id")
local repo_url sparse_path source name
repo_url=$(echo "$info" | jq -r '.repo_url')
sparse_path=$(echo "$info" | jq -r '.sparse_path')
source=$(echo "$info" | jq -r '.source')
name=$(echo "$info" | jq -r '.name')
local clone_dir="$output_dir/${tpl_id}"
rm -rf "$clone_dir"
mkdir -p "$clone_dir"
log_info "Скачивание шаблона \"$name\"..."
# Для HTML5 UP — отдельный репо с папками
if [ "$source" = "html5up" ]; then
local tmp_clone="/tmp/html5up_clone_$$"
rm -rf "$tmp_clone"
# Sparse checkout
git clone --depth 1 --filter=blob:none --sparse "$repo_url" "$tmp_clone" 2>/dev/null
if [ $? -ne 0 ]; then
# Fallback: полный clone
git clone --depth 1 "$repo_url" "$tmp_clone" 2>/dev/null
fi
if [ -d "$tmp_clone" ]; then
cd "$tmp_clone" && git sparse-checkout set "$sparse_path" 2>/dev/null
if [ -d "$tmp_clone/$sparse_path" ]; then
cp -r "$tmp_clone/$sparse_path"/* "$clone_dir/"
fi
cd - >/dev/null
fi
rm -rf "$tmp_clone"
# Для learning-zone — один большой репо
elif [ "$source" = "learning-zone" ]; then
local tmp_clone="/tmp/lz_clone_$$"
rm -rf "$tmp_clone"
git clone --depth 1 --filter=blob:none --sparse "$repo_url" "$tmp_clone" 2>/dev/null
if [ $? -ne 0 ]; then
git clone --depth 1 "$repo_url" "$tmp_clone" 2>/dev/null
fi
if [ -d "$tmp_clone" ]; then
cd "$tmp_clone" && git sparse-checkout set "$sparse_path" 2>/dev/null
if [ -d "$tmp_clone/$sparse_path" ]; then
cp -r "$tmp_clone/$sparse_path"/* "$clone_dir/"
fi
cd - >/dev/null
fi
rm -rf "$tmp_clone"
# Для StartBootstrap — каждый шаблон в своём репо
elif [ "$source" = "startbootstrap" ]; then
git clone --depth 1 "$repo_url" "$clone_dir" 2>/dev/null
# Убираем .git
rm -rf "$clone_dir/.git"
fi
# Проверяем результат
if [ -f "$clone_dir/index.html" ]; then
log_success "Шаблон \"$name\" скачан"
echo "$clone_dir"
return 0
else
log_error "Шаблон не содержит index.html"
log_dim "Путь: $clone_dir"
ls -la "$clone_dir" 2>/dev/null
return 1
fi
}
# ── Полный интерактивный процесс выбора ──────────────────────────────────────
interactive_template_selection() {
load_catalog || return 1
# Выбор категории
local cat_id
cat_id=$(select_category)
[ $? -ne 0 ] && return 1
# Выбор шаблона
local tpl_id
tpl_id=$(select_template "$cat_id")
[ $? -ne 0 ] && return 1
# Скачивание
local template_dir
template_dir=$(download_template "$tpl_id")
[ $? -ne 0 ] && return 1
echo "$template_dir"
return 0
}
#!/bin/bash
# GoTelegram v2.2 — Каталог шаблонов сайтов
# Выбор из ~200 шаблонов, превью-ссылки, скачивание через git sparse-checkout
CATALOG_FILE="$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")/templates_catalog.json"
TEMPLATES_CACHE="/tmp/gotelegram_templates"
# ── Загрузка каталога ────────────────────────────────────────────────────────
load_catalog() {
if [ ! -f "$CATALOG_FILE" ]; then
log_error "Каталог шаблонов не найден: $CATALOG_FILE"
return 1
fi
return 0
}
# ── Категории ────────────────────────────────────────────────────────────────
get_categories() {
jq -r '.categories[] | "\(.id)|\(.name)|\(.icon)|\(.templates | length)"' "$CATALOG_FILE" 2>/dev/null
}
get_category_name() {
local cat_id="$1"
jq -r ".categories[] | select(.id == \"$cat_id\") | .name" "$CATALOG_FILE" 2>/dev/null
}
# ── Шаблоны по категории ────────────────────────────────────────────────────
get_templates_by_category() {
local cat_id="$1"
jq -r ".categories[] | select(.id == \"$cat_id\") | .templates[] | \"\(.id)|\(.name)|\(.source)|\(.preview_url)\"" "$CATALOG_FILE" 2>/dev/null
}
# ── Информация о шаблоне ────────────────────────────────────────────────────
get_template_info() {
local tpl_id="$1"
jq ".categories[].templates[] | select(.id == \"$tpl_id\")" "$CATALOG_FILE" 2>/dev/null
}
get_template_field() {
local tpl_id="$1"
local field="$2"
jq -r ".categories[].templates[] | select(.id == \"$tpl_id\") | .$field" "$CATALOG_FILE" 2>/dev/null
}
# ── Интерактивный выбор категории ────────────────────────────────────────────
select_category() {
load_catalog || return 1
echo ""
echo -e " ${BOLD}${WHITE}📂 Категории шаблонов сайтов:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
local cats=()
local i=1
while IFS='|' read -r id name icon count; do
[ "$count" -eq 0 ] && continue
local emoji
case "$icon" in
briefcase) emoji="🏢" ;;
shopping-cart) emoji="🛒" ;;
heart) emoji="🏥" ;;
book) emoji="🎓" ;;
palette) emoji="📸" ;;
home) emoji="🏠" ;;
utensils) emoji="🍕" ;;
rocket) emoji="🎨" ;;
chart-bar) emoji="🔧" ;;
*) emoji="📄" ;;
esac
printf " ${CYAN}%2d)${NC} ${emoji} %-30s ${DIM}(%d шаблонов)${NC}\n" "$i" "$name" "$count"
cats+=("$id")
((i++))
done < <(get_categories)
printf " ${CYAN}%2d)${NC} 🎲 Случайный шаблон\n" "$i"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -ne " ${WHITE}Выбор:${NC} "
read -r choice
# Случайный
if [ "$choice" -eq "$i" ] 2>/dev/null; then
local random_cat="${cats[$((RANDOM % ${#cats[@]}))]}"
echo "$random_cat"
return 0
fi
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then
echo "${cats[$((choice-1))]}"
return 0
fi
log_error "Неверный выбор"
return 1
}
# ── Интерактивный выбор шаблона ──────────────────────────────────────────────
select_template() {
local cat_id="$1"
local cat_name
cat_name=$(get_category_name "$cat_id")
echo ""
echo -e " ${BOLD}${WHITE}📋 $cat_name — доступные шаблоны:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}"
local tpls=()
local i=1
while IFS='|' read -r id name source preview; do
printf " ${CYAN}%2d)${NC} %-30s ${DIM}[%s]${NC}\n" "$i" "$name" "$source"
tpls+=("$id")
((i++))
done < <(get_templates_by_category "$cat_id")
if [ ${#tpls[@]} -eq 0 ]; then
log_info "В этой категории нет шаблонов"
return 1
fi
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}"
echo -ne " ${WHITE}Выбор (1-$((i-1))):${NC} "
read -r choice
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then
local selected_id="${tpls[$((choice-1))]}"
# Показываем превью
show_template_preview "$selected_id"
echo "$selected_id"
return 0
fi
log_error "Неверный выбор"
return 1
}
# ── Показ превью шаблона ────────────────────────────────────────────────────
show_template_preview() {
local tpl_id="$1"
local info
info=$(get_template_info "$tpl_id")
local name source preview_url repo_url description
name=$(echo "$info" | jq -r '.name')
source=$(echo "$info" | jq -r '.source')
preview_url=$(echo "$info" | jq -r '.preview_url // empty')
repo_url=$(echo "$info" | jq -r '.repo_url // empty')
description=$(echo "$info" | jq -r '.description // "—"')
echo ""
echo -e " ${BOLD}${WHITE}🔍 Превью шаблона:${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo -e " ${WHITE}Название:${NC} $name"
echo -e " ${WHITE}Источник:${NC} $source"
echo -e " ${WHITE}Описание:${NC} $description"
if [ -n "$preview_url" ]; then
echo ""
echo -e " ${GREEN}👁 Превью:${NC} ${CYAN}${preview_url}${NC}"
echo -e " ${DIM}Откройте ссылку в браузере для просмотра шаблона${NC}"
fi
if [ -n "$repo_url" ]; then
echo -e " ${DIM}📦 Репо: ${repo_url}${NC}"
fi
# Благодарность автору
echo ""
echo -e " ${MAGENTA}💜 Спасибо авторам ${source} за открытый код!${NC}"
echo -e " ${DIM}$(printf '─%.0s' {1..55})${NC}"
echo ""
if ! confirm "Установить этот шаблон?"; then
return 1
fi
return 0
}
# ── Скачивание шаблона ───────────────────────────────────────────────────────
download_template() {
local tpl_id="$1"
local output_dir="${2:-$TEMPLATES_CACHE}"
local info
info=$(get_template_info "$tpl_id")
local repo_url sparse_path source name
repo_url=$(echo "$info" | jq -r '.repo_url')
sparse_path=$(echo "$info" | jq -r '.sparse_path')
source=$(echo "$info" | jq -r '.source')
name=$(echo "$info" | jq -r '.name')
local clone_dir="$output_dir/${tpl_id}"
rm -rf "$clone_dir"
mkdir -p "$clone_dir"
log_info "Скачивание шаблона \"$name\"..."
# Для HTML5 UP — отдельный репо с папками
if [ "$source" = "html5up" ]; then
local tmp_clone="/tmp/html5up_clone_$$"
rm -rf "$tmp_clone"
# Sparse checkout
git clone --depth 1 --filter=blob:none --sparse "$repo_url" "$tmp_clone" 2>/dev/null
if [ $? -ne 0 ]; then
# Fallback: полный clone
git clone --depth 1 "$repo_url" "$tmp_clone" 2>/dev/null
fi
if [ -d "$tmp_clone" ]; then
cd "$tmp_clone" && git sparse-checkout set "$sparse_path" 2>/dev/null
if [ -d "$tmp_clone/$sparse_path" ]; then
cp -r "$tmp_clone/$sparse_path"/* "$clone_dir/"
fi
cd - >/dev/null
fi
rm -rf "$tmp_clone"
# Для learning-zone — один большой репо
elif [ "$source" = "learning-zone" ]; then
local tmp_clone="/tmp/lz_clone_$$"
rm -rf "$tmp_clone"
git clone --depth 1 --filter=blob:none --sparse "$repo_url" "$tmp_clone" 2>/dev/null
if [ $? -ne 0 ]; then
git clone --depth 1 "$repo_url" "$tmp_clone" 2>/dev/null
fi
if [ -d "$tmp_clone" ]; then
cd "$tmp_clone" && git sparse-checkout set "$sparse_path" 2>/dev/null
if [ -d "$tmp_clone/$sparse_path" ]; then
cp -r "$tmp_clone/$sparse_path"/* "$clone_dir/"
fi
cd - >/dev/null
fi
rm -rf "$tmp_clone"
# Для StartBootstrap — каждый шаблон в своём репо
elif [ "$source" = "startbootstrap" ]; then
git clone --depth 1 "$repo_url" "$clone_dir" 2>/dev/null
# Убираем .git
rm -rf "$clone_dir/.git"
fi
# Проверяем результат
if [ -f "$clone_dir/index.html" ]; then
log_success "Шаблон \"$name\" скачан"
echo "$clone_dir"
return 0
else
log_error "Шаблон не содержит index.html"
log_dim "Путь: $clone_dir"
ls -la "$clone_dir" 2>/dev/null
return 1
fi
}
# ── Полный интерактивный процесс выбора ──────────────────────────────────────
interactive_template_selection() {
load_catalog || return 1
# Выбор категории
local cat_id
cat_id=$(select_category)
[ $? -ne 0 ] && return 1
# Выбор шаблона
local tpl_id
tpl_id=$(select_template "$cat_id")
[ $? -ne 0 ] && return 1
# Скачивание
local template_dir
template_dir=$(download_template "$tpl_id")
[ $? -ne 0 ] && return 1
echo "$template_dir"
return 0
}