317 lines
11 KiB
Bash
317 lines
11 KiB
Bash
#!/bin/bash
|
|
# -*- coding: utf-8 -*-
|
|
###########################################################################
|
|
# #
|
|
# envbot - an IRC bot in bash #
|
|
# Copyright (C) 2007-2008 Arvid Norlander #
|
|
# #
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# This program is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
|
# #
|
|
###########################################################################
|
|
#---------------------------------------------------------------------
|
|
## Provides nick tracking API for other modules.
|
|
#---------------------------------------------------------------------
|
|
|
|
module_nicktracking_INIT() {
|
|
modinit_API='2'
|
|
modinit_HOOKS='after_load before_connect on_numeric on_NICK on_QUIT on_KICK on_PART on_JOIN'
|
|
helpentry_module_nicktracking_description="Provides nicktracking backend for other modules."
|
|
}
|
|
|
|
module_nicktracking_UNLOAD() {
|
|
unset module_nicktracking_channels
|
|
hash_reset module_nicktracking_channels_nicks
|
|
hash_reset module_nicktracking_nicks
|
|
# Private functions
|
|
unset module_nicktracking_clear_nick module_nicktracking_clear_chan
|
|
unset module_nicktracking_parse_names
|
|
unset module_nicktracking_add_channel_nick
|
|
unset module_nicktracking_remove_channel_nick
|
|
# API functions
|
|
unset module_nicktracking_get_hostmask_by_nick
|
|
unset module_nicktracking_get_channel_nicks
|
|
return 0
|
|
}
|
|
|
|
module_nicktracking_REHASH() {
|
|
return 0
|
|
}
|
|
|
|
|
|
#################
|
|
# API functions #
|
|
#################
|
|
|
|
#---------------------------------------------------------------------
|
|
## Return hostmask of a nick
|
|
## @Type API
|
|
## @param Nick to find hostmask for
|
|
## @param Variable to return hostmask in
|
|
## @Note If no nick is found (or data about the nick
|
|
## @Note is missing currently), the return variable will be empty.
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_get_hostmask_by_nick() {
|
|
hash_get 'module_nicktracking_nicks' "$(tr '[:upper:]' '[:lower:]' <<< "$1")" "$2"
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
## Return list of nicks on a channel
|
|
## @Type API
|
|
## @param Channel to check
|
|
## @param Variable to return space separated list in
|
|
## @return 0 Channel data exists.
|
|
## @return 1 We don't track this channel.
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_get_channel_nicks() {
|
|
if list_contains 'module_nicktracking_channels' "$1"; then
|
|
hash_get 'module_nicktracking_channels_nicks' "$1" "$2"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
|
|
#####################
|
|
# Private functions #
|
|
#####################
|
|
|
|
#---------------------------------------------------------------------
|
|
## Check if a nick should be removed
|
|
## @Type Private
|
|
## @param Nick to check
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_clear_nick() {
|
|
# If not on a channel any more, remove knowledge about nick.
|
|
if ! hash_search 'module_nicktracking_channels_nicks' "$1"; then
|
|
hash_unset 'module_nicktracking_nicks' "$1"
|
|
fi
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
## Clear a channel (if we part it or such)
|
|
## @Type Private
|
|
## @param Channel name
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_clear_chan() {
|
|
list_remove 'module_nicktracking_channels' "$1" 'module_nicktracking_channels'
|
|
# Get list and then unset it.
|
|
local nicks=
|
|
hash_get 'module_nicktracking_channels_nicks' "$1" 'nicks'
|
|
hash_unset 'module_nicktracking_channels_nicks' "$1"
|
|
# Sigh, this isn't fast I know...
|
|
local nick
|
|
for nick in $nicks; do
|
|
module_nicktracking_clear_nick "$nick"
|
|
done
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
## Parse RPL_NAMREPLY data.
|
|
## @Type Private
|
|
## @param NAMES data
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_parse_names() {
|
|
if [[ $1 =~ ^[=*@]?\ *(#[^ ]+)\ +:(.+) ]]; then
|
|
local channel="${BASH_REMATCH[1]}"
|
|
local nicks="${BASH_REMATCH[2]}"
|
|
local entry nick realnick
|
|
# Loop through the entries
|
|
for entry in $nicks; do
|
|
# This will work both with and without NAMESX
|
|
if [[ $entry =~ [$server_PREFIX_prefixes]*([^ ]+) ]]; then
|
|
nick="${BASH_REMATCH[1]}"
|
|
# Is UHNAMES enabled?
|
|
# If yes lets take care of hostmask.
|
|
if [[ $server_UHNAMES -eq 1 ]]; then
|
|
parse_hostmask_nick "$nick" 'realnick'
|
|
realnick="$(tr '[:upper:]' '[:lower:]' <<< "$realnick")"
|
|
hash_set 'module_nicktracking_nicks' "$realnick" "$nick"
|
|
# Add to nick list of channel if not in list
|
|
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$realnick" || \
|
|
hash_append 'module_nicktracking_channels_nicks' "$channel" "$realnick"
|
|
else
|
|
realnick="$(tr '[:upper:]' '[:lower:]' <<< "$nick")"
|
|
# Add to nick list of channel if not in list
|
|
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$realnick" || \
|
|
hash_append 'module_nicktracking_channels_nicks' "$channel" "$realnick"
|
|
fi
|
|
else
|
|
log_error_file unknown_data.log "module_nicktracking_parse_names: Uh uh, regex for inner loop is bad, couldn't parse: $nick"
|
|
log_error_file unknown_data.log "module_nicktracking_parse_names: Please report a bug with the above message"
|
|
fi
|
|
done
|
|
else
|
|
log_error_file unknown_data.log "module_nicktracking_parse_names: Uh uh, outer regex is bad, couldn't parse: $1"
|
|
log_error_file unknown_data.log "module_nicktracking_parse_names: Please report a bug with the above message"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
## Parse RPL_WHOREPLY data.
|
|
## @Type Private
|
|
## @param WHO data
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_parse_who() {
|
|
# Read the who data into an array then extract the data from the array.
|
|
local whodata
|
|
read -ra whodata <<< "$1"
|
|
local channel="${whodata[0]}"
|
|
local ident="${whodata[1]}"
|
|
local host="${whodata[2]}"
|
|
local nick="${whodata[4]}"
|
|
local lowernick="$(tr '[:upper:]' '[:lower:]' <<< "$nick")"
|
|
# Set the hash tables
|
|
hash_set 'module_nicktracking_nicks' "$lowernick" "${nick}!${ident}@${host}"
|
|
# We don't want to add twice
|
|
hash_contains 'module_nicktracking_channels_nicks' "$channel" "$lowernick" || \
|
|
hash_append 'module_nicktracking_channels_nicks' "$channel" "$lowernick"
|
|
}
|
|
|
|
|
|
#---------------------------------------------------------------------
|
|
## Add a nick to a channel
|
|
## @Type Private
|
|
## @param Channel
|
|
## @param Hostmask
|
|
## @param Nick
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_add_channel_nick() {
|
|
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$3")"
|
|
hash_append 'module_nicktracking_channels_nicks' "$1" "$nick"
|
|
hash_set 'module_nicktracking_nicks' "$nick" "$2"
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
## Remove a nick from a channel
|
|
## @Type Private
|
|
## @param Channel
|
|
## @param Nick
|
|
#---------------------------------------------------------------------
|
|
module_nicktracking_remove_channel_nick() {
|
|
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$2")"
|
|
hash_substract 'module_nicktracking_channels_nicks' "$1" "$nick"
|
|
module_nicktracking_clear_nick "$nick"
|
|
}
|
|
|
|
|
|
#########
|
|
# Hooks #
|
|
#########
|
|
|
|
module_nicktracking_after_load() {
|
|
# Handle case of loading while bot is running
|
|
if [[ $server_connected -eq 1 ]]; then
|
|
module_nicktracking_channels="$channels_current"
|
|
local channel
|
|
for channel in $module_nicktracking_channels; do
|
|
send_raw "NAMES $channel"
|
|
# We have to send a WHO #channel if servers doesn't support UHNAMES.
|
|
if [[ $server_UHNAMES -eq 0 ]]; then
|
|
send_raw "WHO $channel"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
module_nicktracking_before_connect() {
|
|
# Reset state.
|
|
unset module_nicktracking_channels
|
|
hash_reset module_nicktracking_channels_nicks
|
|
hash_reset module_nicktracking_nicks
|
|
return 0
|
|
}
|
|
|
|
|
|
##########################
|
|
# Message handling hooks #
|
|
##########################
|
|
|
|
module_nicktracking_on_numeric() {
|
|
case $1 in
|
|
"$numeric_RPL_NAMREPLY")
|
|
# TODO: Parse NAMES
|
|
module_nicktracking_parse_names "$2"
|
|
;;
|
|
"$numeric_RPL_WHOREPLY")
|
|
module_nicktracking_parse_who "$2"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
module_nicktracking_on_NICK() {
|
|
local oldnick oldident oldhost oldentry
|
|
parse_hostmask "$1" 'oldnick' 'oldident' 'oldhost'
|
|
local oldlowercase="$(tr '[:upper:]' '[:lower:]' <<< "$oldnick")"
|
|
local newlowercase="$(tr '[:upper:]' '[:lower:]' <<< "$2")"
|
|
# Remove old and add new.
|
|
hash_get 'module_nicktracking_nicks' "$oldlowercase" 'oldentry'
|
|
hash_unset 'module_nicktracking_nicks' "$oldlowercase"
|
|
hash_set 'module_nicktracking_nicks' "$newlowercase" "${2}!${oldident}@${oldhost}"
|
|
local channel
|
|
# Loop through the channels
|
|
for channel in $module_nicktracking_channels; do
|
|
hash_replace 'module_nicktracking_channels_nicks' "$channel" "$oldnick" "$newlowercase"
|
|
done
|
|
return 0
|
|
}
|
|
|
|
module_nicktracking_on_QUIT() {
|
|
local whoquit=
|
|
parse_hostmask_nick "$1" 'whoquit'
|
|
local nick="$(tr '[:upper:]' '[:lower:]' <<< "$whoquit")"
|
|
hash_unset 'module_nicktracking_nicks' "$nick"
|
|
local channel
|
|
# Remove from channel
|
|
for channel in $module_nicktracking_channels; do
|
|
hash_substract 'module_nicktracking_channels_nicks' "$channel" "$nick"
|
|
done
|
|
}
|
|
|
|
module_nicktracking_on_KICK() {
|
|
local whogotkicked="$3"
|
|
if [[ $whogotkicked == $server_nick_current ]]; then
|
|
module_nicktracking_clear_chan "$2"
|
|
else
|
|
module_nicktracking_remove_channel_nick "$2" "$whogotkicked"
|
|
fi
|
|
}
|
|
|
|
module_nicktracking_on_PART() {
|
|
# Check if it was us
|
|
local whoparted=
|
|
parse_hostmask_nick "$1" 'whoparted'
|
|
if [[ $whoparted == $server_nick_current ]]; then
|
|
module_nicktracking_clear_chan "$2"
|
|
else
|
|
module_nicktracking_remove_channel_nick "$2" "$whoparted"
|
|
fi
|
|
}
|
|
|
|
module_nicktracking_on_JOIN() {
|
|
local whojoined=
|
|
parse_hostmask_nick "$1" 'whojoined'
|
|
if [[ $whojoined == $server_nick_current ]]; then
|
|
module_nicktracking_channels+=" $2"
|
|
hash_set 'module_nicktracking_channels_nicks' "$2" "$server_nick_current"
|
|
# We have to send a WHO #channel if servers doesn't support UHNAMES.
|
|
if [[ $server_UHNAMES -eq 0 ]]; then
|
|
send_raw "WHO $2"
|
|
fi
|
|
else
|
|
module_nicktracking_add_channel_nick "$2" "$1" "$whojoined"
|
|
fi
|
|
}
|