/usr/lib/python3/dist-packages/friends/protocols/linkedin.py is in friends-linkedin 0.2.0+14.04.20140217.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | # friends-dispatcher -- send & receive messages from any social network
# Copyright (C) 2013 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""The LinkedIn protocol plugin."""
__all__ = [
'LinkedIn',
]
import logging
from friends.utils.base import Base, feature
from friends.utils.http import Downloader
from friends.utils.time import iso8601utc
log = logging.getLogger(__name__)
def make_fullname(firstName=None, lastName=None, **ignored):
"""Converts dict(firstName='Bob', lastName='Loblaw') into 'Bob Loblaw'."""
return ' '.join(name for name in (firstName, lastName) if name)
class LinkedIn(Base):
_api_base = ('https://api.linkedin.com/v1/{endpoint}?format=json' +
'&secure-urls=true&oauth2_access_token={token}')
def _whoami(self, authdata):
"""Identify the authenticating user."""
# http://developer.linkedin.com/documents/profile-fields
url = self._api_base.format(
endpoint='people/~:(id,first-name,last-name)',
token=self._get_access_token())
result = Downloader(url).get_json()
self._account.user_id = result.get('id')
self._account.user_name = make_fullname(**result)
def _publish_entry(self, entry, stream='messages'):
"""Publish a single update into the Dee.SharedModel."""
message_id = entry.get('updateKey')
content = entry.get('updateContent', {})
person = content.get('person', {})
name = make_fullname(**person)
person_id = person.get('id', '')
status = person.get('currentStatus')
picture = person.get('pictureUrl', '')
url = person.get('siteStandardProfileRequest', {}).get('url', '')
timestamp = entry.get('timestamp', 0)
# We need to divide by 1000 here, as LinkedIn's timestamps have
# milliseconds.
iso_time = iso8601utc(int(timestamp/1000))
likes = entry.get('numLikes', 0)
if None in (message_id, status):
# Something went wrong; just ignore this malformed message.
return
args = dict(
message_id=message_id,
stream=stream,
message=status,
likes=likes,
sender_id=person_id,
sender=name,
icon_uri=picture,
url=url,
timestamp=iso_time
)
self._publish(**args)
@feature
def home(self):
"""Gather and publish public timeline messages."""
url = self._api_base.format(
endpoint='people/~/network/updates',
token=self._get_access_token()) + '&type=STAT'
result = Downloader(url).get_json()
for update in result.get('values', []):
self._publish_entry(update)
return self._get_n_rows()
@feature
def receive(self):
"""Gather and publish all incoming messages."""
return self.home()
@feature
def contacts(self):
"""Retrieve a list of up to 500 LinkedIn connections."""
# http://developer.linkedin.com/documents/connections-api
connections = Downloader(
url=self._api_base.format(
endpoint='people/~/connections',
token=self._get_access_token())
).get_json().get('values', [])
for connection in connections:
uid = connection.get('id', 'private')
fullname = make_fullname(**connection)
if uid != 'private' and not self._previously_stored_contact(uid):
self._push_to_eds(
uid=uid,
name=fullname,
link=connection.get(
'siteStandardProfileRequest', {}).get('url'))
return len(connections)
|