diff options
Diffstat (limited to 'modules/m_nicktracking.sh')
-rw-r--r-- | modules/m_nicktracking.sh | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/modules/m_nicktracking.sh b/modules/m_nicktracking.sh new file mode 100644 index 0000000..34b6873 --- /dev/null +++ b/modules/m_nicktracking.sh @@ -0,0 +1,316 @@ +#!/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 +} |