From 8097430a810ac1535fe5304f74991b16ff58b064 Mon Sep 17 00:00:00 2001
From: "B.Greenham" <taros34@hotmail.com>
Date: Sun, 4 Apr 2010 15:58:07 -0400
Subject: [PATCH] Allow /ojoin !#channel/%#channel, if admin/halfop are
 enabled.

---
 TODO-SHADOW          |  1 -
 extensions/README    |  2 +-
 extensions/m_ojoin.c | 29 +++++++++++++++++++++++++++--
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/TODO-SHADOW b/TODO-SHADOW
index 4ef2bfb..447dc22 100644
--- a/TODO-SHADOW
+++ b/TODO-SHADOW
@@ -1,6 +1,5 @@
 Todo list for ShadowIRCd 6.1
 -----------------------------
-* update ojoin/omode/etc to use +ah
 * notice/message !#channel and %#channel
 * Add a disable_oper option to auth {} to not allow users in that auth block
   to use OPER.
diff --git a/extensions/README b/extensions/README
index 9ba97b1..877f026 100644
--- a/extensions/README
+++ b/extensions/README
@@ -36,7 +36,7 @@ m_oaccept.c    - OACCEPT - Add metadata to a user that will allow you to
                  Syntax: OACCEPT <nick>
 
 m_ojoin.c      - OJOIN - Join a channel through any modes or limits with 
-                         an optional status (@+)
+                         an optional status (!@%+)
                  Syntax: OJOIN [status]<channel>
 
 m_olist.c      - OLIST - Lists channels like LIST, but shows hidden
diff --git a/extensions/m_ojoin.c b/extensions/m_ojoin.c
index 239cd44..8c29f6d 100644
--- a/extensions/m_ojoin.c
+++ b/extensions/m_ojoin.c
@@ -65,7 +65,7 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
 		return 0;
 	}
 
-	if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+')
+	if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!')
 	{
 		parv[1]++;
 		move_me = 1;
@@ -98,7 +98,20 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
 			me.name, parv[1],
 			source_p->name, source_p->username, source_p->host);
 
-	if(*parv[1] == '@')
+	if(*parv[1] == '!' && ConfigChannel.use_admin)
+	{
+		add_user_to_channel(chptr, source_p, CHFL_ADMIN);
+		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
+			      ":%s SJOIN %ld %s + :!%s",
+			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
+		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
+				     source_p->name,
+				     source_p->username, source_p->host, chptr->chname);
+		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
+				     me.name, chptr->chname, source_p->name);
+
+	}
+	else if(*parv[1] == '@')
 	{
 		add_user_to_channel(chptr, source_p, CHFL_CHANOP);
 		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
@@ -111,6 +124,18 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
 				     me.name, chptr->chname, source_p->name);
 
 	}
+	else if(*parv[1] == '%' && ConfigChannel.use_halfop)
+	{
+		add_user_to_channel(chptr, source_p, CHFL_HALFOP);
+		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
+			      ":%s SJOIN %ld %s + :%s%s",
+			      me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id);
+		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
+				     source_p->name,
+				     source_p->username, source_p->host, chptr->chname);
+		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
+				     me.name, chptr->chname, source_p->name);
+	}
 	else if(*parv[1] == '+')
 	{
 		add_user_to_channel(chptr, source_p, CHFL_VOICE);