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