在Node.js GraphQL API上整合Instagram基本显示API

424 阅读16分钟

在靠近用户的地方部署容器

本工程教育(EngEd)计划由科支持。

在全球范围内即时部署容器。Section是经济实惠、简单而强大的。

免费开始吧。

在Node.js GraphQL API上整合Instagram基本显示API

2021年7月1日

Instagram是一个在2010年推出的照片和视频分享的社交网络服务。它目前是使用最多的社交媒体应用程序之一,拥有超过10亿用户。

截至2019年10月,Instagram的母组织Facebook发布了Instagram基本显示API。该API允许用户获得其Instagram账户的个人资料信息、媒体(照片和视频)。限制条件是,你不能访问其他Instagram用户的数据。

目标

在这篇文章中,我们将在Node.js GraphQL API上整合Instagram基本显示API。

前提条件

要跟上本文的进度,必须具备以下条件。

  • 在你的电脑上安装Node.js
  • GraphQL的工作知识。
  • 对JavaScript的工作知识。

概述

创建一个Facebook开发者账户

要创建一个Facebook开发者账户,请遵循以下步骤。

创建一个应用程序

为了使用Instagram的API,我们需要创建一个应用程序。要做到这一点,我们将遵循以下步骤。

  • 在你的仪表板页面,在应用程序部分,点击创建应用程序按钮。

  • 在弹出的窗口中,选择消费者,然后点击继续

  • 输入你的应用程序显示名称,然后点击创建应用程序

  • 在随后的页面中,在产品部分,在Instagram基本显示产品上点击设置

  • 在接下来的页面中,阅读所提供的信息,然后点击下面的创建应用程序。在出现的弹出窗口中确认应用程序的名称。

  • 在产生的页面中,我们需要在提供的条目中添加一些有效的URL。对于这篇文章,我们将使用httpstat.us。这是一个根据请求的性质生成HTTP状态代码的服务。

    例如,一个*httpstat.us/200*将返回一个200 状态代码。

    在表格中,我们将输入链接,产生一个200 状态代码,如下所示

    urls-insta-display-app

  • App Review for Instagram Basic Display部分,点击Add to Submissionforinstagram_graph_user_profile_and_instagram_graph_user_media,以便能够访问Instagram的用户资料和媒体。

  • 点击下面的Save Changes 按钮。

添加一个Instagram测试用户

为了在开发中使用Instagram的基本显示API,我们将不得不添加一个测试用户。要做到这一点,我们将遵循以下步骤。

  • 在左边的侧边栏,点击 "角色",然后点击 "角色"。

  • 滚动到底部,并点击添加Instagram测试者按钮。

  • 在弹出的窗口中,输入你将在文章中使用的Instagram账户的用户名。确保它是一个你可以登录的Instagram账户,因为你将被要求接受发送的请求。

  • 在点击提交时,该账户将出现在该部分,并附有一个Pending 的文字。Instagram账户的所有者应该先接受它才是完整的。

  • 登录到你输入了用户名的那个特定Instagram账户。

  • 设置部分,找到应用程序和网站。在随后的部分,点击TESTER INVITES标签。你最近创建的应用程序应该列在那里,如下所示。

    tester-invites

    点击 "接受"按钮。

  • 好哇!!!你的Instagram应用现在已经配置好了,现在是时候设置我们的项目了。

设置项目

为了设置该项目,我们将遵循以下步骤。

  • 创建一个文件夹instagram-display-api-graphql

  • 打开VS Code到那个特定的文件夹。

  • 通过按**ctrl+shift+`**打开VS Code终端。

  • 在出现的终端中,键入.NET。

    npm init --y
    

    以默认设置初始化应用程序。

  • 按以下方式构建应用程序。project_structure

安装必要的依赖项

开始时,我们将安装整个应用程序所需的所有依赖项。

这些依赖项如下。

  • 快递。用于Node.js的极简网络应用框架。
  • apollo-server-express。用于为GraphQL服务器提供一个基于Express.js的集成。
  • axios。用于从Instagram API发送请求和接收响应。
  • cors。用于控制客户端访问。
  • dotenv。用于访问.env 文件中的环境变量。
  • graphql。用于为我们的API提供一个查询语言。
  • request。用于向Instagram API发送需要表单数据的请求并接收适当的响应。
  • nodemon。用于在我们做出改变时自动重新启动我们的Node.js服务器。

我们按以下方式安装它们。

npm i express apollo-server-express axios cors dotenv graphql request nodemon

获取授权代码

对于我们使用API,第一步是获得授权码。它提供了一个对Instagram API的认证机制。

为了获得授权码,我们遵循以下步骤。

  • 首先要获得我们应用程序的证书。要做到这一点,请进入你的仪表板页面。在左侧边栏的底部,点击Instagram基本显示基本显示

  • 在出现的页面中,向下滚动找到Instagram应用ID,和Instagram应用秘密,复制它们并适当地粘贴到项目根部的.env 文件中。你的.env 文件应该类似于。

    credentials

  • 在设置完你的证书后,我们应该在src/index.js 文件中添加以下内容来设置服务器了。

    const express = require("express");
    const cors = require("cors");
    require("dotenv").config();
    const PORT = process.env.PORT || 4000;
    
    // initialize express
    const app = express();
    
    // express configs
    app.use(cors()); // cors set up
    app.use(express.json()); // json format
    app.use(express.urlencoded({ extended: false })); // data parsing
    
    // routes
    
    // getting-authorization-code
    app.get("/get-auth-code", (req, res, next) => {
      return res.send(
        `<a href='https://api.instagram.com/oauth/authorize?client_id=${process.env.INSTAGRAM_APP_ID}&redirect_uri=${process.env.REDIRECT_URI}&scope=user_media,user_profile&response_type=code'> Connect to Instagram </a>`
      );
    });
    
    // start server on the PORT.
    app.listen(PORT, () => console.log(`Server started on port: ${PORT}`));
    

    从上面来看,我们是。

    • 要求我们需要的软件包。
    • 为我们的应用程序设置运行的端口。
    • 初始化Express。
    • 为express应用程序添加一些配置。
    • 设置获取授权码的路径。
    • 通过监听指定的端口来启动服务器。
  • 编辑package.json 中的scripts 部分,如下所示。

    scripts-section

  • 在你最近打开的VsCode终端,运行以下命令。

    npm run dev
    

    这将在PORT 4000上启动服务器。

  • 在你的网络浏览器中,打开http:localhost:4000/get-auth-code。在那里,点击链接 "连接到Instagram"以连接到你的Instagram账户。

  • 在弹出的窗口中,点击 "允许",之后你将被重定向到一个不同的页面。在这个新页面上,在URL部分,我们有一个代码参数,如下所示。url-code

    复制整个代码,直到我们有# 。不要包括# 。将代码粘贴到你的.env 文件。你的.env 文件现在应该类似于。

    new-env

获得短暂的访问令牌

在获得授权代码后,我们现在可以获得短命的访问令牌。它被定义为短暂的,因为它只在一个小时内有效。访问令牌通常会随着你向API发出的每一个认证请求一起发送。

为了获得短命的访问令牌,我们将遵循以下步骤。

  • 在我们的应用程序中引入Apollo server 。要做到这一点,我们将编辑我们的src/index.js ,如下所示。
    • 在顶部要求它作为一个包。

      const { ApolloServer } = require("apollo-server-express");
      
    • 要求类型定义和解析器。

      const typeDefs = require("./schema");
      const resolvers = require("./resolvers");
      
    • 在快速配置之后,我们将配置Apollo server ,如下所示。

      const server = new ApolloServer({ typeDefs, resolvers });
      server.start().then(() => {
        return server.applyMiddleware({ app });
      });
      

      上述配置接收了typeDefs,也就是模式解析器。服务器被启动,然后Express实例,App作为中间件被应用。

  • schema/index.js 文件中,我们设置了模式。
    • 首先要求gql ,从apollo-server-express 。它将为我们要写的查询增加一些亮点。

      const { gql } = require("apollo-server-express");
      
    • 我们定义了API在获得短期访问令牌时发送的响应模式。

      const AccessTokenResponse = gql`
        type AccessTokenResponse {
          access_token: String!
          user_id: Float!
        }
      `;
      

      响应将包括一个access_token ,它是一个String ,一个user_id ,它是一个Float

    • 然后,我们为该模式定义整体的Query 。它将容纳所有的方法和它们各自的响应模式。

      const Query = gql`
        type Query {
          getShortLivedAccessToken: AccessTokenResponse
        }
      `;
      

      从上面来看,方法getShortLivedAccessToken 将返回一个模式为AccessTokenResponse 的响应。

    • 然后我们导出Query ,以及AccessTokenResponse

      module.exports = [AccessTokenResponse, Query];
      

      我们把它导出为一个数组,因为在整个文章中,我们将定义其他模式。

  • 在模式中的定义之后,我们现在要解决解析器的问题。要做到这一点,请进入resolvers/Instagram.js
    • 首先需要必要的包。

      const { UserInputError } = require("apollo-server-express");
      const { get } = require("axios").default;
      const { post } = require("request");
      const { promisify } = require("util");
      require("dotenv").config();
      
    • UserInputError。将用于向用户发送一个错误。

    • get。用于向Instagram API发送GET请求。

    • post。用于向Instagram API发送POST请求,Form Data

    • promisify:用于将回调转为基于承诺的函数。

    • dotenv:用于加载环境变量。

    • 从请求中答应post 函数。

      const postAsync = promisify(post);
      
    • 初始化函数以获得access token

      async function getShortLivedAccessToken() {
        // sending the request.
        let { body, statusCode } = await postAsync({
          url: `https://api.instagram.com/oauth/access_token `,
          formData: {
            client_id: process.env.INSTAGRAM_APP_ID,
            client_secret: process.env.INSTAGRAM_APP_SECRET,
            redirect_uri: "https://httpstat.us/200",
            code: process.env.AUTHORIZATION_CODE,
            grant_type: "authorization_code",
          },
          headers: {
            "content-type": "multipart/form-data",
            host: "api.instagram.com",
          },
        });
      
        // getting the response.
        let response = JSON.parse(body);
      
        // checking the status code for error.
        if (statusCode !== 200) {
          let error_message = response.error_message;
          // if error exists, sending the error.
          return new UserInputError(error_message);
        }
      
        // if no error exists, returning the response.
        return response;
      }
      

从上面来看,我们是。

  • 向API发送请求。

  • 从API获得响应。

  • 检查响应的状态代码以检测错误。

  • 如果存在错误,发送错误信息。

  • 如果不存在错误,则发送响应。

  • 从文件中导出函数。

    module.exports = {
      getShortLivedAccessToken,
    };
    
  • resolvers/Instagram.js 文件中声明了函数后,我们还需要在resolvers/index.js 文件中使它被知道。从这个文件中,我们将导出我们在schema/index.js 文件中声明的一般Query 对象。因此,对于我们将在resolvers/Instagram.js 文件中声明的所有函数,我们必须在这里让它们每一个都知道。现在,我们将添加以下内容。

    // get the defined function(s)
    const { getShortLivedAccessToken } = require("./instagram");
    
    // general query object
    const Query = {
      Query: {
        getShortLivedAccessToken: () => getShortLivedAccessToken(),
      },
    };
    
    // export the Query object
    module.exports = Query;
    
  • 在把getShortLivedAccessToken添加到resolvers/index.js ,我们就可以测试这个功能了。为此,我们将遵循以下步骤。

  • 如果尚未启动开发服务器,则通过运行来启动。

    npm run dev
    
    • 从你的浏览器中,访问:http://localhost:4000/graphql.

    • 在左边提供的空间中,写下以下查询。

      query GetShortToken{
        getShortLivedAccessToken{
          access_token
          user_id
        }
      }
      

上述查询调用getShortLivedAccessToken 方法,然后从该方法的响应中提取access_tokenuser_id

  • 点击左侧窗格和右侧窗格中间对齐的播放按钮。

  • 观察结果。如果你得到一个无效的client secretcode 的错误,或者你的authorization code 已经过期,请重温上一步,通过按ctrl + c 来停止它,然后按npm run dev 来启动它,手动重启服务器。否则,如果你没有得到错误,你在右边的响应应该类似于。

short-lived-at-response

  • 将响应中的访问令牌值复制到你的.env 文件。你的.env 文件现在应该类似于。

env-with-sat

获得长效访问令牌

由于短命的访问令牌具有有限的时间空间,所以生成具有较长时间空间的访问令牌是至关重要的。它们被称为长效访问令牌。它们的有效期为60天

为了得到一个长寿命的访问令牌,我们将遵循以下步骤。

  • schema/index.js ,我们添加其模式定义如下。

    const LongLivedAccessToken = gql`
      type LongLivedAccessToken {
        access_token: String!
        token_type: String!
        expires_in: Float!
      }
    `;
    

    上述模式定义了获取长效访问令牌的响应将包括:一个访问令牌,一个令牌类型,和一个过期值。

  • 在查询对象中添加获取长效访问令牌的方法。

    const Query = gql`
      type Query {
        getShortLivedAccessToken: AccessTokenResponse
        getLongLivedAccessToken: LongLivedAccessToken
      }
    `;
    
  • 将模式定义添加到导出的数组中。

    module.exports = [AccessTokenResponse, LongLivedAccessToken, Query];
    
  • 导出模式后,我们进行resolvers/Instagram.js ,并定义一个函数,从API中获取长效访问令牌

    // getting a long lived access token
    async function getLongLivedAccessToken() {
      let response;
    
      try {
        // send a request to the API
        response = await get("https://graph.instagram.com/access_token", {
          params: {
            grant_type: "ig_exchange_token",
            client_secret: process.env.INSTAGRAM_APP_SECRET,
            access_token: process.env.SHORT_LIVED_AT,
          },
          headers: {
            host: "graph.instagram.com",
          },
        });
      } catch (error) {
        // If an error occurs, return it.
        return new UserInputError(error);
      }
    
      // If no error, get the response and return it.
      response = response["data"];
      return response;
    }
    

    从上面来看,我们是。

  • 向API发送一个GET请求。

  • 听取任何可能发生的错误并将其返回。

  • 如果没有错误发生,我们将发送回响应。

  • 将该函数添加到导出的对象中。

module.exports = {
  getShortLivedAccessToken,
  getLongLivedAccessToken,
};
  • resolvers/index.js 文件中,导入该函数。

    const {
      getShortLivedAccessToken,
      getLongLivedAccessToken,
    } = require("./instagram");
    
    • 把它添加到查询对象中。

      const Query = {
        Query: {
          getShortLivedAccessToken: () => getShortLivedAccessToken(),
          getLongLivedAccessToken: () => getLongLivedAccessToken(),
        },
      };
      
  • 之后,我们就可以测试功能了。要做到这一点。

  • 确保你的开发服务器已经启动并运行。

  • 在你的浏览器中,在我们之前的同一标签中,点击+ ,打开另一个窗格。

  • 在产生的窗格中,在左边,添加以下查询。

      query GetLongLivedToken {
        getLongLivedAccessToken{
          access_token
          token_type
          expires_in
        }
     }

上述查询调用getLongLivedAccessToken方法并提取_access_token、token_typeexpires_in

  • 点击中间的播放按钮,观察结果。
  • 如果你的短命访问令牌已经过期,请转到上一个步骤。否则,你的响应应该类似于。

long-lived-at-response

  • 从响应中复制你的访问令牌到你的.env 文件。你的.env 文件应该类似于。

env-with-llat.png

获取用户资料数据

在一个Instagram账户上,我们可以获得该特定账户的个人资料数据。这里的个人资料数据涉及账户类型ID媒体数量用户名

为了实现上述功能,我们将按照以下步骤进行。

  • schema/index.js 中添加其模式定义。

    const ProfileData = gql`
      type ProfileData {
        account_type: String!
        id: String!
        media_count: Int!
        username: String!
      }
    `;
    

从上面来看,我们要将我们的响应设置为包含account_typeidmedia_countusername,因为这是我们想要得到的东西。

  • 将获取个人资料数据的方法添加到查询对象中。

    const Query = gql`
      type Query {
        getShortLivedAccessToken: AccessTokenResponse
        getLongLivedAccessToken: LongLivedAccessToken
        getProfileData: ProfileData
      }
    `;
    
  • 将上面定义的模式添加到导出的数组中。

    module.exports = [
      AccessTokenResponse,
      LongLivedAccessToken,
      ProfileData,
      Query,
    ];
    
  • 在定义了模式后,我们在resolvers/Instagram.js 文件中设置了从API中获取个人资料数据的函数,如下所示。

    // getting profile data
    async function getProfileData() {
      let response;
      // send request to the API
      try {
        response = await get("https://graph.instagram.com/me", {
          params: {
            fields: "id,username,media_count,account_type",
            access_token: process.env.LONG_LIVED_AT,
          },
          headers: {
            host: "graph.instagram.com",
          },
        });
      } catch (error) {
        // catch and return the error
        return new UserInputError(error);
      }
    
      // get the data and return it.
      response = response["data"];
      return response;
    }
    

从上面来看,我们是。

  • 向API发送请求。

  • 监听任何发生的错误。如果有,我们就返回错误。

  • 否则,如果没有错误,我们返回发送的数据。

  • 将上述函数添加到导出的对象中。

    module.exports = {
      getShortLivedAccessToken,
      getLongLivedAccessToken,
      getProfileData,
    };
    
  • resolvers/index.js ,导入该函数。

const {
    getShortLivedAccessToken,
    getLongLivedAccessToken,
    getProfileData,
  } = require("./instagram");
  • 将该函数添加到查询对象中。
const Query = {
  Query: {
    getShortLivedAccessToken: () => getShortLivedAccessToken(),
    getLongLivedAccessToken: () => getLongLivedAccessToken(),
    getProfileData: () => getProfileData(),
  },
};
  • 测试功能。

  • 确保开发服务器已经启动并运行。

  • 在与之前相同的浏览器标签中,点击+ ,打开一个单独的窗格。在窗格的左侧,添加以下查询。

query getProfileData {
  getProfileData{
    account_type
    id
    media_count
    username
  }
}

从上面来看,我们正在调用getProfileData函数并提取account_type**,id**,media_count**,username

  • 点击中间的播放按钮,如果一切正常,你应该收到一个类似的回应。

profile-data-response

如果出现错误,请重温一下步骤。

获取用户的媒体数据

媒体数据是用户在他或她的Instagram账户中发布的数据。前面过程中的media_count值是用户发布的媒体数据的计数。

这里的媒体可以是一张照片,一段视频,或者一个旋转木马相册。为了设置获取用户的媒体的功能,我们将按照以下步骤进行。

  • 首先,为我们将要接收的数据设置模式。
const MediaData = gql`
  scalar Date
  type MediaData {
    caption: String
    id: String
    media_type: String
    media_url: String
    permalink: String
    thumbnail_url: String
    timestamp: Date
    username: String
  }
`;

从上面来看,我们设定媒体数据将包括标题ID*、media_type*、media_urlpermalinkthumbnail_urltimestampusername

  • 在查询对象中添加获取用户媒体数据的方法。
const Query = gql`
  type Query {
    getShortLivedAccessToken: AccessTokenResponse
    getLongLivedAccessToken: LongLivedAccessToken
    getProfileData: ProfileData
    getUserMediaData: [MediaData]
  }
`;

从上面来看,我们要添加getUserMediaData方法,它将返回一个MediaData类型的数据数组。

  • MediaData类型添加到导出的数组中。
module.exports = [
  AccessTokenResponse,
  LongLivedAccessToken,
  ProfileData,
  MediaData,
  Query,
];
  • resolvers/Instagram.js ,我们设置了一个获取媒体数据的函数,如下所示。
// getting media data
async function getUserMediaData() {
  let response;

  // sending request to API
  try {
    response = await get("https://graph.instagram.com/me/media", {
      params: {
        fields:
          "id,caption,media_url,media_type,permalink,thumbnail_url,timestamp,username",
        access_token: process.env.LONG_LIVED_AT,
      },
      headers: {
        host: "graph.instagram.com",
      },
    });
  } catch (error) {
    // Catching an error, and returning it.
    return new UserInputError(error);
  }

  // If no error, returning the response.
  response = response["data"];
  return response.data;
}

从上面来看,我们是。

  • 向API发送请求。

  • 倾听任何错误,捕捉它,并返回它。

  • 如果没有错误,从API返回响应。

  • 将该函数添加到导出的对象中。

module.exports = {
  getShortLivedAccessToken,
  getLongLivedAccessToken,
  getProfileData,
  getUserMediaData,
};
  • resolvers/index.js

  • 导入该函数。

    const {
      getShortLivedAccessToken,
      getLongLivedAccessToken,
      getProfileData,
      getUserMediaData,
    } = require("./instagram");
    
  • 将该函数添加到查询对象中。

    const Query = {
      Query: {
        getShortLivedAccessToken: () => getShortLivedAccessToken(),
        getLongLivedAccessToken: () => getLongLivedAccessToken(),
        getProfileData: () => getProfileData(),
        getUserMediaData: () => getUserMediaData(),
      },
    };
    
  • 为了测试功能。

  • 确保开发服务器已经启动并运行。

  • 在你的浏览器中,在前一个标签中,点击+ ,打开一个单独的标签。在新标签页的左边窗格中,添加以下查询。

    query getMediaData{
      getUserMediaData{
        caption
        id
        media_type
        media_url
        permalink
        thumbnail_url
        timestamp
        username
    
      }
    }
    

下面的查询调用getUserMediaData函数,并从响应中提取标题IDmedia_type、media_url、permalinkthumbnail_url、timestamp_、username_。

  • 点击中间的播放按钮。观察右侧的响应。如果你遇到任何错误,重温一下步骤。否则,如果你有一些媒体发布到该Instagram帐户,你的反应应该是类似的。

media-data-response

如果你没有发布一些媒体数据,你的响应将是一个空数组。

总结

在这篇文章中,我们通过以下步骤成功地在Node.js GraphQL API上集成了Instagram的基本显示API。

参考资料

为了获得更多关于本文所涉及的工具和技术的见解,最好是通过以下资源。

总结

通过Instagram的基本显示API,你可以将Instagram账户整合到各种应用程序中,以提供各种自动化方案。

在最终完成的代码中,可以从这个GitHub仓库访问,其中增加了关于以下用例的功能。

  • 获取单个媒体的信息。
  • 获取一个相册的信息。
  • 刷新一个长期存在的访问令牌。

请务必检查一下。

快乐的黑客攻击!!


同行评审贡献者::Adrian Murage

类似文章

[

How to Create a Reusable React Form component Hero Image

语言

如何创建一个可重复使用的React表单组件

阅读更多

](www.section.io/engineering…

Building a payroll system with next.js Hero Image

语言, Node.js

用Next.js构建一个薪资系统

阅读更多信息

](www.section.io/engineering…

Creating and Utilizing Decorators in Django example image

架构

在Django中创建和使用装饰器

阅读更多内容

](www.section.io/engineering…)