From 63a863ec7fc313d111c33406d06dce8f837f85c4 Mon Sep 17 00:00:00 2001
From: Holger Nahrstaedt <holgernahrstaedt@gmx.de>
Date: Fri, 9 Oct 2020 22:03:22 +0200
Subject: [PATCH] Fix get_discussions

* improved get_discussions calls, fallback to condenser when tags api not available
* Fix detection when content does not exists
---
 CHANGELOG.rst                  |  3 ++
 beem/comment.py                | 21 +++++++++-----
 beem/discussions.py            | 50 ++++++++++++++++++++++------------
 beem/market.py                 |  6 ++--
 beemapi/exceptions.py          |  4 +++
 beemapi/noderpc.py             |  2 ++
 tests/beem/test_discussions.py |  8 +++---
 7 files changed, 64 insertions(+), 30 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e6b0333d..a0f77b3f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,9 @@ Changelog
 * Remove remaining py2 code
 * Run unit tests on beta.openhive.network
 * Fix compatibility issues with HF 24
+* account get_follow_count, get_followers and get_following have been fixed
+* improved get_discussions calls, fallback to condenser when tags api not available
+* Fix detection when content does not exists
 
 0.24.9
 ------
diff --git a/beem/comment.py b/beem/comment.py
index 43d784bd..ba70ed07 100644
--- a/beem/comment.py
+++ b/beem/comment.py
@@ -164,7 +164,11 @@ class Comment(BlockchainObject):
                     content =content[0]
             except:
                 if self.blockchain.config["use_condenser"]:
-                    content = self.blockchain.rpc.get_content(author, permlink)
+                    from beemapi.exceptions import InvalidParameters
+                    try:
+                        content = self.blockchain.rpc.get_content(author, permlink)
+                    except InvalidParameters:
+                        raise ContentDoesNotExistsException(self.identifier)
                 else:
                     content =self.blockchain.rpc.find_comments({"start": [author, permlink], "limit": 1, "order": "by_permlink"}, api="database")
                     if content is not None and "comments" in content:
@@ -172,7 +176,11 @@ class Comment(BlockchainObject):
                     if isinstance(content, list) and len(content) >0:
                         content =content[0]                
         else:
-            content = self.blockchain.rpc.get_content(author, permlink)
+            from beemapi.exceptions import InvalidParameters
+            try:            
+                content = self.blockchain.rpc.get_content(author, permlink)
+            except InvalidParameters:
+                raise ContentDoesNotExistsException(self.identifier)                
         if not content or not content['author'] or not content['permlink']:
             raise ContentDoesNotExistsException(self.identifier)
         content = self._parse_json_data(content)
@@ -837,7 +845,7 @@ class RecentReplies(list):
             Default: True
         :param Steem blockchain_instance: Steem() instance to use when accesing a RPC
     """
-    def __init__(self, author, skip_own=True, lazy=False, full=True, blockchain_instance=None, **kwargs):
+    def __init__(self, author, skip_own=True, start_permlink="", limit=100, lazy=False, full=True, blockchain_instance=None, **kwargs):
         if blockchain_instance is None:
             if kwargs.get("steem_instance"):
                 blockchain_instance = kwargs["steem_instance"]
@@ -847,11 +855,10 @@ class RecentReplies(list):
         if not self.blockchain.is_connected():
             return None
         self.blockchain.rpc.set_next_node_on_empty_reply(True)
-        state = self.blockchain.rpc.get_state("/@%s/recent-replies" % author)
-        replies = state["accounts"][author].get("recent_replies", [])
+        account = Account(author, blockchain_instance=self.blockchain)
+        replies = account.get_account_posts(sort="replies", raw_data=True)
         comments = []
-        for reply in replies:
-            post = state["content"][reply]
+        for post in replies:
             if skip_own and post["author"] == author:
                 continue
             comments.append(Comment(post, lazy=lazy, full=full, blockchain_instance=self.blockchain))
diff --git a/beem/discussions.py b/beem/discussions.py
index 6f52824f..7f6855b3 100644
--- a/beem/discussions.py
+++ b/beem/discussions.py
@@ -218,9 +218,10 @@ class Discussions_by_trending(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_trending(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_trending(reduced_query)
         if raw_data:
             super(Discussions_by_trending, self).__init__(
@@ -268,10 +269,11 @@ class Discussions_by_author_before_date(list):
                 blockchain_instance = kwargs["hive_instance"]        
         self.blockchain = blockchain_instance or shared_blockchain_instance()
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             discussion_query = {"author": author, "start_permlink": start_permlink, "before_date": before_date, "limit": limit}
             posts = self.blockchain.rpc.get_discussions_by_author_before_date(discussion_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_author_before_date(author, start_permlink, before_date, limit)
         if raw_data:
             super(Discussions_by_author_before_date, self).__init__(
@@ -319,9 +321,10 @@ class Comment_discussions_by_payout(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_comment_discussions_by_payout(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_comment_discussions_by_payout(reduced_query)
         if raw_data:
             super(Comment_discussions_by_payout, self).__init__(
@@ -369,9 +372,10 @@ class Post_discussions_by_payout(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_post_discussions_by_payout(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_post_discussions_by_payout(reduced_query)
         if raw_data:
             super(Post_discussions_by_payout, self).__init__(
@@ -419,9 +423,10 @@ class Discussions_by_created(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_created(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_created(reduced_query)
         if raw_data:
             super(Discussions_by_created, self).__init__(
@@ -469,9 +474,10 @@ class Discussions_by_active(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_active(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_active(reduced_query)
         if raw_data:
             super(Discussions_by_active, self).__init__(
@@ -520,9 +526,10 @@ class Discussions_by_cashout(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_cashout(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_cashout(reduced_query)
         if raw_data:
             super(Discussions_by_cashout, self).__init__(
@@ -570,9 +577,10 @@ class Discussions_by_votes(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_votes(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_votes(reduced_query)
         if raw_data:
             super(Discussions_by_votes, self).__init__(
@@ -620,9 +628,10 @@ class Discussions_by_children(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]         
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_children(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_children(reduced_query)
         if raw_data:
             super(Discussions_by_votes, self).__init__(
@@ -670,9 +679,10 @@ class Discussions_by_hot(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_hot(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_hot(reduced_query)
         if raw_data:
             super(Discussions_by_hot, self).__init__(
@@ -720,9 +730,10 @@ class Discussions_by_feed(list):
                     "start_author", "start_permlink"]:
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_feed(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             # limit = discussion_query["limit"]
             # account = discussion_query["tag"]
             # entryId = 0
@@ -772,13 +783,14 @@ class Discussions_by_blog(list):
         for key in ["tag", "limit", "filter_tags", "select_authors", "select_tags", "truncate_body",
                     "start_author", "start_permlink"]:
             if key in discussion_query:
-                reduced_query[key] = discussion_query[key]        
+                reduced_query[key] = discussion_query[key]     
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             self.blockchain.rpc.set_next_node_on_empty_reply(True)
             posts = self.blockchain.rpc.get_discussions_by_blog(reduced_query, api="tags")
             if 'discussions' in posts:
                 posts = posts['discussions']  # inconsistent format across node types
-        else:
+        if len(posts) == 0:
             self.blockchain.rpc.set_next_node_on_empty_reply(False)
             # limit = discussion_query["limit"]
             # account = discussion_query["tag"]
@@ -830,11 +842,12 @@ class Discussions_by_comments(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]         
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_comments(reduced_query, api="tags")
             if 'discussions' in posts:
                 posts = posts['discussions']  # inconsistent format across node types
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_comments(reduced_query)
         if raw_data:
             super(Discussions_by_comments, self).__init__(
@@ -882,9 +895,10 @@ class Discussions_by_promoted(list):
             if key in discussion_query:
                 reduced_query[key] = discussion_query[key]        
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             posts = self.blockchain.rpc.get_discussions_by_promoted(reduced_query, api="tags")['discussions']
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_discussions_by_promoted(reduced_query)
         if raw_data:
             super(Discussions_by_promoted, self).__init__(
@@ -927,6 +941,7 @@ class Replies_by_last_update(list):
                 blockchain_instance = kwargs["hive_instance"]        
         self.blockchain = blockchain_instance or shared_blockchain_instance()
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             try:
                 posts = self.blockchain.rpc.get_replies_by_last_update(discussion_query, api="tags")
@@ -934,7 +949,7 @@ class Replies_by_last_update(list):
                     posts = posts['discussions']
             except:
                 posts = self.blockchain.rpc.get_replies_by_last_update(discussion_query["start_author"], discussion_query["start_permlink"], discussion_query["limit"])
-        else:
+        if len(posts) == 0:
             posts = self.blockchain.rpc.get_replies_by_last_update(discussion_query["start_author"], discussion_query["start_permlink"], discussion_query["limit"])
         if posts is None:
             posts = []
@@ -978,9 +993,10 @@ class Trending_tags(list):
                 blockchain_instance = kwargs["hive_instance"]        
         self.blockchain = blockchain_instance or shared_blockchain_instance()
         self.blockchain.rpc.set_next_node_on_empty_reply(self.blockchain.rpc.get_use_appbase() and use_appbase)
+        posts = []
         if self.blockchain.rpc.get_use_appbase() and use_appbase:
             tags = self.blockchain.rpc.get_trending_tags(discussion_query, api="tags")['tags']
-        else:
+        if len(posts) == 0:
             tags = self.blockchain.rpc.get_trending_tags(discussion_query["start_tag"], discussion_query["limit"], api="tags")
         super(Trending_tags, self).__init__(
             [
diff --git a/beem/market.py b/beem/market.py
index a3a914d9..5f83fe2e 100644
--- a/beem/market.py
+++ b/beem/market.py
@@ -127,10 +127,12 @@ class Market(dict):
             * ``highest_bid``: Price of the highest bid
             * ``sbd_volume``: Volume of SBD
             * ``steem_volume``: Volume of STEEM
+            * ``hbd_volume``: Volume of HBD
+            * ``hive_volume``: Volume of HIVE
             * ``percent_change``: 24h change percentage (in %)
 
             .. note::
-                Market is STEEM:SBD and prices are SBD per STEEM!
+                Market is HIVE:HBD and prices are HBD per HIVE!
 
             Sample Output:
 
@@ -176,7 +178,7 @@ class Market(dict):
         if "sbd_volume" in ticker:
             data["sbd_volume"] = Amount(ticker["sbd_volume"], blockchain_instance=self.blockchain)
         elif "hbd_volume" in ticker:
-            data["sbd_volume"] = Amount(ticker["hbd_volume"], blockchain_instance=self.blockchain)
+            data["hbd_volume"] = Amount(ticker["hbd_volume"], blockchain_instance=self.blockchain)
         if "steem_volume" in ticker:
             data["steem_volume"] = Amount(ticker["steem_volume"], blockchain_instance=self.blockchain)
         elif "hive_volume" in ticker:
diff --git a/beemapi/exceptions.py b/beemapi/exceptions.py
index 5c758ae6..b504bfbf 100644
--- a/beemapi/exceptions.py
+++ b/beemapi/exceptions.py
@@ -96,6 +96,10 @@ class InvalidEndpointUrl(Exception):
     pass
 
 
+class InvalidParameters(Exception):
+    pass
+
+
 class UnnecessarySignatureDetected(Exception):
     pass
 
diff --git a/beemapi/noderpc.py b/beemapi/noderpc.py
index ce8cc830..a7c5bb69 100644
--- a/beemapi/noderpc.py
+++ b/beemapi/noderpc.py
@@ -133,6 +133,8 @@ class NodeRPC(GrapheneRPC):
             raise exceptions.UnnecessarySignatureDetected(msg)
         elif re.search("WinError", msg):
             raise exceptions.RPCError(msg)
+        elif re.search("Invalid parameters", msg):
+            raise exceptions.InvalidParameters()
         elif re.search("Unable to acquire database lock", msg):
             self.nodes.sleep_and_check_retries(str(msg), call_retry=True)
             doRetry = True
diff --git a/tests/beem/test_discussions.py b/tests/beem/test_discussions.py
index 65f8edc6..ac480dcb 100644
--- a/tests/beem/test_discussions.py
+++ b/tests/beem/test_discussions.py
@@ -63,7 +63,7 @@ class Testcases(unittest.TestCase):
         bts = self.bts
         query = Query()
         query["limit"] = 2
-        # query["tag"] = "holger80"
+        query["tag"] = "hive"
         d = Discussions_by_created(query, steem_instance=bts)
         self.assertEqual(len(d), 2)
 
@@ -125,11 +125,11 @@ class Testcases(unittest.TestCase):
     def test_promoted(self):
         bts = self.bts
         query = Query()
-        query["limit"] = 1
-        query["tag"] = "banjo"
+        query["limit"] = 2
+        query["tag"] = "hive"
         d = Discussions_by_promoted(query, steem_instance=bts)
         discussions = Discussions(steem_instance=bts)
         d2 = []
-        for dd in discussions.get_discussions("promoted", query, limit=10):
+        for dd in discussions.get_discussions("promoted", query, limit=2):
             d2.append(dd)
         self.assertEqual(len(d), len(d2))
-- 
GitLab