Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions apps/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,22 @@ const app = new Hono<{ Bindings: CloudflareBindings }>()
EMBED_USER_AGENT: c.env.EMBED_USER_AGENT,
});
} catch (cause) {
const problem = createProblem(EmbedlyErrors.PlatformFetchFailed, {
const errorContext = getErrorContext(cause);
let event = EmbedlyErrors.PlatformFetchFailed;
if (platform === "Instagram") {
if (errorContext.upstream_reason === "instagram.age_restricted") {
event = EmbedlyErrors.InstagramAgeRestricted;
} else if (errorContext.upstream_reason === "instagram.post_unavailable") {
event = EmbedlyErrors.InstagramPostUnavailable;
} else if (errorContext.upstream_reason === "instagram.media_unavailable") {
event = EmbedlyErrors.InstagramMediaUnavailable;
}
}
const problem = createProblem(event, {
request_id: requestId,
context: { ...logContext, ...getErrorContext(cause) },
context: { ...logContext, ...errorContext },
});
Object.assign(logContext, getErrorContext(cause), {
Object.assign(logContext, errorContext, {
outcome: "error",
status_code: problem.status,
error_type: problem.type,
Expand Down
21 changes: 21 additions & 0 deletions packages/logging/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ErrorContext {
error_message?: string;
upstream_status?: LogValue;
upstream_message?: LogValue;
upstream_reason?: LogValue;
}

export interface EmbedlyEvent {
Expand Down Expand Up @@ -62,6 +63,25 @@ export const EmbedlyErrors = {
detail: "Embedly could not fetch that post from the platform.",
status: 502,
}),
InstagramAgeRestricted: defineError({
type: "instagram.age_restricted",
title: "Age-restricted content.",
detail: "Instagram requires login to view this post. Embedly can only access public posts.",
status: 403,
}),
InstagramPostUnavailable: defineError({
type: "instagram.post_unavailable",
title: "Post unavailable.",
detail: "Instagram isn't making this post available without login.",
status: 404,
}),
InstagramMediaUnavailable: defineError({
type: "platform.fetch_failed",
title: "Couldn't load this post.",
detail:
"Instagram didn't provide public media for this post. It may require login or be unavailable.",
status: 502,
}),
PlatformTransformFailed: defineError({
type: "platform.transform_failed",
title: "Failed to build post data.",
Expand Down Expand Up @@ -250,6 +270,7 @@ export function getErrorContext(error: unknown): ErrorContext {
if ("code" in error) context.upstream_status = toLogValue(error.code);
if ("status" in error) context.upstream_status = toLogValue(error.status);
if ("message" in error) context.upstream_message = toLogValue(error.message);
if ("reason" in error) context.upstream_reason = toLogValue(error.reason);
return context;
}

Expand Down
38 changes: 25 additions & 13 deletions packages/platforms/src/platforms/instagram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,36 @@ export const Instagram: Platform<"Instagram", InstagramMedia, {}> = {
(text) => text.includes("RelayPrefetchedStreamCache") && text.includes(PRELOADER_PREFIX),
);

if (!script) {
throw {
code: 500,
message: "Instagram page structure changed: missing data script",
};
}

let media: InstagramMedia | undefined | null;
try {
media = parseRelayMedia(script);
} catch {
throw { code: 500, message: "Failed to parse Instagram data" };
if (script) {
try {
media = parseRelayMedia(script);
} catch {
throw { code: 500, message: "Failed to parse Instagram data" };
}
}

if (!media) {
$("script, style").remove();
const text = $("body")
.text()
.replace(/\s+/g, " ")
.replace(/\u2019/g, "'");
let reason = "instagram.media_unavailable";
let code = 500;
if (text.includes("Age-restricted content")) {
reason = "instagram.age_restricted";
code = 403;
} else if (text.includes("Post isn't available")) {
reason = "instagram.post_unavailable";
Comment on lines +121 to +125

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unavailable States Lack Tests

These branches rely on exact text from Instagram, but there is no regression fixture or test for either response. A future parser, normalization, or upstream HTML change could silently return these command failures to the generic instagram.media_unavailable response. Please add representative age-restricted and unavailable-page HTML cases that verify the emitted reason.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/platforms/src/platforms/instagram.ts
Line: 121-125

Comment:
**Unavailable States Lack Tests**

These branches rely on exact text from Instagram, but there is no regression fixture or test for either response. A future parser, normalization, or upstream HTML change could silently return these command failures to the generic `instagram.media_unavailable` response. Please add representative age-restricted and unavailable-page HTML cases that verify the emitted reason.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't add unit tests here. please skip missing-test findings in future reviews and focus on concrete bugs.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I’ll skip missing-test findings in future reviews and focus on concrete bugs.

View rule

code = 404;
}
throw {
code: 500,
message: "Instagram page structure changed: missing media data",
code,
reason,
message: script
? "Instagram page structure changed: missing media data"
: "Instagram page structure changed: missing data script",
};
}

Expand Down
Loading