pipedream icon indicating copy to clipboard operation
pipedream copied to clipboard

[BUG] Twitter actions are using camelCase instead of snake_case

Open ctrlaltdylan opened this issue 3 years ago • 0 comments

Describe the bug It appears the mediaIds prop is using camel case in the Create Tweet action here:

https://github.com/PipedreamHQ/pipedream/blob/23144807af52ffb2512fe3c064e6ae76cc7c0eae/components/twitter/twitter.app.mjs#L308

However, the Twitter API is expecting snake_case like media_ids.

I believe this is causing problems with users trying to create Tweets.

To Reproduce Steps to reproduce the behavior:

  1. Use this code step to attempt to generate a media_id for associating with a Tweet:
import axios from 'axios';
import { axios as platformAxios } from '@pipedream/platform';

// To use previous step data, pass the `steps` object to the run() function
export default defineComponent({
  props: {
    twitter: {
      type: 'app',
      app: 'twitter'
    },
    url: {
      type: 'string',
      label: "Photo URL",
      description: 'Full URL to the image to download then upload to a Tweet',
    },
    media_type: {
      type: 'string',
      label: "Media Type",
      description: 'The MIME type of the media being uploaded. See https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-init'
    }
  },
  async run({ steps, $ }) {
    // Data we need to make the Twitter API request
    const oauthSignerUri = this.twitter.$auth.oauth_signer_uri
    const token = {
      key: this.twitter.$auth.oauth_access_token,
      secret: this.twitter.$auth.oauth_refresh_token,
    }
    const signConfig = {
      token,
      oauthSignerUri
    }

    // Download image, base64 encode it, then upload the media to Twitter
    const imageResponse = await axios({
      url: this.url,
      method: "GET",
      responseType: "arraybuffer"
    })

    const file = Buffer.from(imageResponse.data, 'binary')
    const total_bytes = file.length
    const base64EncodedFile = file.toString('base64')
    const media_type = this.media_type;

    // First, tell Twitter the type of file you're uploading, how big it is, etc.
    // https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-init
    const mediaUploadInitRequest = {
      method: 'POST',
      data: '',
      url: "https://upload.twitter.com/1.1/media/upload.json",
      params: {
        command: "INIT",
        total_bytes,
        media_type,
      }
    }

    // Twitter returns a media_id_string that we use to upload the file,
    // and to reference it in future steps
    const uploadMediaInitResponse = await platformAxios($, mediaUploadInitRequest, signConfig)
    $.export('uploadMediaInitResponse', uploadMediaInitResponse);
    const mediaIdString = uploadMediaInitResponse.media_id_string;
    $.export('mediaIdString', mediaIdString);

    // Split the file into chunks, APPEND each chunk
    const splitStringRe = new RegExp('.{1,' + 1000 + '}', 'g');
    const chunks = base64EncodedFile.match(splitStringRe);

    for (const [segment_index, media_data] of chunks.entries()) {
      console.log(`Processing chunk ${segment_index}`)
      // APPEND file content in chunks
      // See https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-append
      const mediaUploadAppendRequest = {
        method: 'POST',
        data: '',
        url: "https://upload.twitter.com/1.1/media/upload.json",
        params: {
          command: "APPEND",
          media_id: this.mediaIdString,
          segment_index,
          media_data,
        }
      }
      await platformAxios($, mediaUploadAppendRequest, signConfig)
    }

    // Finally, tell Twitter we're done uploading
    // https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-finalize
    const mediaUploadFinalizeRequest = {
        method: 'POST',
        data: '',
        url: "https://upload.twitter.com/1.1/media/upload.json",
        params: {
          command: "FINALIZE",
          media_id: mediaIdString,
        }
      }
      await platformAxios($, mediaUploadFinalizeRequest, signConfig)
  },
})
  1. Attempt to associate that image with a Create Tweet action and include that media ID in the mediaIds prop.
  2. See that no image is uploaded to the tweet.

Expected behavior I expect to be able to use all Twitter props.

Screenshots

Please see this public thread for additional information: https://pipedream.com/community/t/advice-for-uploading-media-to-twitter-in-v2/2866/9

Additional context

See this official Twitter tutorial for uploading images and sending them in tweets:

https://developer.twitter.com/en/docs/tutorials/uploading-media

ctrlaltdylan avatar Jul 25 '22 19:07 ctrlaltdylan