diff --git a/common/contract-details.ts b/common/contract-details.ts
index 02af6359..c231b1e4 100644
--- a/common/contract-details.ts
+++ b/common/contract-details.ts
@@ -27,10 +27,10 @@ export function contractMetrics(contract: Contract) {
export function contractTextDetails(contract: Contract) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const dayjs = require('dayjs')
- const { closeTime, tags } = contract
+ const { closeTime, groupLinks } = contract
const { createdDate, resolvedDate, volumeLabel } = contractMetrics(contract)
- const hashtags = tags.map((tag) => `#${tag}`)
+ const groupHashtags = groupLinks?.slice(0, 5).map((g) => `#${g.name}`)
return (
`${resolvedDate ? `${createdDate} - ${resolvedDate}` : createdDate}` +
@@ -40,7 +40,7 @@ export function contractTextDetails(contract: Contract) {
).format('MMM D, h:mma')}`
: '') +
` • ${volumeLabel}` +
- (hashtags.length > 0 ? ` • ${hashtags.join(' ')}` : '')
+ (groupHashtags ? ` • ${groupHashtags.join(' ')}` : '')
)
}
@@ -92,6 +92,7 @@ export const getOpenGraphProps = (contract: Contract) => {
creatorAvatarUrl,
description,
numericValue,
+ resolution,
}
}
@@ -103,6 +104,7 @@ export type OgCardProps = {
creatorUsername: string
creatorAvatarUrl?: string
numericValue?: string
+ resolution?: string
}
export function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
@@ -113,22 +115,32 @@ export function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
creatorOutcome,
acceptorOutcome,
} = challenge || {}
+ const {
+ probability,
+ numericValue,
+ resolution,
+ creatorAvatarUrl,
+ question,
+ metadata,
+ creatorUsername,
+ creatorName,
+ } = props
const { userName, userAvatarUrl } = acceptances?.[0] ?? {}
const probabilityParam =
- props.probability === undefined
+ probability === undefined
? ''
- : `&probability=${encodeURIComponent(props.probability ?? '')}`
+ : `&probability=${encodeURIComponent(probability ?? '')}`
const numericValueParam =
- props.numericValue === undefined
+ numericValue === undefined
? ''
- : `&numericValue=${encodeURIComponent(props.numericValue ?? '')}`
+ : `&numericValue=${encodeURIComponent(numericValue ?? '')}`
const creatorAvatarUrlParam =
- props.creatorAvatarUrl === undefined
+ creatorAvatarUrl === undefined
? ''
- : `&creatorAvatarUrl=${encodeURIComponent(props.creatorAvatarUrl ?? '')}`
+ : `&creatorAvatarUrl=${encodeURIComponent(creatorAvatarUrl ?? '')}`
const challengeUrlParams = challenge
? `&creatorAmount=${creatorAmount}&creatorOutcome=${creatorOutcome}` +
@@ -136,16 +148,21 @@ export function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
`&acceptedName=${userName ?? ''}&acceptedAvatarUrl=${userAvatarUrl ?? ''}`
: ''
+ const resolutionUrlParam = resolution
+ ? `&resolution=${encodeURIComponent(resolution)}`
+ : ''
+
// URL encode each of the props, then add them as query params
return (
`https://manifold-og-image.vercel.app/m.png` +
- `?question=${encodeURIComponent(props.question)}` +
+ `?question=${encodeURIComponent(question)}` +
probabilityParam +
numericValueParam +
- `&metadata=${encodeURIComponent(props.metadata)}` +
- `&creatorName=${encodeURIComponent(props.creatorName)}` +
+ `&metadata=${encodeURIComponent(metadata)}` +
+ `&creatorName=${encodeURIComponent(creatorName)}` +
creatorAvatarUrlParam +
- `&creatorUsername=${encodeURIComponent(props.creatorUsername)}` +
- challengeUrlParams
+ `&creatorUsername=${encodeURIComponent(creatorUsername)}` +
+ challengeUrlParams +
+ resolutionUrlParam
)
}
diff --git a/og-image/api/_lib/challenge-template.ts b/og-image/api/_lib/challenge-template.ts
index 6dc43ac1..647d69b6 100644
--- a/og-image/api/_lib/challenge-template.ts
+++ b/og-image/api/_lib/challenge-template.ts
@@ -1,85 +1,5 @@
-import { sanitizeHtml } from './sanitizer'
import { ParsedRequest } from './types'
-
-function getCss(theme: string, fontSize: string) {
- let background = 'white'
- let foreground = 'black'
- let radial = 'lightgray'
-
- if (theme === 'dark') {
- background = 'black'
- foreground = 'white'
- radial = 'dimgray'
- }
- // To use Readex Pro: `font-family: 'Readex Pro', sans-serif;`
- return `
- @import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Readex+Pro:wght@400;700&display=swap');
-
- body {
- background: ${background};
- background-image: radial-gradient(circle at 25px 25px, ${radial} 2%, transparent 0%), radial-gradient(circle at 75px 75px, ${radial} 2%, transparent 0%);
- background-size: 100px 100px;
- height: 100vh;
- font-family: "Readex Pro", sans-serif;
- }
-
- code {
- color: #D400FF;
- font-family: 'Vera';
- white-space: pre-wrap;
- letter-spacing: -5px;
- }
-
- code:before, code:after {
- content: '\`';
- }
-
- .logo-wrapper {
- display: flex;
- align-items: center;
- align-content: center;
- justify-content: center;
- justify-items: center;
- }
-
- .logo {
- margin: 0 75px;
- }
-
- .plus {
- color: #BBB;
- font-family: Times New Roman, Verdana;
- font-size: 100px;
- }
-
- .spacer {
- margin: 150px;
- }
-
- .emoji {
- height: 1em;
- width: 1em;
- margin: 0 .05em 0 .1em;
- vertical-align: -0.1em;
- }
-
- .heading {
- font-family: 'Major Mono Display', monospace;
- font-size: ${sanitizeHtml(fontSize)};
- font-style: normal;
- color: ${foreground};
- line-height: 1.8;
- }
-
- .font-major-mono {
- font-family: "Major Mono Display", monospace;
- }
-
- .text-primary {
- color: #11b981;
- }
- `
-}
+import { getTemplateCss } from './template-css'
export function getChallengeHtml(parsedReq: ParsedRequest) {
const {
@@ -112,7 +32,7 @@ export function getChallengeHtml(parsedReq: ParsedRequest) {
diff --git a/og-image/api/_lib/parser.ts b/og-image/api/_lib/parser.ts
index 6d5c9b3d..131a3cc4 100644
--- a/og-image/api/_lib/parser.ts
+++ b/og-image/api/_lib/parser.ts
@@ -21,6 +21,7 @@ export function parseRequest(req: IncomingMessage) {
creatorName,
creatorUsername,
creatorAvatarUrl,
+ resolution,
// Challenge attributes:
challengerAmount,
@@ -71,6 +72,7 @@ export function parseRequest(req: IncomingMessage) {
question:
getString(question) || 'Will you create a prediction market on Manifold?',
+ resolution: getString(resolution),
probability: getString(probability),
numericValue: getString(numericValue) || '',
metadata: getString(metadata) || 'Jan 1 • M$ 123 pool',
diff --git a/og-image/api/_lib/template-css.ts b/og-image/api/_lib/template-css.ts
new file mode 100644
index 00000000..f4ca6660
--- /dev/null
+++ b/og-image/api/_lib/template-css.ts
@@ -0,0 +1,81 @@
+import { sanitizeHtml } from './sanitizer'
+
+export function getTemplateCss(theme: string, fontSize: string) {
+ let background = 'white'
+ let foreground = 'black'
+ let radial = 'lightgray'
+
+ if (theme === 'dark') {
+ background = 'black'
+ foreground = 'white'
+ radial = 'dimgray'
+ }
+ // To use Readex Pro: `font-family: 'Readex Pro', sans-serif;`
+ return `
+ @import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Readex+Pro:wght@400;700&display=swap');
+
+ body {
+ background: ${background};
+ background-image: radial-gradient(circle at 25px 25px, ${radial} 2%, transparent 0%), radial-gradient(circle at 75px 75px, ${radial} 2%, transparent 0%);
+ background-size: 100px 100px;
+ height: 100vh;
+ font-family: "Readex Pro", sans-serif;
+ }
+
+ code {
+ color: #D400FF;
+ font-family: 'Vera';
+ white-space: pre-wrap;
+ letter-spacing: -5px;
+ }
+
+ code:before, code:after {
+ content: '\`';
+ }
+
+ .logo-wrapper {
+ display: flex;
+ align-items: center;
+ align-content: center;
+ justify-content: center;
+ justify-items: center;
+ }
+
+ .logo {
+ margin: 0 75px;
+ }
+
+ .plus {
+ color: #BBB;
+ font-family: Times New Roman, Verdana;
+ font-size: 100px;
+ }
+
+ .spacer {
+ margin: 150px;
+ }
+
+ .emoji {
+ height: 1em;
+ width: 1em;
+ margin: 0 .05em 0 .1em;
+ vertical-align: -0.1em;
+ }
+
+ .heading {
+ font-family: 'Major Mono Display', monospace;
+ font-size: ${sanitizeHtml(fontSize)};
+ font-style: normal;
+ color: ${foreground};
+ line-height: 1.8;
+ }
+
+ .font-major-mono {
+ font-family: "Major Mono Display", monospace;
+ }
+
+ .text-primary {
+ color: #11b981;
+ }
+ `
+}
diff --git a/og-image/api/_lib/template.ts b/og-image/api/_lib/template.ts
index f59740c5..26f7677e 100644
--- a/og-image/api/_lib/template.ts
+++ b/og-image/api/_lib/template.ts
@@ -1,85 +1,5 @@
-import { sanitizeHtml } from './sanitizer'
import { ParsedRequest } from './types'
-
-function getCss(theme: string, fontSize: string) {
- let background = 'white'
- let foreground = 'black'
- let radial = 'lightgray'
-
- if (theme === 'dark') {
- background = 'black'
- foreground = 'white'
- radial = 'dimgray'
- }
- // To use Readex Pro: `font-family: 'Readex Pro', sans-serif;`
- return `
- @import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Readex+Pro:wght@400;700&display=swap');
-
- body {
- background: ${background};
- background-image: radial-gradient(circle at 25px 25px, ${radial} 2%, transparent 0%), radial-gradient(circle at 75px 75px, ${radial} 2%, transparent 0%);
- background-size: 100px 100px;
- height: 100vh;
- font-family: "Readex Pro", sans-serif;
- }
-
- code {
- color: #D400FF;
- font-family: 'Vera';
- white-space: pre-wrap;
- letter-spacing: -5px;
- }
-
- code:before, code:after {
- content: '\`';
- }
-
- .logo-wrapper {
- display: flex;
- align-items: center;
- align-content: center;
- justify-content: center;
- justify-items: center;
- }
-
- .logo {
- margin: 0 75px;
- }
-
- .plus {
- color: #BBB;
- font-family: Times New Roman, Verdana;
- font-size: 100px;
- }
-
- .spacer {
- margin: 150px;
- }
-
- .emoji {
- height: 1em;
- width: 1em;
- margin: 0 .05em 0 .1em;
- vertical-align: -0.1em;
- }
-
- .heading {
- font-family: 'Major Mono Display', monospace;
- font-size: ${sanitizeHtml(fontSize)};
- font-style: normal;
- color: ${foreground};
- line-height: 1.8;
- }
-
- .font-major-mono {
- font-family: "Major Mono Display", monospace;
- }
-
- .text-primary {
- color: #11b981;
- }
- `
-}
+import { getTemplateCss } from './template-css'
export function getHtml(parsedReq: ParsedRequest) {
const {
@@ -92,6 +12,7 @@ export function getHtml(parsedReq: ParsedRequest) {
creatorUsername,
creatorAvatarUrl,
numericValue,
+ resolution,
} = parsedReq
const MAX_QUESTION_CHARS = 100
const truncatedQuestion =
@@ -99,6 +20,49 @@ export function getHtml(parsedReq: ParsedRequest) {
? question.slice(0, MAX_QUESTION_CHARS) + '...'
: question
const hideAvatar = creatorAvatarUrl ? '' : 'hidden'
+
+ let resolutionColor = 'text-primary'
+ let resolutionString = 'Yes'
+ switch (resolution) {
+ case 'YES':
+ break
+ case 'NO':
+ resolutionColor = 'text-red-500'
+ resolutionString = 'No'
+ break
+ case 'CANCEL':
+ resolutionColor = 'text-yellow-500'
+ resolutionString = 'N/A'
+ break
+ case 'MKT':
+ resolutionColor = 'text-blue-500'
+ resolutionString = numericValue ? numericValue : probability
+ break
+ }
+
+ const resolutionDiv = `
+
+
+ ${resolutionString}
+
+ ${
+ resolution === 'CANCEL' ? '' : 'resolved'
+ }
+ `
+
+ const probabilityDiv = `
+
+ ${probability}
+ chance
+ `
+
+ const numericValueDiv = `
+
+ ${numericValue}
+ expected
+
+ `
+
return `
@@ -108,7 +72,7 @@ export function getHtml(parsedReq: ParsedRequest) {
@@ -148,21 +112,20 @@ export function getHtml(parsedReq: ParsedRequest) {
${truncatedQuestion}
-
-
${probability}
-
${probability !== '' ? 'chance' : ''}
-
- ${
- numericValue !== '' && probability === '' ? numericValue : ''
- }
- ${numericValue !== '' ? 'expected' : ''}
-
+
+ ${
+ resolution
+ ? resolutionDiv
+ : numericValue
+ ? numericValueDiv
+ : probabilityDiv
+ }
-
diff --git a/og-image/api/_lib/types.ts b/og-image/api/_lib/types.ts
index ef0a8135..ac1e7699 100644
--- a/og-image/api/_lib/types.ts
+++ b/og-image/api/_lib/types.ts
@@ -19,6 +19,7 @@ export interface ParsedRequest {
creatorName: string
creatorUsername: string
creatorAvatarUrl: string
+ resolution: string
// Challenge attributes:
challengerAmount: string
challengerOutcome: string