def send_inline_reply(self, text): page_id = self._data['_expandable']['container'] page_id = re.search(r'/([^/]*$)', page_id).groups()[0] try: root_id = self._data['ancestors'][0]['_links']['self'] root_id = re.search(r'/([^/]*$)', root_id).groups()[0] except IndexError: # It's the root element already root_id = self.id url = f"rest/inlinecomments/1.0/comments/{root_id}/replies" params = { 'containerId': page_id, } data = { "body": md_to_html(text), "commentId": int(root_id), } headers = { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', } r = make_request(url, params, method='POST', data=json.dumps(data), headers=headers) if r.status_code == 200: return True log.debug(r.request.headers) log.debug(r.request.body) log.debug(r.text) return False
def post_comment(self, size=None): # TODO refactor to reduce duplicate code # TODO let the user pick topic_id = 16 post_id = send_sketch(topic_id) if not post_id: self.app.alert("Failed to send sketch", 'error') return help_text = cs.REPLY_MSG reply = self.app.get_long_input(help_text) if not reply: self.app.alert("Reply empty, aborting", 'warning') return reply = md_to_html(reply, url_encode='html') headers = { 'X-Atlassian-Token': 'no-check', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', } data = f"{reply}&topicId={topic_id}&spaceKey=~admin" url = f"rest/microblog/1.0/microposts/{post_id}" r = make_request(url, method='PUT', data=data, headers=headers, no_token=True) if r.status_code == 200: self.app.alert("Microblog post sent", 'info') else: self.app.alert("Failed to send microblog post", 'error')
def __init__(self, page_id, first=None, second=None): self.page_id = page_id self.title = "Diff" url = f'rest/api/content/{page_id}' params = {'expand': 'version,body.view'} # get first body if first: self.first = first params['status'] = 'historical' params['version'] = first r = make_request(url, params=params) data = r.json() self.first = data['version']['number'] self.version1 = data['body']['view']['value'] tofile = "Version number %d by %s, %s" % ( self.first, data['version']['by']['displayName'], convert_date(data['version']['when']), ) # get second body if not second: self.second = self.first - 1 else: self.second = second params['version'] = self.second params['status'] = 'historical' r = make_request(url, params=params) data = r.json() self.version2 = data['body']['view']['value'] fromfile = "Version number %d by %s, %s" % ( self.second, data['version']['by']['displayName'], convert_date(data['version']['when']), ) self.diff = create_diff(self.version2, self.version1, fromfile=fromfile, tofile=tofile, html=True) if not self.diff: self.diff = cs.DIFF_EMPTY help_string = cs.DIFF_VIEW_HELP super().__init__(self.diff, color=True, help_string=help_string)
def get_comments_of_page(id): """Retrieve comments of a page from the Confluence API :id: the id of the page """ def get_by_id(children, cid): for c in children: if cid in list(c.keys()): return c # id = re.search('/([^/]*)$', url).groups()[0] log.debug("Get comment tree of page %s" % id) url = f'rest/api/content/{id}/child/comment' params = { 'expand': 'body.view,content,history.lastUpdated,version,ancestors,' 'extensions.inlineProperties,version', 'depth': 'all', 'limit': 9999, } items = [] while True: r = make_request(url, params=params) parsed = r.json() items += parsed['results'] links = parsed['_links'] if 'next' in links: url = links['next'] else: break result = [] # Build the structure returned by Confluence into something more useful. # Most importantly, it's a flat list of all items with each item # possessing a list of its ancestors. We want a nested list. for c in items: parent = result # Step down the ancestor list # ATTENTION: Apparently the order is arbitrary... can break for a in reversed(c['ancestors']): parent = get_by_id(parent, a['id'])['children'] parent.append({ c['id']: Comment(c), 'children': [], }) # log.debug(result) return result
def unlike(self): id = self.id log.debug("Unliking %s" % id) r = make_request( f'rest/likes/1.0/content/{id}/likes', method='DELETE', # headers=headers, data="") if r.status_code == 200: self.liked = False return True log.error("Unlike failed") return False
def open_content_in_cli_browser(app, id): log.debug("Build HTML view for page with id '%s'" % id) if not id: app.alert("Object has no ID", 'error') return rest_url = f"rest/api/content/{id}?expand=body.view" r = make_request(rest_url) if not r.ok: app.alert("Request failed (%d)" % r.status_code, 'error') return content = r.json() content = content["body"]["view"]["value"] content = f"<html><head></head><body>{content}</body></html>" open_doc_in_cli_browser(content.encode(), app)
def like(self, size=None): obj = self.focus.obj post_id = obj._data['id'] headers = { 'X-Atlassian-Token': 'no-check', } url = f"rest/microblog/1.0/microposts/{post_id}/like" r = make_request(url, method='POST', headers=headers, no_token=True) if r.status_code == 200: if r.text == 'true': self.app.alert("You liked this", 'info') elif r.text == 'false': self.app.alert("You unliked this", 'info') else: self.app.alert("Like failed", 'error')
def get_entries(self): r = make_request("rest/api/search", params=self.params) result = [] response = r.json() if r.ok and response: for each in response['results']: obj = ContentWrapper(each) try: if not getattr(obj.content, 'blacklisted', False): result.append(self._entryclass(obj)) except AttributeError: result.append(self._entryclass(obj)) # result = change_filter(result) self.app.alert('Received %d items' % len(result), 'info') self.params["start"] += \ self.params["limit"] return result
def like(self): id = self.id log.debug("Liking %s" % id) headers = { 'Content-Type': 'application/json', } r = make_request(f'rest/likes/1.0/content/{id}/likes', method='POST', headers=headers, data='') if r.status_code == 200: self.liked = True return True if r.status_code == 400: # already liked self.liked = True log.error("Like failed") return False
def send_sketch(topic_id): """Gets a post ID for a new microblog entry""" headers = { 'X-Atlassian-Token': 'no-check', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', } data = f"topicId={topic_id}" url = f"rest/microblog/1.0/sketch" r = make_request(url, method='POST', data=data, headers=headers, no_token=True) if not r.status_code == 200: return post_id = r.text return post_id
def reply(self, size=None): obj = self.entries[0].obj author = obj._data['authorFullName'] topic_id = obj._data['topic']['id'] parent_id = obj._data['id'] post_id = send_sketch(topic_id) if not post_id: self.app.alert("Failed to send sketch", 'error') return prev_msg = obj._data['renderedContent'] prev_msg = prev_msg.splitlines() prev_msg = '\n'.join([f"## > {line}" for line in prev_msg]) prev_msg = "## %s wrote:\n%s" % (author, prev_msg) help_text = cs.REPLY_MSG + prev_msg reply = self.app.get_long_input(help_text) if not reply: self.app.alert("Reply empty, aborting", 'warning') return reply = md_to_html(reply, url_encode='html') headers = { 'X-Atlassian-Token': 'no-check', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', } data = f"{reply}&parentId={parent_id}&spaceKey=~admin" url = f"rest/microblog/1.0/microposts/{post_id}" r = make_request(url, method='PUT', data=data, headers=headers, no_token=True) if r.status_code == 200: self.app.alert("Reply sent", 'info') else: self.app.alert("Failed to send reply", 'error')
def get_microblog(self): """Load Microblog entries via HTTP""" log.info("Fetch microblog...") response = make_request( "rest/microblog/1.0/microposts/search", params={ "offset": self.offset, "limit": self.limit, "replyLimit": self.replyLimit, }, method='POST', data=self.post_data, headers={ "Content-Type": "application/json", }, ) entries = response.json() result = [] for e in entries['microposts']: result.append(MicroblogEntry(MicroblogObject(e), is_reply=False)) self.offset += len(result) return result
def send_comment_reply(self, text): page_id = self._data['_expandable']['container'] page_id = re.search(r'/([^/]*$)', page_id).groups()[0] url = (f'/rest/tinymce/1/content/{page_id}/' f'comments/{self.id}/comment') params = {'actions': 'true'} answer = md_to_html(text, url_encode='html') uuid = str(uuid4()) headers = { 'X-Atlassian-Token': 'no-check', } data = f'{answer}&watch=false&uuid={uuid}' r = make_request(url, params, method='POST', data=data, headers=headers, no_token=True) if r.status_code == 200: return True return False