From e24d8889fcdf43cc0eae74e2f6be11020fc42458 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:24:02 +0530 Subject: [PATCH] Cal 710 turn dataimagejpegbase64 avatar into (#1429) * --wip * added next-config custom header path * added avatar endpoint * cleanup --wip * adding gravatar fallback support --wip * added endpoint rewrite and avatar access * gravatar support added * build err fix * updated HeadSEO with new avatar logic * --wip * adds og compat * added truncated bio * cleanup * changed truncate of body from 24 chars to 32 chars * removed unused, commented code * removed trailing whitespace * requested changes Co-authored-by: Peer Richelsen --- components/seo/head-seo.tsx | 35 +++++++++++++++++++++---------- next.config.js | 8 +++++++ pages/[user].tsx | 5 +++-- pages/api/user/avatar.ts | 42 +++++++++++++++++++++++++++++++++++++ pages/settings/profile.tsx | 1 - 5 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 pages/api/user/avatar.ts diff --git a/components/seo/head-seo.tsx b/components/seo/head-seo.tsx index 41354e47..8dcbfcb3 100644 --- a/components/seo/head-seo.tsx +++ b/components/seo/head-seo.tsx @@ -10,8 +10,8 @@ export type HeadSeoProps = { description: string; siteName?: string; name?: string; - avatar?: string; url?: string; + username?: string; canonical?: string; nextSeoProps?: NextSeoProps; }; @@ -39,9 +39,6 @@ const buildSeoMeta = (pageProps: { images: [ { url: image, - //width: 1077, - //height: 565, - //alt: "Alt image" }, ], }, @@ -66,11 +63,14 @@ const buildSeoMeta = (pageProps: { }; }; -const constructImage = (name: string, avatar: string, description: string): string => { +const constructImage = (name: string, description: string, username: string): string => { return ( encodeURIComponent("Meet **" + name + "**
" + description).replace(/'/g, "%27") + ".png?md=1&images=https%3A%2F%2Fcal.com%2Flogo-white.svg&images=" + - encodeURIComponent(avatar) + (process.env.NEXT_PUBLIC_APP_URL || process.env.BASE_URL) + + "/" + + username + + "/avatar.png" ); }; @@ -82,18 +82,31 @@ export const HeadSeo: React.FC = (props) => title, description, name = null, - avatar = null, + username = null, siteName, canonical = defaultUrl, nextSeoProps = {}, } = props; + const truncatedDescription = description.length > 32 ? description.substring(0, 31) + "..." : description; const pageTitle = title + " | Cal.com"; - let seoObject = buildSeoMeta({ title: pageTitle, image, description, canonical, siteName }); + let seoObject = buildSeoMeta({ + title: pageTitle, + image, + description: truncatedDescription, + canonical, + siteName, + }); - if (name && avatar) { - const pageImage = getSeoImage("ogImage") + constructImage(name, avatar, description); - seoObject = buildSeoMeta({ title: pageTitle, description, image: pageImage, canonical, siteName }); + if (name && username) { + const pageImage = getSeoImage("ogImage") + constructImage(name, truncatedDescription, username); + seoObject = buildSeoMeta({ + title: pageTitle, + description: truncatedDescription, + image: pageImage, + canonical, + siteName, + }); } const seoProps: NextSeoProps = merge(nextSeoProps, seoObject); diff --git a/next.config.js b/next.config.js index e74df98e..762e55bb 100644 --- a/next.config.js +++ b/next.config.js @@ -72,6 +72,14 @@ module.exports = () => plugins.reduce((acc, next) => next(acc), { return config; }, + async rewrites() { + return [ + { + source: "/:user/avatar.png", + destination: "/api/user/avatar?username=:user", + }, + ] + }, async redirects() { return [ { diff --git a/pages/[user].tsx b/pages/[user].tsx index 8d42c8f5..4dd7f396 100644 --- a/pages/[user].tsx +++ b/pages/[user].tsx @@ -29,9 +29,10 @@ export default function User(props: inferSSRProps) { <> {isReady && (
diff --git a/pages/api/user/avatar.ts b/pages/api/user/avatar.ts new file mode 100644 index 00000000..550723fc --- /dev/null +++ b/pages/api/user/avatar.ts @@ -0,0 +1,42 @@ +import crypto from "crypto"; +import type { NextApiRequest, NextApiResponse } from "next"; + +import prisma from "@lib/prisma"; +import { defaultAvatarSrc } from "@lib/profile"; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + // const username = req.url?.substring(1, req.url.lastIndexOf("/")); + const username = req.query.username as string; + const user = await prisma.user.findUnique({ + where: { + username: username, + }, + select: { + avatar: true, + email: true, + }, + }); + + const emailMd5 = crypto + .createHash("md5") + .update(user?.email as string) + .digest("hex"); + const img = user?.avatar; + if (img) { + const decoded = img + .toString() + .replace("data:image/png;base64,", "") + .replace("data:image/jpeg;base64,", ""); + const imageResp = Buffer.from(decoded, "base64"); + res.writeHead(200, { + "Content-Type": "image/png", + "Content-Length": imageResp.length, + }); + res.end(imageResp); + } else { + res.writeHead(302, { + Location: defaultAvatarSrc({ md5: emailMd5 }), + }); + res.end(); + } +} diff --git a/pages/settings/profile.tsx b/pages/settings/profile.tsx index 767cf01a..54e0f3c4 100644 --- a/pages/settings/profile.tsx +++ b/pages/settings/profile.tsx @@ -220,7 +220,6 @@ function SettingsView(props: ComponentProps & { localeProp: str />
-