Skip to content

Commit

Permalink
fix missing keys, refactor out main component
Browse files Browse the repository at this point in the history
  • Loading branch information
ItzDerock committed Feb 10, 2024
1 parent 7065d0b commit 84f17f2
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 75 deletions.
69 changes: 4 additions & 65 deletions src/generator/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { ChannelType, type Awaitable, type Channel, type Message, type Role, type User } from 'discord.js';
import { type Awaitable, type Channel, type Message, type Role, type User } from 'discord.js';
import ReactDOMServer from 'react-dom/server';
import React, { Suspense } from 'react';
import { DiscordHeader, DiscordMessages } from '@derockdev/discord-components-react';
import DiscordMessage from './renderers/message';
import MessageContent, { RenderType } from './renderers/content';
import React from 'react';
import { buildProfiles } from '../utils/buildProfiles';
import { revealSpoiler, scrollToMessage } from '../static/client';
import { readFileSync } from 'fs';
import path from 'path';
import { renderToString } from '@derockdev/discord-components-core/hydrate';
import { streamToString } from '../utils/utils';
import DiscordMessages from './transcript';

// read the package.json file and get the @derockdev/discord-components-core version
let discordComponentsVersion = '^3.6.1';
Expand Down Expand Up @@ -41,65 +39,6 @@ export type RenderMessageContext = {
export default async function render({ messages, channel, callbacks, ...options }: RenderMessageContext) {
const profiles = buildProfiles(messages);

const elements = (
<DiscordMessages style={{ minHeight: '100vh' }}>
{/* header */}
<DiscordHeader
guild={channel.isDMBased() ? 'Direct Messages' : channel.guild.name}
channel={
channel.isDMBased()
? channel.type === ChannelType.DM
? channel.recipient?.tag ?? 'Unknown Recipient'
: 'Unknown Recipient'
: channel.name
}
icon={channel.isDMBased() ? undefined : channel.guild.iconURL({ size: 128 }) ?? undefined}
>
{channel.isThread() ? (
`Thread channel in ${channel.parent?.name ?? 'Unknown Channel'}`
) : channel.isDMBased() ? (
`Direct Messages`
) : channel.isVoiceBased() ? (
`Voice Text Channel for ${channel.name}`
) : channel.type === ChannelType.GuildCategory ? (
`Category Channel`
) : 'topic' in channel && channel.topic ? (
<MessageContent
content={channel.topic}
context={{ messages, channel, callbacks, type: RenderType.REPLY, ...options }}
/>
) : (
`This is the start of #${channel.name} channel.`
)}
</DiscordHeader>

{/* body */}
<Suspense>
{messages.map((message) => (
<DiscordMessage message={message} context={{ messages, channel, callbacks, ...options }} key={message.id} />
))}
</Suspense>

{/* footer */}
<div style={{ textAlign: 'center', width: '100%' }}>
{options.footerText
? options.footerText
.replaceAll('{number}', messages.length.toString())
.replace('{s}', messages.length > 1 ? 's' : '')
: `Exported ${messages.length} message${messages.length > 1 ? 's' : ''}.`}{' '}
{options.poweredBy ? (
<span style={{ textAlign: 'center' }}>
Powered by{' '}
<a href="https://github.com/ItzDerock/discord-html-transcripts" style={{ color: 'lightblue' }}>
discord-html-transcripts
</a>
.
</span>
) : null}
</div>
</DiscordMessages>
);

// NOTE: this renders a STATIC site with no interactivity
// if interactivity is needed, switch to renderToPipeableStream and use hydrateRoot on client.
const stream = ReactDOMServer.renderToStaticNodeStream(
Expand Down Expand Up @@ -154,7 +93,7 @@ export default async function render({ messages, channel, callbacks, ...options
minHeight: '100vh',
}}
>
{elements}
<DiscordMessages messages={messages} channel={channel} callbacks={callbacks} {...options} />
</body>

{/* Make sure the script runs after the DOM has loaded */}
Expand Down
4 changes: 2 additions & 2 deletions src/generator/renderers/attachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export async function Attachments(props: { message: Message; context: RenderMess

return (
<DiscordAttachments slot="attachments">
{props.message.attachments.map((attachment) => (
<Attachment attachment={attachment} context={props.context} />
{props.message.attachments.map((attachment, id) => (
<Attachment attachment={attachment} context={props.context} key={id} />
))}
</DiscordAttachments>
);
Expand Down
2 changes: 1 addition & 1 deletion src/generator/renderers/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function ComponentRow({ row, id }: { row: ActionRow<MessageAction
return (
<DiscordActionRow key={id}>
{row.components.map((component, id) => (
<Component component={component} id={id} />
<Component component={component} id={id} key={id} />
))}
</DiscordActionRow>
);
Expand Down
4 changes: 2 additions & 2 deletions src/generator/renderers/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ async function MessageASTNodes({
if (Array.isArray(nodes)) {
return (
<>
{nodes.map((node) => (
<MessageSingleASTNode node={node} context={context} />
{nodes.map((node, i) => (
<MessageSingleASTNode node={node} context={context} key={i} />
))}
</>
);
Expand Down
14 changes: 10 additions & 4 deletions src/generator/renderers/message.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
DiscordAttachments,
DiscordCommand,
DiscordMessage,
DiscordMessage as DiscordMessageComponent,
DiscordReaction,
DiscordReactions,
DiscordThread,
Expand All @@ -18,13 +18,19 @@ import { DiscordEmbed } from './embed';
import MessageReply from './reply';
import DiscordSystemMessage from './systemMessage';

export default async function Message({ message, context }: { message: MessageType; context: RenderMessageContext }) {
export default async function DiscordMessage({
message,
context,
}: {
message: MessageType;
context: RenderMessageContext;
}) {
if (message.system) return <DiscordSystemMessage message={message} />;

const isCrosspost = message.reference && message.reference.guildId !== message.guild?.id;

return (
<DiscordMessage
<DiscordMessageComponent
id={`m-${message.id}`}
timestamp={message.createdAt.toISOString()}
key={message.id}
Expand Down Expand Up @@ -111,6 +117,6 @@ export default async function Message({ message, context }: { message: MessageTy
)}
</DiscordThread>
)}
</DiscordMessage>
</DiscordMessageComponent>
);
}
74 changes: 74 additions & 0 deletions src/generator/transcript.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { DiscordHeader, DiscordMessages as DiscordMessagesComponent } from '@derockdev/discord-components-react';
import { ChannelType } from 'discord.js';
import React, { Suspense } from 'react';
import type { RenderMessageContext } from '.';
import MessageContent, { RenderType } from './renderers/content';
import DiscordMessage from './renderers/message';

/**
* The core transcript component.
* Expects window.$discordMessage.profiles to be set for profile information.
*
* @param props Messages, channel details, callbacks, etc.
* @returns
*/
export default async function DiscordMessages({ messages, channel, callbacks, ...options }: RenderMessageContext) {
return (
<DiscordMessagesComponent style={{ minHeight: '100vh' }}>
{/* header */}
<DiscordHeader
guild={channel.isDMBased() ? 'Direct Messages' : channel.guild.name}
channel={
channel.isDMBased()
? channel.type === ChannelType.DM
? channel.recipient?.tag ?? 'Unknown Recipient'
: 'Unknown Recipient'
: channel.name
}
icon={channel.isDMBased() ? undefined : channel.guild.iconURL({ size: 128 }) ?? undefined}
>
{channel.isThread() ? (
`Thread channel in ${channel.parent?.name ?? 'Unknown Channel'}`
) : channel.isDMBased() ? (
`Direct Messages`
) : channel.isVoiceBased() ? (
`Voice Text Channel for ${channel.name}`
) : channel.type === ChannelType.GuildCategory ? (
`Category Channel`
) : 'topic' in channel && channel.topic ? (
<MessageContent
content={channel.topic}
context={{ messages, channel, callbacks, type: RenderType.REPLY, ...options }}
/>
) : (
`This is the start of #${channel.name} channel.`
)}
</DiscordHeader>

{/* body */}
<Suspense>
{messages.map((message) => (
<DiscordMessage message={message} context={{ messages, channel, callbacks, ...options }} key={message.id} />
))}
</Suspense>

{/* footer */}
<div style={{ textAlign: 'center', width: '100%' }}>
{options.footerText
? options.footerText
.replaceAll('{number}', messages.length.toString())
.replace('{s}', messages.length > 1 ? 's' : '')
: `Exported ${messages.length} message${messages.length > 1 ? 's' : ''}.`}{' '}
{options.poweredBy ? (
<span style={{ textAlign: 'center' }}>
Powered by{' '}
<a href="https://github.com/ItzDerock/discord-html-transcripts" style={{ color: 'lightblue' }}>
discord-html-transcripts
</a>
.
</span>
) : null}
</div>
</DiscordMessagesComponent>
);
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
type ObjectType,
} from './types';

// re-export component for custom rendering
export { default as DiscordMessages } from './generator/transcript';

// version check
const versionPrefix = version.split('.')[0];

Expand Down
1 change: 0 additions & 1 deletion tests/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ client.on('ready', async () => {
process.exit(1);
}

console.log('Generating transcript for', channel);
console.time('transcript');
const attachment = await createTranscript(channel);
console.timeEnd('transcript');
Expand Down

0 comments on commit 84f17f2

Please sign in to comment.