#!/bin/bash # Hard requirement for lighttpd printf "Content-Type: text/plain\n\n" # Initialize basic variables . /etc/konata.conf # Parse incoming messages input=$(cat /dev/stdin) msg=$(jq -r '.message.text' <<< $input | sed "s/_/\ /g") cmd=$(cut -d" " -f1 <<< $msg) args=($(cut -sd" " -f2- <<< $msg)) chat=$(jq -r '.message.chat.id' <<< $input) user=$(jq -r '.message.from.username' <<< $input) # Append bot's tag to any command without one if ! grep -q "/.*@" <<< $cmd then cmd=${cmd}@$bot fi # Convert k.command to /command if grep -q "k\." <<< $cmd then cmd=$(sed "s/k\./\//g" <<< $cmd) fi # Functions for outgoing messages sendmsg(){ # Escape any special characters first, see https://0x0.st/NO7J. fmt=$(sed 's/[>#+-=|{}.!]/\\&/g' <<< $1 | sed 's/\t//g') sendraw "$fmt" } escape(){ sed "s/[$1]/\\\&/g" <<< $2 } sendraw(){ curl -sX POST "https://api.telegram.org/bot$token/sendMessage" \ -d "chat_id=$chat" -d "parse_mode=markdownv2" \ -d "disable_web_page_preview=true" \ --data-urlencode "text=$1" } sendlog(){ chat=$logchat sendmsg "$1" } sendfile(){ curl -sF document=@"$1" "https://api.telegram.org/bot$token/sendDocument?chat_id=$chat" } sendpic(){ curl -sX POST "https://api.telegram.org/bot$token/sendPhoto" \ -d "chat_id=$chat" -d "parse_mode=markdownv2" \ -d "photo=$1" -d "caption=$2" } # Internal checks args(){ if [ -z ${args[*]} ] then sendmsg "Don't just click me like that. See /help@$bot for more info on how to use this bot." exit 1 fi } admin(){ case $user in ghnou) true ;; *) fail ;; esac debug "Admin @$user tried to execute $cmd and was approved." } fail(){ debug "User @$user tried to execute $cmd and was rejected." sendmsg "Sorry, you are not allowed to use this command!" exit 1 } # Debugging commands debug(){ [ ! -z $debug ] && echo "[DEBUG] $1" >&2 } # Public commands help(){ sendmsg "Hiya! I'm [ghnou](https://t.me/ghnou)'s personal bot, Konata. Currently I have the following features: - /help - Show this help message. - /alive - Check whether I'm running. - /cv \[country\] - Check COVID-19 stats. - /id - Get the current chat's ID. - /ud \[term\] - Get a definition from Urban Dictionary. - /konata - Get one of my selfies :3 - /konachan \[query\] - Get a picture from Konachan. - /4c \[board\] - Get a random image from 4chan. - /lfy \[query\] - Let me look that up for you... - /ip \[address\] - Get information for an IP address. - /repo - Get my source code. Admin only commands: - /mp3 \[link\] - Download an mp3 file from YouTube. - /stat - Uptime, memory, storage stats. - /term - Execute a command on the system. And a lot more to come!" } alive(){ sendmsg "Alive and well!" } cv(){ args stats=$(curl -s "https://corona.lmao.ninja/v2/countries/${args[*]}") mapfile -t cv <<< $(jq -cr '.[]' <<< $stats) if [ "${cv[4]}" == "0" ] then updated="Perhaps the stats are not updated yet?" fi if [ ! -z ${cv[1]} ] then pct(){ bc <<< "scale = 2; $1 / 10000"; } sendmsg "*Today's COVID-19 stats for ${cv[1]}:* Cases: ${cv[4]} Active: ${cv[9]} Total: ${cv[3]} \($(pct ${cv[11]})%\) Tests: ${cv[13]} \($(pct ${cv[14]})%\) Queried at $(date +'%Y-%m-%d %H:%M %Z'). Stay safe and get yourself vaccinated! $updated" else sendmsg "This country doesn't have any stats!" fi } id(){ sendmsg "Chat ID: $chat" } ud(){ args enc=$(echo "${args[*]}" | sed "s/\ /%20/g") res=$(curl -s "https://api.urbandictionary.com/v0/define?term=$enc") if jq -re '.list[0].definition' <<< $res then def=$(jq -r '.list[0].definition' <<< $res | sed "s/[][]//g") sam=$(jq -r '.list[0].example' <<< $res | sed "s/[][]//g") sendmsg "*Definition for __${args[*]}__:* $(escape "()" "$def") *Example:* $(escape "()" "$sam")" else sendmsg "No definition found for ${args[*]}." fi } konata(){ args="izumi_konata" konachan } konachan(){ args query=$(sed "s/\ /_/g" <<< ${args[*]}) data=$(curl -s "https://konachan.net/post.json?limit=1&page=1&tags=order:random%20$query") jpeg=$(jq -r '.[0].jpeg_url' <<< $data) file=$(jq -r '.[0].file_url' <<< $data) sfw=$(jq -r '.[0].rating' <<< $data) if [ $sfw == "s" ] then sendpic "$jpeg" "[sauce]($file)" elif [ $sfw == "q" ] || [ $sfw == "x" ] then sendmsg "This picture appears to be NSFW! Here's the [sauce]($file)." else sendmsg "No data!" fi } 4c(){ args tmp="/tmp/4chan" json="$tmp/${args[0]}.json" [ ! -d $tmp ] && mkdir $tmp [ $(find $json -mmin +60) ] && rm $json [ ! -f $json ] && wget -O $json https://a.4cdn.org/${args[0]}/threads.json thread=$(jq -r '.[].threads[].no' < $json | shuf | head -n1) img=$(curl -s https://a.4cdn.org/${args[0]}/thread/$thread.json | jq -r '.posts[].tim' | shuf | head -n1) url="https://i.4cdn.org/${args[0]}/$img" # TODO: Try to determine from JSON output whether image is PNG or JPG. sendpic "$url.jpg" sendpic "$url.png" } lfy(){ args query=$(sed "s/\ /+/g" <<< ${args[*]}) sendmsg "[Let me look that up for you](https://lmgtfy.app/?s=d&iee=1&q=$query)" } ip(){ args ip=${args[0]} res=$(curl -s http://ip-api.com/json/$ip) # See https://0x0.st/Nlc0 for reference. mapfile -t data <<< $(jq -cr '.[]' <<< $res) sendmsg "*IP information for $ip:* *Country:* ${data[1]} *Region:* ${data[4]} *City:* ${data[6]} ${data[5]} *ISP:* ${data[10]} *ASN:* ${data[12]} *Time:* $(TZ=${data[9]} date +'%H:%M %Z')" } repo(){ sendmsg "You can find my source code [here](https://git.ghnou.su/ghnou/konata)." } # Administrative mp3(){ admin args tmp="/tmp/mp3" [ ! -d $tmp ] && mkdir $tmp sendmsg "Downloading, this might take a while..." youtube-dl -f 140 --max-filesize 50M -o "$tmp/%(title)s.%(ext)s" "${args[*]}" rm $tmp/*.part if [ -f $tmp/* ] then sendfile "$tmp/$(ls $tmp)" rm $tmp/* else sendmsg "I couldn't download this file. Perhaps it's too large?" fi } stat(){ admin total=$(grep MemTotal /proc/meminfo | awk '{print $2}') avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}') used=$(bc <<< "scale=1; ($total-$avail) / 1024") sendmsg "$(uptime | cut -c2-) I am using ${used}M of memory and \ $(df -h / | tail -n1 | awk '{print $3}') of storage." } term(){ admin sendmsg "\`$(whoami)@${HOSTNAME}:${PWD}$\` \`${args[*]}\` \`$(echo ${args[*]} | bash - 2>&1)\`" } # Notes and such anyone(){ sendmsg "Quite possibly. [Why do you ask?](https://dontasktoask.com)" } # Miscellaneous tag(){ sendmsg "Please stand by, he'll get to your message soon™️..." sendlog "You've been tagged: $msg" } # Match incoming messages case "$cmd" in # Public commands /help@$bot) help ;; /start@$bot) help ;; /alive@$bot) alive ;; /cv@$bot*) cv ;; /id@$bot) id ;; /ud@$bot*) ud ;; /konata@$bot) konata ;; /konachan@$bot*) konachan ;; /4c@$bot*) 4c ;; /lfy@$bot*) lfy ;; /ip@$bot*) ip ;; /repo@$bot) repo ;; # Administrative /mp3@$bot*) mp3 ;; /stat@$bot) stat ;; /term@$bot*) term ;; # Notes and such !anyone*) anyone ;; esac case "$msg" in # Miscellaneous *@ghnou*) tag ;; esac