]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/mod-memoserv.c
Finally fixed all those pesky warnings
[irc/evilnet/x3.git] / src / mod-memoserv.c
index c800b3e00a0d9c8e38bd87b7bfb0c4a05af436cf..036902a1616fd06e58fd33f5999d8a906a352979 100644 (file)
@@ -6,7 +6,7 @@
  *
  * x3 is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * Restart srvx with the updated conf file (as above, butwith "bot"
  * "MemoServ"), and bind the commands to it:
  * /msg opserv bind memoserv * *memoserv.*
- * /msg opserv bind memoserv set *modcmd.joiner
+ * /msg opserv bind memoserv set *memoserv.set
  */
 
 #include "chanserv.h"
 #include "conf.h"
 #include "modcmd.h"
 #include "nickserv.h"
+#include "opserv.h"
 #include "saxdb.h"
+#include "mail.h"
 #include "timeq.h"
 
 #define KEY_MAIN_ACCOUNTS "accounts"
@@ -65,8 +67,9 @@ static const struct message_entry msgtab[] = {
     { "MSMSG_UNKNOWN_SEND_FLAG", "Unreccognised send flag '%c', message not sent." },
     { "MSMSG_MEMO_SENT", "Message sent to $b%s$b (ID# %d)." },
     { "MSMSG_NO_MESSAGES", "You have no messages." },
-    { "MSMSG_MEMOS_FOUND", "Found $b%d$b matches.\nUse /msg $S READ <ID> to read a message." },
-    { "MSMSG_CLEAN_INBOX", "You have $b%d$b or more messages, please clean out your inbox.\nUse /msg $S READ <ID> to read a message." },
+    { "MSMSG_MEMOS_FOUND", "Found $b%d$b matches." },
+    { "MSMSG_HOWTO_READ", "Use READ <ID> to read a message." },
+    { "MSMSG_CLEAN_INBOX", "You have $b%d$b or more messages, please clean out your inbox.\nUse READ <ID> to read a message." },
     { "MSMSG_LIST_HEAD",      "$bID$b   $bFrom$b       $bTime Sent$b" },
     { "MSMSG_LIST_FORMAT",    "%-2u     %s $b%s$b          %s" },
     { "MSMSG_HISTORY_HEADER", "$bID$b   $bTo$b          $bTime Sent$b" },
@@ -83,11 +86,11 @@ static const struct message_entry msgtab[] = {
     { "MSMSG_EXPIRY_OFF", "I am currently not expiring messages. (turned off)" },
     { "MSMSG_EXPIRY", "Messages will be expired when they are %s old (%d seconds)." },
     { "MSMSG_MESSAGES_EXPIRED", "$b%lu$b message(s) expired." },
-    { "MSMSG_MEMOS_INBOX", "You have $b%d$b new message(s) in your inbox and %d old messages.  Use /msg $S LIST to list them." },
-    { "MSMSG_NEW_MESSAGE", "You have a new message from $b%s$b. /msg $S LIST" },
+    { "MSMSG_MEMOS_INBOX", "You have $b%d$b new message(s) in your inbox and %d old messages.  Use LIST to list them." },
+    { "MSMSG_NEW_MESSAGE", "You have a new message from $b%s$b. Use LIST to see your messages." },
     { "MSMSG_FULL_INBOX",  "$b%s$b cannot recieve anymore memos as their inbox is full" },
     { "MSMSG_DELETED_ALL", "Deleted all of your messages." },
-    { "MSMSG_USE_CONFIRM", "Please use /msg $S DELETE * $bCONFIRM$b to delete $uall$u of your messages." },
+    { "MSMSG_USE_CONFIRM", "Please use DELETE * $bCONFIRM$b to delete $uall$u of your messages." },
 
     { "MSMSG_STATUS_HIST_TOTAL",   "I have $b%u$b history entries in my database." },
     { "MSMSG_STATUS_TOTAL",   "I have $b%u$b memos in my database." },
@@ -96,18 +99,24 @@ static const struct message_entry msgtab[] = {
 
     { "MSMSG_INVALID_OPTION",  "$b%s$b is not a valid option." },
     { "MSMSG_INVALID_BINARY",  "$b%s$b is an invalid binary value." },
-    { "MSMSG_SET_NOTIFY",          "$bNotify:        $b %s" },
-    { "MSMSG_SET_AUTHNOTIFY",      "$bAuthNotify:    $b %s" },
-    { "MSMSG_SET_PRIVATE",         "$bPrivate:       $b %s" },
-    { "MSMSG_SET_IGNORERECIEPTS",  "$bIgnoreReciepts:$b %s" },
-    { "MSMSG_SET_SENDRECIEPTS",    "$bSendReciepts:  $b %s" },
-    { "MSMSG_SET_LIMIT",           "$bLimit:         $b %d" },
+    { "MSMSG_SET_AUTHNOTIFY",      "$bAuthNotify$b:       %s" },
+    { "MSMSG_SET_NEWNOTIFY",       "$bNewNotify$b:        %s" },
+    { "MSMSG_SET_PRIVMSG",         "$bPrivmsg$b:          %s" },
+    { "MSMSG_SET_PRIVATE",         "$bPrivate$b:          %s" },
+    { "MSMSG_SET_IGNORERECIEPTS",  "$bIgnoreReciepts$b:   %s" },
+    { "MSMSG_SET_SENDRECIEPTS",    "$bSendReciepts$b:     %s" },
+    { "MSMSG_SET_LIMIT",           "$bLimit$b:            %d" },
     { "MSMSG_SET_OPTIONS",         "$bMessaging Options$b" },
     { "MSMSG_SET_OPTIONS_END", "-------------End of Options-------------" },
 
     { "MSMSG_LIST_END",        "--------------End of Memos--------------" },
     { "MSMSG_BAR",             "----------------------------------------"},
 
+    { "MSEMAIL_NEWMEMO_SUBJECT", "New %s %s message from %s" },
+    { "MSEMAIL_NEWMEMO_BODY", "This email has been sent to let you know that %s has sent you a message via %s.\n\n  The message is: %s.\n\nTo delete this message just type in /msg %s delete %d when on %s next." },
+
+    { "MSMSG_DEFCON_NO_NEW_MEMOS", "You cannot send new memos at this time, please try again soon." },
+
     { NULL, NULL }
 };
 
@@ -138,9 +147,9 @@ struct userNode *memoserv;
                                      return 0; }
 
 DECLARE_LIST(memoList, struct memo*);
-DEFINE_LIST(memoList, struct memo*);
+DEFINE_LIST(memoList, struct memo*)
 DECLARE_LIST(historyList, struct history*);
-DEFINE_LIST(historyList, struct history*);
+DEFINE_LIST(historyList, struct history*)
 
 /* memo_account.flags fields */
 #define MEMO_NOTIFY_NEW      0x00000001
@@ -148,10 +157,11 @@ DEFINE_LIST(historyList, struct history*);
 #define MEMO_DENY_NONCHANNEL 0x00000004
 #define MEMO_IGNORE_RECIEPTS 0x00000008
 #define MEMO_ALWAYS_RECIEPTS 0x00000010
+#define MEMO_USE_PRIVMSG     0x00000020
 
 struct memo_account {
     struct handle_info *handle;
-    unsigned int flags;
+    unsigned int flags : 6;
     unsigned int limit;
     struct memoList sent;
     struct memoList recvd;
@@ -175,7 +185,9 @@ extern struct string_list *autojoin_channels;
 const char *memoserv_module_deps[] = { NULL };
 static struct module *memoserv_module;
 static struct log_type *MS_LOG;
-static unsigned long memosSent, memosExpired;
+static unsigned long memoCount;
+static unsigned long memosSent;
+static unsigned long memosExpired;
 static struct dict *memos; /* memo_account->handle->handle -> memo_account */
 static struct dict *historys;
 static dict_t memoserv_opt_dict; /* contains option_func_t* */
@@ -193,7 +205,7 @@ memoserv_get_account(struct handle_info *hi)
     if (!ma)
         return ma;
     ma->handle = hi;
-    ma->flags = MEMO_NOTIFY_NEW | MEMO_NOTIFY_LOGIN;
+    ma->flags = MEMO_NOTIFY_NEW | MEMO_NOTIFY_LOGIN | MEMO_USE_PRIVMSG;
     ma->limit = memoserv_conf.limit;
     dict_insert(memos, ma->handle->handle, ma);
     dict_insert(historys, ma->handle->handle, ma);
@@ -207,6 +219,7 @@ delete_memo(struct memo *memo)
     memoList_remove(&memo->sender->sent, memo);
     free(memo->message);
     free(memo);
+    memoCount--;
 }
 
 static void
@@ -243,10 +256,10 @@ do_expire(void)
 {
     dict_iterator_t it;
     for (it = dict_first(memos); it; it = iter_next(it)) {
-        struct memo_account *acct = iter_data(it);
+        struct memo_account *account = iter_data(it);
         unsigned int ii;
-        for (ii = 0; ii < acct->sent.used; ++ii) {
-            struct memo *memo = acct->sent.list[ii];
+        for (ii = 0; ii < account->sent.used; ++ii) {
+            struct memo *memo = account->sent.list[ii];
             if ((now - memo->sent) > memoserv_conf.message_expiry) {
                 delete_memo(memo);
                 memosExpired++;
@@ -256,10 +269,10 @@ do_expire(void)
     }
 
     for (it = dict_first(historys); it; it = iter_next(it)) {
-        struct memo_account *acct = iter_data(it);
+        struct memo_account *account = iter_data(it);
         unsigned int ii;
-        for (ii = 0; ii < acct->hsent.used; ++ii) {
-            struct history *history = acct->hsent.list[ii];
+        for (ii = 0; ii < account->hsent.used; ++ii) {
+            struct history *history = account->hsent.list[ii];
             if ((now - history->sent) > memoserv_conf.message_expiry) {
                 delete_history(history);
                 memosExpired++;
@@ -302,7 +315,6 @@ static struct memo*
 add_memo(time_t sent, struct memo_account *recipient, struct memo_account *sender, char *message, int nfrom_read)
 {
     struct memo *memo;
-    struct history *history;
 
     memo = calloc(1, sizeof(*memo));
     if (!memo)
@@ -320,9 +332,10 @@ add_memo(time_t sent, struct memo_account *recipient, struct memo_account *sende
     memo->sent = sent;
     memo->message = strdup(message);
     memosSent++;
+    memoCount++;
 
     if (nfrom_read)
-        history = add_history(sent, recipient, sender, memo->id);
+        add_history(sent, recipient, sender, memo->id);
 
     return memo;
 }
@@ -350,7 +363,7 @@ memoserv_can_send(struct userNode *bot, struct userNode *user, struct memo_accou
 
     if (acct->handle->ignores->used) {
         for (i=0; i < acct->handle->ignores->used; i++) {
-            if (user_matches_glob(user, acct->handle->ignores->list[i], MATCH_USENICK)) {
+            if (user_matches_glob(user, acct->handle->ignores->list[i], MATCH_USENICK, 0)) {
                 match = 1;
                 break;
             }
@@ -394,13 +407,21 @@ static struct memo *find_memo(struct userNode *user, struct svccmd *cmd, struct
 static MODCMD_FUNC(cmd_send)
 {
     char *message;
-    int reciept = 0, inc = 2;
+    int reciept = 0, inc = 2, email = 0;
     struct handle_info *hi;
     struct memo_account *ma, *sender;
     struct memo *memo;
+    char subject[128], body[4096];
+    char *estr;
+    const char *netname, *fmt;
 
     MEMOSERV_MIN_PARAMS(3);
 
+    if (checkDefCon(DEFCON_NO_NEW_MEMOS) && !IsOper(user)) {
+        reply("MSMSG_DEFCON_NO_NEW_MEMOS");
+        return 0;
+    }
+
     if (!(hi = modcmd_get_handle_info(user, argv[1])))
         return 0;
 
@@ -442,7 +463,20 @@ static MODCMD_FUNC(cmd_send)
         struct userNode *other;
 
         for (other = ma->handle->users; other; other = other->next_authed)
-            send_message(other, cmd->parent->bot, "MSMSG_NEW_MESSAGE", user->nick);
+            send_message_type((ma->flags & MEMO_USE_PRIVMSG)? MSG_TYPE_PRIVMSG : MSG_TYPE_NOTICE, other, memoserv ? memoserv : cmd->parent->bot, "MSMSG_NEW_MESSAGE", user->nick);
+    }
+
+    estr = conf_get_data("services/nickserv/email_enabled", RECDB_QSTRING);
+    netname = conf_get_data("server/network", RECDB_QSTRING);
+    email = atoi(estr);
+    if (email && (ma->flags & MEMO_NOTIFY_NEW)) {
+        fmt = handle_find_message(hi, "MSEMAIL_NEWMEMO_SUBJECT");
+        snprintf(subject, sizeof(subject), fmt, netname, memoserv->nick, user->nick);
+
+        fmt = handle_find_message(hi, "MSEMAIL_NEWMEMO_BODY");
+        snprintf(body, sizeof(body), fmt, user->nick, memoserv->nick, message, memoserv->nick, memo_id, netname);
+
+        mail_send(memoserv, hi, subject, body, 0);
     }
 
     reply("MSMSG_MEMO_SENT", ma->handle->handle, memo_id);
@@ -475,8 +509,10 @@ static MODCMD_FUNC(cmd_list)
         reply("MSG_NONE");
     else if (ii == 15)
         reply("MSMSG_CLEAN_INBOX", ii);
-    else
+    else {
         reply("MSMSG_MEMOS_FOUND", ii);
+        reply("MSMSG_HOWTO_READ");
+    }
 
     reply("MSMSG_LIST_END");
 
@@ -534,11 +570,6 @@ static MODCMD_FUNC(cmd_read)
     char posted[24];
     struct tm tm;
 
-    if (!(ma = memoserv_get_account(user->handle_info)))
-        return 0;
-    if (!(memo = find_memo(user, cmd, ma, argv[1], &memoid)))
-        return 0;
-
     if (argc > 2) {
         char *argtwo = argv[2];
         while (*argtwo) {
@@ -565,6 +596,12 @@ static MODCMD_FUNC(cmd_read)
         }
     }
 
+    if (!(ma = memoserv_get_account(user->handle_info)))
+        return 0;
+    
+    if (!(memo = find_memo(user, cmd, ma, argv[1], &memoid)))
+        return 0;
+
     localtime_r(&memo->sent, &tm);
     strftime(posted, sizeof(posted), "%I:%M %p, %m/%d/%Y", &tm);
 
@@ -596,7 +633,7 @@ static MODCMD_FUNC(cmd_read)
                 struct userNode *other;
 
                 for (other = sender->handle->users; other; other = other->next_authed)
-                    send_message(other, cmd->parent->bot, "MSMSG_NEW_MESSAGE", ma->handle->handle);
+                    send_message_type((ma->flags & MEMO_USE_PRIVMSG)? MSG_TYPE_PRIVMSG : MSG_TYPE_NOTICE, other, cmd->parent->bot, "MSMSG_NEW_MESSAGE", ma->handle->handle);
             }
 
 
@@ -705,7 +742,7 @@ set_list(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, int
 {
     option_func_t *opt;
     unsigned int i;
-    char *set_display[] = {"AUTHNOTIFY", "NOTIFY", "PRIVATE", "LIMIT",
+    char *set_display[] = {"AUTHNOTIFY", "NEWNOTIFY", "PRIVMSG", "PRIVATE", "LIMIT",
                            "IGNORERECIEPTS", "SENDRECIEPTS"};
 
     reply("MSMSG_SET_OPTIONS");
@@ -744,7 +781,7 @@ static MODCMD_FUNC(cmd_oset)
 
     MEMOSERV_MIN_PARAMS(2);
 
-    if (!(hi = get_victim_oper(cmd, user, argv[1])))
+    if (!(hi = get_victim_oper(user, argv[1])))
         return 0;
 
     if (argc < 3) {
@@ -760,7 +797,7 @@ static MODCMD_FUNC(cmd_oset)
     return opt(cmd, user, hi, 1, argc-2, argv+2);
 }
 
-static OPTION_FUNC(opt_notify)
+static OPTION_FUNC(opt_newnotify)
 {
     struct memo_account *ma;
     char *choice;
@@ -780,7 +817,30 @@ static OPTION_FUNC(opt_notify)
     }
 
     choice = (ma->flags & MEMO_NOTIFY_NEW) ? "on" : "off";
-    reply("MSMSG_SET_NOTIFY", choice);
+    reply("MSMSG_SET_NEWNOTIFY", choice);
+    return 1;
+}
+
+static OPTION_FUNC(opt_privmsg)
+{
+    struct memo_account *ma;
+    char *choice;
+
+    if (!(ma = memoserv_get_account(hi)))
+        return 0;
+    if (argc > 1) {
+        choice = argv[1];
+        if (enabled_string(choice)) {
+            ma->flags |= MEMO_USE_PRIVMSG;
+        } else if (disabled_string(choice)) {
+            ma->flags &= ~MEMO_USE_PRIVMSG;
+        } else {
+            reply("MSMSG_INVALID_BINARY", choice);
+            return 0;
+        }
+    }
+    choice = (ma->flags & MEMO_USE_PRIVMSG) ? "on" : "off";
+    reply("MSMSG_SET_PRIVMSG", choice);
     return 1;
 }
 
@@ -919,7 +979,7 @@ static MODCMD_FUNC(cmd_status)
     }
 
     reply("MSMSG_STATUS_HIST_TOTAL", hc);
-    reply("MSMSG_STATUS_TOTAL", mc);
+    reply("MSMSG_STATUS_TOTAL", memoCount);
     reply("MSMSG_STATUS_EXPIRED", memosExpired);
     reply("MSMSG_STATUS_SENT", memosSent);
     return 1;
@@ -1052,7 +1112,6 @@ memoserv_history_read(const char *key, struct record_data *hir)
 {
     char *str;
     struct handle_info *sender, *recipient;
-    struct history *history;
     unsigned long id;
     time_t sent;
 
@@ -1090,7 +1149,7 @@ memoserv_history_read(const char *key, struct record_data *hir)
         return 0;
     }
 
-    history = add_history(sent, memoserv_get_account(recipient), memoserv_get_account(sender), id);
+    add_history(sent, memoserv_get_account(recipient), memoserv_get_account(sender), id);
 
     return 0;
 }
@@ -1131,9 +1190,10 @@ memoserv_write_users(struct saxdb_context *ctx, struct memo_account *ma)
 static int
 memoserv_write_memos(struct saxdb_context *ctx, struct memo *memo)
 {
-    char str[7];
+    char str[20];
 
-    saxdb_start_record(ctx, inttobase64(str, memo->id, sizeof(str)), 0);
+    memset(str, '\0', sizeof(str));
+    saxdb_start_record(ctx, inttobase64(str, memo->id, sizeof(str)-1), 0);
 
     saxdb_write_int(ctx, KEY_SENT, memo->sent);
     saxdb_write_int(ctx, KEY_ID, memo->id);
@@ -1154,9 +1214,10 @@ memoserv_write_memos(struct saxdb_context *ctx, struct memo *memo)
 static int
 memoserv_write_history(struct saxdb_context *ctx, struct history *history)
 {
-    char str[7];
+    char str[20];
 
-    saxdb_start_record(ctx, inttobase64(str, history->id, sizeof(str)), 0);
+    memset(str, '\0', sizeof(str));
+    saxdb_start_record(ctx, inttobase64(str, history->id, sizeof(str)-1), 0);
 
     saxdb_write_int(ctx, KEY_SENT, history->sent);
     saxdb_write_int(ctx, KEY_ID, history->id);
@@ -1210,14 +1271,14 @@ memoserv_saxdb_write(struct saxdb_context *ctx)
 }
 
 static void
-memoserv_cleanup(void)
+memoserv_cleanup(UNUSED_ARG(void *extra))
 {
     dict_delete(memos);
     dict_delete(historys);
 }
 
 static void
-memoserv_check_messages(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle))
+memoserv_check_messages(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle), UNUSED_ARG(void *extra))
 {
     unsigned int ii, unseen;
     struct memo_account *ma;
@@ -1233,12 +1294,12 @@ memoserv_check_messages(struct userNode *user, UNUSED_ARG(struct handle_info *ol
                 unseen++;
         }
         if (ma->recvd.used && memoserv)
-            if(unseen) send_message(user, memoserv, "MSMSG_MEMOS_INBOX", unseen, ma->recvd.used - unseen);
+            if(unseen) send_message_type((ma->flags & MEMO_USE_PRIVMSG)? 1 : 0, user, memoserv, "MSMSG_MEMOS_INBOX", unseen, ma->recvd.used - unseen);
     }
 }
 
 static void
-memoserv_rename_account(struct handle_info *hi, const char *old_handle)
+memoserv_rename_account(struct handle_info *hi, const char *old_handle, UNUSED_ARG(void *extra))
 {
     struct memo_account *ma;
     if (!(ma = dict_find(memos, old_handle, NULL)))
@@ -1251,7 +1312,7 @@ memoserv_rename_account(struct handle_info *hi, const char *old_handle)
 }
 
 static void
-memoserv_unreg_account(UNUSED_ARG(struct userNode *user), struct handle_info *handle)
+memoserv_unreg_account(UNUSED_ARG(struct userNode *user), struct handle_info *handle, UNUSED_ARG(void *extra))
 {
     dict_remove(memos, handle->handle);
     dict_remove(historys, handle->handle);
@@ -1264,11 +1325,11 @@ memoserv_init(void)
     memos = dict_new();
     historys = dict_new();
     dict_set_free_data(memos, delete_memo_account);
-    reg_auth_func(memoserv_check_messages);
-    reg_handle_rename_func(memoserv_rename_account);
-    reg_unreg_func(memoserv_unreg_account);
+    reg_auth_func(memoserv_check_messages, NULL);
+    reg_handle_rename_func(memoserv_rename_account, NULL);
+    reg_unreg_func(memoserv_unreg_account, NULL);
     conf_register_reload(memoserv_conf_read);
-    reg_exit_func(memoserv_cleanup);
+    reg_exit_func(memoserv_cleanup, NULL);
     saxdb_register("MemoServ", memoserv_saxdb_read, memoserv_saxdb_write);
 
     memoserv_module = module_register("MemoServ", MS_LOG, "mod-memoserv.help", NULL);
@@ -1286,7 +1347,8 @@ memoserv_init(void)
 
     memoserv_opt_dict = dict_new();
     dict_insert(memoserv_opt_dict, "AUTHNOTIFY", opt_authnotify);
-    dict_insert(memoserv_opt_dict, "NOTIFY", opt_notify);
+    dict_insert(memoserv_opt_dict, "NEWNOTIFY", opt_newnotify);
+    dict_insert(memoserv_opt_dict, "PRIVMSG", opt_privmsg);
     dict_insert(memoserv_opt_dict, "PRIVATE", opt_private);
     dict_insert(memoserv_opt_dict, "IGNORERECIEPTS", opt_ignorereciepts);
     dict_insert(memoserv_opt_dict, "SENDRECIEPTS", opt_sendreciepts);
@@ -1316,8 +1378,13 @@ memoserv_finalize(void) {
     str = database_get_data(conf_node, "bot", RECDB_QSTRING);
     if (str) {
         memoserv = memoserv_conf.bot;
-    } else
+        const char *modes = conf_get_data("modules/memoserv/modes", RECDB_QSTRING);
+        memoserv = AddLocalUser(str, str, NULL, "User-User Memorandum Services", modes);
+        service_register(memoserv);
+    } else {
         log_module(MS_LOG, LOG_ERROR, "database_get_data for memoserv_conf.bot failed!");
+        exit(1);
+    }
 
     if (autojoin_channels && memoserv) {
         for (i = 0; i < autojoin_channels->used; i++) {