diff --git a/src/core/plugincallback.c b/src/core/plugincallback.c index 74fd70e..09902b8 100644 --- a/src/core/plugincallback.c +++ b/src/core/plugincallback.c @@ -200,6 +200,7 @@ void plugin_register_callback_functions(struct plugin_handle* handle) handle->hub.set_description = cbfunc_set_hub_description; handle->hub.ucmd_create = cbfunc_ucmd_create; handle->hub.ucmd_add_chat = cbfunc_ucmd_add_chat; + handle->hub.ucmd_add_pm = cbfunc_ucmd_add_pm; handle->hub.ucmd_send = cbfunc_ucmd_send; handle->hub.ucmd_free = cbfunc_ucmd_free; } diff --git a/src/core/pluginucmd.c b/src/core/pluginucmd.c index c45d745..b54e151 100644 --- a/src/core/pluginucmd.c +++ b/src/core/pluginucmd.c @@ -145,6 +145,59 @@ int cbfunc_ucmd_add_chat(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, return 1; } +int cbfunc_ucmd_add_pm(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* to, const char* message, int echo) +{ + /* Double-escape the message - once for when the client sends it back, and + * then again to insert it into the user command message we send to them. */ + char* temp = adc_msg_escape(message); + char* escmsg = adc_msg_escape(temp); + free(temp); + size_t msglen = strlen(escmsg); + + /* If no target SID is given, use the keyword expansion %[userSID] for the + * client to fill in with the currently selected user. */ + size_t tolen = (to == NULL) ? 10 : 4; + + /* Format of an echoed PM: "EMSG\s%[mySID]\s\s\sPM%[mySID]\n". + * Format of a non-echoed PM: "DMSG\s%[mySID]\s\s\sPM%[mySID]\n". */ + size_t required = 32 + tolen + msglen; + if(required > (ucmd->capacity - ucmd->length)) + { + if(ucmd_expand_tt(ucmd, ucmd->capacity + required) == 0) + { + plugin->error_msg = "Could not expand memory to store private message."; + free(escmsg); + return 0; + } + } + + /* Start with the appropriate ADC command plus the client SID placeholder. */ + if(echo) strncpy(ucmd->tt + ucmd->length, "EMSG\\s%[mySID]\\s", 16); + else strncpy(ucmd->tt + ucmd->length, "DMSG\\s%[mySID]\\s", 16); + ucmd->length += 16; + + /* Copy the target ID. */ + if(to != NULL) strncpy(ucmd->tt + ucmd->length, to, tolen); + else strncpy(ucmd->tt + ucmd->length, "%[userSID]", tolen); + ucmd->length += tolen; + + /* Space between target and message. */ + ucmd->tt[ucmd->length++] = '\\'; + ucmd->tt[ucmd->length++] = 's'; + + /* Message. */ + strncpy(ucmd->tt + ucmd->length, escmsg, msglen); + ucmd->length += msglen; + free(escmsg); + + /* Add the PM flag and final line break. */ + strncpy(ucmd->tt + ucmd->length, "\\sPM%[mySID]\\n", 14); + ucmd->length += 14; + + /* Done. */ + return 1; +} + int cbfunc_ucmd_send(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_ucmd* ucmd) { /* Make sure we have a command. */ diff --git a/src/core/pluginucmd.h b/src/core/pluginucmd.h index 0e6f8c8..d1e4baf 100644 --- a/src/core/pluginucmd.h +++ b/src/core/pluginucmd.h @@ -38,6 +38,16 @@ extern struct plugin_ucmd* cbfunc_ucmd_create(struct plugin_handle* plugin, cons */ extern int cbfunc_ucmd_add_chat(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* message, int me); +/* Add a private message to be sent when the user command is clicked. + * To: The SID of the user to send the message to. Leave it blank to send to + * the user that was right-clicked in the user list (i.e., a context-based + * message - only effective if the user command is in the user category). + * Echo: If true, the message is also echoed to the sending user as in a normal + * PM. If false, it is only sent to the target user and the sending user + * will only see any response. + */ +extern int cbfunc_ucmd_add_pm(struct plugin_handle* plugin, struct plugin_ucmd* ucmd, const char* to, const char* message, int echo); + /* Send the user command to a user. */ extern int cbfunc_ucmd_send(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_ucmd* ucmd); diff --git a/src/plugin_api/handle.h b/src/plugin_api/handle.h index d37b8c2..8456118 100644 --- a/src/plugin_api/handle.h +++ b/src/plugin_api/handle.h @@ -125,6 +125,7 @@ typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*); typedef struct plugin_ucmd* (*hfunc_ucmd_create)(struct plugin_handle*, const char*, size_t); typedef int (*hfunc_ucmd_add_chat)(struct plugin_handle*, struct plugin_ucmd*, const char*, int); +typedef int (*hfunc_ucmd_add_pm)(struct plugin_handle*, struct plugin_ucmd*, const char*, const char*, int); typedef int (*hfunc_ucmd_send)(struct plugin_handle*, struct plugin_user*, struct plugin_ucmd*); typedef void (*hfunc_ucmd_free)(struct plugin_handle*, struct plugin_ucmd*); @@ -147,6 +148,7 @@ struct plugin_hub_funcs hfunc_set_hub_description set_description; hfunc_ucmd_create ucmd_create; hfunc_ucmd_add_chat ucmd_add_chat; + hfunc_ucmd_add_pm ucmd_add_pm; hfunc_ucmd_send ucmd_send; hfunc_ucmd_free ucmd_free; };