+
+/*
+ * can_send_part - whether a part message can be sent.
+ *
+ * inputs:
+ * - client parting
+ * - channel being parted
+ * - membership pointer
+ * outputs:
+ * - true if message allowed
+ * - false if message denied
+ * side effects:
+ * - none.
+ */
+static bool
+can_send_part(struct Client *source_p, struct Channel *chptr, struct membership *msptr)
+{
+ if (!can_send(chptr, source_p, msptr))
+ return false;
+ /* Allow chanops to bypass anti_spam_exit_message_time for part messages. */
+ if (is_chanop(msptr))
+ return true;
+ return (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time();
+}
+
+/*
+ * do_message_hook - execute the message hook on a part message reason.
+ *
+ * inputs:
+ * - client parting
+ * - channel being parted
+ * - pointer to reason
+ * outputs:
+ * - true if message is allowed
+ * - false if message is denied or message is now empty
+ * side effects:
+ * - reason may be modified.
+ */
+static bool
+do_message_hook(struct Client *source_p, struct Channel *chptr, const char **reason)
+{
+ hook_data_privmsg_channel hdata;
+
+ hdata.msgtype = MESSAGE_TYPE_PART;
+ hdata.source_p = source_p;
+ hdata.chptr = chptr;
+ hdata.text = *reason;
+ hdata.approved = 0;
+
+ call_hook(h_privmsg_channel, &hdata);
+
+ /* The reason may have been changed by a hook... */
+ *reason = hdata.text;
+
+ return (hdata.approved == 0 && !EmptyString(*reason));
+}