diff options
-rw-r--r-- | facebook/facebook-api.c | 98 | ||||
-rw-r--r-- | facebook/facebook-api.h | 28 | ||||
-rw-r--r-- | facebook/facebook.c | 25 |
3 files changed, 149 insertions, 2 deletions
diff --git a/facebook/facebook-api.c b/facebook/facebook-api.c index 5187c81..39db434 100644 --- a/facebook/facebook-api.c +++ b/facebook/facebook-api.c @@ -343,6 +343,47 @@ static void fb_api_cb_mqtt_connack(fb_mqtt_t *mqtt, gpointer data) } /** + * Handles typing notifications which are to be published to the user. + * + * @param api The #fb_api. + * @param pload The message payload. + **/ +static void fb_api_cb_publish_tn(fb_api_t *api, const GByteArray *pload) +{ + json_value *json; + fb_api_typing_t *typg; + const gchar *str; + gint64 uid; + gint64 state; + + json = fb_api_json_new(api, (gchar*) pload->data, pload->len); + + if (json == NULL) + return; + + if (!fb_json_str_chk(json, "type", &str) || + (g_ascii_strcasecmp(str, "typ") != 0)) + { + goto finish; + } + + if (!fb_json_int_chk(json, "sender_fbid", &uid) || + !fb_json_int_chk(json, "state", &state)) + { + fb_api_error(api, FB_API_ERROR, "Failed to obtain typing state"); + goto finish; + } + + typg = fb_api_typing_new(NULL, state != 0); + typg->uid = g_strdup_printf("%" G_GINT64_FORMAT, uid); + FB_API_FUNC(api, typing, typg); + fb_api_typing_free(typg); + +finish: + json_value_free(json); +} + +/** * Handles message responses which publish the next message queued. * * @param api The #fb_api. @@ -563,7 +604,10 @@ static void fb_api_cb_mqtt_publish(fb_mqtt_t *mqtt, const gchar *topic, fb_util_hexdump(bytes, 2, "Reading message:"); - if (g_ascii_strcasecmp(topic, "/send_message_response") == 0) + + if (g_ascii_strcasecmp(topic, "/orca_typing_notifications") == 0) + fb_api_cb_publish_tn(api, bytes); + else if (g_ascii_strcasecmp(topic, "/send_message_response") == 0) fb_api_cb_publish_mr(api, bytes); else if (g_ascii_strcasecmp(topic, "/t_ms") == 0) fb_api_cb_publish_ms(api, bytes); @@ -950,6 +994,24 @@ void fb_api_publish(fb_api_t *api, const gchar *topic, const gchar *fmt, ...) } /** + * Sends a typing state to a user. + * + * @param api The #fb_api. + * @param uid The target user identifier. + * @param state TRUE if the user is typing, otherwise FALSE. + **/ +void fb_api_typing(fb_api_t *api, const gchar *uid, gboolean state) +{ + g_return_if_fail(api != NULL); + g_return_if_fail(uid != NULL); + + fb_api_publish(api, "/typing", "{" + "\"to\":\"%s\"," + "\"state\":%d" + "}", uid, state != 0); +} + +/** * Creates a new #fb_api_msg. The returned #fb_api_msg should be freed * with #fb_api_msg_free() when no longer needed. * @@ -1019,6 +1081,40 @@ void fb_api_pres_free(fb_api_pres_t *pres) } /** + * Creates a new #fb_api_typing. The returned #fb_api_typing should be + * freed with #fb_api_typing_free() when no longer needed. + * + * @param uid The user identifier. + * @param state TRUE if the user is typing, otherwise FALSE. + * + * @return The #fb_api_typing or NULL on error. + **/ +fb_api_typing_t *fb_api_typing_new(const gchar *uid, gboolean state) +{ + fb_api_typing_t *typg; + + typg = g_new0(fb_api_typing_t, 1); + typg->uid = g_strdup(uid); + typg->state = state; + + return typg; +} + +/** + * Frees all memory used by a #fb_api_typing. + * + * @param typg The #fb_api_typing. + **/ +void fb_api_typing_free(fb_api_typing_t *typg) +{ + if (G_UNLIKELY(typg == NULL)) + return; + + g_free(typg->uid); + g_free(typg); +} + +/** * Creates a new #fb_api_user. The returned #fb_api_user should be * freed with #fb_api_user_free() when no longer needed. * diff --git a/facebook/facebook-api.h b/facebook/facebook-api.h index 0ea0be0..2caace2 100644 --- a/facebook/facebook-api.h +++ b/facebook/facebook-api.h @@ -82,6 +82,9 @@ typedef struct fb_api_msg fb_api_msg_t; /** The structure for representing an #fb_api presence. **/ typedef struct fb_api_pres fb_api_pres_t; +/** The structure for representing an #fb_api user typing state. **/ +typedef struct fb_api_typing fb_api_typing_t; + /** The structure for representing an #fb_api user. **/ typedef struct fb_api_user fb_api_user_t; @@ -159,6 +162,16 @@ struct fb_api_funcs * @param data The user-defined data or NULL. **/ void (*presence) (fb_api_t *api, const GSList *press, gpointer data); + + /** + * The typing function. This is called whenever the #fb_api has + * retrieved a typing state update. + * + * @param api The #fb_api. + * @param typg The #fb_api_typing. + * @param data The user-defined data or NULL. + **/ + void (*typing) (fb_api_t *api, fb_api_typing_t *typg, gpointer data); }; /** @@ -201,6 +214,15 @@ struct fb_api_pres }; /** + * The structure for representing an #fb_api user typing state. + **/ +struct fb_api_typing +{ + gchar *uid; /** The user identifier. **/ + gboolean state; /** TRUE if the user is typing. **/ +}; + +/** * The structure for representing an #fb_api user. **/ struct fb_api_user @@ -234,6 +256,8 @@ void fb_api_message(fb_api_t *api, const gchar *uid, const gchar *msg); void fb_api_publish(fb_api_t *api, const gchar *topic, const gchar *fmt, ...); +void fb_api_typing(fb_api_t *api, const gchar *uid, gboolean state); + fb_api_msg_t *fb_api_msg_new(const gchar *uid, const gchar *text); void fb_api_msg_free(fb_api_msg_t *msg); @@ -242,6 +266,10 @@ fb_api_pres_t *fb_api_pres_new(const gchar *uid, gboolean online); void fb_api_pres_free(fb_api_pres_t *pres); +fb_api_typing_t *fb_api_typing_new(const gchar *uid, gboolean state); + +void fb_api_typing_free(fb_api_typing_t *typg); + fb_api_user_t *fb_api_user_new(const gchar *uid, const gchar *name); void fb_api_user_free(fb_api_user_t *user); diff --git a/facebook/facebook.c b/facebook/facebook.c index 4622ff3..6ab46a3 100644 --- a/facebook/facebook.c +++ b/facebook/facebook.c @@ -139,6 +139,23 @@ static void fb_cb_api_presence(fb_api_t *api, const GSList *press, } /** + * Implemented #fb_api_funcs->typing(). + * + * @param api The #fb_api. + * @param typg The #fb_api_typing. + * @param data The user defined data, which is #fb_data. + **/ +static void fb_cb_api_typing(fb_api_t *api, fb_api_typing_t *typg, + gpointer data) +{ + fb_data_t *fata = data; + guint32 flags; + + flags = typg->state ? OPT_TYPING : 0; + imcb_buddy_typing(fata->ic, typg->uid, flags); +} + +/** * Creates a new #fb_data with an #account. The returned #fb_data * should be freed with #fb_data_free() when no longer needed. * @@ -156,7 +173,8 @@ fb_data_t *fb_data_new(account_t *acc) .connect = fb_cb_api_connect, .contacts = fb_cb_api_contacts, .message = fb_cb_api_message, - .presence = fb_cb_api_presence + .presence = fb_cb_api_presence, + .typing = fb_cb_api_typing }; g_return_val_if_fail(acc != NULL, NULL); @@ -290,6 +308,11 @@ static int fb_buddy_msg(struct im_connection *ic, char *to, char *message, **/ static int fb_send_typing(struct im_connection *ic, char *who, int flags) { + fb_data_t *fata = ic->proto_data; + gboolean state; + + state = (flags & OPT_TYPING) != 0; + fb_api_typing(fata->api, who, state); return 0; } |