Add replies display rpc method (#674)

* Add get replies display entries rpc method

* Add assertion for get replies test case

* Show replies in squeak page

* Show replies in frontend
This commit is contained in:
Jonathan Zernik 2021-01-22 18:32:05 -08:00 committed by GitHub
parent 040d581b44
commit dbff72ec57
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 148 additions and 12 deletions

View file

@ -20,6 +20,7 @@ import SqueakThreadItem from "../../components/SqueakThreadItem";
import {
getSqueakDisplayRequest,
getAncestorSqueakDisplaysRequest,
getReplySqueakDisplaysRequest,
getNetworkRequest,
} from "../../squeakclient/requests"
@ -30,6 +31,7 @@ export default function SqueakPage() {
const { hash } = useParams();
const [squeak, setSqueak] = useState(null);
const [ancestorSqueaks, setAncestorSqueaks] = useState([]);
const [replySqueaks, setReplySqueaks] = useState([]);
const [network, setNetwork] = useState("");
const getSqueak = (hash) => {
@ -38,6 +40,9 @@ export default function SqueakPage() {
const getAncestorSqueaks = (hash) => {
getAncestorSqueakDisplaysRequest(hash, setAncestorSqueaks);
};
const getReplySqueaks = (hash) => {
getReplySqueakDisplaysRequest(hash, setReplySqueaks);
};
const getNetwork = () => {
getNetworkRequest(setNetwork);
};
@ -61,6 +66,9 @@ export default function SqueakPage() {
useEffect(()=>{
getAncestorSqueaks(hash)
},[hash]);
useEffect(()=>{
getReplySqueaks(hash)
},[hash]);
useEffect(()=>{
getNetwork()
},[]);
@ -118,6 +126,29 @@ export default function SqueakPage() {
)
}
function RepliesContent() {
console.log("replySqueaks: " + replySqueaks);
return (
<div>
{replySqueaks
.map(replySqueak =>
<Box
p={1}
key={replySqueak.getSqueakHash()}
>
<SqueakThreadItem
hash={replySqueak.getSqueakHash()}
key={replySqueak.getSqueakHash()}
squeak={replySqueak}
network={network}>
</SqueakThreadItem>
<Divider />
</Box>
)}
</div>
)
}
function SqueakContent() {
return (
<>
@ -130,6 +161,7 @@ export default function SqueakPage() {
network={network}>
</SqueakDetailItem>
</div>
{RepliesContent()}
</>
)
}

View file

@ -42,6 +42,7 @@ import {
MakeSqueakRequest,
GetSqueakDisplayRequest,
GetAncestorSqueakDisplaysRequest,
GetReplySqueakDisplaysRequest,
GetSqueakProfileByAddressRequest,
GetAddressSqueakDisplaysRequest,
CreateContactProfileRequest,
@ -67,6 +68,7 @@ import {
MakeSqueakReply,
GetSqueakDisplayReply,
GetAncestorSqueakDisplaysReply,
GetReplySqueakDisplaysReply,
GetSqueakProfileByAddressReply,
GetAddressSqueakDisplaysReply,
CreateContactProfileReply,
@ -728,6 +730,19 @@ export function getAncestorSqueakDisplaysRequest(hash, handleResponse) {
);
};
export function getReplySqueakDisplaysRequest(hash, handleResponse) {
var request = new GetReplySqueakDisplaysRequest();
request.setSqueakHash(hash);
makeRequest(
'getreplysqueakdisplays',
request,
GetReplySqueakDisplaysReply.deserializeBinary,
(response) => {
handleResponse(response.getSqueakDisplayEntriesList());
}
);
};
// export function getSqueakProfileByAddressRequest(address, handleResponse) {
// var request = new GetSqueakProfileByAddressRequest();
// request.setAddress(address);

View file

@ -342,6 +342,18 @@ def test_make_reply_squeak(
)
assert len(get_ancestors_response.squeak_display_entries) == 3
# Get the replies of the original squeak
get_replies_response = admin_stub.GetReplySqueakDisplays(
squeak_admin_pb2.GetReplySqueakDisplaysRequest(
squeak_hash=saved_squeak_hash,
)
)
assert len(get_replies_response.squeak_display_entries) == 1
assert reply_1_squeak_hash in [
entry.hash
for entry in get_replies_response.squeak_display_entries
]
def test_post_squeak_rate_limit(server_stub, admin_stub, lightning_client, nonfollowing_signing_key):
# Make 10 squeak

View file

@ -132,6 +132,10 @@ service SqueakAdmin {
*/
rpc GetAncestorSqueakDisplays (GetAncestorSqueakDisplaysRequest) returns (GetAncestorSqueakDisplaysReply) {}
/** sqkadmin: `getreplysqueakdisplays`
*/
rpc GetReplySqueakDisplays (GetReplySqueakDisplaysRequest) returns (GetReplySqueakDisplaysReply) {}
/** sqkadmin: `deletesqueak`
*/
rpc DeleteSqueak (DeleteSqueakRequest) returns (DeleteSqueakReply) {}
@ -441,6 +445,16 @@ message GetAncestorSqueakDisplaysReply {
repeated SqueakDisplayEntry squeak_display_entries = 1;
}
message GetReplySqueakDisplaysRequest {
/// Hash of the squeak.
string squeak_hash = 1;
}
message GetReplySqueakDisplaysReply {
/// Multiple squeak display entries
repeated SqueakDisplayEntry squeak_display_entries = 1;
}
message DeleteSqueakRequest {
/// Hash of the created squeak.
string squeak_hash = 1;

View file

@ -312,6 +312,31 @@ class SqueakAdminServerHandler(object):
squeak_display_entries=squeak_display_msgs
)
def handle_get_reply_squeak_display_entries(self, request):
squeak_hash_str = request.squeak_hash
squeak_hash = bytes.fromhex(squeak_hash_str)
logger.info(
"Handle get reply squeak display entries for squeak hash: {}".format(
squeak_hash_str
)
)
squeak_entries_with_profile = (
self.squeak_controller.get_reply_squeak_entries_with_profile(
squeak_hash,
)
)
logger.info(
"Got number of reply squeak entries: {}".format(
len(squeak_entries_with_profile)
)
)
squeak_display_msgs = [
squeak_entry_to_message(entry) for entry in squeak_entries_with_profile
]
return squeak_admin_pb2.GetReplySqueakDisplaysReply(
squeak_display_entries=squeak_display_msgs
)
def handle_delete_squeak(self, request):
squeak_hash_str = request.squeak_hash
squeak_hash = bytes.fromhex(squeak_hash_str)

View file

@ -112,6 +112,9 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
def GetAncestorSqueakDisplays(self, request, context):
return self.handler.handle_get_ancestor_squeak_display_entries(request)
def GetReplySqueakDisplays(self, request, context):
return self.handler.handle_get_reply_squeak_display_entries(request)
def DeleteSqueak(self, request, context):
return self.handler.handle_delete_squeak(request)

View file

@ -321,6 +321,14 @@ def create_app(handler, username, password):
handler.handle_get_ancestor_squeak_display_entries,
)
@app.route("/getreplysqueakdisplays", methods=["POST"])
@login_required
def getreplysqueakdisplays():
return handle_request(
squeak_admin_pb2.GetReplySqueakDisplaysRequest(),
handler.handle_get_reply_squeak_display_entries,
)
@app.route("/getsqueakprofilebyaddress", methods=["POST"])
@login_required
def getsqueakprofilebyaddress():

View file

@ -1,14 +1,14 @@
{
"files": {
"main.js": "/static/js/main.22867821.chunk.js",
"main.js.map": "/static/js/main.22867821.chunk.js.map",
"main.js": "/static/js/main.d8564b4e.chunk.js",
"main.js.map": "/static/js/main.d8564b4e.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
"static/css/2.ea4ba2f0.chunk.css": "/static/css/2.ea4ba2f0.chunk.css",
"static/js/2.80e95388.chunk.js": "/static/js/2.80e95388.chunk.js",
"static/js/2.80e95388.chunk.js.map": "/static/js/2.80e95388.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.bc07b0021f8a965bccc7bfe92f128414.js": "/precache-manifest.bc07b0021f8a965bccc7bfe92f128414.js",
"precache-manifest.05e60b27929cee847424d50d21d0d457.js": "/precache-manifest.05e60b27929cee847424d50d21d0d457.js",
"service-worker.js": "/service-worker.js",
"static/css/2.ea4ba2f0.chunk.css.map": "/static/css/2.ea4ba2f0.chunk.css.map",
"static/js/2.80e95388.chunk.js.LICENSE.txt": "/static/js/2.80e95388.chunk.js.LICENSE.txt",
@ -20,6 +20,6 @@
"static/js/runtime-main.9f0ba400.js",
"static/css/2.ea4ba2f0.chunk.css",
"static/js/2.80e95388.chunk.js",
"static/js/main.22867821.chunk.js"
"static/js/main.d8564b4e.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.80e95388.chunk.js"></script><script src="/static/js/main.22867821.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.80e95388.chunk.js"></script><script src="/static/js/main.d8564b4e.chunk.js"></script></body></html>

View file

@ -1,6 +1,6 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "5cdc31419bcd60d59c96246698025656",
"revision": "7916b44d76f269ebcf519e6e572541c4",
"url": "/index.html"
},
{
@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/2.80e95388.chunk.js.LICENSE.txt"
},
{
"revision": "f1527c6118f16972bc2c",
"url": "/static/js/main.22867821.chunk.js"
"revision": "b0f580ff1000d731110f",
"url": "/static/js/main.d8564b4e.chunk.js"
},
{
"revision": "cc9816de5a8639d377ea",

View file

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.bc07b0021f8a965bccc7bfe92f128414.js"
"/precache-manifest.05e60b27929cee847424d50d21d0d457.js"
);
self.addEventListener('message', (event) => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -367,6 +367,11 @@ class SqueakController:
squeak_hash,
)
def get_reply_squeak_entries_with_profile(self, squeak_hash: bytes):
return self.squeak_db.get_thread_reply_squeak_entries_with_profile(
squeak_hash,
)
def lookup_squeaks(self, addresses: List[str], min_block: int, max_block: int):
return self.squeak_db.lookup_squeaks(
addresses,

View file

@ -242,6 +242,28 @@ class SqueakDb:
# rows = curs.fetchall()
# return [self._parse_squeak_entry_with_profile(row) for row in rows]
def get_thread_reply_squeak_entries_with_profile(self, squeak_hash: bytes):
""" Get all replies for a squeak hash. """
s = (
select([self.squeaks, self.profiles])
.select_from(
self.squeaks.outerjoin(
self.profiles,
self.profiles.c.address == self.squeaks.c.author_address,
)
)
.where(self.squeaks.c.block_header != None) # noqa: E711
.where(self.squeaks.c.hash_reply_sqk == squeak_hash.hex())
.order_by(
self.squeaks.c.n_block_height.desc(),
self.squeaks.c.n_time.desc(),
)
)
with self.get_connection() as connection:
result = connection.execute(s)
rows = result.fetchall()
return [self._parse_squeak_entry_with_profile(row) for row in rows]
def lookup_squeaks(
self,
addresses,