pidgin/purple-plugin-pack

165442c46226
Prepping for a release that's only about 15 months or so overdue.
/*--------------------------------------------------------------------------*
* AUTOPROFILE *
* *
* A Purple away message and profile manager that supports dynamic text *
* *
* AutoProfile is the legal property of its developers. Please refer to *
* the COPYRIGHT file distributed with this source distribution. *
* *
* This program 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
*--------------------------------------------------------------------------*/
#include "autoprofile.h"
#include "log.h"
#include "account.h"
#include "conversation.h"
#include "utility.h"
#include "util.h"
#include "comp_logstats.h"
#include <ctype.h>
#include <string.h>
struct conversation_time {
time_t *start_time;
char *name;
};
/* Represents data about a particular 24 hour period in the logs */
struct log_date {
int year; // The year
int month; // The month
int day; // The day
int received_msgs; // # msgs received
int received_words; // # words received
int sent_msgs; // # msgs sent
int sent_words; // # words sent
GSList *conversation_times; // List of conversation_time pointers
};
/* List of struct log_dates
This is SORTED by most recent first */
static GSList *dates = NULL;
/* Hashtable of log_dates */
static GHashTable *dates_table = NULL;
/* Is the current line part of a message sent or received? */
static gboolean receiving = FALSE;
/* Shortcut vars */
static char *cur_receiver = NULL;
static char *cur_sender = NULL;
/* Implements GCompareFunc */
static gint conversation_time_compare (gconstpointer x, gconstpointer y) {
const struct conversation_time *a = x;
const struct conversation_time *b = y;
if (difftime (*(a->start_time), *(b->start_time)) == 0.0) {
if (!strcmp (a->name, b->name))
return 0;
}
return -1;
}
/* Implements GCompareFunc */
static gint log_date_compare (gconstpointer x, gconstpointer y)
{
const struct log_date *a = y;
const struct log_date *b = x;
if (a->year == b->year) {
if (a->month == b->month) {
if (a->day == b->day)
return 0;
else
return a->day - b->day;
} else {
return a->month - b->month;
}
} else {
return a->year - b->year;
}
}
/* Implements GHashFunc */
static guint log_date_hash (gconstpointer key)
{
const struct log_date *d = key;
return ((d->year * 365) + (d->month * 12) + (d->day));
}
/* Implements GEqualFunc */
static gboolean log_date_equal (gconstpointer x, gconstpointer y)
{
const struct log_date *a = y;
const struct log_date *b = x;
if (a->year == b->year &&
a->month == b->month &&
a->day == b->day) {
return TRUE;
}
return FALSE;
}
/* Returns the struct log_date associated with a particular date.
Will MODIFY list of dates and insert sorted if not yet created */
static struct log_date *get_date (int year, int month, int day)
{
struct log_date *cur_date;
gpointer *node;
cur_date = (struct log_date *)malloc(sizeof(struct log_date));
cur_date->year = year;
cur_date->month = month;
cur_date->day = day;
if ((node = g_hash_table_lookup (dates_table, cur_date))) {
free (cur_date);
return (struct log_date *)node;
} else {
g_hash_table_insert (dates_table, cur_date, cur_date);
cur_date->received_msgs = 0;
cur_date->received_words = 0;
cur_date->sent_msgs = 0;
cur_date->sent_words = 0;
cur_date->conversation_times = NULL;
return cur_date;
}
}
/* Like get_date, except specific to the current date */
static struct log_date *get_today ()
{
time_t the_time;
struct tm *cur_time;
time (&the_time);
cur_time = localtime (&the_time);
return get_date (cur_time->tm_year, cur_time->tm_mon, cur_time->tm_mday);
}
static int string_word_count (const char *line)
{
int count, state;
count = 0;
state = 0;
/* If state is 1, currently processing a word */
while (*line) {
if (state == 0) {
if (!isspace (*line))
state = 1;
} else {
if (isspace (*line)) {
state = 0;
count++;
}
}
line++;
}
if (state == 1)
count++;
return count;
}
/* Figure out if a person is yourself or someone else */
static gboolean is_self (PurpleAccount *a, const char *name) {
GList *accounts, *aliases, *aliases_start;
PurpleAccount *account;
char *normalized;
const char *normalized_alias;
if (cur_sender && !strcmp (cur_sender, name)) {
return TRUE;
}
if (cur_receiver && !strcmp (cur_receiver, name)) {
return FALSE;
}
normalized = strdup (purple_normalize (a, name));
accounts = purple_accounts_get_all ();
aliases_start = aliases = purple_prefs_get_string_list (
"/plugins/gtk/autoprofile/components/logstat/aliases");
while (aliases) {
normalized_alias = purple_normalize (a, (char *)aliases->data);
if (!strcmp (normalized, normalized_alias)) {
free_string_list (aliases_start);
free (normalized);
if (cur_sender)
free (cur_sender);
cur_sender = strdup (name);
return TRUE;
}
aliases = aliases->next;
}
free_string_list (aliases_start);
while (accounts) {
account = (PurpleAccount *)accounts->data;
if (!strcmp (normalized, purple_account_get_username (account))) {
free (normalized);
if (cur_sender)
free (cur_sender);
cur_sender = strdup (name);
return TRUE;
}
accounts = accounts->next;
}
free (normalized);
if (cur_receiver)
free (cur_receiver);
cur_receiver = strdup (name);
return FALSE;
}
/* Parses a line of a conversation */
static void parse_line (PurpleLog *cur_log, char *l, struct log_date *d)
{
char *cur_line, *cur_line_start;
char *name;
char *message;
char *line = l;
if (strlen (line) > 14 && *line == ' ')
line++;
if (strlen (line) > 13 &&
*line == '(' &&
isdigit (*(line + 1)) &&
isdigit (*(line + 2)) &&
*(line + 3) == ':' &&
isdigit (*(line + 4)) &&
isdigit (*(line + 5)) &&
*(line + 6) == ':' &&
isdigit (*(line + 7)) &&
isdigit (*(line + 8)) &&
*(line + 9) == ')' &&
isspace (*(line + 10))) {
cur_line_start = cur_line = line + 11;
while (*cur_line) {
if (*cur_line == ':') {
*cur_line = '\0';
name = cur_line_start;
message = ++cur_line;
receiving = !is_self (cur_log->account, name);
if (receiving) {
d->received_msgs++;
d->received_words += string_word_count (message);
} else {
d->sent_msgs++;
d->sent_words += string_word_count (message);
}
return;
}
cur_line++;
}
}
if (receiving) {
d->received_words += string_word_count (line);
} else {
d->sent_words += string_word_count (line);
}
}
/* Parses a conversation if hasn't been handled yet */
static void parse_log (PurpleLog *cur_log)
{
struct log_date *the_date;
struct tm *the_time;
struct conversation_time *conv_time;
PurpleLogReadFlags flags;
char *content, *cur_content, *cur_content_start, *temp;
the_time = localtime (&(cur_log->time));
the_date = get_date (the_time->tm_year, the_time->tm_mon, the_time->tm_mday);
/* Check for old log and if no conflicts, add to list */
conv_time = (struct conversation_time *)malloc (
sizeof (struct conversation_time));
conv_time->start_time = (time_t *)malloc (sizeof(time_t));
*(conv_time->start_time) = cur_log->time;
conv_time->name = strdup (cur_log->name);
if (g_slist_find_custom (the_date->conversation_times, conv_time,
conversation_time_compare)) {
/* We already processed this! Halt! */
free (conv_time->start_time);
free (conv_time->name);
free (conv_time);
return;
}
the_date->conversation_times = g_slist_prepend (the_date->conversation_times,
conv_time);
/* Start rolling the counters! */
temp = purple_log_read (cur_log, &flags);
if (!strcmp ("html", cur_log->logger->id)) {
content = purple_markup_strip_html (temp);
free (temp);
} else {
content = temp;
}
cur_content_start = cur_content = content;
/* Splits the conversation into lines (each line may not necessarily
be a seperate message */
while (*cur_content) {
if (*cur_content == '\n') {
*cur_content = '\0';
parse_line (cur_log, cur_content_start, the_date);
cur_content_start = cur_content + 1;
}
cur_content++;
}
parse_line (cur_log, cur_content_start, the_date);
free (content);
}
/* Get names of users in logs */
static GList *logstats_get_names (PurpleLogType type, PurpleAccount *account)
{
GDir *dir;
const char *prpl;
GList *ret;
const char *filename;
char *path, *me, *tmp;
ret = NULL;
if (type == PURPLE_LOG_CHAT)
me = g_strdup_printf ("%s.chat", purple_normalize(account,
purple_account_get_username(account)));
else
me = g_strdup (purple_normalize(account,
purple_account_get_username(account)));
/* Get the old logger names */
path = g_build_filename(purple_user_dir(), "logs", NULL);
if (!(dir = g_dir_open(path, 0, NULL))) {
g_free(path);
return ret;
}
while ((filename = g_dir_read_name (dir))) {
if (purple_str_has_suffix (filename, ".log")) {
tmp = strdup (filename);
*(tmp + strlen (filename) - 4) = '\0';
if (!string_list_find (ret, tmp))
ret = g_list_prepend (ret, strdup (tmp));
free (tmp);
}
}
g_dir_close (dir);
g_free (path);
/* Get the account-specific names */
prpl = PURPLE_PLUGIN_PROTOCOL_INFO
(purple_find_prpl (purple_account_get_protocol_id(account)))->list_icon(
account, NULL);
path = g_build_filename(purple_user_dir(), "logs", prpl, me, NULL);
g_free (me);
if (!(dir = g_dir_open(path, 0, NULL))) {
g_free(path);
return ret;
}
while ((filename = g_dir_read_name (dir))) {
if (!string_list_find (ret, filename))
ret = g_list_prepend (ret, strdup (filename));
}
g_dir_close (dir);
g_free (path);
return ret;
}
/* On load, reads in all logs and initializes stats database */
static void logstats_read_logs ()
{
GList *accounts, *logs, *logs_start, *names, *names_start;
PurpleLog *cur_log;
accounts = purple_accounts_get_all();
ap_debug ("logstats", "parsing log files");
while (accounts) {
names_start = names = logstats_get_names (PURPLE_LOG_IM,
(PurpleAccount *)accounts->data);
while (names) {
logs_start = purple_log_get_logs (PURPLE_LOG_IM, (char *)names->data,
(PurpleAccount *)accounts->data);
logs = logs_start;
while (logs) {
cur_log = (PurpleLog *)logs->data;
parse_log (cur_log);
purple_log_free (cur_log);
logs = logs->next;
}
g_list_free (logs_start);
names = names->next;
}
free_string_list (names_start);
accounts = accounts->next;
}
/* Cleanup */
ap_debug ("logstats", "finished parsing log files");
}
/* Implements GHFunc */
static void add_element (gpointer key, gpointer value, gpointer data)
{
dates = g_slist_insert_sorted (dates, value, log_date_compare);
}
/* Updates GList against hashtable */
static void logstats_update_dates ()
{
g_slist_free (dates);
dates = NULL;
g_hash_table_foreach (dates_table, add_element, NULL);
}
/*--------------------- Total calculations -------------------*/
static int get_total (const char *field)
{
GSList *cur_day;
int count;
struct log_date *d;
cur_day = dates;
count = 0;
while (cur_day) {
d = (struct log_date *)cur_day->data;
if (!strcmp (field, "received_msgs")) {
count += d->received_msgs;
} else if (!strcmp (field, "received_words")) {
count += d->received_words;
} else if (!strcmp (field, "sent_msgs")) {
count += d->sent_msgs;
} else if (!strcmp (field, "sent_words")) {
count += d->sent_words;
} else if (!strcmp (field, "num_convos")) {
count += g_slist_length (d->conversation_times);
}
cur_day = cur_day->next;
}
return count;
}
static int get_recent_total (const char *field, int hours)
{
GSList *cur_day;
int count;
struct log_date *d;
time_t cur_day_time;
cur_day = dates;
count = 0;
while (cur_day) {
d = (struct log_date *)cur_day->data;
cur_day_time = purple_time_build (d->year + 1900, d->month + 1, d->day,
0, 0, 0);
if (difftime (time (NULL), cur_day_time) > (double) hours * 60.0 * 60.0)
break;
if (!strcmp (field, "received_msgs")) {
count += d->received_msgs;
} else if (!strcmp (field, "sent_msgs")) {
count += d->sent_msgs;
} else if (!strcmp (field, "num_convos")) {
count += g_slist_length (d->conversation_times);
}
cur_day = cur_day->next;
}
return count;
}
static int num_days_since_start ()
{
GSList *first_day;
double difference;
struct log_date *d;
first_day = g_slist_last (dates);
if (!first_day)
return 0;
d = (struct log_date *)first_day->data;
difference = difftime (
time (NULL), purple_time_build (d->year + 1900, d->month + 1, d->day,
0, 0, 0));
return (int) difference / (60.0 * 60.0 * 24.0);
}
static struct log_date *get_max_date (const char *field)
{
struct log_date *max_date, *cur_date;
int max_so_far, cur_max;
GSList *cur_day;
max_so_far = 0;
max_date = NULL;
cur_day = dates;
while (cur_day) {
cur_date = (struct log_date *)cur_day->data;
if (!strcmp (field, "conversations")) {
cur_max = g_slist_length (cur_date->conversation_times);
} else if (!strcmp (field, "received")) {
cur_max = cur_date->received_msgs;
} else if (!strcmp (field, "sent")) {
cur_max = cur_date->sent_msgs;
} else if (!strcmp (field, "total")) {
cur_max = cur_date->sent_msgs + cur_date->received_msgs;
} else {
cur_max = 0;
}
if (cur_max >= max_so_far) {
max_date = cur_date;
max_so_far = cur_max;
}
cur_day = cur_day->next;
}
return max_date;
}
static char *date_string (const char *field)
{
struct log_date *d;
char *output;
struct tm *t_struct;
time_t t;
GSList *last_day;
last_day = g_slist_last (dates);
if (!last_day)
return NULL;
if (!strcmp (field, "first")) {
d = (struct log_date *) last_day->data;
} else {
d = get_max_date (field);
}
if (!d)
return NULL;
output = (char *)malloc (sizeof(char) * AP_SIZE_MAXIMUM);
t_struct = (struct tm *)malloc(sizeof(struct tm));
t_struct->tm_year = d->year;
t_struct->tm_mon = d->month;
t_struct->tm_mday = d->day;
t_struct->tm_sec = 0;
t_struct->tm_min = 0;
t_struct->tm_hour = 0;
t = mktime (t_struct);
free (t_struct);
t_struct = localtime (&t);
strftime (output, AP_SIZE_MAXIMUM - 1, "%a %b %d, %Y", t_struct);
return output;
}
static int get_max (const char *field)
{
struct log_date *max_date = get_max_date (field);
if (!max_date)
return 0;
if (!strcmp (field, "conversations")) {
return g_slist_length (max_date->conversation_times);
} else if (!strcmp (field, "received")) {
return max_date->received_msgs;
} else if (!strcmp (field, "sent")) {
return max_date->sent_msgs;
} else if (!strcmp (field, "total")) {
return max_date->sent_msgs + max_date->received_msgs;
} else {
ap_debug ("logstats", "get-max: invalid parameter");
return 0;
}
}
/*--------------------- Signal handlers ----------------------*/
static void logstats_received_im (PurpleAccount *account, char *sender,
char *message, int flags)
{
struct log_date *the_date;
the_date = get_today ();
the_date->received_msgs++;
the_date->received_words += string_word_count (message);
receiving = TRUE;
}
static void logstats_sent_im (PurpleAccount *account, const char *receiver,
const char *message)
{
struct log_date *the_date;
the_date = get_today ();
the_date->sent_msgs++;
the_date->sent_words += string_word_count (message);
receiving = FALSE;
}
static void logstats_conv_created (PurpleConversation *conv)
{
struct log_date *the_date;
struct conversation_time *the_time;
if (conv->type == PURPLE_CONV_TYPE_IM) {
the_time = malloc (sizeof(struct conversation_time));
the_time->name = strdup (conv->name);
the_time->start_time = malloc (sizeof(time_t));
time (the_time->start_time);
the_date = get_today ();
the_date->conversation_times = g_slist_prepend (
the_date->conversation_times, the_time);
logstats_update_dates ();
}
}
/*--------------------------- Main functions -------------------------*/
/* Component load */
void logstats_load (struct widget *w)
{
int count;
char *msg;
if (!purple_prefs_get_bool (
"/plugins/gtk/autoprofile/components/logstat/enabled")) {
return;
}
/* Initialize database */
dates_table = g_hash_table_new (log_date_hash, log_date_equal);
logstats_read_logs ();
logstats_update_dates ();
/* Debug */
msg = (char *)malloc (sizeof(char) * AP_SIZE_MAXIMUM);
count = get_total ("received_msgs");
g_snprintf (msg, AP_SIZE_MAXIMUM, "received msg total is %d", count);
ap_debug ("logstats", msg);
count = get_total ("sent_msgs");
g_snprintf (msg, AP_SIZE_MAXIMUM, "sent msg total is %d", count);
ap_debug ("logstats", msg);
count = get_total ("received_words");
g_snprintf (msg, AP_SIZE_MAXIMUM, "received word total is %d", count);
ap_debug ("logstats", msg);
count = get_total ("sent_words");
g_snprintf (msg, AP_SIZE_MAXIMUM, "sent word total is %d", count);
ap_debug ("logstats", msg);
count = get_total ("num_convos");
g_snprintf (msg, AP_SIZE_MAXIMUM, "num conversations is %d", count);
ap_debug ("logstats", msg);
count = g_slist_length (dates);
g_snprintf (msg, AP_SIZE_MAXIMUM, "num days with conversations is %d", count);
ap_debug ("logstats", msg);
free(msg);
/* Connect signals */
purple_signal_connect (purple_conversations_get_handle (),
"received-im-msg", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_received_im), NULL);
purple_signal_connect (purple_conversations_get_handle (),
"sent-im-msg", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_sent_im), NULL);
purple_signal_connect (purple_conversations_get_handle (),
"conversation-created", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_conv_created), NULL);
}
/* Component unload */
void logstats_unload (struct widget *w)
{
struct log_date *cur_date;
struct conversation_time *cur_time;
GSList *temp;
if (!purple_prefs_get_bool (
"/plugins/gtk/autoprofile/components/logstat/enabled")) {
return;
}
/* Disconnect signals */
purple_signal_disconnect (purple_conversations_get_handle (),
"received-im-msg", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_received_im));
purple_signal_disconnect (purple_conversations_get_handle (),
"sent-im-msg", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_sent_im));
purple_signal_disconnect (purple_conversations_get_handle (),
"conversation-created", ap_get_plugin_handle (),
PURPLE_CALLBACK (logstats_conv_created));
logstats_update_dates ();
/* Free all the memory */
while (dates) {
cur_date = (struct log_date *)dates->data;
while (cur_date->conversation_times) {
temp = cur_date->conversation_times;
cur_time = (struct conversation_time *)temp->data;
cur_date->conversation_times = temp->next;
free (cur_time->start_time);
free (cur_time->name);
free (cur_time);
g_slist_free_1 (temp);
}
free (cur_date);
temp = dates;
dates = dates->next;
g_slist_free_1 (temp);
}
if (cur_receiver) {
free (cur_receiver);
cur_receiver = NULL;
}
if (cur_sender) {
free (cur_sender);
cur_sender = NULL;
}
g_hash_table_destroy (dates_table);
dates_table = NULL;
}
/* Generate the output */
static char *logstats_generate (struct widget *w)
{
char *buf, *output, *date;
int state;
const char *format;
if (!purple_prefs_get_bool (
"/plugins/gtk/autoprofile/components/logstat/enabled")) {
return NULL;
}
format = purple_prefs_get_string (
"/plugins/gtk/autoprofile/components/logstat/format");
output = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
*output = '\0';
buf = (char *)malloc (sizeof(char)*AP_SIZE_MAXIMUM);
*buf = '\0';
state = 0;
while (*format) {
if (state == 1) {
switch (*format) {
case '%':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
break;
case 'R':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("received_msgs"));
break;
case 'r':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("received_words"));
break;
case 'S':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("sent_msgs"));
break;
case 's':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("sent_words"));
break;
case 'T':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
get_total ("sent_msgs") + get_total ("received_msgs"));
break;
case 't':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
get_total ("sent_words") + get_total ("received_words"));
break;
case 'D':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
num_days_since_start ());
break;
case 'd':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, g_slist_length (dates));
break;
case 'N':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_total ("num_convos"));
break;
case 'n':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("num_convos") / (double) g_slist_length (dates));
break;
case 'i':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("conversations"));
break;
case 'I':
date = date_string ("conversations");
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
free (date);
break;
case 'j':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("sent"));
break;
case 'J':
date = date_string ("sent");
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
free (date);
break;
case 'k':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("received"));
break;
case 'K':
date = date_string ("received");
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
free (date);
break;
case 'l':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_max ("total"));
break;
case 'L':
date = date_string ("total");
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
free (date);
break;
case 'f':
date = date_string ("first");
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%s", output, date);
free (date);
break;
case 'u':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("received_words") / (double) get_total ("received_msgs"));
break;
case 'v':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("sent_words") / (double) get_total ("sent_msgs"));
break;
case 'w':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) (get_total ("received_words") + get_total ("sent_words")) / (double) (get_total("received_msgs") + get_total ("sent_msgs")));
break;
case 'U':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("received_msgs") / (double) get_total ("num_convos"));
break;
case 'V':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("sent_msgs") / (double) get_total ("num_convos"));
break;
case 'W':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) (get_total ("received_msgs") + get_total ("sent_msgs")) / (double) get_total("num_convos"));
break;
case 'x':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("received_words") / (double) g_slist_length (dates));
break;
case 'y':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("sent_words") / (double) g_slist_length (dates));
break;
case 'z':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
((double) get_total ("received_words") + (double) get_total ("sent_words")) / (double) g_slist_length (dates));
break;
case 'X':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("received_msgs") / (double) g_slist_length (dates));
break;
case 'Y':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) get_total ("sent_msgs") / (double) g_slist_length (dates));
break;
case 'Z':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.2f", output,
(double) (get_total ("received_msgs") + get_total ("sent_msgs")) / (double) g_slist_length (dates));
break;
case 'p':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%.1f", output,
100.0 * (double) g_slist_length (dates) / (double) num_days_since_start ());
break;
case 'a':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
((struct log_date *) dates->data)->received_msgs);
break;
case 'b':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
((struct log_date *) dates->data)->sent_msgs);
break;
case 'c':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
g_slist_length (((struct log_date *) dates->data)->conversation_times));
break;
case 'e':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
((struct log_date *) dates->data)->sent_msgs + ((struct log_date *) dates->data)->received_msgs);
break;
case 'A':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("received_msgs", 24 * 7));
break;
case 'B':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("sent_msgs", 24 * 7));
break;
case 'C':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output, get_recent_total ("num_convos", 24 * 7));
break;
case 'E':
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%d", output,
get_recent_total ("received_msgs", 24 * 7) + get_recent_total ("received_msgs", 24 * 7));
break;
default:
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
break;
}
strcpy (output, buf);
format++;
state = 0;
} else {
if (*format == '%') {
state = 1;
} else {
g_snprintf (buf, AP_SIZE_MAXIMUM, "%s%c", output, *format);
strcpy (output, buf);
}
format++;
}
}
free (buf);
return output;
}
/* Initialize preferences */
static void logstats_init (struct widget *w)
{
purple_prefs_add_none ("/plugins/gtk/autoprofile/components/logstat");
purple_prefs_add_bool (
"/plugins/gtk/autoprofile/components/logstat/enabled", FALSE);
purple_prefs_add_string (
"/plugins/gtk/autoprofile/components/logstat/format", "");
purple_prefs_add_string_list (
"/plugins/gtk/autoprofile/components/logstat/aliases", NULL);
}
/* The heart of the component */
static char *identifiers [7] = {
N_("logs"),
N_("log"),
N_("stat"),
N_("stats"),
N_("logstats"),
N_("log statistics"),
NULL
};
struct component logstats =
{
N_("Purple log statistics"),
N_("Display various statistics about your message and system logs"),
identifiers,
logstats_generate,
logstats_init,
logstats_load,
logstats_unload,
NULL,
logstats_prefs
};