#!/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. 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 * $2 / $3"; } mil(){ bc <<< "scale = 3; $1 / 1000000"; } kil(){ bc <<< "scale = 2; $1 / 1000"; } sendmsg "*Today's COVID-19 stats for ${cv[1]}:* *Cases:* ${cv[4]} *Active:* $(kil ${cv[9]})k *Deaths:* ${cv[6]} \($(kil ${cv[5]})k t, $(pct 100 ${cv[5]} ${cv[3]})% c, $(pct 100 ${cv[5]} ${cv[15]})% p\) *Total:* $(kil ${cv[3]})k \($(pct 1 ${cv[11]} 10000)%\) *Tests:* $(mil ${cv[13]})M \($(pct 1 ${cv[14]} 10000)%\) *Population:* $(mil ${cv[15]})M 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 } sys(){ admin mtot=$(grep MemTotal /proc/meminfo | awk '{print $2}') mavl=$(grep MemAvailable /proc/meminfo | awk '{print $2}') mem=$(bc <<< "scale=1; ($mtot-$mavl) / 1024") ups=$(cut -d. -f1 < /proc/uptime) upd=$(bc <<< "$ups / 60 / 60 / 24") disk=$(df -h / | tail -n1 | awk '{print $3}') kernel=$(uname -r) load=$(cut -d' ' -f1,2,3 < /proc/loadavg) sendmsg "*System usage stats:* *Memory:* ${mem}M *Disk:* ${disk} *Kernel:* ${kernel} *Uptime:* ${upd}d *Load:* ${load}" } neo(){ admin sendmsg "\`$(neofetch --stdout)\`" } sh(){ 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™️..." chid=$(jq -r '.message.chat.id' <<< $input | sed 's/-100//') msgid=$(jq -r '.message.message_id' <<< $input) uname=$(jq -r '.message.from.username' <<< $input) uid=$(jq -r '.message.from.id' <<< $input) text=$(jq -r '.message.text' <<< $input) sendlog "*You've been tagged.* *User:* [$uname](tg://user?id=$uid) *Link:* [here](https://t.me/c/$chid/$msgid) *Message contents:* $(escape "()" "$text")" } hiya(){ sendmsg "Hiya! :3" } # 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 ;; /sys@$bot) sys ;; /neo@$bot) neo ;; /sh@$bot*) sh ;; # Notes and such !anyone*) anyone ;; esac case "$msg" in # Miscellaneous *@ghnou*) tag ;; *Konata*) hiya ;; esac