From 343f480ba79f38c0f5fb85348e0051f9451574ba Mon Sep 17 00:00:00 2001
From: holgern <holgernahrstaedt@gmx.de>
Date: Wed, 28 Aug 2019 10:02:53 +0200
Subject: [PATCH] More improvements for HF21

* add options use_tags_api to use database api to get comments
* fix get_similar_account_names
* add more try expect to fail back to condenser api
---
 beem/account.py    | 153 ++++++++++++++++++++++++++-------------------
 beem/blockchain.py |   2 +-
 beem/comment.py    |  32 ++++++++--
 beem/vote.py       |  15 +++--
 4 files changed, 125 insertions(+), 77 deletions(-)

diff --git a/beem/account.py b/beem/account.py
index 54b3b2dc..c5bbef2c 100644
--- a/beem/account.py
+++ b/beem/account.py
@@ -99,7 +99,7 @@ class Account(BlockchainObject):
             return
         self.steem.rpc.set_next_node_on_empty_reply(self.steem.rpc.get_use_appbase())
         if self.steem.rpc.get_use_appbase():
-                account = self.steem.rpc.find_accounts({'accounts': [self.identifier]}, api="database")
+            account = self.steem.rpc.find_accounts({'accounts': [self.identifier]}, api="database")
         else:
             if self.full:
                 account = self.steem.rpc.get_accounts(
@@ -391,9 +391,12 @@ class Account(BlockchainObject):
             return None
         self.steem.rpc.set_next_node_on_empty_reply(False)
         if self.steem.rpc.get_use_appbase():
-            rep = self.steem.rpc.get_account_reputations({'account_lower_bound': self["name"], 'limit': 1}, api="follow")['reputations']
-            if len(rep) > 0:
-                rep = int(rep[0]['reputation'])
+            try:
+                rep = self.steem.rpc.get_account_reputations({'account_lower_bound': self["name"], 'limit': 1}, api="follow")['reputations']
+                if len(rep) > 0:
+                    rep = int(rep[0]['reputation'])
+            except:
+                rep = int(self['reputation'])
         else:
             rep = int(self['reputation'])
         return reputation_to_score(rep)
@@ -623,32 +626,38 @@ class Account(BlockchainObject):
         if not self.steem.is_connected():
             return None
         self.steem.rpc.set_next_node_on_empty_reply(False)
-        if raw_data and short_entries and self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_feed_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
-            ]
-        elif raw_data and short_entries and not self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_feed_entries(account, start_entry_id, limit, api='follow')
-            ]
-        elif raw_data and self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
-            ]
-        elif raw_data and not self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
-            ]
-        elif not raw_data and self.steem.rpc.get_use_appbase():
-            from .comment import Comment
-            return [
-                Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
-            ]
-        else:
-            from .comment import Comment
-            return [
-                Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
-            ]
+        success = True
+        if self.steem.rpc.get_use_appbase():
+            try:
+                if raw_data and short_entries:
+                    return [
+                        c for c in self.steem.rpc.get_feed_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
+                    ]
+                elif raw_data:
+                    return [
+                        c for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
+                    ]
+                elif not raw_data:
+                    from .comment import Comment
+                    return [
+                        Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')["feed"]
+                    ]
+            except:
+                success = False
+        if not self.steem.rpc.get_use_appbase() or not success:
+            if raw_data and short_entries:
+                return [
+                    c for c in self.steem.rpc.get_feed_entries(account, start_entry_id, limit, api='follow')
+                ]
+            elif raw_data:
+                return [
+                    c for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
+                ]
+            else:
+                from .comment import Comment
+                return [
+                    Comment(c['comment'], steem_instance=self.steem) for c in self.steem.rpc.get_feed(account, start_entry_id, limit, api='follow')
+                ]
 
     def get_feed_entries(self, start_entry_id=0, limit=100, raw_data=True,
                          account=None):
@@ -726,41 +735,50 @@ class Account(BlockchainObject):
         if not self.steem.is_connected():
             raise OfflineHasNoRPCException("No RPC available in offline mode!")
         self.steem.rpc.set_next_node_on_empty_reply(False)
-        if raw_data and short_entries and self.steem.rpc.get_use_appbase():
-            ret = self.steem.rpc.get_blog_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
-            if isinstance(ret, dict) and "blog" in ret:
-                ret = ret["blog"]
-            return [
-                c for c in ret
-            ]
-        elif raw_data and short_entries and not self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_blog_entries(account, start_entry_id, limit, api='follow')
-            ]
-        elif raw_data and self.steem.rpc.get_use_appbase():
-            ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
-            if isinstance(ret, dict) and "blog" in ret:
-                ret = ret["blog"]            
-            return [
-                c for c in ret
-            ]
-        elif raw_data and not self.steem.rpc.get_use_appbase():
-            return [
-                c for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
-            ]
-        elif not raw_data and self.steem.rpc.get_use_appbase():
-            from .comment import Comment
-            ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
-            if isinstance(ret, dict) and "blog" in ret:
-                ret = ret["blog"]
-            return [
-                Comment(c["comment"], steem_instance=self.steem) for c in ret
-            ]                
-        else:
-            from .comment import Comment
-            return [
-                Comment(c["comment"], steem_instance=self.steem) for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
-            ]
+        success = True
+        if self.steem.rpc.get_use_appbase():
+            try:
+                if raw_data and short_entries:
+                    ret = self.steem.rpc.get_blog_entries({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
+                    if isinstance(ret, dict) and "blog" in ret:
+                        ret = ret["blog"]
+                    return [
+                        c for c in ret
+                    ]
+                elif raw_data:
+                    ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
+                    if isinstance(ret, dict) and "blog" in ret:
+                        ret = ret["blog"]            
+                    return [
+                        c for c in ret
+                    ]
+                elif not raw_data:
+                    from .comment import Comment
+                    ret = self.steem.rpc.get_blog({'account': account, 'start_entry_id': start_entry_id, 'limit': limit}, api='follow')
+                    if isinstance(ret, dict) and "blog" in ret:
+                        ret = ret["blog"]
+                    return [
+                        Comment(c["comment"], steem_instance=self.steem) for c in ret
+                    ]
+            except:
+                success = False
+        
+        if not self.steem.rpc.get_use_appbase() or not success:
+            if raw_data and short_entries:
+                return [
+                    c for c in self.steem.rpc.get_blog_entries(account, start_entry_id, limit, api='follow')
+                ]
+    
+            elif raw_data:
+                return [
+                    c for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
+                ]
+              
+            else:
+                from .comment import Comment
+                return [
+                    Comment(c["comment"], steem_instance=self.steem) for c in self.steem.rpc.get_blog(account, start_entry_id, limit, api='follow')
+                ]
 
     def get_blog_authors(self, account=None):
         """ Returns a list of authors that have had their content reblogged on a given blog account
@@ -787,7 +805,10 @@ class Account(BlockchainObject):
             raise OfflineHasNoRPCException("No RPC available in offline mode!")
         self.steem.rpc.set_next_node_on_empty_reply(False)
         if self.steem.rpc.get_use_appbase():
-            return self.steem.rpc.get_blog_authors({'blog_account': account}, api='follow')['blog_authors']
+            try:
+                return self.steem.rpc.get_blog_authors({'blog_account': account}, api='follow')['blog_authors']
+            except:
+                return self.steem.rpc.get_blog_authors(account, api='follow')
         else:
             return self.steem.rpc.get_blog_authors(account, api='follow')
 
diff --git a/beem/blockchain.py b/beem/blockchain.py
index 27ef0283..ef78c73d 100644
--- a/beem/blockchain.py
+++ b/beem/blockchain.py
@@ -924,7 +924,7 @@ class Blockchain(object):
             return None
         self.steem.rpc.set_next_node_on_empty_reply(False)
         if self.steem.rpc.get_use_appbase():
-            account = self.steem.rpc.list_accounts({'start': name, 'limit': limit}, api="database")
+            account = self.steem.rpc.list_accounts({'start': name, 'limit': limit, 'order': 'by_name'}, api="database")
             if bool(account):
                 return account["accounts"]
         else:
diff --git a/beem/comment.py b/beem/comment.py
index 2c0b5010..7403d065 100644
--- a/beem/comment.py
+++ b/beem/comment.py
@@ -28,6 +28,7 @@ class Comment(BlockchainObject):
 
         :param str authorperm: identifier to post/comment in the form of
             ``@author/permlink``
+        :param boolean use_tags_api: when set to False, list_comments from the database_api is used
         :param Steem steem_instance: :class:`beem.steem.Steem` instance to use when accessing a RPC
 
 
@@ -49,12 +50,14 @@ class Comment(BlockchainObject):
     def __init__(
         self,
         authorperm,
+        use_tags_api=True,
         full=True,
         lazy=False,
         steem_instance=None
     ):
         self.full = full
         self.lazy = lazy
+        self.use_tags_api = use_tags_api
         self.steem = steem_instance or shared_steem_instance()
         if isinstance(authorperm, string_types) and authorperm != "":
             [author, permlink] = resolve_authorperm(authorperm)
@@ -146,7 +149,14 @@ class Comment(BlockchainObject):
         self.steem.rpc.set_next_node_on_empty_reply(True)
         if self.steem.rpc.get_use_appbase():
             try:
-                content = self.steem.rpc.get_discussion({'author': author, 'permlink': permlink}, api="tags")
+                if self.use_tags_api:
+                    content = self.steem.rpc.get_discussion({'author': author, 'permlink': permlink}, api="tags")
+                else:
+                    content =self.steem.rpc.list_comments({"start":[author, permlink], "limit":1, "order":"by_permlink"}, api="database")
+                if content is not None and "comments" in content:
+                    content =content["comments"]
+                if isinstance(content, list) and len(content) >0:
+                    content =content[0]
             except:
                 content = self.steem.rpc.get_content(author, permlink)
         else:
@@ -373,9 +383,15 @@ class Comment(BlockchainObject):
             voter = Account(self["author"], steem_instance=self.steem)
         else:
             voter = Account(voter, steem_instance=self.steem)
-        for vote in self["active_votes"]:
-            if voter["name"] == vote["voter"]:
-                specific_vote = vote
+        if "active_votes" in self:
+            for vote in self["active_votes"]:
+                if voter["name"] == vote["voter"]:
+                    specific_vote = vote
+        else:
+            active_votes = self.get_votes()
+            for vote in active_votes:
+                if voter["name"] == vote["voter"]:
+                    specific_vote = vote 
         if specific_vote is not None and (raw_data or not self.is_pending()):
             return specific_vote
         elif specific_vote is not None:
@@ -512,7 +528,11 @@ class Comment(BlockchainObject):
             pending_rewards = True
 
         active_votes = {}
-        for vote in self["active_votes"]:
+        if "active_votes" in self:
+            active_votes_list = self["active_votes"]
+        else:
+            active_votes_list = self.get_votes()
+        for vote in active_votes_list:
             if total_vote_weight > 0:
                 claim = max_rewards * int(vote["weight"]) / total_vote_weight
             else:
@@ -586,7 +606,7 @@ class Comment(BlockchainObject):
 
     def get_votes(self, raw_data=False):
         """Returns all votes as ActiveVotes object"""
-        if raw_data:
+        if raw_data and "active_votes" in self:
             return self["active_votes"]
         from .vote import ActiveVotes
         return ActiveVotes(self, lazy=False, steem_instance=self.steem)
diff --git a/beem/vote.py b/beem/vote.py
index f8c4bafa..1950fb0d 100644
--- a/beem/vote.py
+++ b/beem/vote.py
@@ -98,7 +98,10 @@ class Vote(BlockchainObject):
         try:
             self.steem.rpc.set_next_node_on_empty_reply(True)
             if self.steem.rpc.get_use_appbase():
-                votes = self.steem.rpc.get_active_votes({'author': author, 'permlink': permlink}, api="tags")['votes']
+                try:
+                    votes = self.steem.rpc.get_active_votes({'author': author, 'permlink': permlink}, api="tags")['votes']
+                except:
+                    votes = self.steem.rpc.get_active_votes(author, permlink, api="database_api")
             else:
                 votes = self.steem.rpc.get_active_votes(author, permlink, api="database_api")
         except UnkownKey:
@@ -348,9 +351,13 @@ class ActiveVotes(VotesObject):
                 votes = authorperm["active_votes"]
             elif self.steem.rpc.get_use_appbase():
                 self.steem.rpc.set_next_node_on_empty_reply(True)
-                votes = self.steem.rpc.get_active_votes({'author': authorperm["author"],
-                                                         'permlink': authorperm["permlink"]},
-                                                        api="tags")['votes']
+                try:
+                    
+                    votes = self.steem.rpc.get_active_votes({'author': authorperm["author"],
+                                                             'permlink': authorperm["permlink"]},
+                                                            api="tags")['votes']
+                except:
+                    votes = self.steem.rpc.get_active_votes(authorperm["author"], authorperm["permlink"])
             else:
                 votes = self.steem.rpc.get_active_votes(authorperm["author"], authorperm["permlink"])
             authorperm = authorperm["authorperm"]
-- 
GitLab