File: person.py

package info (click to toggle)
python-pypump 0.3%2Bgit20130823.1.97bffc6-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 328 kB
  • ctags: 333
  • sloc: python: 1,630; makefile: 140; sh: 7
file content (247 lines) | stat: -rw-r--r-- 8,609 bytes parent folder | download
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
##
# Copyright (C) 2013 Jessica T. (Tsyesika) <xray7224@googlemail.com>
# 
# 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, either version 3 of the License, or 
# (at your option) any later version. 
# 
# 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/>.
##

from datetime import datetime
from dateutil.parser import parse

from requests_oauthlib import OAuth1

from pypump.openid import OpenID
from pypump import exception
from pypump.exception.PumpException import PumpException
from pypump.models import AbstractModel
from pypump.compatability import *

@implement_to_string
class Person(AbstractModel):

    _mapping = {
        "preferredUsername":"username",
        "displayName":"display_name",
    }


    TYPE = "person"
    ENDPOINT = "/api/user/{username}/feed"

    id = ""
    username = ""
    display_name = ""
    url = "" # url to profile
    updated = None # Last time this was updated
    published = None # when they joined (I think?)
    location = None # place item
    summary = "" # lil bit about them =]    
    image = None # Image items

    inbox = None
    outbox = None

    is_self = False # is this you?

    def __init__(self, webfinger=None, id="", username="", url="", summary="", 
                 inbox=None, outbox=None, display_name="", image=None, 
                 published=None, updated=None, location=None, me=None, 
                 *args, **kwargs):
        """
        id - the ID of the person. e.g. acct:Username@server.example
        username - persons username
        url - url to profile
        summary - summary of the user
        inbox - This is the person's inbox
        outbox - This is the person's outbox
        display_name - what the user want's to show up (defualt: username)
        image - image of the user (default: No image/None)
        published - when the user joined pump (default: now)
        updated - when the user last updated their profile (default: published)
        location - where the user resides (default: No location/None)
        me - you, used to set is_self, if not given it assumes this person _isn't_ you
        """
        super(Person, self).__init__(*args, **kwargs)

        # okay we need to check if the webfinger is being used
        if isinstance(webfinger, string_types):
            # first clean up
            webfinger = webfinger.lstrip(" ").rstrip(" ")
            # okay now we need to look if it's on our servers or not.
            if "@" in webfinger:
                username, server = webfinger.split("@")
            else:
                # they probably just gave a username, the assumption is it's on our server!
                username, server = webfinger, self._pump.server
            if username == self._pump.nickname and server == self._pump.server:
                self.inbox = self._pump.Inbox(self) if inbox is None else inbox
            self.outbox = self._pump.Outbox(self) if outbox is None else outbox
            # now do some checking
            if server == self._pump.server:
                # cool we can get quite a bit of info.
                data = self._pump.request("/api/user/{0}/profile".format(username))
            else:
                self.id = "acct:%s@%s" % (username, server)
                self.username = username
                self.server = server
                self.is_self = False
                url = "{proto}://{server}/api/user/{username}/profile".format(
                        proto=self._pump.protocol,
                        server=self.server,
                        username=self.username
                        )

                # register client as we need to use the client credentials
                self.register_client()
                data = self._pump.request(url, client=self.client)
            self.unserialize(data, obj=self)
            return

        self.id = id
        self.inbox = self._pump.Inbox(self) if inbox is None else inbox
        self.username = username
        self.url = url
        self.summary = summary
        self.image = image        

        if display_name:
            self.display_name = display_name
        else:
            self.display_name = self.username

        if published:
            self.published = published
        else:
            self.published = datetime.now()
        
        if updated:
            self.updated = updated
        else:
            self.updated = self.published

        if me and self.id == me.id:
            self.is_self = True
            self.outbox = self._pump.Outbox(self)
            self.message = self.outbox

    @property
    def webfinger(self):
        return self.id[5:]

    def register_client(self):
        """ Registers client on foreign server """
        openid = OpenID(
                self.server,
                self._pump.client_name,
                self._pump.client_type
                )
        openid.pypump = self._pump
        self.client_credentials = openid.register_client()
        self.client = OAuth1(
                client_key=self.client_credentials.key,
                client_secret=self.client_credentials.secret
                )

    def follow(self): 
        """ You follow this user """
        activity = {
            "verb":"follow",
            "object":{
                "id":self.id,
                "objectType":self.objectType,
            }
        }

        endpoint = self.ENDPOINT.format(username=self._pump.nickname)

        data = self._pump.request(endpoint, method="POST", data=activity)

        if "error" in data:
            raise PumpException(data["error"])

        self.unserialize(data, obj=self) 
        return True

    def unfollow(self):
        """ Unfollow a user """
        activity = {
            "verb":"stop-following",
            "object":{
                "id":self.id,
                "objectType":self.objectType,
            }
        }

        endpoint = self.ENDPOINT.format(username=self._pump.nickname)

        data = self._pump.request(endpoint, method="POST", data=activity)

        if "error" in data:
            raise PumpException(data["error"])

        self.unserialize(data, obj=self) 
        return True

    def __repr__(self):
        return "<Person: {person}>".format(person=self.id.replace("acct:", ""))

    def __str__(self):
        return self.__repr__()

    @classmethod
    def unserialize_service(cls, data, obj):
        """ Unserializes the data from a service """
        id = data["id"]
        display = data["displayName"]
        updated = parse(data["updated"]) if "updated" in data else datetime.now()
        published = parse(data["published"]) if "published" in data else updated

        if obj is None:
            obj = cls()

        obj.id = id
        obj.display = display
        obj.updated = updated
        obj.published = published
        return obj

    @classmethod
    def unserialize(cls, data, obj=None):
        """ Goes from JSON -> Person object """
        if data.get("objectType", "") == "service":
            return cls.unserialize_service(data, obj)

        self = cls() if obj is None else obj

        if "verb" in data and data["verb"] in ["follow", "stop-following"]:
            return None

        try:
            username = data["preferredUsername"]
            display = data["displayName"]
        except KeyError:
            # This will be fixed properly soon.
            return None

        self.id = data["id"]
        self.username = username
        self.display_name = display
        self.url = data["links"]["self"]["href"]
        self.summary = data["summary"] if "summary" in data else ""
        self.updated = parse(data["updated"]) if "updated" in data else datetime.now()
        self.published = parse(data["published"]) if "published" in data else self.updated
        self.me = True if "acct:%s@%s" % (cls._pump.nickname, cls._pump.server) == self.id else False
        self.location = cls._pump.Location.unserialize(data["location"]) if "location" in data else None

        self.updated = parse(data["updated"]) if "updated" in data else datetime.now()
        return self