diff --git a/matrix-api.c b/matrix-api.c index a8528ce..18b365c 100644 --- a/matrix-api.c +++ b/matrix-api.c @@ -846,6 +846,48 @@ MatrixApiRequestData *matrix_api_download_file(MatrixConnectionData *conn, return fetch_data; } +/** + * Download a thumbnail for a file + * @param uri URI string in the form mxc://example.com/unique + */ +MatrixApiRequestData *matrix_api_download_thumb(MatrixConnectionData *conn, + const gchar *uri, + gsize max_size, + unsigned int width, unsigned int height, gboolean scale, + MatrixApiCallback callback, + MatrixApiErrorCallback error_callback, + MatrixApiBadResponseCallback bad_response_callback, + gpointer user_data) +{ + GString *url; + MatrixApiRequestData *fetch_data; + char tmp[64]; + + /* Sanity check the uri - TODO: Add more sanity */ + if (strncmp(uri, "mxc://", 6)) { + error_callback(conn, user_data, "bad media uri"); + return NULL; + } + url = g_string_new(conn->homeserver); + g_string_append(url, "_matrix/media/r0/thumbnail/"); + g_string_append(url, uri + 6); /* i.e. after the mxc:// */ + sprintf(tmp, "?width=%u", width); + g_string_append(url, tmp); + sprintf(tmp, "&height=%u", height); + g_string_append(url, tmp); + g_string_append(url, scale ? "&method=scale": "&method=crop"); + + /* I'd like to validate the headers etc a bit before downloading the + * data (maybe using _handle_header_completed), also I'm not convinced + * purple always does sane things on over-size. + */ + fetch_data = matrix_api_start(url->str, "GET", NULL, conn, callback, + error_callback, bad_response_callback, user_data, max_size); + g_string_free(url, TRUE); + + return fetch_data; +} + #if 0 MatrixApiRequestData *matrix_api_get_room_state(MatrixConnectionData *conn, const gchar *room_id, diff --git a/matrix-api.h b/matrix-api.h index 4245cd7..8448af5 100644 --- a/matrix-api.h +++ b/matrix-api.h @@ -277,6 +277,34 @@ MatrixApiRequestData *matrix_api_download_file(MatrixConnectionData *conn, MatrixApiBadResponseCallback bad_response_callback, gpointer user_data); +/** + * Download a thumbnail for a file + * + * @param conn The connection with which to make the request + * @param uri The Matrix uri to fetch starting mxc:// + * @param max_size A maximum size of file to receive. + * @param width Desired width; the server might not obey + * @param height Desired height; the server might not obey + * @param scale True to scale, false to crop + * @param callback Function to be called when the request completes + * @param error_callback Function to be called if there is an error making + * the request. If NULL, matrix_api_error will be + * used. + * @param bad_response_callback Function to be called if the API gives a non-200 + * response. If NULL, matrix_api_bad_response will be + * used. + * @param user_data Opaque data to be passed to the callbacks + * + */ +MatrixApiRequestData *matrix_api_download_thumb(MatrixConnectionData *conn, + const gchar *uri, + gsize max_size, + unsigned int width, unsigned int height, gboolean scale, + MatrixApiCallback callback, + MatrixApiErrorCallback error_callback, + MatrixApiBadResponseCallback bad_response_callback, + gpointer user_data); + #if 0 /** * Get the current state of a room diff --git a/matrix-room.c b/matrix-room.c index ab631af..86dcf89 100644 --- a/matrix-room.c +++ b/matrix-room.c @@ -600,6 +600,7 @@ static gboolean _handle_incoming_image(PurpleConversation *conv, MatrixConnectionData *conn = _get_connection_data_from_conversation(conv); MatrixApiRequestData *fetch_data = NULL; struct ReceiveImageData *rid; + gboolean use_thumb = FALSE; const gchar *url; JsonObject *json_info_object; @@ -625,9 +626,7 @@ static gboolean _handle_incoming_image(PurpleConversation *conv, /* OK, we've got some (optional) info on the image */ size = matrix_json_object_get_int_member(json_info_object, "size"); if (size > purple_max_image_size) { - purple_debug_info("matrixprpl", "image too large %" PRId64 "\n", size); - /* TODO: Switch to a thumbnail */ - return FALSE; + use_thumb = TRUE; } mime_type = matrix_json_object_get_string_member(json_info_object, "mimetype"); @@ -649,10 +648,26 @@ static gboolean _handle_incoming_image(PurpleConversation *conv, rid->room_id = room_id; rid->original_body = g_strdup(msg_body); - fetch_data = matrix_api_download_file(conn, url, purple_max_image_size, - _image_download_complete, - _image_download_error, - _image_download_bad_response, rid); + if (!use_thumb) { + fetch_data = matrix_api_download_file(conn, url, + purple_max_image_size, + _image_download_complete, + _image_download_error, + _image_download_bad_response, rid); + } else { + /* TODO: Configure the size of thumbnails, and provide + * a way for the user to get the full image if they want. + * 640x480 is a good a width as any and reasonably likely to + * fit in the byte size limit unless someone has a big long + * tall png. + */ + fetch_data = matrix_api_download_thumb(conn, url, + purple_max_image_size, + 640, 480, TRUE, /* Scaled */ + _image_download_complete, + _image_download_error, + _image_download_bad_response, rid); + } purple_conversation_set_data(conv, PURPLE_CONV_DATA_ACTIVE_SEND, fetch_data);