• BSA Lab.
      home

  • apps
    Главная
  • contacts
    Об авторе
  • library_books
    Блог
  • shop
    Портфолио
    keyboard_arrow_down
    • Google API
    • Gapi-People
      wc
    • Gapi-Email
      mail_outline
    • Gapi-Examples
      more

    • Silex (PHP micro-framework)
    • Silex-MVC
      desktop_windows
    • Silex-UBKI
      last_page

    • Zend (PHP framework)
    • ZF-MyBlog
      library_books
    • ZF2-ASM
      show_chart

    • Node.js
    • Express-Passport
      verified_user
    • Feathers-Examples
      more

    • Vue.js (JavaScript framework)
    • Vue-Resume
      account_circle
    • Vue-Business-Light
      work
    • Vue-Examples
      more
    • Vuex-Examples
      more

    • Nuxt (JavaScript framework)
    • Nuxt-Business-Light
      work
    • Nuxt-Vuetify-Start
      picture_in_picture

  • Темы
  • message
    WEB ресурсы
    keyboard_arrow_down
    • Обзор
      filter_none

  • message
    Google Client API
    keyboard_arrow_down
    • Обзор
      filter_none
    • Gmail-Send
      contact_mail
    • Gmail-Inbox
      mail_outline
BSA / Portfolio-gapi-examples
  • Информация

  • contact_mail
    Контакты
  • contacts
    Об авторе
  • public
    Мои проекты на GitHub
Google API - примеры
Демонстрация работы Google API сервисов.

2017-11-14

shop

Введение.

В приложении представленны примеры, которые демонстрируют использование некоторых Google сервисов, таких как People, GMail и т.д. Само приложение разработано с помощью Nuxt.js. Nuxt.js — это фреймворк для универсальных приложений на Vue.js.

Этот проект на GitHub можно посмотреть здесь

Демонстрацию этого проекта можно посмотреть здесь

Ресурсы

Google API
Google API Клиентская Библиотека для JavaScript
Google People API
Документация
Method: people.get
Method: people.connections.list
Gmail API
Документация
Структура электронного сообщения
RFC 1521 — Почтовый стандарт MIME
RFC 5322 — Формат сообщений Internet (IMF)
Nuxt.js
Документация
Vue.js
Vue Router
Vuex

Работа приложения

Это приложение демонстрирует работу следующих Google сервисов:

People API

  • Method: people.get
  • Method: people.connections.list

Gmail API

  • Method: users.messages: send
  • Methods: users.messages: list/get

Установка/Конфигурация/Построение приложения

Приложение можно установить с GitHub, варианты построения приложения можно посмотреть в пр.1.

пр.1

    # install dependencies
    $ npm install # Or yarn install

    # environment variables
    # Add file "app/env.js" to your project to set user environment variables.
    # See the sample file "app/env.example.js".

    # serve with hot reload at localhost:3000
    $ npm run dev

    # build for production and launch server
    $ npm run build
    $ npm start

    # generate static project
    $ npm run generate

Структура приложения

Приложение имеет следующую структуру см. пр.2.

пр.2

    |--gapi-examples
    |-- app/
    |  |-- assets/          # Un-compiled assets such as Less, Sass or JavaScript
    |  |-- components/      # Vue.js Components
    |  |-- config/          # Configuration files
    |  |-- layouts/         # Application Layouts
    |  |-- middleware/      # Application Middleware (functions that can be run before rendering)
    |  |-- pages/           # Application Views and Routes
    |  |-- plugins/         # Javascript plugins
    |  |-- static/          # Static files. (each file inside this directory is mapped to "/")
    |  |-- store/           # Vuex Store files
    |  |-- env.example.js   # Example of env.js (user configuration file)
    |  `-- env.js           # User configuration file
    |
    |-- docs/               # folder created with the command ($ npm run generate)
    |-- node_modules/       # folder created with the command ($ npm install # Or yarn install)
    |-- .gitignore          # Git ignore file
    |-- LICENSE.md          # License file
    |-- nuxt.config.js      # Nuxt configuration file
    |-- package.json        # NPM configuration file
    `-- README.md           # Readme file

Загрузка/Инициализация клиенской библиотеки Google API

Вначале нужно загрузить и инициализировать клиенскую библиотеку Google API см. пр.3. Загрузка происходит с помощью функции loadGapi() при создании компонента в модуле /app/layouts/default.vue.

пр.3


    ...

    /**
    * Google Client load/init
    * @param params (Object)
    *  etc. {
    *  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    *  clientId: 'xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
    *  discoveryDocs: [ 'https://people.googleapis.com/$discovery/rest?version=v1',
    *                   'https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest'],
    *  scope: 'profile
    *          https://www.googleapis.com/auth/contacts.readonly
    *          https://www.googleapis.com/auth/gmail.readonly
    *          https://www.googleapis.com/auth/gmail.send'
    *  }
    * @return {Promise}
    */
    loadClient (params) {
        return new Promise(function (resolve, reject) {
            _loadGoogleApi().then(function () {
                if (debug) {
                    console.log('loadGoogleAPI - OK')
                }
                return _initClient(params)
            }).then(function () {
                if (debug) {
                    console.log('googleClient.init - OK')
                }
                // Load gmail library
                window.gapi.client.load('gmail', 'v1', resolve)
            })
        })
    }

    /**
    * Load google api
    * @return {Promise}
    * @private
    */
    _loadGoogleApi () {
        return new Promise(function (resolve, reject) {
            const script = document.createElement('script')
            script.src = 'https://apis.google.com/js/platform.js'
            script.onreadystatechange = script.onload = function () {
                if (!script.readyState || /loaded|complete/.test(script.readyState)) {
                    setTimeout(function () {
                        resolve()
                    }, 500)
                }
            }
            document.getElementsByTagName('head')[0].appendChild(script)
        })
    }

    /**
    * Google client  load/init
    * @param params (Object)
    *  etc. {
    *  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    *  clientId: 'xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
    *  discoveryDocs: [ 'https://people.googleapis.com/$discovery/rest?version=v1',
    *                   'https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest'],
    *  scope: 'profile
    *          https://www.googleapis.com/auth/contacts.readonly
    *          https://www.googleapis.com/auth/gmail.readonly
    *          https://www.googleapis.com/auth/gmail.send'
    *  }
    * @return {Promise}
    * @private
    */
    _initClient (params) {
        return new Promise(function (resolve, reject) {
            // Client Init
            const initClient = function () {
                window.gapi.client.init(params).then(() => {
                    resolve()
                }, (error) => {
                    console.error('gapi.client.init - Error', error)
                    alert(`gapi.client.init - Error: ${error.error}\n Details: ${error.details}`)
                })
            }
            window.gapi.load('client:auth2', initClient)
        })
    }

    ...

Авторизация пользователя на Google сервере

В приложении авторизация пользователя происходит на странице сайта Login. Без авторизации пользователя доступ к демонстрационным примерам - запрещен! Авторизация пользователя происходит в модуле /app/pages/login.vue с помощью функции GoogleAuth.signIn(), см. пр.4.

пр.4


    ...

    /**
    * Google SignIn
    * @param successCallback (Function)
    * @param errorCallback (Function)
    */
    signIn (successCallback, errorCallback) {
        window.gapi.auth2.getAuthInstance().signIn().then(function (googleUser) {
            successCallback(googleUser)
            if (debug) {
                console.log('GoogleAuth.signIn - OK')
            }
        }, function (error) {
            errorCallback(error)
            console.log('GoogleAuth.signIn - Error: ', error)
        })
    }

    ...

Google People API (Method: people.get)

В приложении эта операция выполняется в модуле /app/pages/services/people-get.vue по адресу /services/people-get При этом мы можем получить иноформацию для конкретного пользователя по его уникальному имени. Используя имя people/me мы получим информацию о самом авторизированном пользователе см. пр.5.

пр.5


        ...

        getMyNames() {
          return new Promise((resolve, reject) => {
            window.gapi.client.people.people.get({
              'resourceName': 'people/me',
              'personFields': 'names,emailAddresses'
            }).then((resp) => {
              const names = resp.result.names[0]
              if (debug) {
                console.log('api.people.get - Executed: ')
              }
              resolve(names)
            }, (error) => {
              console.log('people.get - Error. ', `Error: ${error}`)
              alert(`Error: ${error}`)
            })
          })
        }

        ...

Google People API (Method: people.connections.list)

В приложении эта операция выполняется в модуле /app/pages/services/people-connections.vue по адресу /services/people-connections Обеспечивает список авторизированных пользовательских контактов, и их профайлов см. пр.6.

пр.6


        ...

        getMyConnections() {
          let myConnections = []
          return new Promise((resolve, reject) => {
            window.gapi.client.people.people.connections.list({
              'resourceName': 'people/me',
              'pageSize': 10,
              'personFields': 'names,emailAddresses'
            }).then(function (response) {
              const connections = response.result.connections
              if (connections.length > 0) {
                for (let i = 0; i < connections.length; i++) {
                  const person = connections[i]
                  if (person.names && person.names.length > 0) {
                    myConnections.push(person.names[0].displayName)
                  } else {
                    myConnections.push('No display name found for connection.')
                  }
                }
              } else {
                myConnections.push('No upcoming events found.')
              }
              if (debug) {
                console.log('api.people.connections - Executed')
              }
              resolve(myConnections)
            }, (error) => {
              console.log('people.connections - Error. ', `Error: ${error}`)
              alert(`Error: ${error}`)
            })
          })
        }

        ...

Передача email сообщений (Method: users.messages: send)

В приложении эта операция выполняется в модуле /app/pages/services/gmail-send-message.vue по адресу /services/gmail-send-message Этот метод отправляет указанное сообщение получателям в To, Cc, Bcc заголовках. см. пр.7.

пр.7


    ...

    /**
    * Send email
    * @param params
    * etc.{
    userId: 'me',
    to: my@test.com,
    subject: Request for my resume from the employer,
    message: 'My Message!',
    callback: function () {
    ....
    }
    * }
    */
    send (params) {
        try {
            const headers = {
                'To': params.to,
                'Subject': params.subject,
                'Content-Type': 'text/html; charset="UTF-8"'
            }

            let email = ''
            _.forEach(headers, function (value, key) {
                email += `${key}: ${value}` + '\r\n'
            })

            email += '\r\n' + params.message
            const base64EncodedEmail = _b64UrlEncodeUnicode(email)
            const sendRequest = window.gapi.client.gmail.users.messages.send({
                'userId': params.userId,
                'resource': {
                    'raw': base64EncodedEmail
                }
            })
            sendRequest.execute(params.callback)
        } catch (e) {
            throw e
        }
    }

    /**
    * To encode the unicode string into Base64-encoded-url value
    *
    * @param str
    * @return {string}
    */
    _b64UrlEncodeUnicode (str) {
        // first we use encodeURIComponent to get percent-encoded UTF-8,
        // then we convert the percent encodings into raw bytes which
        // can be fed into btoa.
        const b64Encoded = btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
            function toSolidBytes (match, p1) {
                return String.fromCharCode('0x' + p1)
            }))
        // Replace for URL
        return b64Encoded.replace(/\+/g, '-').replace(/\//g, '_')
    }

    ...

Получение сообщений в формате (text/html; charset="UTF-8")

В приложении эта операция выполняется в модуле /app/pages/services/gmail-display-inbox.vue по адресу /services/gmail-display-inbox Для получения сообщений в формате (text/html; charset="UTF-8") используются команды (Users.messages: list/get) см. пр.8.

пр.8


    ...

   /**
   * Get inbox messages
   * @param params
   * etc. {
      userId: 'me',
      labelIds: 'INBOX',
      maxResults: 10
   * }
   * @return {Promise}
   */
  getInbox (params) {
    let arrPromises = []
    return new Promise((resolve, reject) => {
        _getMyMessagesList(params)
        .then(list => {
          _.forEach(list, function (item) {
            arrPromises.push(_getMessageForId(item.id, params.userId))
          })
          const allPromises = Promise.all(arrPromises)
          resolve(allPromises)
        })
    })
  }

  _getMyMessagesList (params) {
    // Execute this request for 'gmail.users.messages.list'
    const request = window.gapi.client.gmail.users.messages.list(params)
    return new Promise((resolve, reject) => {
      request.execute(function (response) {
        if (debug) {
          console.log('api.gmail.users.messages.list - Executed: ', response.messages)
        }
        resolve(response.messages)
      })
    })
  }

  _getMessageForId (id, userId) {
    let _message = {}
    // Execute this request for 'gmail.users.messages.get'
    const messageRequest = window.gapi.client.gmail.users.messages.get({
      'userId': userId,
      'id': id
    })
    return new Promise((resolve, reject) => {
      messageRequest.execute(message => {
        // Parsing  message
        _message.id = message.id
        _message.from = _getHeader(message.payload.headers, 'From')
        _message.subject = _getHeader(message.payload.headers, 'Subject')
        _message.date = _getHeader(message.payload.headers, 'Date')
        _message.reply_to = _getHeader(message.payload.headers, 'Reply-to')
        _message.message_id = _getHeader(message.payload.headers, 'Message-ID')
        _message.body = _getBody(message.payload)
        if (debug) {
          console.log('api.gmail.users.messages.get - Executed: ', _message)
        }
        resolve(_message)
      })
    })
  }

  _getHeader (headers, index) {
    let headerValue = ''
    _.forEach(headers, function (header) {
      if (header.name.toLowerCase() === index.toLowerCase()) {
        headerValue = header.value
      }
    })
    return headerValue
  }

  _getBody (message) {
    var encodedBody = ''
    try {
      if (typeof message.parts === 'undefined') {
        encodedBody = message.body.data
      } else {
        encodedBody = _getHTMLPart(message.parts)
      }
      return _b64UrlDecodeUnicode(encodedBody)
    } catch (error) {
      console.error('apiGmail._getBody - Error', error)
      throw error
    }
  }

  _getHTMLPart (arr) {
    for (let x = 0; x <= arr.length; x++) {
      if (typeof arr[x].parts === 'undefined') {
        if (arr[x].mimeType === 'text/html') {
          return arr[x].body.data
        }
      } else {
        return _getHTMLPart(arr[x].parts)
      }
    }
    return ''
  }

  /**
   * To decode the Base64-encoded-url value back into a String
   *
   * @param str
   * @return {string}
   */
  _b64UrlDecodeUnicode (str) {
    const encodedBody = str.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(encodedBody).split('').map(function (c) {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    }).join(''))
  }

    ...

© 2017 Сергей Бескоровайный
language Разработчик:
BSA Lab.