Search code examples
node.jsdiscord

Basic-FTP Configuration


I am attempting to use basic-ftp to upload files to a FTP server. What I am wanting to do is create a discord channel transcript via "discord-html-transcripts" (which I have configured) but I then want for this to upload to my FTP server to which the scripts are unable to comprehend.

I have tried using many different items of such as creating Buffers, Removing Buffers and it still does not want to seem to work.

Code

const { Colors } = require("discord.js");
const { Client } = require("basic-ftp");
const config = require("../../configuration");
const ticketTranscript = require("discord-html-transcripts");
const enquiriesNotifications = config.enquiriesNotifications;

module.exports = {
  data: {
    id: "enquiry-transcript",
  },
  async execute(interaction) {
    const channelName = interaction.channel.name;
    const transcriptName = `${channelName}_${Date.now()}.html`;

    const clientFtp = new Client();
    try {
      await clientFtp.access({
        host: "ftp.southlondonroleplay.co.uk",
        port: 21,
        user: "InspectorColeAccess",
        password: "1234567890",
      });

      console.log("[File Transfer] Uploading transcript to FTP server...");

      // Create the transcript content
      console.log("[Debugging Information] Creating transcript...");
      const transcriptAttachment = await ticketTranscript.createTranscript(
        interaction.channel,
        {
          limit: -1,
          returnType: "attachment",
          filename: `${transcriptName}`,
          saveImages: true,
          footerText: "Central London Roleplay",
          poweredBy: false,
        }
      );
      console.log(
        "[Debugging Information] Transcript created:",
        transcriptAttachment
      );

      // Extract transcript content
      const transcriptContent =
        transcriptAttachment.attachment.toString("utf-8");
      console.log(
        "[Debugging Information] Transcript content:",
        transcriptContent
      );

      // Upload the transcript to the FTP server
      await clientFtp.uploadFrom(
        Buffer.from(transcriptContent),
        `/PortalTickets/${transcriptName}`
      );

      console.log("[File Transfer] Transcript uploaded successfully");

      const transcriptLink = `https://clrp.co.uk/enquirytranscripts/${transcriptName}`;

      // Send message to the enquiriesNotifications channel with transcript link
      await interaction.guild.channels.cache.get(enquiriesNotifications).send({
        embeds: [
          {
            title: "Enquiry Closed",
            description:
              "A community enquiry has been closed with a transcript. Details relating to this action are reflected below:",
            fields: [
              {
                name: "Closed by",
                value: `${interaction.user}`,
                inline: true,
              },
              {
                name: "Enquiry Channel",
                value: `${interaction.channel.name}`,
                inline: true,
              },
              {
                name: "Enquiry Transcript",
                value: `${transcriptLink}`,
                inline: true,
              },
            ],
            color: Colors.Red,
            footer: {
              text: "Central London Roleplay",
            },
            timestamp: new Date(),
          },
        ],
        files: [
          {
            attachment: Buffer.from(transcriptContent),
            name: transcriptName,
          },
        ],
      });

      // Send confirmation message to the enquiry channel
      await interaction.channel.send({
        embeds: [
          {
            title: "Enquiry Deletion",
            description: `This enquiry has been closed by ${interaction.user}\n\nAll Transcripts are saved and stored within our Discord notification channels and Community Portal for training and audit purposes. All data is processed in accordance with our Data Privacy & Protection Policy.`,
            color: Colors.Red,
            footer: {
              text: "Central London Roleplay",
            },
            timestamp: new Date(),
          },
        ],
      });

      // Delete the enquiry channel after 5 seconds
      setTimeout(() => {
        interaction.channel.delete();
      }, 5000);
    } catch (error) {
      console.error(
        "[Debugging Information] Error Uploading Transcript to the Portal",
        error
      );
      // Handle error gracefully, inform the user, and log the error
      await interaction.reply({
        content: "An error occurred while processing your request.",
        ephemeral: true,
      });
    } finally {
      // Close the FTP connection
      await clientFtp.close();
    }
  },
};

Error

[Debugging Information] Error Uploading Transcript to the Portal TypeError: source.once is not a function
    at Client._uploadFromStream (F:\Stuffs\CentralLondon\node_modules\basic-ftp\dist\Client.js:391:16)
    at Client._uploadWithCommand (F:\Stuffs\CentralLondon\node_modules\basic-ftp\dist\Client.js:366:21)
    at Client.uploadFrom (F:\Stuffs\CentralLondon\node_modules\basic-ftp\dist\Client.js:347:21)
    at Object.execute (F:\Stuffs\CentralLondon\communityBot\communityComponents\clientButtons\enquiry-transcript.js:53:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.execute (F:\Stuffs\CentralLondon\communityBot\communityEvents\clientEvents\interactionCreate.js:28:9)

Solution

  • Seems like you're creating a Buffer from a string while uploadFrom requires a stream.

    const { Readable } = require('stream');
    
    const stream = Readable.from(string); // converts string to a readable stream
    

    In short, you're looking for

    const { Readable } = require('stream');
    ...
    
    await clientFtp.uploadFrom(
      Readable.from(transcriptContent),
      `/PortalTickets/${transcriptName}`
    );
    

    note: you can also pass the buffer to Readable.from

    more on Readable.from https://nodejs.org/api/stream.html#streamreadablefromiterable-options

    Similar errors requiring streams https://github.com/search?q=repo%3Apatrickjuchli%2Fbasic-ftp%20source.once&type=issues