]> git.0d.be Git - empathy.git/blob - libempathy/empathy-message.c
Add 'original-timestamp' to EmpathyMessage
[empathy.git] / libempathy / empathy-message.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2004-2007 Imendio AB
4  * Copyright (C) 2007-2008 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  *
21  * Authors: Mikael Hallendal <micke@imendio.com>
22  *          Xavier Claessens <xclaesse@gmail.com>
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28
29 #include <glib/gi18n-lib.h>
30
31 #include <telepathy-glib/util.h>
32 #include <telepathy-glib/account.h>
33 #include <telepathy-glib/account-manager.h>
34
35 #include <telepathy-logger/entity.h>
36 #include <telepathy-logger/event.h>
37 #include <telepathy-logger/text-event.h>
38 #ifdef HAVE_CALL_LOGS
39 # include <telepathy-logger/call-event.h>
40 #endif
41
42 #include "empathy-message.h"
43 #include "empathy-utils.h"
44 #include "empathy-enum-types.h"
45
46 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyMessage)
47 typedef struct {
48         TpMessage *tp_message;
49         TpChannelTextMessageType  type;
50         EmpathyContact           *sender;
51         EmpathyContact           *receiver;
52         gchar                    *token;
53         gchar                    *supersedes;
54         gchar                    *body;
55         gint64                    timestamp;
56         gint64                    original_timestamp;
57         gboolean                  is_backlog;
58         guint                     id;
59         gboolean                  incoming;
60         TpChannelTextMessageFlags flags;
61 } EmpathyMessagePriv;
62
63 static void empathy_message_finalize   (GObject            *object);
64 static void message_get_property      (GObject            *object,
65                                        guint               param_id,
66                                        GValue             *value,
67                                        GParamSpec         *pspec);
68 static void message_set_property      (GObject            *object,
69                                        guint               param_id,
70                                        const GValue       *value,
71                                        GParamSpec         *pspec);
72
73 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
74
75 enum {
76         PROP_0,
77         PROP_TYPE,
78         PROP_SENDER,
79         PROP_RECEIVER,
80         PROP_TOKEN,
81         PROP_SUPERSEDES,
82         PROP_BODY,
83         PROP_TIMESTAMP,
84         PROP_ORIGINAL_TIMESTAMP,
85         PROP_IS_BACKLOG,
86         PROP_INCOMING,
87         PROP_FLAGS,
88         PROP_TP_MESSAGE,
89 };
90
91 static void
92 empathy_message_class_init (EmpathyMessageClass *class)
93 {
94         GObjectClass *object_class;
95
96         object_class = G_OBJECT_CLASS (class);
97         object_class->finalize     = empathy_message_finalize;
98         object_class->get_property = message_get_property;
99         object_class->set_property = message_set_property;
100
101         g_object_class_install_property (object_class,
102                                          PROP_TYPE,
103                                          g_param_spec_uint ("type",
104                                                             "Message Type",
105                                                             "The type of message",
106                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
107                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
108                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
109                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
110                                                             G_PARAM_CONSTRUCT_ONLY));
111         g_object_class_install_property (object_class,
112                                          PROP_SENDER,
113                                          g_param_spec_object ("sender",
114                                                               "Message Sender",
115                                                               "The sender of the message",
116                                                               EMPATHY_TYPE_CONTACT,
117                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
118         g_object_class_install_property (object_class,
119                                          PROP_RECEIVER,
120                                          g_param_spec_object ("receiver",
121                                                               "Message Receiver",
122                                                               "The receiver of the message",
123                                                               EMPATHY_TYPE_CONTACT,
124                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
125         g_object_class_install_property (object_class,
126                                          PROP_TOKEN,
127                                          g_param_spec_string ("token",
128                                                               "Message Token",
129                                                               "The message-token",
130                                                               NULL,
131                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
132         g_object_class_install_property (object_class,
133                                          PROP_SUPERSEDES,
134                                          g_param_spec_string ("supersedes",
135                                                               "Supersedes Token",
136                                                               "The message-token this message supersedes",
137                                                               NULL,
138                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
139         g_object_class_install_property (object_class,
140                                          PROP_BODY,
141                                          g_param_spec_string ("body",
142                                                               "Message Body",
143                                                               "The content of the message",
144                                                               NULL,
145                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
146                                                               G_PARAM_CONSTRUCT_ONLY));
147         g_object_class_install_property (object_class,
148                                          PROP_TIMESTAMP,
149                                          g_param_spec_int64 ("timestamp",
150                                                             "timestamp",
151                                                             "timestamp",
152                                                             G_MININT64, G_MAXINT64, 0,
153                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
154                                                             G_PARAM_CONSTRUCT_ONLY));
155         g_object_class_install_property (object_class,
156                                          PROP_ORIGINAL_TIMESTAMP,
157                                          g_param_spec_int64 ("original-timestamp",
158                                                              "Original Timestamp",
159                                                              "Timestamp of the original message",
160                                                              G_MININT64, G_MAXINT64, 0,
161                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
162         g_object_class_install_property (object_class,
163                                          PROP_IS_BACKLOG,
164                                          g_param_spec_boolean ("is-backlog",
165                                                                "History message",
166                                                                "If the message belongs to history",
167                                                                FALSE,
168                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
169                                                                G_PARAM_CONSTRUCT_ONLY));
170
171
172         g_object_class_install_property (object_class,
173                                          PROP_INCOMING,
174                                          g_param_spec_boolean ("incoming",
175                                                                "Incoming",
176                                                                "If this is an incoming (as opposed to sent) message",
177                                                                FALSE,
178                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
179                                                                G_PARAM_CONSTRUCT_ONLY));
180
181         g_object_class_install_property (object_class,
182                                          PROP_FLAGS,
183                                          g_param_spec_uint ("flags",
184                                                                "Flags",
185                                                                "The TpChannelTextMessageFlags of this message",
186                                                                0, G_MAXUINT, 0,
187                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
188                                                                G_PARAM_CONSTRUCT_ONLY));
189
190         g_object_class_install_property (object_class,
191                                          PROP_TP_MESSAGE,
192                                          g_param_spec_object ("tp-message",
193                                                                "TpMessage",
194                                                                "The TpMessage of this message",
195                                                                TP_TYPE_MESSAGE,
196                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
197                                                                G_PARAM_CONSTRUCT_ONLY));
198
199         g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
200
201 }
202
203 static void
204 empathy_message_init (EmpathyMessage *message)
205 {
206         EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
207                 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
208
209         message->priv = priv;
210         priv->timestamp = empathy_time_get_current ();
211 }
212
213 static void
214 empathy_message_finalize (GObject *object)
215 {
216         EmpathyMessagePriv *priv;
217
218         priv = GET_PRIV (object);
219
220         if (priv->sender) {
221                 g_object_unref (priv->sender);
222         }
223         if (priv->receiver) {
224                 g_object_unref (priv->receiver);
225         }
226
227         if (priv->tp_message) {
228                 g_object_unref (priv->tp_message);
229         }
230
231         g_free (priv->token);
232         g_free (priv->supersedes);
233         g_free (priv->body);
234
235         G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
236 }
237
238 static void
239 message_get_property (GObject    *object,
240                       guint       param_id,
241                       GValue     *value,
242                       GParamSpec *pspec)
243 {
244         EmpathyMessagePriv *priv;
245
246         priv = GET_PRIV (object);
247
248         switch (param_id) {
249         case PROP_TYPE:
250                 g_value_set_uint (value, priv->type);
251                 break;
252         case PROP_SENDER:
253                 g_value_set_object (value, priv->sender);
254                 break;
255         case PROP_RECEIVER:
256                 g_value_set_object (value, priv->receiver);
257                 break;
258         case PROP_TOKEN:
259                 g_value_set_string (value, priv->token);
260                 break;
261         case PROP_SUPERSEDES:
262                 g_value_set_string (value, priv->supersedes);
263                 break;
264         case PROP_BODY:
265                 g_value_set_string (value, priv->body);
266                 break;
267         case PROP_TIMESTAMP:
268                 g_value_set_int64 (value, priv->timestamp);
269                 break;
270         case PROP_ORIGINAL_TIMESTAMP:
271                 g_value_set_int64 (value, priv->original_timestamp);
272                 break;
273         case PROP_IS_BACKLOG:
274                 g_value_set_boolean (value, priv->is_backlog);
275                 break;
276         case PROP_INCOMING:
277                 g_value_set_boolean (value, priv->incoming);
278                 break;
279         case PROP_FLAGS:
280                 g_value_set_uint (value, priv->flags);
281                 break;
282         case PROP_TP_MESSAGE:
283                 g_value_set_object (value, priv->tp_message);
284                 break;
285         default:
286                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
287                 break;
288         };
289 }
290
291 static void
292 message_set_property (GObject      *object,
293                       guint         param_id,
294                       const GValue *value,
295                       GParamSpec   *pspec)
296 {
297         EmpathyMessagePriv *priv;
298
299         priv = GET_PRIV (object);
300
301         switch (param_id) {
302         case PROP_TYPE:
303                 priv->type = g_value_get_uint (value);
304                 break;
305         case PROP_SENDER:
306                 empathy_message_set_sender (EMPATHY_MESSAGE (object),
307                                            EMPATHY_CONTACT (g_value_get_object (value)));
308                 break;
309         case PROP_RECEIVER:
310                 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
311                                              EMPATHY_CONTACT (g_value_get_object (value)));
312                 break;
313         case PROP_TOKEN:
314                 g_assert (priv->token == NULL); /* construct only */
315                 priv->token = g_value_dup_string (value);
316                 break;
317         case PROP_SUPERSEDES:
318                 g_assert (priv->supersedes == NULL); /* construct only */
319                 priv->supersedes = g_value_dup_string (value);
320                 break;
321         case PROP_BODY:
322                 g_assert (priv->body == NULL); /* construct only */
323                 priv->body = g_value_dup_string (value);
324                 break;
325         case PROP_TIMESTAMP:
326                 priv->timestamp = g_value_get_int64 (value);
327                 if (priv->timestamp <= 0)
328                         priv->timestamp = empathy_time_get_current ();
329                 break;
330         case PROP_ORIGINAL_TIMESTAMP:
331                 priv->original_timestamp = g_value_get_int64 (value);
332                 break;
333         case PROP_IS_BACKLOG:
334                 priv->is_backlog = g_value_get_boolean (value);
335                 break;
336         case PROP_INCOMING:
337                 priv->incoming = g_value_get_boolean (value);
338                 break;
339         case PROP_FLAGS:
340                 priv->flags = g_value_get_uint (value);
341                 break;
342         case PROP_TP_MESSAGE:
343                 priv->tp_message = g_value_dup_object (value);
344                 break;
345         default:
346                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
347                 break;
348         };
349 }
350
351 EmpathyMessage *
352 empathy_message_from_tpl_log_event (TplEvent *logevent)
353 {
354         EmpathyMessage *retval = NULL;
355         TpAccountManager *acc_man = NULL;
356         TpAccount *account = NULL;
357         TplEntity *receiver = NULL;
358         TplEntity *sender = NULL;
359         gchar *body = NULL;
360         const gchar *token = NULL, *supersedes = NULL;
361         EmpathyContact *contact;
362         TpChannelTextMessageType type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
363         gint64 original_timestamp;
364
365         g_return_val_if_fail (TPL_IS_EVENT (logevent), NULL);
366
367         acc_man = tp_account_manager_dup ();
368         /* FIXME Currently Empathy shows in the log viewer only valid accounts, so it
369          * won't be selected any non-existing (ie removed) account.
370          * When #610455 will be fixed, calling tp_account_manager_ensure_account ()
371          * might add a not existing account to the AM. tp_account_new () probably
372          * will be the best way to handle it.
373          * Note: When creating an EmpathyContact from a TplEntity instance, the
374          * TpAccount is passed *only* to let EmpathyContact be able to retrieve the
375          * avatar (contact_get_avatar_filename () need a TpAccount).
376          * If the way EmpathyContact stores the avatar is changes, it might not be
377          * needed anymore any TpAccount passing and the following call will be
378          * useless */
379         account = tp_account_manager_ensure_account (acc_man,
380                         tpl_event_get_account_path (logevent));
381         g_object_unref (acc_man);
382
383         if (TPL_IS_TEXT_EVENT (logevent)) {
384                 TplTextEvent *textevent = TPL_TEXT_EVENT (logevent);
385
386                 body = g_strdup (tpl_text_event_get_message (textevent));
387
388                 type = tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent));
389                 token = tpl_text_event_get_message_token (textevent);
390                 supersedes = tpl_text_event_get_supersedes_token (textevent);
391
392                 original_timestamp = tpl_text_event_get_original_timestamp (textevent);
393         }
394 #ifdef HAVE_CALL_LOGS
395         else if (TPL_IS_CALL_EVENT (logevent)) {
396                 TplCallEvent *call = TPL_CALL_EVENT (logevent);
397
398                 if (tpl_call_event_get_end_reason (call) == TPL_CALL_END_REASON_NO_ANSWER)
399                         body = g_strdup_printf (_("Missed call from %s"),
400                                 tpl_entity_get_alias (tpl_event_get_sender (logevent)));
401                 else if (tpl_entity_get_entity_type (tpl_event_get_sender (logevent)) == TPL_ENTITY_SELF)
402                         body = g_strdup_printf (_("Called %s"),
403                                 tpl_entity_get_alias (tpl_event_get_receiver (logevent)));
404                 else
405                         body = g_strdup_printf (_("Call from %s"),
406                                 tpl_entity_get_alias (tpl_event_get_sender (logevent)));
407         }
408 #endif
409         else {
410                 /* Unknown event type */
411                 return NULL;
412         }
413
414         receiver = tpl_event_get_receiver (logevent);
415         sender = tpl_event_get_sender (logevent);
416
417         retval = g_object_new (EMPATHY_TYPE_MESSAGE,
418                 "type", type,
419                 "token", token,
420                 "supersedes", supersedes,
421                 "body", body,
422                 "is-backlog", TRUE,
423                 "timestamp", tpl_event_get_timestamp (logevent),
424                 "original-timestamp", original_timestamp,
425                 NULL);
426
427         if (receiver != NULL) {
428                 contact = empathy_contact_from_tpl_contact (account, receiver);
429                 empathy_message_set_receiver (retval, contact);
430                 g_object_unref (contact);
431         }
432
433         if (sender != NULL) {
434                 contact = empathy_contact_from_tpl_contact (account, sender);
435                 empathy_message_set_sender (retval, contact);
436                 g_object_unref (contact);
437         }
438
439         g_free (body);
440
441         return retval;
442 }
443
444 TpMessage *
445 empathy_message_get_tp_message (EmpathyMessage *message)
446 {
447         EmpathyMessagePriv *priv;
448
449         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
450
451         priv = GET_PRIV (message);
452
453         return priv->tp_message;
454 }
455
456 TpChannelTextMessageType
457 empathy_message_get_tptype (EmpathyMessage *message)
458 {
459         EmpathyMessagePriv *priv;
460
461         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
462                               TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
463
464         priv = GET_PRIV (message);
465
466         return priv->type;
467 }
468
469 EmpathyContact *
470 empathy_message_get_sender (EmpathyMessage *message)
471 {
472         EmpathyMessagePriv *priv;
473
474         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
475
476         priv = GET_PRIV (message);
477
478         return priv->sender;
479 }
480
481 void
482 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
483 {
484         EmpathyMessagePriv *priv;
485         EmpathyContact     *old_sender;
486
487         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
488         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
489
490         priv = GET_PRIV (message);
491
492         old_sender = priv->sender;
493         priv->sender = g_object_ref (contact);
494
495         if (old_sender) {
496                 g_object_unref (old_sender);
497         }
498
499         g_object_notify (G_OBJECT (message), "sender");
500 }
501
502 EmpathyContact *
503 empathy_message_get_receiver (EmpathyMessage *message)
504 {
505         EmpathyMessagePriv *priv;
506
507         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
508
509         priv = GET_PRIV (message);
510
511         return priv->receiver;
512 }
513
514 void
515 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
516 {
517         EmpathyMessagePriv *priv;
518         EmpathyContact     *old_receiver;
519
520         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
521         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
522
523         priv = GET_PRIV (message);
524
525         old_receiver = priv->receiver;
526         priv->receiver = g_object_ref (contact);
527
528         if (old_receiver) {
529                 g_object_unref (old_receiver);
530         }
531
532         g_object_notify (G_OBJECT (message), "receiver");
533 }
534
535 const gchar *
536 empathy_message_get_token (EmpathyMessage *message)
537 {
538         EmpathyMessagePriv *priv;
539
540         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
541
542         priv = GET_PRIV (message);
543
544         return priv->token;
545 }
546
547 const gchar *
548 empathy_message_get_supersedes (EmpathyMessage *message)
549 {
550         EmpathyMessagePriv *priv;
551
552         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
553
554         priv = GET_PRIV (message);
555
556         return priv->supersedes;
557 }
558
559 gboolean
560 empathy_message_is_edit (EmpathyMessage *message)
561 {
562         EmpathyMessagePriv *priv;
563
564         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
565
566         priv = GET_PRIV (message);
567
568         return !tp_str_empty (priv->supersedes);
569 }
570
571 const gchar *
572 empathy_message_get_body (EmpathyMessage *message)
573 {
574         EmpathyMessagePriv *priv;
575
576         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
577
578         priv = GET_PRIV (message);
579
580         return priv->body;
581 }
582
583 gint64
584 empathy_message_get_timestamp (EmpathyMessage *message)
585 {
586         EmpathyMessagePriv *priv;
587
588         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
589
590         priv = GET_PRIV (message);
591
592         return priv->timestamp;
593 }
594
595 gint64
596 empathy_message_get_original_timestamp (EmpathyMessage *message)
597 {
598         EmpathyMessagePriv *priv;
599
600         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
601
602         priv = GET_PRIV (message);
603
604         return priv->original_timestamp;
605 }
606
607 gboolean
608 empathy_message_is_backlog (EmpathyMessage *message)
609 {
610         EmpathyMessagePriv *priv;
611
612         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
613
614         priv = GET_PRIV (message);
615
616         return priv->is_backlog;
617 }
618
619 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
620 gboolean
621 empathy_message_should_highlight (EmpathyMessage *message)
622 {
623         EmpathyContact *contact;
624         const gchar   *msg, *to;
625         gchar         *cf_msg, *cf_to;
626         gchar         *ch;
627         gboolean       ret_val;
628         TpChannelTextMessageFlags flags;
629
630         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
631
632         ret_val = FALSE;
633
634         msg = empathy_message_get_body (message);
635         if (!msg) {
636                 return FALSE;
637         }
638
639         contact = empathy_message_get_receiver (message);
640         if (!contact || !empathy_contact_is_user (contact)) {
641                 return FALSE;
642         }
643
644         to = empathy_contact_get_alias (contact);
645         if (!to) {
646                 return FALSE;
647         }
648
649         flags = empathy_message_get_flags (message);
650         if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK) {
651                 /* FIXME: Ideally we shouldn't highlight scrollback messages only if they
652                  * have already been received by the user before (and so are in the logs) */
653                 return FALSE;
654         }
655
656         cf_msg = g_utf8_casefold (msg, -1);
657         cf_to = g_utf8_casefold (to, -1);
658
659         ch = strstr (cf_msg, cf_to);
660         if (ch == NULL) {
661                 goto finished;
662         }
663         if (ch != cf_msg) {
664                 /* Not first in the message */
665                 if (!IS_SEPARATOR (*(ch - 1))) {
666                         goto finished;
667                 }
668         }
669
670         ch = ch + strlen (cf_to);
671         if (ch >= cf_msg + strlen (cf_msg)) {
672                 ret_val = TRUE;
673                 goto finished;
674         }
675
676         if (IS_SEPARATOR (*ch)) {
677                 ret_val = TRUE;
678                 goto finished;
679         }
680
681 finished:
682         g_free (cf_msg);
683         g_free (cf_to);
684
685         return ret_val;
686 }
687
688 TpChannelTextMessageType
689 empathy_message_type_from_str (const gchar *type_str)
690 {
691         if (strcmp (type_str, "normal") == 0) {
692                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
693         }
694         if (strcmp (type_str, "action") == 0) {
695                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
696         }
697         else if (strcmp (type_str, "notice") == 0) {
698                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
699         }
700         else if (strcmp (type_str, "auto-reply") == 0) {
701                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
702         }
703
704         return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
705 }
706
707 const gchar *
708 empathy_message_type_to_str (TpChannelTextMessageType type)
709 {
710         switch (type) {
711         case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
712                 return "action";
713         case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
714                 return "notice";
715         case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
716                 return "auto-reply";
717         case TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT:
718                 return "delivery-report";
719         case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
720         default:
721                 return "normal";
722         }
723 }
724
725 gboolean
726 empathy_message_is_incoming (EmpathyMessage *message)
727 {
728         EmpathyMessagePriv *priv = GET_PRIV (message);
729
730         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
731
732         return priv->incoming;
733 }
734
735 gboolean
736 empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
737 {
738         EmpathyMessagePriv *priv1;
739         EmpathyMessagePriv *priv2;
740
741         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
742         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
743
744         priv1 = GET_PRIV (message1);
745         priv2 = GET_PRIV (message2);
746
747         if (priv1->timestamp == priv2->timestamp &&
748                         !tp_strdiff (priv1->body, priv2->body)) {
749                 return TRUE;
750         }
751
752         return FALSE;
753 }
754
755 TpChannelTextMessageFlags
756 empathy_message_get_flags (EmpathyMessage *self)
757 {
758         EmpathyMessagePriv *priv = GET_PRIV (self);
759
760         g_return_val_if_fail (EMPATHY_IS_MESSAGE (self), 0);
761
762         return priv->flags;
763 }
764
765 EmpathyMessage *
766 empathy_message_new_from_tp_message (TpMessage *tp_msg,
767                                      gboolean incoming)
768 {
769         EmpathyMessage *message;
770         gchar *body;
771         TpChannelTextMessageFlags flags;
772         gint64 original_timestamp;
773         const GHashTable *part = tp_message_peek (tp_msg, 0);
774
775         g_return_val_if_fail (TP_IS_MESSAGE (tp_msg), NULL);
776
777         body = tp_message_to_text (tp_msg, &flags);
778
779         original_timestamp = tp_asv_get_int64 (part,
780                 "original-message-received", NULL);
781
782         message = g_object_new (EMPATHY_TYPE_MESSAGE,
783                 "body", body,
784                 "token", tp_message_get_token (tp_msg),
785                 "supersedes", tp_message_get_supersedes (tp_msg),
786                 "type", tp_message_get_message_type (tp_msg),
787                 "timestamp", tp_message_get_received_timestamp (tp_msg),
788                 "original-timestamp", original_timestamp,
789                 "flags", flags,
790                 "is-backlog", flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK,
791                 "incoming", incoming,
792                 "tp-message", tp_msg,
793                 NULL);
794
795         g_free (body);
796         return message;
797 }