Update lib/main.sh and process_event from pbot-ng, remove issue_tracker_change_detector, to fix hyperbot vunerability
This commit is contained in:
449
process_event
Normal file
449
process_event
Normal file
@@ -0,0 +1,449 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This function reads tags of xml in the same way read normally reads lines.
|
||||
function rdom
|
||||
{
|
||||
local IFS=\>
|
||||
read -d \< element content
|
||||
}
|
||||
|
||||
function tell_fact # thing channel
|
||||
{
|
||||
thing="${1}"
|
||||
declare -l lower_case_thing="${thing}"
|
||||
channel="${2}"
|
||||
|
||||
if [[ -s "info/${lower_case_thing}" ]]
|
||||
then
|
||||
# For the first entry we will say like: `thing is: '
|
||||
first="${thing} is: "
|
||||
|
||||
uniq "info/${lower_case_thing}" |
|
||||
while read line
|
||||
do
|
||||
send_msg "${channel}" "${first}${line}"
|
||||
first=''
|
||||
done
|
||||
|
||||
return
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
source common_codez
|
||||
|
||||
function remember_fact
|
||||
{
|
||||
if grep "^${is}$" "info/${thing}" &>/dev/null
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: I know."
|
||||
else
|
||||
echo "${is}" >> "info/${thing}"
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: Remembered."
|
||||
fi
|
||||
}
|
||||
|
||||
function forget_fact
|
||||
{
|
||||
number_of_matching_lines=$(grep -c "^${isnt}" "info/${thing}")
|
||||
|
||||
case "${number_of_matching_lines}" in
|
||||
0 )
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: I know."
|
||||
;;
|
||||
1 )
|
||||
grep -v "^${isnt}" "info/${thing}" | sponge "info/${thing}"
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: OK, entry removed."
|
||||
;;
|
||||
* )
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: Ambiguos."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function process_event
|
||||
{
|
||||
my_own_name='hyperbot'
|
||||
|
||||
person="${sender%%!*}"
|
||||
|
||||
# Remove any forward slashes.
|
||||
personoslash="${person//\/}"
|
||||
declare -l personoslashlower="${personoslash}"
|
||||
|
||||
channel_it_came_from="$( echo ${line} | cut -d ' ' -f 3 )"
|
||||
|
||||
# If it's a private message
|
||||
[[ "${channel_it_came_from}" == "${my_own_name}" ]] && channel_it_came_from="${personoslash}"
|
||||
|
||||
######################
|
||||
# Echo injected data #
|
||||
######################
|
||||
|
||||
# Should send a message like: echo 'This is the message' > /tmp/un-provoked-message-store
|
||||
|
||||
injected_data=0
|
||||
|
||||
line_filtered=${line##*PRIVMSG +([![:space:]]) :}
|
||||
|
||||
if [[ ${personoslash} == tlCJ99mfZl ]]
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${line_filtered}"
|
||||
injected_data=1
|
||||
else
|
||||
###############################################################
|
||||
# This is a message from a user. Make preperations to process #
|
||||
###############################################################
|
||||
|
||||
the_time_now=$(date +%s)
|
||||
|
||||
# Make this person a folder if they don't already have one.
|
||||
if ! [[ -d "announcements/people/${personoslashlower}" ]]
|
||||
then
|
||||
mkdir -p "announcements/people/${personoslashlower}"
|
||||
fi
|
||||
|
||||
# Record that the person has been seen, and when.
|
||||
touch "announcements/people/${personoslashlower}/seen"
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# We want to get only the message part of the line
|
||||
sentence="${line#* }"
|
||||
sentence="${sentence#* }"
|
||||
sentence="${sentence#* :}"
|
||||
|
||||
##########################
|
||||
# Shared libraries error #
|
||||
##########################
|
||||
|
||||
the_time_now=$(date +%s)
|
||||
|
||||
# If someone complains about error while loading shared libraries error
|
||||
# then recomend them to the issue tracker.
|
||||
if [[ ${sentence} == *"error while loading shared libraries"* ]]
|
||||
then
|
||||
# Make sure they have not already been recommended to the bug
|
||||
# tracker less than one day ago.
|
||||
sharlibsrecfile="announcements/people/${personoslashlower}/shared_libs"
|
||||
|
||||
# Have we recommended them to the bug tracker before?
|
||||
if [[ -f ${sharlibsrecfile} ]]
|
||||
then
|
||||
# Was it less than a day ago?
|
||||
(( ( $( stat -c %Y ${sharlibsrecfile} ) + 86400 ) > the_time_now )) && rec_recent=1 || rec_recent=0
|
||||
else
|
||||
rec_recent=0
|
||||
fi
|
||||
|
||||
if ! (( rec_recent ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${person}: please report a bug, specifying the exact error message, package of the failing command and architecture: https://issues.hyperbola.info"
|
||||
touch "${sharlibsrecfile}"
|
||||
fi
|
||||
fi
|
||||
|
||||
##########
|
||||
# Repeat #
|
||||
##########
|
||||
|
||||
[[ ${sentence} != ${i_repeated} ]] && say_again=yesyes
|
||||
|
||||
# If two different people say the same thing in a row then say it again
|
||||
# for fun.
|
||||
if [[ ${sentence} == ${lastline} ]] && [[ ${person} != ${lastsender} ]] && [[ ${say_again} != nono ]] && [[ ${sentence} != "${my_own_name}: "* ]] # If two different people say the same thing to me in quick sucession I shouldn't repeat them.
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${sentence}"
|
||||
i_repeated="${sentence}"
|
||||
say_again=nono
|
||||
fi
|
||||
|
||||
lastline="${sentence}"
|
||||
lastsender="${person}"
|
||||
|
||||
#################
|
||||
# Announcements #
|
||||
#################
|
||||
|
||||
# If someone has sent this person a message then echo it to
|
||||
# them.
|
||||
if [[ -f "announcements/people/${personoslashlower}/messages" ]]
|
||||
then
|
||||
uniq "announcements/people/${personoslashlower}/messages" |
|
||||
while read line
|
||||
do
|
||||
# The first field is the time, in *nix seconds, that
|
||||
# the message was sent. The second is the name of the
|
||||
# sender. And the rest is the message.
|
||||
intermediate="${line#* }"
|
||||
sender_u="${intermediate%% *}"
|
||||
message_u="${intermediate#* }"
|
||||
time_sent="${line%% *}"
|
||||
|
||||
seconds_ago_seen="$(( the_time_now - time_sent ))"
|
||||
minutes_ago_seen="$(( ( the_time_now - time_sent ) / 60 ))"
|
||||
hours_ago_seen="$(( ( the_time_now - time_sent ) / 3600 ))"
|
||||
days_ago_seen="$(( ( the_time_now - time_sent ) / 86400 ))"
|
||||
months_ago_seen="$(( ( the_time_now - time_sent ) / 2592000 ))"
|
||||
years_ago_seen="$(( ( the_time_now - time_sent ) / 31104000 ))"
|
||||
if (( seconds_ago_seen < 120 ))
|
||||
then
|
||||
units="${seconds_ago_seen} seconds"
|
||||
elif (( minutes_ago_seen < 120 ))
|
||||
then
|
||||
units="${minutes_ago_seen} minutes"
|
||||
elif (( hours_ago_seen < 48 ))
|
||||
then
|
||||
units="${hours_ago_seen} hours"
|
||||
elif (( days_ago_seen < 60 ))
|
||||
then
|
||||
units="${days_ago_seen} days"
|
||||
elif (( months_ago_seen < 24 ))
|
||||
then
|
||||
units="${months_ago_seen} months"
|
||||
else
|
||||
units="${years_ago_seen} years"
|
||||
fi
|
||||
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: ${sender_u} told me to tell you, (${units} ago): ${message_u}"
|
||||
done
|
||||
rm "announcements/people/${personoslashlower}/messages"
|
||||
fi
|
||||
|
||||
#####################
|
||||
# Page title getter #
|
||||
#####################
|
||||
|
||||
# We don't want to get the page title if it's injected data.
|
||||
if [[ ${line} =~ http://[^\ ]+ ]] || [[ ${line} =~ https://[^\ ]+ ]] &&
|
||||
(( ! injected_data ))
|
||||
then
|
||||
url_to_get="${BASH_REMATCH}"
|
||||
|
||||
the_title=$(
|
||||
curl -L --compressed "${url_to_get}" 2> /dev/null |
|
||||
while rdom
|
||||
do
|
||||
if [[ ${element} = title ]] || [[ ${element} = TITLE ]]
|
||||
then
|
||||
sed 's/ / /g' <<< "${content}" | replace_wierd_html_chars
|
||||
fi
|
||||
done
|
||||
)
|
||||
|
||||
if ! [[ -z ${the_title} ]]
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "Page title: \`${the_title}'"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "${sentence}" in
|
||||
########
|
||||
# Seen #
|
||||
########
|
||||
|
||||
"${my_own_name}: when did you last see"* )
|
||||
subject="${sentence##${my_own_name}: when did you last see }"
|
||||
subject="${subject##${my_own_name}: when did you last see: }" # If there's an `:', we can still handle it.
|
||||
subject="${subject%\?}"
|
||||
subject="${subject%% *}"
|
||||
declare -l subjectlower="${subject}"
|
||||
|
||||
if [[ "${subject}" == ${my_own_name} ]]
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak 0 seconds ago."
|
||||
elif [[ -f "announcements/people/${subjectlower}/seen" ]]
|
||||
then
|
||||
seconds_ago_seen="$(( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ))"
|
||||
minutes_ago_seen="$(( ( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ) / 60 ))"
|
||||
hours_ago_seen="$(( ( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ) / 3600 ))"
|
||||
days_ago_seen="$(( ( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ) / 86400 ))"
|
||||
months_ago_seen="$(( ( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ) / 2592000 ))"
|
||||
years_ago_seen="$(( ( the_time_now - $( stat -c %Y announcements/people/${subjectlower}/seen ) ) / 31104000 ))"
|
||||
if (( seconds_ago_seen < 120 ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${seconds_ago_seen} seconds ago."
|
||||
elif (( minutes_ago_seen < 120 ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${minutes_ago_seen} minutes ago."
|
||||
elif (( hours_ago_seen < 48 ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${hours_ago_seen} hours ago."
|
||||
elif (( days_ago_seen < 60 ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${days_ago_seen} days ago."
|
||||
elif (( months_ago_seen < 24 ))
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${months_ago_seen} months ago."
|
||||
else
|
||||
send_msg "${channel_it_came_from}" "I last saw ${subject} speak ${years_ago_seen} years ago."
|
||||
fi
|
||||
else
|
||||
send_msg "${channel_it_came_from}" "I never saw ${subject} speak."
|
||||
fi
|
||||
;;
|
||||
########
|
||||
# tell #
|
||||
########
|
||||
|
||||
"${my_own_name}: tell "+([![:space:]])":"+([[:space:]])+([![:space:]])* )
|
||||
# The line will be something such as:
|
||||
# hyperbot: tell user: hi
|
||||
process="${sentence##${my_own_name}: tell }"
|
||||
subject="${process%%:*}"
|
||||
message="${process#*:}"
|
||||
message="${message# }"
|
||||
|
||||
if [[ "${subject}" == "${my_own_name}" ]]
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${my_own_name}: ${personoslash} told me to tell you, (0 seconds ago): ${message}"
|
||||
else
|
||||
declare -l subjectlower="${subject}"
|
||||
|
||||
[[ -d "announcements/people/${subjectlower}" ]] || mkdir -p "announcements/people/${subjectlower}"
|
||||
# The time in *nix seconds is saved there so that
|
||||
# hyperbot can say how long ago the massage was sent
|
||||
# when he gives it to it's recipient.
|
||||
echo "$(date +%s) ${personoslash} ${message}" >> "announcements/people/${subjectlower}/messages"
|
||||
|
||||
response='certainly'
|
||||
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: ${response}"
|
||||
|
||||
if ! [[ -f "announcements/people/${subjectlower}/seen" ]]
|
||||
then
|
||||
send_msg "${channel_it_came_from}" "${personoslash}: WARNING: I HAVE NEVER SEEN \"${subject}\" HERE BEFORE. CHECK YOUR SPELLING."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
############
|
||||
# factoids #
|
||||
############
|
||||
|
||||
"${my_own_name}: "+([!/])" is "+([![:space:]])* )
|
||||
declare -l thing="${sentence#${my_own_name}: }"
|
||||
thing="${thing%% is *}"
|
||||
is="${sentence#* is }"
|
||||
|
||||
remember_fact
|
||||
;;
|
||||
"${my_own_name}: "+([!/])" is: "+([![:space:]])* )
|
||||
declare -l thing="${sentence#${my_own_name}: }"
|
||||
thing="${thing%% is: *}"
|
||||
is="${sentence#* is: }"
|
||||
|
||||
remember_fact
|
||||
;;
|
||||
"${my_own_name}: "+([![:space:]])" isn't "+([![:space:]])* )
|
||||
declare -l thing="${sentence#${my_own_name}: }"
|
||||
thing="${thing%% isn\'t *}"
|
||||
isnt="${sentence#* isn\'t }"
|
||||
|
||||
forget_fact
|
||||
;;
|
||||
"${my_own_name}: "+([![:space:]])" isn't: "+([![:space:]])* )
|
||||
declare -l thing="${sentence#${my_own_name}: }"
|
||||
thing="${thing%% isn\'t: *}"
|
||||
isnt="${sentence#* isn\'t: }"
|
||||
|
||||
forget_fact
|
||||
;;
|
||||
','+([!/]) )
|
||||
thing="${sentence#,}"
|
||||
|
||||
tell_fact "${thing}" "${channel_it_came_from}"
|
||||
;;
|
||||
#############
|
||||
# Footnotes #
|
||||
#############
|
||||
|
||||
*\[[[:digit:]]\]* )
|
||||
declare -a fn
|
||||
|
||||
while read -d $'\0' file
|
||||
do
|
||||
#if match = grep "${file##*/}[ ]\?\[[[:digit:]]\]" <<< "${sentence}"
|
||||
filename="${file##*/}"
|
||||
|
||||
declare -l lowersentence="${sentence}"
|
||||
|
||||
if [[ " ${lowersentence}" =~ [^[:alnum:]]${filename}[\ ]?\[[[:digit:]]\] ]]
|
||||
then
|
||||
index="${BASH_REMATCH: -2:1}"
|
||||
|
||||
fn[${index}]=$(head -1 "${file}")
|
||||
fi
|
||||
done < <(find info -print0)
|
||||
|
||||
for (( n=0 ; n<50 ; n++ ))
|
||||
do
|
||||
str="${fn[${n}]}"
|
||||
|
||||
[[ -z "${str}" ]] && continue
|
||||
|
||||
send_msg "${channel_it_came_from}" "[${n}] ${str}"
|
||||
done
|
||||
;;
|
||||
########################
|
||||
# unrecognised command #
|
||||
########################
|
||||
|
||||
${my_own_name}:* | ','* )
|
||||
while read line
|
||||
do
|
||||
send_msg "${personoslash}" "${line}"
|
||||
done <<< cat << EOF
|
||||
Command not recognised. Example commands:
|
||||
${my_own_name}: tell Jack: hi Jack
|
||||
${my_own_name}: when did you last see Jill?
|
||||
${my_own_name}: lemon is yummy
|
||||
${my_own_name}: lemon isn't yummy
|
||||
,lemon
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
# ' this comment fixes a bug in emacs shell-script-mode that messes up the syntax highlighting
|
||||
|
||||
# I'm dissabling this feature for now as it was being abused
|
||||
# and would need an overhaul to be abuse-proof + nobody uses it afaik
|
||||
# ##########################
|
||||
# # tell someone something #
|
||||
# ##########################
|
||||
|
||||
# # TODO: this should be in the case statement
|
||||
|
||||
# if [[ "${sentence}" =~ ${my_own_name}: tell\ [^\ ]+\ about\ [^\ ]+ ]]
|
||||
# then
|
||||
# # TODO: There should be the following three constraints to
|
||||
# # prevent abuse.
|
||||
# # 1. People may only ask the bot to tell someone about
|
||||
# # something in the #hyperbola channel, not by query.
|
||||
# # 2. hyperbot will only tell someone something if they're a user
|
||||
# # he has seen in the past week
|
||||
# # 3. each person may use tell no more than 10 times in
|
||||
# # three hours.
|
||||
|
||||
# gotit="${BASH_REMATCH}" # will be like: `,tell jack about blah'
|
||||
|
||||
# dudep1="${gotit#,tell }"
|
||||
# dude="${dudep1%% *}"
|
||||
# thing="${gotit##* }"
|
||||
|
||||
# if [[ -n "${dude}" ]] && [[ -n "${thing}" ]]
|
||||
# then
|
||||
# tell_fact "${thing}" "${dude}" || send_msg "${channel_it_came_from}" "${personoslash}: Error, failed to tell ${dude} about ${thing}"
|
||||
# fi
|
||||
# fi
|
||||
|
||||
# TODO: add a birthday announcement feature, cointoss feature, timer
|
||||
# feature.
|
||||
|
||||
#########
|
||||
# Tests #
|
||||
#########
|
||||
|
||||
#echo "${line}"
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user