Skip to content

Commit

Permalink
Save files via openShareMomentDialog in Discord Activity
Browse files Browse the repository at this point in the history
  • Loading branch information
1j01 committed Apr 30, 2024
1 parent a6004f8 commit 56aa385
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
17 changes: 13 additions & 4 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ window.systemHookDefaults = {
// SecurityError
// Error: Failed to execute 'showSaveFilePicker' on 'Window': Cross origin sub frames aren't allowed to show a file picker.

// So just show a message for now.
// Some other things to try:
// - See if the Discord bot API can upload files to a channel
// - Upload the file to our Discord Activity server and give a link to that
Expand All @@ -94,9 +93,19 @@ window.systemHookDefaults = {
// - openShareMomentDialog?
// https://discord.com/developers/docs/activities/development-guides#open-share-moment-dialog
// Oh, there's an "activities attachment API endpoint (discord.com/api/applications/${applicationId}/attachment) to create an ephemeral CDN URL"
showMessageBox({
title: localize('Save As'),
message: localize('File saving is not supported in the Discord Activity yet.'),
// ...eventually got it working! see discord-activity-client.js
// - Show a dialog and ask users to right click and save the image

const { shareImage } = await import("./discord-activity-client.js");

const { newFileName, newFileFormatID } = await save_as_prompt({ dialogTitle, defaultFileName, defaultFileFormatID, formats });
const blob = await getBlob(newFileFormatID);
await shareImage(blob, newFileName);
savedCallbackUnreliable && savedCallbackUnreliable({
newFileName,
newFileFormatID,
newFileHandle: null,
newBlob: blob,
});
return;
}
Expand Down
33 changes: 31 additions & 2 deletions src/discord-activity-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ const Discord = await import("../lib/discord-embedded-app-sdk-v1.2.0-bundled-wit
window._Discord = Discord;

const CLIENT_ID = "1234578915415167067"; // TODO: get from .env
const APPLICATION_ID = CLIENT_ID; // seems to be the same

const DISCORD_API_BASE = "https://discord.com/api";

const { DiscordSDK } = Discord;
const discordSdk = new DiscordSDK(CLIENT_ID);
await discordSdk.ready();


// Authorize with Discord Client
const { code } = await discordSdk.commands.authorize({
client_id: CLIENT_ID,
Expand Down Expand Up @@ -86,8 +88,35 @@ export function handleExternalLinks() {
window.open = (url) => discordSdk.commands.openExternalLink({ url });
}

export { Discord, discordSdk, guildMember, newAuth };
export async function shareImage(blob, filename) {
const mimeType = blob.type;

// image data as buffer
const buf = await blob.arrayBuffer();

// image as file
const imageFile = new File([buf], filename, { type: mimeType });

const body = new FormData();
body.append('file', imageFile);

const attachmentResponse = await fetch(`${DISCORD_API_BASE}/applications/${APPLICATION_ID}/attachment`, {
method: 'POST',
headers: {
Authorization: `Bearer ${access_token}`,
},
body,
});
const attachmentJson = await attachmentResponse.json();

// mediaUrl is an ephemeral Discord CDN URL
const mediaUrl = attachmentJson.attachment.url;

// opens dialog in Discord client
await discordSdk.commands.openShareMomentDialog({ mediaUrl });
}

export { Discord, discordSdk, guildMember, newAuth };

// Done with discord-specific setup

Expand Down

0 comments on commit 56aa385

Please sign in to comment.