#define KEY_RECIPIENT "to"
#define KEY_FROM "from"
#define KEY_MESSAGE "msg"
+#undef KEY_READ /* thanks microsoft! */
#define KEY_READ "read"
+#define KEY_ACCOUNTS "accounts"
+#define KEY_MESSAGES "messages"
static const struct message_entry msgtab[] = {
+ { "MSMSG_CANNOT_SEND_SELF", "You cannot send to yourself." },
{ "MSMSG_CANNOT_SEND", "You cannot send to account $b%s$b." },
{ "MSMSG_MEMO_SENT", "Message sent to $b%s$b." },
{ "MSMSG_NO_MESSAGES", "You have no messages." },
{ "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." },
+ { "MSMSG_NEW_MESSAGE", "You have a new message from $b%s$b (ID $b%d$b)." },
{ "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_STATUS_TOTAL", "I have $b%u$b memos in my database." },
struct memo_account *recipient;
struct memo_account *sender;
char *message;
- time_t sent;
+ unsigned long sent;
unsigned int is_read : 1;
};
DECLARE_LIST(memoList, struct memo*);
-DEFINE_LIST(memoList, struct memo*);
+DEFINE_LIST(memoList, struct memo*)
/* memo_account.flags fields */
#define MEMO_NOTIFY_NEW 1
static struct {
struct userNode *bot;
- int message_expiry;
+ unsigned long message_expiry;
} memoserv_conf;
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 memo_account *
memoList_remove(&memo->sender->sent, memo);
free(memo->message);
free(memo);
+ memoCount--;
}
static 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++;
}
static struct memo*
-add_memo(time_t sent, struct memo_account *recipient, struct memo_account *sender, char *message)
+add_memo(unsigned long sent, struct memo_account *recipient, struct memo_account *sender, char *message)
{
struct memo *memo;
memo->sent = sent;
memo->message = strdup(message);
memosSent++;
+ memoCount++;
return memo;
}
static int
-memoserv_can_send(struct userNode *bot, struct userNode *user, struct memo_account *acct)
+memoserv_can_send(struct userNode *bot, struct userNode *user, struct memo_account *account)
{
extern struct userData *_GetChannelUser(struct chanData *channel, struct handle_info *handle, int override, int allow_suspended);
struct userData *dest;
if (!user->handle_info)
return 0;
- if (!(acct->flags & MEMO_DENY_NONCHANNEL))
+ if (user->handle_info == account->handle) {
+ send_message(user, bot, "MSMSG_CANNOT_SEND_SELF");
+ return 0;
+ }
+ if (!(account->flags & MEMO_DENY_NONCHANNEL))
return 1;
- for (dest = acct->handle->channels; dest; dest = dest->u_next)
- if (_GetChannelUser(dest->channel, user->handle_info, 1, 0))
+ for (dest = account->handle->channels; dest; dest = dest->u_next) {
+ if (dest->seen && _GetChannelUser(dest->channel, user->handle_info, 1, 0))
return 1;
- send_message(user, bot, "MSMSG_CANNOT_SEND", acct->handle->handle);
+ }
+ send_message(user, bot, "MSMSG_CANNOT_SEND", account->handle->handle);
return 0;
}
if (ma->flags & MEMO_NOTIFY_NEW) {
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(other, cmd->parent->bot, "MSMSG_NEW_MESSAGE", user->nick, ma->recvd.used - 1);
}
reply("MSMSG_MEMO_SENT", ma->handle->handle);
return 1;
struct memo *memo;
unsigned int ii;
char posted[24];
- struct tm tm;
+ time_t feh;
if (!(ma = memoserv_get_account(user->handle_info)))
return 0;
reply("MSMSG_LIST_HEAD");
for (ii = 0; (ii < ma->recvd.used) && (ii < 15); ++ii) {
memo = ma->recvd.list[ii];
- localtime_r(&memo->sent, &tm);
- strftime(posted, sizeof(posted), "%I:%M %p, %m/%d/%Y", &tm);
+ feh = memo->sent;
+ strftime(posted, sizeof(posted), "%I:%M %p, %m/%d/%Y", localtime(&feh));
reply("MSMSG_LIST_FORMAT", ii, memo->sender->handle->handle, posted);
}
if (ii == 0)
unsigned int memoid;
struct memo *memo;
char posted[24];
- struct tm tm;
+ time_t memo_sent;
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);
+ memo_sent = memo->sent;
+ strftime(posted, sizeof(posted), "%I:%M %p, %m/%d/%Y", localtime(&memo_sent));
reply("MSMSG_MEMO_HEAD", memoid, memo->sender->handle->handle, posted);
send_message_type(4, user, cmd->parent->bot, "%s", memo->message);
memo->is_read = 1;
return 1;
}
- intervalString(interval, memoserv_conf.message_expiry);
+ intervalString(interval, memoserv_conf.message_expiry, user->handle_info);
reply("MSMSG_EXPIRY", interval, memoserv_conf.message_expiry);
return 1;
}
static MODCMD_FUNC(cmd_status)
{
- reply("MSMSG_STATUS_TOTAL", dict_size(memos));
+ reply("MSMSG_STATUS_TOTAL", memoCount);
reply("MSMSG_STATUS_EXPIRED", memosExpired);
reply("MSMSG_STATUS_SENT", memosSent);
return 1;
}
static int
-memoserv_saxdb_read(struct dict *db)
+memoserv_saxdb_read_messages(struct dict *db)
{
char *str;
struct handle_info *sender, *recipient;
struct record_data *hir;
struct memo *memo;
dict_iterator_t it;
- time_t sent;
+ unsigned long sent;
for (it = dict_first(db); it; it = iter_next(it)) {
hir = iter_data(it);
log_module(MS_LOG, LOG_ERROR, "Date sent not present in memo %s; skipping", iter_key(it));
continue;
}
- sent = atoi(str);
+ sent = strtoul(str, NULL, 0);
if (!(str = database_get_data(hir->d.object, KEY_RECIPIENT, RECDB_QSTRING))) {
log_module(MS_LOG, LOG_ERROR, "Recipient not present in memo %s; skipping", iter_key(it));
return 0;
}
+static void
+memoserv_saxdb_read_accounts(struct dict *db)
+{
+ struct memo_account *ma;
+ struct handle_info *hi;
+ struct record_data *rd;
+ dict_iterator_t it;
+ const char *str;
+
+ for (it = dict_first(db); it; it = iter_next(it)) {
+ hi = get_handle_info(iter_key(it));
+ if (hi == NULL) {
+ log_module(MS_LOG, LOG_WARNING, "No account known for %s.", iter_key(it));
+ continue;
+ }
+
+ ma = memoserv_get_account(hi);
+ if (ma == NULL) {
+ log_module(MS_LOG, LOG_WARNING, "Unable to allocate memory for account %s.", iter_key(it));
+ continue;
+ }
+
+ rd = iter_data(it);
+ if (rd->type == RECDB_QSTRING) {
+ str = rd->d.qstring;
+ } else {
+ log_module(MS_LOG, LOG_WARNING, "Unexpected rectype %d for accounts/%s.", rd->type, iter_key(it));
+ continue;
+ }
+
+ if (str != NULL)
+ ma->flags = strtol(str, NULL, 0);
+ }
+}
+
+static int
+memoserv_saxdb_read(struct dict *db)
+{
+ struct dict *obj;
+
+ obj = database_get_data(db, KEY_ACCOUNTS, RECDB_OBJECT);
+ if (obj == NULL) {
+ return memoserv_saxdb_read_messages(db);
+ } else {
+ memoserv_saxdb_read_accounts(obj);
+ obj = database_get_data(db, KEY_MESSAGES, RECDB_OBJECT);
+ return memoserv_saxdb_read_messages(obj);
+ }
+}
+
static int
memoserv_saxdb_write(struct saxdb_context *ctx)
{
dict_iterator_t it;
struct memo_account *ma;
struct memo *memo;
- char str[7];
+ char str[17];
unsigned int id = 0, ii;
+ saxdb_start_record(ctx, "accounts", 1);
+ for (it = dict_first(memos); it; it = iter_next(it)) {
+ ma = iter_data(it);
+ saxdb_write_int(ctx, ma->handle->handle, ma->flags);
+ }
+ saxdb_end_record(ctx);
+
+ saxdb_start_record(ctx, "messages", 1);
for (it = dict_first(memos); it; it = iter_next(it)) {
ma = iter_data(it);
for (ii = 0; ii < ma->recvd.used; ++ii) {
memo = ma->recvd.list[ii];
- saxdb_start_record(ctx, inttobase64(str, id++, sizeof(str)), 0);
+ snprintf(str, sizeof(str), "%x", id++);
+ saxdb_start_record(ctx, str, 0);
saxdb_write_int(ctx, KEY_SENT, memo->sent);
saxdb_write_string(ctx, KEY_RECIPIENT, memo->recipient->handle->handle);
saxdb_write_string(ctx, KEY_FROM, memo->sender->handle->handle);
saxdb_end_record(ctx);
}
}
+ saxdb_end_record(ctx);
+
return 0;
}