Add support for link preview descriptions.

This commit is contained in:
Greyson Parrelli
2020-08-25 16:05:39 -04:00
committed by GitHub
parent a3438c4f8d
commit c78e098cb4
19 changed files with 151 additions and 58 deletions

View File

@@ -22,45 +22,56 @@ public class LinkPreview {
@JsonProperty
private final String title;
@JsonProperty
private final String description;
@JsonProperty
private final AttachmentId attachmentId;
@JsonIgnore
private final Optional<Attachment> thumbnail;
public LinkPreview(@NonNull String url, @NonNull String title, @NonNull DatabaseAttachment thumbnail) {
public LinkPreview(@NonNull String url, @NonNull String title, @NonNull String description, @NonNull DatabaseAttachment thumbnail) {
this.url = url;
this.title = title;
this.description = description;
this.thumbnail = Optional.of(thumbnail);
this.attachmentId = thumbnail.getAttachmentId();
}
public LinkPreview(@NonNull String url, @NonNull String title, @NonNull Optional<Attachment> thumbnail) {
public LinkPreview(@NonNull String url, @NonNull String title, @NonNull String description, @NonNull Optional<Attachment> thumbnail) {
this.url = url;
this.title = title;
this.description = description;
this.thumbnail = thumbnail;
this.attachmentId = null;
}
public LinkPreview(@JsonProperty("url") @NonNull String url,
@JsonProperty("title") @NonNull String title,
@JsonProperty("description") @Nullable String description,
@JsonProperty("attachmentId") @Nullable AttachmentId attachmentId)
{
this.url = url;
this.title = title;
this.description = Optional.fromNullable(description).or("");
this.attachmentId = attachmentId;
this.thumbnail = Optional.absent();
}
public String getUrl() {
public @NonNull String getUrl() {
return url;
}
public String getTitle() {
public @NonNull String getTitle() {
return title;
}
public Optional<Attachment> getThumbnail() {
public @NonNull String getDescription() {
return description;
}
public @NonNull Optional<Attachment> getThumbnail() {
return thumbnail;
}
@@ -68,11 +79,11 @@ public class LinkPreview {
return attachmentId;
}
public String serialize() throws IOException {
public @NonNull String serialize() throws IOException {
return JsonUtils.toJson(this);
}
public static LinkPreview deserialize(@NonNull String serialized) throws IOException {
public static @NonNull LinkPreview deserialize(@NonNull String serialized) throws IOException {
return JsonUtils.fromJson(serialized, LinkPreview.class);
}
}

View File

@@ -105,7 +105,7 @@ public class LinkPreviewRepository {
}
if (!metadata.getImageUrl().isPresent()) {
callback.onSuccess(new LinkPreview(url, metadata.getTitle().get(), Optional.absent()));
callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), metadata.getDescription().or(""), Optional.absent()));
return;
}
@@ -113,7 +113,7 @@ public class LinkPreviewRepository {
if (!metadata.getTitle().isPresent() && !attachment.isPresent()) {
callback.onError(Error.PREVIEW_NOT_AVAILABLE);
} else {
callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), attachment));
callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), metadata.getDescription().or(""), attachment));
}
});
@@ -147,17 +147,18 @@ public class LinkPreviewRepository {
return;
}
String body = OkHttpUtil.readAsString(response.body(), FAILSAFE_MAX_TEXT_SIZE);
OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(body);
Optional<String> title = openGraph.getTitle();
Optional<String> imageUrl = openGraph.getImageUrl();
String body = OkHttpUtil.readAsString(response.body(), FAILSAFE_MAX_TEXT_SIZE);
OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(body);
Optional<String> title = openGraph.getTitle();
Optional<String> description = openGraph.getDescription();
Optional<String> imageUrl = openGraph.getImageUrl();
if (imageUrl.isPresent() && !LinkPreviewUtil.isValidPreviewUrl(imageUrl.get())) {
Log.i(TAG, "Image URL was invalid or for a non-whitelisted domain. Skipping.");
imageUrl = Optional.absent();
}
callback.accept(new Metadata(title, imageUrl));
callback.accept(new Metadata(title, description, imageUrl));
}
});
@@ -225,7 +226,7 @@ public class LinkPreviewRepository {
Optional<Attachment> thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP);
callback.onSuccess(new LinkPreview(packUrl, title, thumbnail));
callback.onSuccess(new LinkPreview(packUrl, title, "", thumbnail));
} else {
callback.onError(Error.PREVIEW_NOT_AVAILABLE);
}
@@ -268,7 +269,7 @@ public class LinkPreviewRepository {
thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP);
}
callback.onSuccess(new LinkPreview(groupUrl, title, thumbnail));
callback.onSuccess(new LinkPreview(groupUrl, title, "", thumbnail));
} else {
Log.i(TAG, "Group is not locally available for preview generation, fetching from server");
@@ -284,7 +285,7 @@ public class LinkPreviewRepository {
if (bitmap != null) bitmap.recycle();
}
callback.onSuccess(new LinkPreview(groupUrl, joinInfo.getTitle(), thumbnail));
callback.onSuccess(new LinkPreview(groupUrl, joinInfo.getTitle(), "", thumbnail));
}
} catch (ExecutionException | InterruptedException | IOException | VerificationFailedException e) {
Log.w(TAG, "Failed to fetch group link preview.", e);
@@ -337,21 +338,27 @@ public class LinkPreviewRepository {
private static class Metadata {
private final Optional<String> title;
private final Optional<String> description;
private final Optional<String> imageUrl;
Metadata(Optional<String> title, Optional<String> imageUrl) {
this.title = title;
this.imageUrl = imageUrl;
Metadata(Optional<String> title, Optional<String> description, Optional<String> imageUrl) {
this.title = title;
this.description = description;
this.imageUrl = imageUrl;
}
static Metadata empty() {
return new Metadata(Optional.absent(), Optional.absent());
return new Metadata(Optional.absent(), Optional.absent(), Optional.absent());
}
Optional<String> getTitle() {
return title;
}
Optional<String> getDescription() {
return description;
}
Optional<String> getImageUrl() {
return imageUrl;
}

View File

@@ -154,8 +154,9 @@ public final class LinkPreviewUtil {
private final @Nullable String htmlTitle;
private final @Nullable String faviconUrl;
private static final String KEY_TITLE = "title";
private static final String KEY_IMAGE_URL = "image";
private static final String KEY_TITLE = "title";
private static final String KEY_DESCRIPTION_URL = "description";
private static final String KEY_IMAGE_URL = "image";
public OpenGraph(@NonNull Map<String, String> values, @Nullable String htmlTitle, @Nullable String faviconUrl) {
this.values = values;
@@ -170,6 +171,10 @@ public final class LinkPreviewUtil {
public @NonNull Optional<String> getImageUrl() {
return OptionalUtil.absentIfEmpty(Util.getFirstNonEmpty(values.get(KEY_IMAGE_URL), faviconUrl));
}
public @NonNull Optional<String> getDescription() {
return OptionalUtil.absentIfEmpty(values.get(KEY_DESCRIPTION_URL));
}
}
public interface HtmlDecoder {