Compare commits

...

35 Commits

Author SHA1 Message Date
Apoorv Mishra 9102a36716 fix: presentUnfurl 2023-07-23 20:39:16 +05:30
Apoorv Mishra 6c538d00c0 fix: coalesce to empty str 2023-07-23 13:26:13 +05:30
Apoorv Mishra 520d81ae9f fix: revert HoverPreview changes from back merge 2023-07-23 08:57:59 +05:30
Apoorv Mishra e497c9f93e Merge branch 'main' into feat/5109/url-preview 2023-07-23 08:54:03 +05:30
Apoorv Mishra c9e5173e7c feat: pipe external urls through iframely 2023-07-23 08:16:38 +05:30
Apoorv Mishra f3c8b7306b fix: cleanup 2023-07-21 18:59:16 +05:30
Apoorv Mishra 3d4ef30129 fix: prevent flash of previously rendered card 2023-07-21 17:02:12 +05:30
Apoorv Mishra 233edf88ec fix: summary remained same when switching to adjacent elements 2023-07-21 16:50:13 +05:30
Apoorv Mishra 5f67fa7895 fix: disable text fadeout for mentions and use correct background for dark mode 2023-07-21 16:43:08 +05:30
Tom Moor 8e495bc00b Guard no data 2023-07-20 21:20:00 -04:00
Tom Moor eae82710ce cleanup 2023-07-20 21:13:59 -04:00
Tom Moor 64b834512f cleanup 2023-07-20 20:50:03 -04:00
Apoorv Mishra f0895b1170 fix: use actor user combo as names 2023-07-20 23:56:52 +05:30
Apoorv Mishra 8086cfd6ef fix: presenters/unfurls 2023-07-20 23:38:16 +05:30
Apoorv Mishra 2e3b340a1d fix: extract description part as utils in models 2023-07-20 17:29:12 +05:30
Apoorv Mishra e6f1a06e07 fix: viewed just now 2023-07-20 14:28:33 +05:30
Apoorv Mishra d123cd6bfb fix: different hover preview types as separate components 2023-07-20 12:25:35 +05:30
Apoorv Mishra 568627c65f fix: use document.getSummary() 2023-07-20 10:37:01 +05:30
Apoorv Mishra f390a22821 fix: reuse parseMentionUrl 2023-07-20 10:33:48 +05:30
Apoorv Mishra accbac2a15 fix: go with thumbnailUrl 2023-07-20 09:56:49 +05:30
Apoorv Mishra 65c441f3dc fix: serve description in response 2023-07-19 23:46:34 +05:30
Apoorv Mishra 0d88608e0f fix: move date-fns locales to shared 2023-07-19 23:45:15 +05:30
Apoorv Mishra d52b162157 fix: summary 2023-07-19 20:52:18 +05:30
Apoorv Mishra 647b022223 feat: show avatar for mentions 2023-07-19 16:45:16 +05:30
Apoorv Mishra 26fe15702f fix: show correct card 2023-07-18 20:44:02 +05:30
Apoorv Mishra cf422dab43 Revert "fix: better to cleanup upon unmount"
This reverts commit 14bc077cec.
2023-07-18 19:22:58 +05:30
Apoorv Mishra cc3541cf72 Revert "fix: a little space between the elem and card to prevent opposing events"
This reverts commit d1cfa02dff.
2023-07-18 19:22:35 +05:30
Apoorv Mishra d1cfa02dff fix: a little space between the elem and card to prevent opposing events 2023-07-18 17:10:55 +05:30
Apoorv Mishra 14bc077cec fix: better to cleanup upon unmount 2023-07-18 15:24:37 +05:30
Apoorv Mishra 965fbe5218 fix: useCallback not necessary 2023-07-18 13:31:54 +05:30
Apoorv Mishra 03a77721c2 fix: do not show same preview for adjacent elements 2023-07-18 13:27:53 +05:30
Apoorv Mishra 3db37a3bf9 fix: <Link /> warning 2023-07-18 09:17:08 +05:30
Apoorv Mishra 29cb3d0fe8 fix: show doc summary and fix linking 2023-07-18 09:17:08 +05:30
Apoorv Mishra 38938c6240 feat(app): preview mentions 2023-07-18 09:17:06 +05:30
Apoorv Mishra 994b7ad047 feat(server): urls.unfurl endpoint 2023-07-18 09:15:26 +05:30
11 changed files with 119 additions and 15 deletions
+4
View File
@@ -181,3 +181,7 @@ RATE_LIMITER_ENABLED=true
# Configure default throttling parameters for rate limiter
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60
# Iframely API config
IFRAMELY_URL=
IFRAMELY_API_KEY=
+5
View File
@@ -0,0 +1,5 @@
{
"name": "Iframely",
"description": "Integrate Iframely to enable unfurling of arbitrary urls",
"requiredEnvVars": ["IFRAMELY_URL", "IFRAMELY_API_KEY"]
}
+3
View File
@@ -0,0 +1,3 @@
{
"extends": "../../../server/.babelrc"
}
+24
View File
@@ -0,0 +1,24 @@
import fetch from "fetch-with-proxy";
import env from "@server/env";
import { InvalidRequestError } from "@server/errors";
class Iframely {
private static apiUrl = `${env.IFRAMELY_URL}/api`;
private static apiKey = env.IFRAMELY_API_KEY;
public static async get(url: string, type = "oembed") {
try {
const res = await fetch(
`${this.apiUrl}/${type}?url=${encodeURIComponent(url)}&api_key=${
this.apiKey
}`
);
const data = await res.json();
return data;
} catch (err) {
throw InvalidRequestError(err);
}
}
}
export default Iframely;
+3
View File
@@ -0,0 +1,3 @@
import Iframely from "./iframely";
export const unfurl = async (url: string) => Iframely.get(url);
+18
View File
@@ -601,6 +601,24 @@ export class Environment {
this.AWS_S3_UPLOAD_MAX_SIZE
);
/**
* Iframely url
*/
@IsOptional()
@IsUrl({
require_tld: false,
allow_underscores: true,
protocols: ["http", "https"],
})
public IFRAMELY_URL = process.env.IFRAMELY_URL ?? "https://iframe.ly";
/**
* Iframely API key
*/
@IsOptional()
@CannotUseWithout("IFRAMELY_URL")
public IFRAMELY_API_KEY = process.env.IFRAMELY_API_KEY ?? "";
/**
* The product name
*/
+14
View File
@@ -0,0 +1,14 @@
import { Unfurl } from "@shared/types";
function presentUnfurl(data: any): Unfurl {
return {
url: data.url,
type: data.type,
title: data.title,
description: data.description,
thumbnailUrl: data.thumbnail_url,
meta: data.meta,
};
}
export default presentUnfurl;
+16 -13
View File
@@ -8,8 +8,10 @@ import validate from "@server/middlewares/validate";
import { Document, User } from "@server/models";
import { authorize } from "@server/policies";
import { presentDocument, presentMention } from "@server/presenters/unfurls";
import presentUnfurl from "@server/presenters/unfurls/unfurl";
import { APIContext } from "@server/types";
import { RateLimiterStrategy } from "@server/utils/RateLimiter";
import { Iframely } from "@server/utils/unfurl";
import * as T from "./schema";
const router = new Router();
@@ -47,22 +49,23 @@ router.post(
}
const previewDocumentId = parseDocumentSlug(url);
if (!previewDocumentId) {
ctx.response.status = 204;
if (previewDocumentId) {
const document = previewDocumentId
? await Document.findByPk(previewDocumentId, {
userId: actor.id,
})
: undefined;
if (!document) {
throw NotFoundError("Document does not exist");
}
authorize(actor, "read", document);
ctx.body = presentDocument(document, actor);
return;
}
const document = previewDocumentId
? await Document.findByPk(previewDocumentId, {
userId: actor.id,
})
: undefined;
if (!document) {
throw NotFoundError("Document does not exist");
}
authorize(actor, "read", document);
ctx.body = presentDocument(document, actor);
const data = await Iframely.unfurl(url);
ctx.body = presentUnfurl(data);
}
);
+4
View File
@@ -446,3 +446,7 @@ export type CollectionJSONExport = {
[id: string]: AttachmentJSONExport;
};
};
export type UnfurlResolver = {
unfurl: (url: string) => Promise<any>;
};
+24
View File
@@ -0,0 +1,24 @@
import path from "path";
import glob from "glob";
import { startCase } from "lodash";
import env from "@server/env";
import Logger from "@server/logging/Logger";
import { UnfurlResolver } from "@server/types";
const resolvers: Record<string, UnfurlResolver> = {};
const rootDir = env.ENVIRONMENT === "test" ? "" : "build";
glob
.sync(path.join(rootDir, "plugins/*/server/unfurl.js"))
.forEach((filePath: string) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const resolver: UnfurlResolver = require(path.join(
process.cwd(),
filePath
));
const name = startCase(filePath.split("/")[2]);
resolvers[name] = resolver;
Logger.debug("utils", `Registered unfurl resolver ${filePath}`);
});
export const Iframely = resolvers["Iframely"];
+4 -2
View File
@@ -214,13 +214,15 @@ export enum UnfurlType {
Document = "document",
}
export type Unfurl<T = unknown> = {
export type OEmbedType = "photo" | "video" | "rich";
export type Unfurl<T = OEmbedType> = {
url?: string;
type: T;
title: string;
description: string;
thumbnailUrl?: string | null;
meta: Record<string, string>;
meta?: Record<string, string>;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any