Compare commits
1 Commits
master
...
f/objectap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f53443188 |
160
pydiscourse/apidev.py
Normal file
160
pydiscourse/apidev.py
Normal file
@ -0,0 +1,160 @@
|
||||
""" A higher level API wrapper for communicating with a Discourse instance
|
||||
|
||||
EXPERIMENTAL, subject to complete and radical change
|
||||
|
||||
Goal
|
||||
------
|
||||
A pythonic wrapper around the discourse API that minimizes requests by lazy loading of data.
|
||||
|
||||
"""
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def datetime_from(date):
|
||||
DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
|
||||
# XXX not handling timezone, but we're not using it yet
|
||||
return datetime.strptime(date[:-6], DATE_FORMAT)
|
||||
|
||||
|
||||
class DiscourseUser(object):
|
||||
username = None
|
||||
userid = None
|
||||
avatar_template = None
|
||||
default_avatar_size = 40
|
||||
|
||||
def avatar(self, size=None):
|
||||
if size is None:
|
||||
size = self.default_avatar_size
|
||||
return self.avatar_template.replace(u'{size}', unicode(size))
|
||||
|
||||
def __repr__(self):
|
||||
return '<DiscourseUser {0} {1}>'.format(self.userid, self.username)
|
||||
|
||||
@classmethod
|
||||
def from_summary(cls, summary):
|
||||
instance = cls()
|
||||
instance.username = summary['username']
|
||||
instance.userid = summary['id']
|
||||
instance.avatar_template = summary['avatar_template']
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class DiscourseUserSet(object):
|
||||
def __init__(self, users):
|
||||
self.users = users
|
||||
|
||||
self.byname = {u.username: u for u in users}
|
||||
self.byid = {u.userid: u for u in users}
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.users)
|
||||
|
||||
def __getitem__(self, item):
|
||||
try:
|
||||
return self.byname[item]
|
||||
except KeyError:
|
||||
return self.byid[item]
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response):
|
||||
users = [DiscourseUser.from_summary(u) for u in response.get('users', [])]
|
||||
return cls(users)
|
||||
|
||||
|
||||
class DiscoursePost(object):
|
||||
default_avatar_size = 40
|
||||
|
||||
def avatar(self, size=None):
|
||||
if size is None:
|
||||
size = self.default_avatar_size
|
||||
return self.avatar_template.replace(u'{size}', unicode(size))
|
||||
|
||||
def date_created(self):
|
||||
return datetime_from(self.data['created_at'])
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data):
|
||||
instance = cls()
|
||||
instance.data = data
|
||||
|
||||
return instance
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return self.data[attr]
|
||||
|
||||
|
||||
class DiscourseTopic(object):
|
||||
def __init__(self):
|
||||
self.posts = None
|
||||
self.data = None
|
||||
self.raw_response = None
|
||||
|
||||
def created_by(self):
|
||||
return DiscourseUser.from_summary(self.data['details']['created_by'])
|
||||
|
||||
def created_at(self):
|
||||
return datetime_from(self.data['created_at'])
|
||||
|
||||
def last_posted_at(self):
|
||||
return datetime_from(self.data['last_posted_at'])
|
||||
|
||||
def num_unread(self):
|
||||
if self.data['unseen']:
|
||||
return 1
|
||||
|
||||
return self.data['new_posts']
|
||||
|
||||
def participants(self):
|
||||
return [DiscourseUser.from_summary(u) for u in self.data['participants']]
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response):
|
||||
instance = DiscourseTopic.from_dict(response)
|
||||
instance.raw_response = response
|
||||
instance.posts = []
|
||||
for post in response['post_stream']['posts']:
|
||||
instance.posts.append(DiscoursePost.from_dict(post))
|
||||
|
||||
return instance
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data):
|
||||
instance = cls()
|
||||
instance.data = data
|
||||
return instance
|
||||
|
||||
def fetch_remaining_posts(self, discourse):
|
||||
""" The initial topic response is paginated, this makes another request to get additional posts
|
||||
"""
|
||||
if self.data['posts_count'] > len(self.posts):
|
||||
missing = self.data['post_stream']['stream'][len(self.posts):]
|
||||
response = discourse.posts(self.id, missing)
|
||||
for post in response['post_stream']['posts']:
|
||||
self.posts.append(DiscoursePost.from_dict(post))
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return self.data[attr]
|
||||
|
||||
def __repr__(self):
|
||||
return u'<Topic {0}>'.format(self.title)
|
||||
|
||||
|
||||
class DiscourseTopicSet(object):
|
||||
def __init__(self, topics):
|
||||
self.topics = topics
|
||||
|
||||
def all(self):
|
||||
return self.topics
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.topics)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.topics)
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response):
|
||||
topics = response.get('topic_list', {}).get('topics', [])
|
||||
topics = [DiscourseTopic.from_dict(t) for t in topics]
|
||||
return cls(topics)
|
||||
Loading…
x
Reference in New Issue
Block a user