/* eslint-disable no-underscore-dangle */
/* eslint-disable better-mutation/no-mutating-methods */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import xml from 'xml-js'
import Icon from './icon'
import ButtonContent from './button-content'
import { extractTitleFromEntry, extractEmailFromEntry, extractPhoneNumberFromEntry } from './utils'
const SCOPE = 'https://www.googleapis.com/auth/spreadsheets.readonly'
const MAX_RESULTS = '999' // TODO Make this parametable or paginate
class GoogleContacts extends Component {
constructor(props) {
super(props)
this.signIn = this.signIn.bind(this)
this.handleImportContacts = this.handleImportContacts.bind(this)
this.handleParseContacts = this.handleParseContacts.bind(this)
this.state = {
hovered: false,
active: false
}
}
componentDidMount() {
const { jsSrc } = this.props
;((d, s, id, cb) => {
const element = d.getElementsByTagName(s)[0]
const fjs = element
let js = element
js = d.createElement(s)
js.id = id
js.src = jsSrc
if (fjs && fjs.parentNode) {
fjs.parentNode.insertBefore(js, fjs)
} else {
d.head.appendChild(js)
}
js.onload = cb
})(document, 'script', 'google-contacts')
}
handleImportContacts(res) {
const { onFailure } = this.props
if (res) {
const authResponse = res.getAuthResponse();
window.gapi.load('client', () => {
window.gapi.client
.request({
path: '/m8/feeds/contacts/full',
params: { 'max-results': MAX_RESULTS},
headers: {
'GData-Version': '3.0',
Authorization: `Bearer ${authResponse.access_token}`
}
})
.then(response => this.handleParseContacts(response), err => onFailure(err))
})
}
}
handleParseContacts(response) {
const { onSuccess } = this.props
// Now let's parse the XML...
const options = { ignoreDeclaration: true, ignoreComment: true, compact: true }
const parsed = xml.xml2js(response.body, options)
// Iterate over each contact.
const results = []
Object.keys(parsed.feed.entry).forEach(key => {
if (
parsed.feed.entry[key] &&
parsed.feed.entry[key]['gd:email'] &&
parsed.feed.entry[key]['gd:email']._attributes &&
parsed.feed.entry[key]['gd:email']._attributes.address
) {
results.push({
title: extractTitleFromEntry(parsed.feed.entry[key]),
email: extractEmailFromEntry(parsed.feed.entry[key]),
phoneNumber: extractPhoneNumberFromEntry(parsed.feed.entry[key])
})
}
})
onSuccess(results)
}
signIn(e) {
const {
clientId,
cookiePolicy,
loginHint,
hostedDomain,
redirectUri,
discoveryDocs,
onRequest,
onFailure,
uxMode,
accessType,
responseType,
prompt,
onSuccess
} = this.props
const params = {
client_id: clientId,
cookie_policy: cookiePolicy,
login_hint: loginHint,
hosted_domain: hostedDomain,
discoveryDocs,
ux_mode: uxMode,
redirect_uri: redirectUri,
scope: SCOPE,
access_type: accessType
}
if (responseType === 'code') {
params.access_type = 'offline'
}
if (e) {
e.preventDefault() // to prevent submit if used within form
}
if (!this.state.disabled) {
const _signIn = () => {
const auth2 = window.gapi.auth2.getAuthInstance()
const options = { prompt }
onRequest()
if (responseType === 'code') {
auth2.grantOfflineAccess(options).then(res => onSuccess(res), err => onFailure(err))
} else {
auth2.signIn(options).then(res => this.handleImportContacts(res), err => onFailure(err))
}
}
window.gapi.load('auth2', () => {
if (!window.gapi.auth2.getAuthInstance()) {
window.gapi.auth2.init(params).then(_signIn)
} else {
_signIn()
}
})
}
}
render() {
const { tag, type, className, disabledStyle, buttonText, children, render, theme, icon } = this.props
const disabled = this.state.disabled || this.props.disabled
if (render) {
return render({ onClick: this.signIn })
}
const initialStyle = {
backgroundColor: theme === 'dark' ? 'rgb(66, 133, 244)' : '#fff',
display: 'inline-flex',
alignItems: 'center',
color: theme === 'dark' ? '#fff' : 'rgba(0, 0, 0, .54)',
boxShadow: '0 2px 2px 0 rgba(0, 0, 0, .24), 0 0 1px 0 rgba(0, 0, 0, .24)',
padding: 0,
borderRadius: 2,
border: '1px solid transparent',
fontSize: 14,
fontWeight: '500',
fontFamily: 'Roboto, sans-serif'
}
const hoveredStyle = {
cursor: 'pointer',
opacity: 0.9
}
const activeStyle = {
cursor: 'pointer',
backgroundColor: theme === 'dark' ? '#3367D6' : '#eee',
color: theme === 'dark' ? '#fff' : 'rgba(0, 0, 0, .54)',
opacity: 1
}
const defaultStyle = (() => {
if (disabled) {
return Object.assign({}, initialStyle, disabledStyle)
}
if (this.state.active) {
if (theme === 'dark') {
return Object.assign({}, initialStyle, activeStyle)
}
return Object.assign({}, initialStyle, activeStyle)
}
if (this.state.hovered) {
return Object.assign({}, initialStyle, hoveredStyle)
}
return initialStyle
})()
const googleLoginButton = React.createElement(
tag,
{
onMouseEnter: () => this.setState({ hovered: true }),
onMouseLeave: () => this.setState({ hovered: false, active: false }),
onMouseDown: () => this.setState({ active: true }),
onMouseUp: () => this.setState({ active: false }),
onClick: this.signIn,
style: defaultStyle,
type,
disabled,
className
},
[
icon && <Icon key={1} active={this.state.active} />,
<ButtonContent icon={icon} key={2}>
{children || buttonText}
</ButtonContent>
]
)
return googleLoginButton
}
}
export default GoogleContacts
In React project I need to login with gamil and get contacts of user I found package called Googlecontacts.This is code of the GoogleContacts package to get contacts from Google API, But I'm getting the 403 error. This error shows that my scope is wrong! I tried a lot of scopes but I coudn't get contacts of gamil. What is the right scope for google contacts?
The google contacts api requires that your user grant your application access to their contacts data with one of the following scopes
You apear to be using
const SCOPE = 'https://www.googleapis.com/auth/spreadsheets.readonly'
Which is not going to grant you access to the users Google contacts only their Google sheets. Which is what the following message is telling you
Request had insufficient authentication scopes with google contacts
Google contacts has nothing to do with Gmail. Google contacts is its own system.
The contacts api will only return the contacts that the user has added to Google contacts. While contacts and gmail are softly linked your not going to see a list of everyone that may have sent the user an email in Google contacts unless the user added them.