From c1ea3a8644d445375f955464db26767b55424785 Mon Sep 17 00:00:00 2001 From: clinton Date: Tue, 24 Feb 2009 08:02:04 +0000 Subject: [PATCH] Implement `bot:channel-users' Scheme function Returns a list of users in a channel. The user objects are opaque and should only be accessed via the accessors: * `bot:channel-user-nick' user => nickname * `bot:channel-user-user/host' user => user@host string * `bot:channel-user-mode' user => channel mode bitvector The channel mode bitvector may further inspected using: * `bot:channel-user-has-modes?' user . modes => boolean Where MODES is a list of mode identifiers. Valid values are: * `bot:mode/op' * `bot:mode/voice' * `bot:mode/away' * `bot:mode/ircop' Convenience functions for checking individual mode flags are available: * `bot:channel-user-op?' user => boolean * `bot:channel-user-voice?' user => boolean * `bot:channel-user-away?' user => boolean * `bot:channel-user-ircop' user => boolean Additionally some futzing with other bits are included because C++ is an evil language and I had to beat it gently with a hammer until it did what I wanted. --- scripts/bobot-utils.scm | 29 +++++++++++++++++++++++++++-- source/ChannelUserList.H | 2 +- source/Interp.C | 8 ++++++++ source/ScriptCommands.C | 36 +++++++++++++++++++++++++++++++++++- source/ScriptCommands.H | 10 ++++++++++ source/User.H | 5 +++++ 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/scripts/bobot-utils.scm b/scripts/bobot-utils.scm index baa69bf..e9f8bbc 100644 --- a/scripts/bobot-utils.scm +++ b/scripts/bobot-utils.scm @@ -9,7 +9,8 @@ (module-use! (resolve-module '(guile-user) #f) the-bot-module) -(use-modules (srfi srfi-13)) +(use-modules (srfi srfi-1) + (srfi srfi-13)) (define-public %bot:loadpath (list (string-append (getenv "HOME") @@ -125,8 +126,32 @@ ((#\cr) (string m-quote #\r)) (else (string chr))))) ls))))))) + +;;; bot:channel-users user object accessors +(define-public (bot:channel-user-nick cu) + (first cu)) + +(define-public (bot:channel-user-user/host cu) + (second cu)) + +(define-public (bot:channel-user-mode cu) + (third cu)) + +(define-public (bot:channel-user-has-modes? cu . modes) + (let ((mode (apply logior modes))) + (= (logand (bot:channel-user-mode cu)) mode mode))) + +(define-public (bot:channel-user-op? cu) + (bot:channel-user-has-modes? cu bot:mode/op)) + +(define-public (bot:channel-user-voice? cu) + (bot:channel-user-has-modes? cu bot:mode/voice)) + +(define-public (bot:channel-user-away? cu) + (bot:channel-user-has-modes? cu bot:mode/away)) - +(define-public (bot:channel-user-ircop? cu) + (bot:channel-user-has-modes? cu bot:mode/op)) ;;; DEPRECATED FUNCTION NAMES ;;; These are provided for backwards compatibility diff --git a/source/ChannelUserList.H b/source/ChannelUserList.H index 4a96417..c86ac16 100644 --- a/source/ChannelUserList.H +++ b/source/ChannelUserList.H @@ -71,7 +71,7 @@ public: unsigned int operator_count () const throw (); template - void foreach (const T & fun) + void foreach (T & fun) { BotLock foreach_lock (users_mutex); std::for_each (users.begin (), users.end (), fun); diff --git a/source/Interp.C b/source/Interp.C index e634d35..dbd6bee 100644 --- a/source/Interp.C +++ b/source/Interp.C @@ -131,6 +131,12 @@ interp_init_helper (void* unused) scm_c_define ("bot:user-friend", scm_from_int (User::FRIEND)); scm_c_define ("bot:user-master", scm_from_int (User::MASTER)); + // user channel modes + scm_c_define ("bot:mode/op", scm_from_int (User::OP_MODE)); + scm_c_define ("bot:mode/voice", scm_from_int (User::VOICE_MODE)); + scm_c_define ("bot:mode/away", scm_from_int (User::AWAY_MODE)); + scm_c_define ("bot:mode/ircop", scm_from_int (User::IRCOP_MODE)); + // protection scm_c_define ("bot:protection/none", scm_from_int (User::NO_PROT)); scm_c_define ("bot:protection/no-ban", scm_from_int (User::NO_BAN)); @@ -199,6 +205,8 @@ interp_init_helper (void* unused) bot_new_procedure ("bot:change-command-level", (SCMFunc)ScriptCommands::ChangeCommandLevel, 2, 0, 0); + scm_c_define_gsubr ("bot:channel-users", 1, 0, 0, + (SCMFunc)ScriptCommands::ChannelUsers); scm_c_define_gsubr ("bot:ctcp", 3, 0, 0, (SCMFunc)ScriptCommands::CTCP); scm_c_define_gsubr ("bot:ctcp-reply", 3, 0, 0, diff --git a/source/ScriptCommands.C b/source/ScriptCommands.C index 6788b03..502a9f8 100644 --- a/source/ScriptCommands.C +++ b/source/ScriptCommands.C @@ -1,6 +1,6 @@ // ScriptCommands.C -*- C++ -*- // Copyright (c) 1998 Etienne BERNARD -// Copyright (C) 2002,2005,2008 Clinton Ebadi +// Copyright (C) 2002,2005,2008,2009 Clinton Ebadi // 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 @@ -29,6 +29,7 @@ #include "Bot.H" #include "BotInterp.H" +#include "ChannelList.H" #include "Commands.H" #include "DCCManager.H" #include "DCCPerson.H" @@ -181,6 +182,39 @@ ScriptCommands::ChangeCommandLevel(SCM command, SCM level) return SCM_BOOL_T; } + +void +ScriptCommands::collect_channel_users::operator() (SCM *list, User user) + const +{ + *list = scm_cons (scm_list_n (Utils::str2scm (user.get_nick()), + Utils::str2scm (user.get_userhost ()), + scm_from_int (user.get_mode ()), + SCM_UNDEFINED), + *list); +} + +SCM +ScriptCommands::ChannelUsers (SCM channel_name) +{ + VERIFY_STRING (channel_name); + + Channel *channel = Interp::bot->channelList->getChannel (Utils::scm2str (channel_name)); + + if (!channel) + return SCM_BOOL_F; + + SCM* list = (SCM*)scm_gc_malloc (sizeof (SCM), "ScriptCommands::ChannelUsers"); + *list = SCM_EOL; + + collect_channel_users c; + + channel->for_each_channel_users (std::bind1st (c, list)); + + scm_remember_upto_here_1 (list); + return scm_reverse_x (*list, SCM_UNDEFINED); +} + SCM ScriptCommands::CTCP(SCM to, SCM command , SCM message) { diff --git a/source/ScriptCommands.H b/source/ScriptCommands.H index 231baeb..2c725e6 100644 --- a/source/ScriptCommands.H +++ b/source/ScriptCommands.H @@ -28,6 +28,10 @@ #include +#include + +class User; + class ScriptCommands { public: static SCM Action(SCM, SCM); @@ -36,6 +40,7 @@ public: static SCM AddShit(SCM, SCM, SCM, SCM, SCM); static SCM Ban(SCM, SCM); static SCM ChangeCommandLevel(SCM, SCM); + static SCM ChannelUsers (SCM); static SCM CTCP(SCM, SCM, SCM); static SCM CTCPReply(SCM, SCM, SCM); static SCM Cycle(SCM); @@ -109,6 +114,11 @@ public: SCM sendWho(SCM); SCM sendWhois(SCM); */ +private: + struct collect_channel_users : std::binary_function + { + void operator() (SCM*, User) const; + }; }; #endif diff --git a/source/User.H b/source/User.H index 9839cf0..9eef8d8 100644 --- a/source/User.H +++ b/source/User.H @@ -67,6 +67,10 @@ public: int getProt() const; bool getAop() const; + std::string get_nick () const { return nick; } + std::string get_userhost () const { return userhost; } + int get_mode () const { return mode; } + bool operator< (const User &) const; bool operator== (const User &) const; @@ -74,6 +78,7 @@ public: friend class Parser; friend class ChannelUserList; friend class Commands; + friend class ScriptCommands; friend class UserCommands; }; -- 2.20.1