diff --git a/scripts/components/bot_tg.sh b/scripts/components/bot_tg.sh new file mode 100644 index 00000000..58b91a26 --- /dev/null +++ b/scripts/components/bot_tg.sh @@ -0,0 +1,210 @@ +#!/bin/sh + +. "$CRASHDIR"/configs/gateway.cfg +OFFSET=0 +API="https://api.telegram.org/bot$TG_TOKEN" +STATE_FILE="/tmp/ShellCrash/tgbot_state" +LOGFILE="/tmp/ShellCrash/tgbot.log" + +### --- 基础函数 --- ### +setproxy(){ + [ -n "$(pidof CrashCore)" ] && { + [ -n "$authentication" ] && auth="$authentication@" + [ -z "$mix_port" ] && mix_port=7890 + export https_proxy="http://${auth}127.0.0.1:$mix_port" + } +} +webget() { + setproxy + if curl --version >/dev/null 2>&1; then + curl -kfsSl --connect-timeout 3 $1 2>/dev/null + else + wget -Y on -q --timeout=3 -O - $1 + fi +} +webpost() { + setproxy + if curl --version >/dev/null 2>&1; then + curl -kfsSl -X POST --connect-timeout 3 -H "Content-Type: application/json; charset=utf-8" "$1" -d "$2" >/dev/null 2>&1 + else + wget -Y on -q --timeout=3 --method=POST --header="Content-Type: application/json; charset=utf-8" --body-data="$2" "$1" + fi +} +send_msg() { + TEXT="$1" + webpost "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\"}" +} +send_help(){ + TEXT=$(cat < "$LOGFILE" +} +do_stop_fw() { + redir_mod_bf=$redir_mod + redir_mod='纯净模式' + setconfig redir_mod $redir_mod + "$CRASHDIR"/start.sh stop_firewall + echo "ShellCrash 已切换到纯净模式!" > "$LOGFILE" +} +do_restart() { + "$CRASHDIR"/start.sh restart + echo "ShellCrash 服务已重启!" > "$LOGFILE" +} +do_refresh() { + "$CRASHDIR"/start.sh hotupdate + echo "ShellCrash 已完成热更新订阅!" > "$LOGFILE" +} +do_set_sub() { + #echo "$1" "$2" >> "$CRASHDIR"/configs/providers.cfg + echo "错误,还未完成的功能!" > "$LOGFILE" + +} + +### --- 轮询主进程 --- ### +polling(){ + while true; do + UPDATES=$(webget "$API/getUpdates?timeout=25&offset=$OFFSET") + + echo "$UPDATES" | grep -q '"update_id"' || continue + + OFFSET=$(echo "$UPDATES" | grep -o '"update_id":[0-9]*' | tail -n1 | cut -d: -f2) + OFFSET=$((OFFSET + 1)) + + ### --- 处理按钮事件 --- ### + CALLBACK=$(echo "$UPDATES" | grep -o '"data":"[^"]*"' | head -n1 | sed 's/.*:"//;s/"$//') + + case "$CALLBACK" in + "start_redir") + if [ "$redir_mod" = '纯净模式' ];then + do_start_fw + send_msg "已切换到$redir_mod_bf!" + else + send_msg "当前已经是$redir_mod!" + fi + send_menu + continue + ;; + "stop_redir") + if [ "$redir_mod" != '纯净模式' ];then + do_stop_fw + send_msg "已切换到纯净模式" + else + send_msg "当前已经是纯净模式!" + fi + send_menu + continue + ;; + "restart") + do_restart + send_msg "🔄 服务已重启" + sleep 10 + send_menu + continue + ;; + "refresh") + do_refresh + send_msg "🌀 刷新完成:\n$(cat "$LOGFILE")" + send_menu + continue + ;; + "set_sub") + echo "await_sub" > "$STATE_FILE" + send_msg "✏ 请输入新的订阅链接:" + continue + ;; + esac + + + ### --- 处理订阅输入 --- ### + TEXT=$(echo "$UPDATES" | grep -o '"text":"[^"]*"' | tail -n1 | sed 's/.*"text":"//;s/"$//') + + if [ "$(cat "$STATE_FILE" 2>/dev/null)" = "await_sub" ]; then + echo "" > "$STATE_FILE" + do_set_sub "$TEXT" + send_msg "订阅更新完成:\n$(cat "$LOGFILE")" + send_menu + continue + fi + + + ### 处理命令 ### + case "$TEXT" in + /crash) + send_menu + ;; + /help) + send_help + ;; + esac + + done +} + +polling + diff --git a/scripts/components/ddns_op.sh b/scripts/components/ddns_op.sh new file mode 100644 index 00000000..a51d3afb --- /dev/null +++ b/scripts/components/ddns_op.sh @@ -0,0 +1,178 @@ +#! /bin/bash +# Copyright (C) Juewuy + +ddns_dir=/etc/config/ddns +tmp_dir=/tmp/ddns_$USER + +[ ! -f $ddns_dir ] && echo -e "本脚本依赖OpenWrt内置的DDNS服务,当前设备无法运行,已退出!" && exit 1 +echo ----------------------------------------------- +echo -e "\033[30;46m欢迎使用ShellDDNS!\033[0m" +echo -e "TG群:\033[36;4mhttps://t.me/ShellCrash\033[0m" + +add_ddns() { + cat >>$ddns_dir </dev/null 2>&1 & + sleep 3 + echo 服务已经添加! +} +set_ddns() { + echo ----------------------------------------------- + read -p "请输入你的域名 > " str + [ -z "$str" ] && domain=$domain || domain=$str + echo ----------------------------------------------- + read -p "请输入用户名或邮箱 > " str + [ -z "$str" ] && username=$username || username=$str + echo ----------------------------------------------- + read -p "请输入密码或令牌秘钥 > " str + [ -z "$str" ] && password=$password || password=$str + echo ----------------------------------------------- + read -p "请输入检测更新间隔(单位:分钟;默认为10) > " check_interval + [ -z "$check_interval" ] || [ "$check_interval" -lt 1 -o "$check_interval" -gt 1440 ] && check_interval=10 + echo ----------------------------------------------- + read -p "请输入强制更新间隔(单位:小时;默认为24) > " force_interval + [ -z "$force_interval" ] || [ "$force_interval" -lt 1 -o "$force_interval" -gt 240 ] && force_interval=24 + echo ----------------------------------------------- + echo -e "请核对如下信息:" + echo -e "服务商: \033[32m$service\033[0m" + echo -e "域名: \033[32m$domain\033[0m" + echo -e "用户名: \033[32m$username\033[0m" + echo -e "检测间隔: \033[32m$check_interval\033[0m" + echo ----------------------------------------------- + read -p "确认添加?(1/0) > " res + [ "$res" = 1 ] && add_ddns || set_ddns +} + +set_service() { + services_dir=/etc/ddns/$serv + [ -s $services_dir ] || services_dir=/usr/share/ddns/list + echo ----------------------------------------------- + echo -e "\033[32m请选择服务提供商\033[0m" + cat $services_dir | grep -v '^#' | awk '{print " "NR" " $1}' + nr=$(cat $services_dir | grep -v '^#' | wc -l) + read -p "请输入对应数字 > " num + if [ -z "$num" ]; then + i= + elif [ "$num" -gt 0 -a "$num" -lt $nr ]; then + service_name=$(cat $services_dir | grep -v '^#' | awk '{print $1}' | sed -n "$num"p | sed 's/"//g') + service=$(echo $service_name | sed 's/\./_/g') + set_ddns + else + echo "输入错误,请重新输入!" + sleep 1 + set_service + fi +} + +network_type() { + echo ----------------------------------------------- + echo -e "\033[32m请选择网络模式\033[0m" + echo -e " 1 \033[36mIPV4\033[0m" + echo -e " 2 \033[36mIPV6\033[0m" + read -p "请输入对应数字 > " num + if [ -z "$num" ]; then + i= + elif [ "$num" = 1 ]; then + use_ipv6=0 + serv=services + set_service + elif [ "$num" = 2 ]; then + use_ipv6=1 + serv=services_ipv6 + set_service + else + echo "输入错误,请重新输入!" + sleep 1 + network_type + fi +} + +rev_service() { + enabled=$(uci show ddns.$service | grep 'enabled' | awk -F "=" '{print $2}' | tr -d "'\"") + [ "$enabled" = 1 ] && enabled_b="停用" || enabled_b="启用" + echo ----------------------------------------------- + echo -e " 1 \033[32m立即更新\033[0m" + echo -e " 2 编辑当前服务\033[0m" + echo -e " 3 $enabled_b当前服务" + echo -e " 4 移除当前服务" + echo -e " 5 查看运行日志" + echo -e " 0 返回上级菜单" + echo ----------------------------------------------- + read -p "请输入对应数字 > " num + if [ -z "$num" -o "$num" = 0 ]; then + i= + elif [ "$num" = 1 ]; then + /usr/lib/ddns/dynamic_dns_updater.sh -S $service start >/dev/null 2>&1 & + sleep 3 + elif [ "$num" = 2 ]; then + domain=$(uci show ddns.$service | grep 'domain' | awk -F "=" '{print $2}' | tr -d "'\"") + username=$(uci show ddns.$service | grep 'username' | awk -F "=" '{print $2}' | tr -d "'\"") + password=$(uci show ddns.$service | grep 'password' | awk -F "=" '{print $2}' | tr -d "'\"") + service_name=$(uci show ddns.$service | grep 'service_name' | awk -F "=" '{print $2}' | tr -d "'\"") + uci delete ddns.$service + set_ddns + elif [ "$num" = 3 ]; then + [ "$enabled" = 1 ] && uci set ddns.$service.enabled='0' || uci set ddns.$service.enabled='1' && sleep 3 + uci commit ddns.$service + elif [ "$num" = 4 ]; then + uci delete ddns.$service + uci commit ddns.$service + elif [ "$num" = 5 ]; then + echo ----------------------------------------------- + cat /var/log/ddns/$service.log 2>/dev/null + sleep 1 + fi +} + +load_ddns() { + nr=0 + cat $ddns_dir | grep 'config service' | awk '{print $3}' | sed "s/\'//g" | sed "s/\"//g" >$tmp_dir + echo ----------------------------------------------- + echo -e "列表 域名 启用 IP地址" + echo ----------------------------------------------- + for service in $(cat $tmp_dir); do + #echo $service >>$tmp_dir + nr=$((nr + 1)) + enabled=$(uci show ddns.$service 2>/dev/null | grep 'enabled' | awk -F "=" '{print $2}' | tr -d "'\"") + domain=$(uci show ddns.$service 2>/dev/null | grep 'domain' | awk -F "=" '{print $2}' | tr -d "'\"") + local_ip=$(sed '1!G;h;$!d' /var/log/ddns/$service.log 2>/dev/null | grep -E 'Registered IP' | tail -1 | awk -F "'" '{print $2}' | tr -d "'\"") + echo -e " $nr $domain $enabled $local_ip" + done + echo -e " $((nr + 1)) 添加DDNS服务" + echo -e " 0 退出" + echo ----------------------------------------------- + read -p "请输入对应序号 > " num + if [ -z "$num" -o "$num" = 0 ]; then + i= + elif [ "$num" -gt $nr ]; then + network_type + load_ddns + elif [ "$num" -gt 0 -a "$num" -le $nr ]; then + service=$(cat $tmp_dir | sed -n "$num"p) + rev_service + load_ddns + else + echo "请输入正确数字!" && load_ddns + fi +} + +load_ddns +rm -rf $tmp_dir diff --git a/scripts/components/gateway.sh b/scripts/components/gateway.sh index c68268b3..52143bbb 100644 --- a/scripts/components/gateway.sh +++ b/scripts/components/gateway.sh @@ -13,7 +13,7 @@ gateway(){ echo -e " 3 配置DDNS自动域名" [ "$disoverride" != "1" ] && { echo -e " 4 自定义公网入站节点" - echo -e " 5 配置\033[32m内网穿透\033[0m(WireGuard/Tailscale)" + echo -e " 5 配置\033[32m内网穿透\033[0m(Tailscale,仅限Singbox)" } echo -e " 0 返回上级菜单 \033[0m" echo ----------------------------------------------- @@ -21,73 +21,160 @@ gateway(){ case "$num" in 0) ;; 1) - setfirewall + set_pub_fw gateway ;; 2) - settgadvbot + set_bot_tg gateway ;; 3) - setddns + set_ddns gateway ;; 4) - setlisteners + set_listeners gateway ;; 5) - setendpoints + if echo "$crashcore" | grep -q 'sing';then + setendpoints + else + echo -e "\033[33m$crashcore内核暂不支持此功能,请先更换内核!\033[0m" + sleep 1 + checkupdate && setcore + fi gateway ;; *) errornum ;; esac } - +set_pub_fw() { #公网防火墙设置 + [ -z "$public_support" ] && public_support=未开启 + [ -z "$public_mixport" ] && public_mixport=未开启 + echo ----------------------------------------------- + echo -e " 1 公网访问Dashboard面板: \033[36m$public_support\033[0m" + echo -e " 2 公网访问Socks/Http代理: \033[36m$public_mixport\033[0m" + echo ----------------------------------------------- + read -p "请输入对应数字 > " num + case $num in + 1) + if [ "$public_support" = "未开启" ]; then + public_support=已开启 + else + public_support=未开启 + fi + setconfig public_support $public_support + setfirewall + ;; + 2) + if [ "$public_mixport" = "未开启" ]; then + if [ "$mix_port" = "7890" -o -z "$authentication" ]; then + echo ----------------------------------------------- + echo -e "\033[33m为了安全考虑,请先修改默认Socks/Http端口并设置代理密码\033[0m" + sleep 1 + setport + else + public_mixport=已开启 + fi + else + public_mixport=未开启 + fi + setconfig public_mixport $public_mixport + setfirewall + ;; + 3) + set_cust_host_ipv4 + setfirewall + ;; + *) + errornum + ;; + esac +} +set_bot_tg_init(){ + echo ----------------------------------------------- + echo -e "请先通过 \033[32;4mhttps://t.me/BotFather\033[0m 申请TG机器人并获取其\033[36mAPI TOKEN\033[0m" + echo ----------------------------------------------- + read -p "请输入你获取到的API TOKEN > " TOKEN + echo ----------------------------------------------- + echo -e "请向\033[32m你申请的机器人\033[31m而不是BotFather\033[0m,发送任意几条消息!" + echo ----------------------------------------------- + read -p "我已经发送完成(1/0) > " res + if [ "$res" = 1 ]; then + url_tg=https://api.telegram.org/bot${TOKEN}/getUpdates + [ -n "$authentication" ] && auth="$authentication@" + export https_proxy="http://${auth}127.0.0.1:$mix_port" + chat=$(webget $url_tg | tail -n -1) + [ -n "$chat" ] && chat_ID=$(echo $chat | grep -oE '"id":.*,"is_bot":false' | sed s'/"id"://'g | sed s'/,"is_bot":false//'g) + [ -z "$chat_ID" ] && { + echo -e "\033[31m无法获取对话ID,请确认使用的不是已经被绑定的机器人,或手动输入ChatID!\033[0m" + echo -e "通常访问 $url_tg 即可看到ChatID,也可以尝试其他方法\033[0m" + read -p "请手动输入ChatID > " chat_ID + } + if [ -n "$chat_ID" ]; then + setconfig TG_TOKEN $TOKEN "$CFG" + setconfig TG_CHATID $chat_ID "$CFG" + #设置机器人快捷命令 + curl -s -X POST "https://api.telegram.org/bot$TOKEN/setMyCommands" \ + -H "Content-Type: application/json" \ + -d '{ + "commands": [ + {"command": "crash", "description": "呼出ShellCrash菜单"}, + {"command": "help", "description": "查看帮助"} + ] + }' + echo -e "\033[32m已完成Telegram机器人设置!\033[0m" + return 0 + else + echo -e "\033[31m无法获取对话ID,请重新配置!\033[0m" + return 1 + fi + fi +} +set_bot_tg_service(){ + if [ "$bot_tg_service" = ON ];then + bot_tg_service=OFF + PID=$(pidof bot_tg.sh) && [ -n "$PID" ] && kill -9 $PID >/dev/null 2>&1 + else + bot_tg_service=ON + [ -z "$(pidof bot_tg.sh)" ] && "$CRASHDIR"/components/bot_tg.sh & + fi + setconfig bot_tg_service "$bot_tg_service" +} +set_bot_tg(){ + [ -n "$ts_auth_key" ] && ts_auth_key_info='已设置' + echo ----------------------------------------------- + echo -e "\033[31m注意:\033[0m由于网络环境原因,此机器人仅限服务启动时运行!" + echo -e "此机器人与推送机器人互不影响,请尽量不要设置成同一机器人" + echo ----------------------------------------------- + echo -e " 1 启用/关闭TG-BOT服务 \033[32m$bot_tg_service\033[0m" + echo -e " 2 TG-BOT绑定设置" + echo -e " 0 返回上级菜单 \033[0m" + echo ----------------------------------------------- + read -p "请输入对应数字 > " num + case "$num" in + 0) ;; + 1) + . "$CFG" + if [ -n "$TG_CHATID" ];then + set_bot_tg_service + else + set_bot_tg_init && set_bot_tg_service + fi + ;; + 2) + set_bot_tg_init && set_bot_tg_service + ;; + *) + errornum + ;; + esac +} +set_ddns(){ + echo +} setendpoints(){ - setwireguard(){ - echo ----------------------------------------------- - echo -e "\033[31m注意:\033[0m脚本默认内核为了节约内存没有编译WireGuard模块\n如需使用请先前往自定义内核更新完整版内核文件!" - echo ----------------------------------------------- - echo -e " 1 设置服务器地址" - echo -e " 2 设置服务器端口" - echo -e " 3 设置服务端公钥" - echo -e " 4 设置本地私钥" - echo -e " 5 设置本地IPV4地址" - echo -e " 6 设置本地IPV6地址" - echo -e " 0 返回上级菜单 \033[0m" - echo ----------------------------------------------- - read -p "请输入对应数字 > " num - read -p "请输入相应内容 > " text - case "$num" in - 0) ;; - 1) - setconfig wg_server "$text" "$CFG" - setwireguard - ;; - 2) - setconfig wg_port "$text" "$CFG" - setwireguard - ;; - 3) - setconfig wg_publickey "$text" "$CFG" - setwireguard - ;; - 4) - setconfig wg_privatekey "$text" "$CFG" - setwireguard - ;; - 5) - setconfig wg_ipv4 "$text" "$CFG" - setwireguard - ;; - 6) - setconfig wg_ipv6 "$text" "$CFG" - setwireguard - ;; - *) errornum ;; - esac - } settailscale(){ [ -n "$ts_auth_key" ] && ts_auth_key_info='已设置' echo ----------------------------------------------- @@ -129,24 +216,5 @@ setendpoints(){ *) errornum ;; esac } - echo ----------------------------------------------- - echo -e "\033[31m注意:\033[0m脚本默认内核为了节约内存没有编译WireGuard/Tailscale模块\n如需使用请先前往自定义内核更新完整版内核文件!" - echo ----------------------------------------------- - echo -e " 1 配置WireGuard客户端" - echo -e " 2 配置Tailscale(仅限Singbox内核)" - echo -e " 0 返回上级菜单" - echo ----------------------------------------------- - read -p "请输入对应数字 > " num - case "$num" in - 0) ;; - 1) - setwireguard - setendpoints - ;; - 2) - settailscale - setendpoints - ;; - *) errornum ;; - esac + settailscale } \ No newline at end of file