* (chicken and egg scenario!)
*/
std::map<char*,char*> internal_userlist;
-
+ std::map<char*,char*> internal_op_userlist;
+ std::map<char*,char*> internal_halfop_userlist;
+ std::map<char*,char*> internal_voice_userlist;
+
/** Channel topic.
* If this is an empty string, no channel topic is set.
*/
* as this is a very fast 32 or 64 bit integer comparison.
*/
void AddUser(char* castuser);
+ void AddOppedUser(char* castuser);
+ void AddHalfoppedUser(char* castuser);
+ void AddVoicedUser(char* castuser);
/** Delete a user pointer to the internal reference list
* @param castuser This should be a pointer to a userrec, casted to char*
* as this is a very fast 32 or 64 bit integer comparison.
*/
void DelUser(char* castuser);
+ void DelOppedUser(char* castuser);
+ void DelHalfoppedUser(char* castuser);
+ void DelVoicedUser(char* castuser);
/** Obrain the internal reference list
* The internal reference list contains a list of userrec*
* @return This function returns a vector of userrec pointers, each of which has been casted to char* to prevent circular references
*/
std::map<char*,char*> *GetUsers();
+ std::map<char*,char*> *GetOppedUsers();
+ std::map<char*,char*> *GetHalfoppedUsers();
+ std::map<char*,char*> *GetVoicedUsers();
/** Creates a channel record and initialises it with default values
*/
void WriteChannel(chanrec* Ptr, userrec* user, char* text, ...);
void WriteChannelLocal(chanrec* Ptr, userrec* user, char* text, ...);
void WriteChannelWithServ(char* ServName, chanrec* Ptr, char* text, ...);
-void ChanExceptSender(chanrec* Ptr, userrec* user, char* text, ...);
+void ChanExceptSender(chanrec* Ptr, userrec* user, char status, char* text, ...);
void Write_NoFormat(int sock,const char *text);
void WriteServ_NoFormat(int sock, const char* text);
void WriteChannel_NoFormat(chanrec* Ptr, userrec* user, const char* text);
void WriteChannelLocal_NoFormat(chanrec* Ptr, userrec* user, const char* text);
void WriteChannelWithServ_NoFormat(char* ServName, chanrec* Ptr, const char* text);
-void ChanExceptSender_NoFormat(chanrec* Ptr, userrec* user, const char* text);
+void ChanExceptSender_NoFormat(chanrec* Ptr, char status, userrec* user, const char* text);
void WriteCommon_NoFormat(userrec *u, const char* text);
void WriteCommonExcept_NoFormat(userrec *u, const char* text);
* @param dest The target of the message
* @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
* @param text the text being sent by the user
+ * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
*/
- virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text);
+ virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text, char status);
/** Called after any NOTICE sent from a user.
* The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
* @param dest The target of the message
* @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
* @param text the text being sent by the user
+ * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone.
*/
- virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text);
+ virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text, char status);
/** Called after every MODE command sent from a user
* The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
}
+void chanrec::AddOppedUser(char* castuser)
+{
+ internal_op_userlist[castuser] = castuser;
+ log(DEBUG,"Added casted user to channel's internal list");
+}
+
+void chanrec::DelOppedUser(char* castuser)
+{
+ std::map<char*,char*>::iterator a = internal_op_userlist.find(castuser);
+ if (a != internal_op_userlist.end())
+ {
+ log(DEBUG,"Removed casted user from channel's internal list");
+ internal_op_userlist.erase(a);
+ return;
+ }
+ log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
+}
+
+void chanrec::AddHalfoppedUser(char* castuser)
+{
+ internal_halfop_userlist[castuser] = castuser;
+ log(DEBUG,"Added casted user to channel's internal list");
+}
+
+void chanrec::DelHalfoppedUser(char* castuser)
+{
+ std::map<char*,char*>::iterator a = internal_halfop_userlist.find(castuser);
+ if (a != internal_halfop_userlist.end())
+ {
+ log(DEBUG,"Removed casted user from channel's internal list");
+ internal_halfop_userlist.erase(a);
+ return;
+ }
+ log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
+}
+
+void chanrec::AddVoicedUser(char* castuser)
+{
+ internal_voice_userlist[castuser] = castuser;
+ log(DEBUG,"Added casted user to channel's internal list");
+}
+
+void chanrec::DelOppedUser(char* castuser)
+{
+ std::map<char*,char*>::iterator a = internal_voice_userlist.find(castuser);
+ if (a != internal_voice_userlist.end())
+ {
+ log(DEBUG,"Removed casted user from channel's internal list");
+ internal_voice_userlist.erase(a);
+ return;
+ }
+ log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
+}
+
std::map<char*,char*> *chanrec::GetUsers()
{
return &internal_userlist;
}
+std::map<char*,char*> *chanrec::GetOppedUsers()
+{
+ return &internal_op_userlist;
+}
+
+std::map<char*,char*> *chanrec::GetHalfoppedUsers()
+{
+ return &internal_halfop_userlist;
+}
+
+std::map<char*,char*> *chanrec::GetVoicedUsers()
+{
+ return &internal_voice_userlist;
+}
+
/* add a channel to a user, creating the record for it if needed and linking
* it to the user record */
{
/* first user in is given ops */
a.uc_modes = UCMODE_OP;
+ Ptr->AddOppedUser((char*)user);
}
else
{
}
return;
}
- else if (parameters[0][0] == '#')
+ char status = 0;
+ if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
+ {
+ status = *parameters[0];
+ parameters[0]++;
+ }
+ if (*parameters[0] == '#')
{
chan = FindChan(parameters[0]);
if (chan)
return;
}
- ChanExceptSender(chan, user, "NOTICE %s :%s", chan->name, parameters[1]);
+ ChanExceptSender(chan, user, status, "NOTICE %s :%s", chan->name, parameters[1]);
FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,parameters[1]));
}
}
return;
}
- else if (parameters[0][0] == '#')
+ char status = 0;
+ if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
+ {
+ status = *parameters[0];
+ parameters[0]++;
+ }
+ if (parameters[0][0] == '#')
{
chan = FindChan(parameters[0]);
if (chan)
return;
}
- ChanExceptSender(chan, user, "PRIVMSG %s :%s", chan->name, parameters[1]);
+ ChanExceptSender(chan, user, status, "PRIVMSG %s :%s", chan->name, parameters[1]);
FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,parameters[1]));
}
else
/* write formatted text from a source user to all users on a channel except
* for the sender (for privmsg etc) */
-void ChanExceptSender(chanrec* Ptr, userrec* user, char* text, ...)
+void ChanExceptSender(chanrec* Ptr, userrec* user, char status, char* text, ...)
{
if ((!Ptr) || (!user) || (!text))
{
vsnprintf(textbuffer, MAXBUF, text, argsPtr);
va_end(argsPtr);
- std::map<char*,char*> *ulist= Ptr->GetUsers();
+ std::map<char*,char*> *ulist;
+ switch (status)
+ {
+ case '@':
+ Ptr->GetOppedUsers();
+ break;
+ case '%':
+ Ptr->GetHalfoppedUsers();
+ break;
+ case '+':
+ Ptr->GetVoicedUsers();
+ break;
+ default:
+ Ptr->GetUsers();
+ break;
+ }
for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
{
char* o = i->second;
}
}
-void ChanExceptSender_NoFormat(chanrec* Ptr, userrec* user, const char* text)
+void ChanExceptSender_NoFormat(chanrec* Ptr, userrec* user, char status, const char* text)
{
if ((!Ptr) || (!user) || (!text))
{
log(DEFAULT,"*** BUG *** ChanExceptSender was given an invalid parameter");
return;
}
- std::map<char*,char*> *ulist= Ptr->GetUsers();
+ std::map<char*,char*> *ulist;
+ switch (status)
+ {
+ case '@':
+ Ptr->GetOppedUsers();
+ break;
+ case '%':
+ Ptr->GetHalfoppedUsers();
+ break;
+ case '+':
+ Ptr->GetVoicedUsers();
+ break;
+ default:
+ Ptr->GetUsers();
+ break;
+ }
for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
{
char* o = i->second;
return NULL;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
+ d->chans[i].channel->AddOppedUser((char*)d);
log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
return NULL;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
+ d->chans[i].channel->AddHalfoppedUser((char*)d);
log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
return NULL;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
+ d->chans[i].channel->AddVoicedUser((char*)d);
log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
return NULL;
}
d->chans[i].uc_modes ^= UCMODE_OP;
+ d->chans[i].channel->DelOppedUser((char*)d);
log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
return NULL;
}
d->chans[i].uc_modes ^= UCMODE_HOP;
+ d->chans[i].channel->DelHalfoppedUser((char*)d);
log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
return NULL;
}
d->chans[i].uc_modes ^= UCMODE_VOICE;
+ d->chans[i].channel->DelVoicedUser((char*)d);
log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
return d->nick;
}
void Module::OnRawSocketClose(int fd) { };
int Module::OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { return 0; };
void Module::OnUserMessage(userrec* user, void* dest, int target_type, std::string text) { };
-void Module::OnUserNotice(userrec* user, void* dest, int target_type, std::string text) { };
-void Module::OnRemoteKill(userrec* source, userrec* dest, std::string reason) { };
+void Module::OnUserNotice(userrec* user, void* dest, int target_type, std::string text, char status) { };
+void Module::OnRemoteKill(userrec* source, userrec* dest, std::string reason, char status) { };
void Module::OnUserInvite(userrec* source,userrec* dest,chanrec* channel) { };
void Module::OnPostLocalTopicChange(userrec* user, chanrec* chan, std::string topic) { };
void Module::OnGetServerDescription(std::string servername,std::string &description) { };
}
else
{
- ChanExceptSender_NoFormat(Channel,User,s.c_str());
+ ChanExceptSender_NoFormat(Channel,User,0,s.c_str());
}
}
{
if ((params.size() >= 2) && (*(params[0].c_str()) != '$'))
{
+ /* Prefixes */
+ if ((*(params[0].c_str()) == '@') || (*(params[0].c_str()) == '%') || (*(params[0].c_str()) == '+'))
+ {
+ params[0] = params[0].substr(1, params[0].length()-1);
+ }
if (*(params[0].c_str()) != '#')
{
// special routing for private messages/notices
}
}
- virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text)
+ virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text, char status)
{
if (target_type == TYPE_USER)
{
{
if (user->fd > -1)
{
+ std::string cname = c->name;
+ if (status)
+ cname = status + cname;
chanrec *c = (chanrec*)dest;
std::deque<TreeServer*> list;
GetListOfServersForChannel(c,list);
{
TreeSocket* Sock = list[i]->GetSocket();
if (Sock)
- Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+std::string(c->name)+" :"+text);
+ Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+cname+" :"+text);
}
}
}
}
- virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text)
+ virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text, char status)
{
if (target_type == TYPE_USER)
{
{
if (user->fd > -1)
{
+ std::string cname = c->name;
+ if (status)
+ cname = status + cname;
chanrec *c = (chanrec*)dest;
std::deque<TreeServer*> list;
GetListOfServersForChannel(c,list);
{
TreeSocket* Sock = list[i]->GetSocket();
if (Sock)
- Sock->WriteLine(":"+std::string(user->nick)+" PRIVMSG "+std::string(c->name)+" :"+text);
+ Sock->WriteLine(":"+std::string(user->nick)+" PRIVMSG "+cname+" :"+text);
}
}
}